隨著 IaC 的普及,維護 Terraform 組態的安全性和合規性變得至關重要。本文介紹如何利用 OPA 和 Conftest 驗證 Terraform 計畫,並示範如何編寫 Rego 政策來檢查 Terraform 版本、EKS 叢集版本和 AWS 區域等組態。我們將逐步講解如何將 Terraform 計畫轉換為 JSON 格式,以便 Conftest 進行分析,並探討 Rego 政策的編寫技巧,包含如何定義規則、處理違規以及輸出錯誤訊息。此外,我們還將示範如何直接解析 Terraform 的 HCL 組態檔案,並使用簡化的 Rego 政策進行驗證,提升效率並降低複雜度。最後,文章將探討 HashiCorp Sentinel 的基本使用,並展望 PaC 與 IaC 整合。

利用Conftest與Rego政策驗證Terraform計畫的有效性

隨著雲端基礎設施即程式碼(IaC)的普及,確保Terraform組態的安全性和合規性變得至關重要。Open Policy Agent(OPA)與Conftest的結合提供了一種強大的工具,用於驗證Terraform計畫是否符合組織的政策和最佳實踐。

從二進位制Terraform計畫到JSON輸出

首先,我們需要將二進位制的Terraform計畫檔案轉換為JSON格式,以便進行進一步的分析。使用terraform show命令可以實作這一點:

# 輸出二進位制Terraform計畫到JSON檔案
$ terraform show -json tfplan > tfplan.json

執行上述命令後,我們得到了一個名為tfplan.json的檔案,其中包含了Terraform計畫的詳細資訊,以JSON格式呈現。接下來,我們可以檢查這個JSON檔案,以確認Terraform版本、Amazon EKS叢集版本和AWS區域等關鍵資訊。

編寫Rego政策以驗證Terraform計畫

為了驗證Terraform計畫是否符合特定的政策要求,我們編寫了以下Rego政策:

# Rego政策以驗證Terraform JSON計畫
package examples.ch11.terraform

import rego.v1

allowed_tf_versions := {"1.5.4"}
allowed_eks_versions := {"1.26", "1.27"}
allowed_regions := {"us-east-1", "us-west-2"}

default allow := false

allow if {
    count(violation) == 0
}

violation contains msg if {
    not input.terraform_version in allowed_tf_versions
    msg := sprintf("無效的Terraform版本,版本必須在%q中", [allowed_tf_versions])
}

violation contains msg if {
    not input.variables.cluster_version.value in allowed_eks_versions
    msg := sprintf("無效的EKS版本,版本必須在%q中", [allowed_eks_versions])
}

violation contains msg if {
    not input.variables.region.value in allowed_regions
    msg := sprintf("無效的區域,區域必須在%q中", [allowed_regions])
}

內容解密:

  1. package examples.ch11.terraform:定義了Rego政策的套件名稱,這有助於組織和管理政策。
  2. import rego.v1:匯入了Rego v1的語法和功能。
  3. allowed_tf_versionsallowed_eks_versionsallowed_regions:定義了允許的Terraform版本、EKS叢集版本和AWS區域。
  4. default allow := false:預設情況下,不允許任何不符合政策的組態。
  5. allow if { count(violation) == 0 }:只有當沒有違規時,才允許透過。
  6. violation contains msg:定義了三個違規規則,分別檢查Terraform版本、EKS叢集版本和AWS區域是否符合允許的值。

使用Conftest驗證Terraform計畫

接下來,我們使用Conftest來驗證tfplan.json檔案是否符合上述Rego政策:

# 使用Conftest命令驗證Terraform JSON檔案
$ conftest test tfplan.json -p policies -n examples.ch11.terraform -o json

內容解密:

  1. conftest test:Conftest的測試命令,用於驗證輸入檔案是否符合指定的Rego政策。
  2. tfplan.json:待驗證的Terraform計畫JSON檔案。
  3. -p policies:指定包含Rego政策的目錄。
  4. -n examples.ch11.terraform:指定要使用的Rego政策套件名稱。
  5. -o json:以JSON格式輸出測試結果。

執行上述命令後,我們得到了驗證結果,顯示了哪些檢查未透過以及具體的原因。

簡化Rego政策與直接解析HCL檔案

除了驗證Terraform計畫的JSON輸出,我們還可以直接解析Terraform的HCL組態檔案,並使用簡化的Rego政策進行驗證。首先,使用Conftest解析HCL檔案:

# 使用Conftest解析HCL檔案
$ conftest parse terraform.tfvars

內容解密:

  1. conftest parse:Conftest的解析命令,用於將HCL檔案轉換為JSON格式。
  2. terraform.tfvars:待解析的Terraform HCL組態檔案。

接下來,我們簡化了Rego政策,以匹配Conftest解析後的JSON輸出:

# 簡化的Rego政策
package examples.ch11.terraform

import rego.v1

allowed_eks_versions := {"1.26", "1.27"}
allowed_regions := {"us-east-1", "us-west-2"}

default allow := false

allow if {
    count(violation) == 0
}

violation contains msg if {
    not input.cluster_version in allowed_eks_versions
    msg := sprintf("無效的EKS版本,版本必須在%q中", [allowed_eks_versions])
}

violation contains msg if {
    not input.region in allowed_regions
    msg := sprintf("無效的區域,區域必須在%q中", [allowed_regions])
}

內容解密:

  1. 簡化了輸入檢查:由於Conftest已經將HCL檔案解析為簡化的JSON結構,因此Rego政策中的輸入檢查也相應簡化。
  2. 保留了核心邏輯:簡化後的Rego政策仍然保留了對EKS版本和AWS區域的檢查邏輯。

最後,我們使用Conftest直接對terraform.tfvars檔案進行驗證,並故意引入了一個AWS區域錯誤:

# 使用Conftest測試HCL檔案,並輸出GitHub格式的結果
$ conftest test -p policies/hcl.rego terraform.tfvars -n examples.ch11.terraform -o github

內容解密:

  1. conftest test:再次使用Conftest的測試命令。
  2. -p policies/hcl.rego:指定簡化的Rego政策檔案。
  3. terraform.tfvars:待驗證的HCL組態檔案。
  4. -o github:以GitHub Actions相容的格式輸出結果。

執行上述命令後,Conftest正確檢測到了引入的AWS區域錯誤,並給出了詳細的錯誤資訊。

隨著雲端技術的不斷演進,IaC工具和實踐也在不斷發展。未來,我們可以期待看到更多根據OPA和Conftest的創新應用,例如:

  • 更廣泛的檔案格式支援,以涵蓋更多種類別的IaC工具和組態檔案。
  • 更強大的策略定義語言,以支援更複雜的合規性需求。
  • 更緊密的CI/CD流程整合,以實作自動化的策略驗證和合規性檢查。

透過持續改進和創新,根據OPA和Conftest的策略驗證將繼續為雲端基礎設施的安全性和合規性提供強有力的保障。

  graph LR;
    A[開始] --> B[生成Terraform計畫];
    B --> C[轉換為JSON格式];
    C --> D[編寫Rego政策];
    D --> E[使用Conftest驗證];
    E --> F[解析HCL檔案];
    F --> G[簡化Rego政策];
    G --> H[直接驗證HCL檔案];
    H --> I[結果輸出與分析];
    I --> J[結論];

圖表翻譯: 此圖表展示了使用Conftest和Rego政策驗證Terraform計畫的有效性的整個流程。首先生成Terraform計畫並將其轉換為JSON格式,接著編寫Rego政策並使用Conftest進行驗證。然後解析HCL檔案並簡化Rego政策,直接對HCL檔案進行驗證。最後輸出結果並進行分析,得出結論。整個流程清晰地展示瞭如何利用這些工具確保Terraform組態的安全性和合規性。

宣告式基礎設施即程式碼(IaC)與政策即程式碼(PaC)的整合應用

隨著雲端運算的普及,基礎設施即程式碼(Infrastructure as Code, IaC)已經成為管理基礎設施的主流方式。IaC 不僅提升了基礎設施的管理效率,還透過最佳實踐(如不可變性基礎設施)減少了對個別運算資源的依賴,使應用程式和使用者經驗變得更加重要。在本章中,我們將重點探討宣告式 IaC,並簡要介紹指令式 IaC,以及如何將 PaC(Policy as Code)應用於 IaC,以控制宣告式 IaC 所做的變更。

使用 Rego 編寫 Terraform 計劃的政策

當將輸入檔案作為 Terraform 計劃匯入時,Rego 政策規則和函式可以根據已知的 Terraform HCL 結構來處理 Terraform 計劃的層次結構,而無需顯式遍歷通用的 JSON 結構。

示例:禁止在 Terraform 計劃中使用 IAM 資源

以下是一個 Rego 政策示例,用於禁止在 Terraform 計劃中包含 aws_iam_policyaws_iam_role 資源型別:

# Rego 政策:禁止在 Terraform 計劃中使用 IAM 資源
package examples.ch11.terraform

import input as tfplan
import rego.v1

disallowed_iam_types := {"aws_iam_policy", "aws_iam_role"}

default tfplan_allow := false

tfplan_allow if {
    count(violation_detected_iam) == 0
}

violation_detected_iam contains msg if {
    detected_iam_resources
    msg := sprintf("IAM 資源不允許在計劃中使用:%q", [disallowed_iam_types])
}

detected_iam_resources if {
    some x in disallowed_iam_types
    resources[x]
}

resources contains res.type if {
    some res in tfplan.resource_changes
    res.type in disallowed_iam_types
}

內容解密:

  1. packageimport 陳述式:定義了 Rego 政策的套件和匯入的輸入資料(Terraform 計劃)和 Rego 版本。
  2. disallowed_iam_types 集合:定義了不允許使用的 IAM 資源型別。
  3. tfplan_allow 規則:當沒有檢測到違規的 IAM 資源時,允許該 Terraform 計劃。
  4. violation_detected_iam 規則:如果檢測到違規的 IAM 資源,則生成錯誤訊息。
  5. detected_iam_resources 規則:檢查是否存在任何不允許的 IAM 資源型別。
  6. resources 規則:遍歷 Terraform 計劃中的資源變更,檢查是否存在違規的資源型別。

使用 Styra DAS 和 Conftest 進行 Terraform 計劃的政策評估

Styra(OPA 的建立者)提供了 Styra DAS Terraform 系統型別,可以直接對 Terraform .tf 檔案進行政策評估,而無需先將其轉換為計劃並再轉換為 JSON。此外,Conftest Policy Packs GitHub 專案提供了多個合規即程式碼的示例,包括 Terraform 示例。Terraform Cloud 也引入了使用 OPA 政策進行政策執行的功能。

測試 Rego 政策

使用 conftest test 命令測試上述政策對一個較長的 Terraform 計劃進行驗證:

conftest test iac-resources/long-tfplan.json -p policies -n examples.ch11.terraform -o json

輸出結果顯示了測試的成功和失敗情況,包括違規的 IAM 資源訊息。

結果分析:

  • successesfailures:顯示了測試的成功和失敗數量。
  • msg 欄位:包含了違規資源的詳細訊息。

使用 Rego Playground 編寫和除錯 Rego 政策

Rego Playground 是編寫和除錯 Rego 政策的有力工具。透過匯入 Terraform 計劃作為 JSON 檔案,並使用 Rego 變數,可以在 Rego Playground 的輸出窗格中顯示計劃或其部分內容,從而更容易地探索和學習計劃的物件模型。

隨著雲端運算和 IaC 的不斷發展,未來 PaC 將在 IaC 中扮演越來越重要的角色。企業需要採用更加自動化和智慧化的政策管理方案,以應對日益複雜的基礎設施環境。同時,開源工具如 OPA 和 Styra DAS 將繼續在 PaC 領域發揮重要作用,幫助企業實作更高效的政策管理和執行。

  graph LR
    A[宣告式 IaC] --> B[Terraform 計劃]
    B --> C[Rego 政策評估]
    C --> D[Styra DAS]
    C --> E[Conftest]
    D --> F[政策執行]
    E --> F
    F --> G[合規性檢查]

圖表翻譯: 此圖示展示了宣告式 IaC 如何透過 Terraform 計劃進行 Rego 政策評估,並利用 Styra DAS 和 Conftest 等工具進行政策執行和合規性檢查的流程。圖中每個節點代表了一個關鍵步驟或工具,最終實作了對基礎設施組態的自動化管理和合規性檢查。

PaC 與 Terraform IaC 的進階應用

HashiCorp Sentinel 的基本介紹與使用

在前一章中,我們探討瞭如何將 PaC(Policy as Code)應用於 IaC(Infrastructure as Code),並著重於 AWS 與 Terraform 的結合。本章將繼續深入研究 Terraform 在 IaC 中的應用,並擴充套件 PaC 的工具選擇。首先,我們將介紹 HashiCorp Sentinel,一種專為驗證 Terraform 工件而設計的 PaC 語言。

HashiCorp Sentinel 是由 HashiCorp 開發的一種策略語言,旨在簡化程式設計人員與非程式設計人員對於策略評估的理解。根據官方檔案,Sentinel 語法簡單易懂。以下是一個簡單的「Hello World」範例:

# sentinel hello world
h = "Hello"
s = " "
w = "World"

func msg(m) {
    return m + w
}

main = rule {
    print(msg(h + s))
}

內容解密:

  1. 變數定義:首先定義了三個字串變數 hsw,分別代表 “Hello”、空格和 “World”。
  2. 函式定義:定義了一個名為 msg 的函式,該函式接受一個引數 m 並傳回 m + w,即將輸入字串與 “World” 連線起來。
  3. 主規則main 規則是 Sentinel 策略的核心,它必須傳回一個布林值。在這個範例中,main 規則呼叫了 msg 函式,並將 “Hello” 和空格連線後的結果傳入,最終列印預出 “Hello World”。

執行上述程式碼在 Sentinel Playground 中會產生以下輸出:

# sentinel hello world playground output
Sentinel Result: true
This result means that all Sentinel policies passed and the protected behavior is allowed.
1 policies evaluated.