本篇延續 Terragrunt 的功能,介紹
課程內容與代碼會放在 Github 上: https://github.com/chechiachang/terraform-30-days
賽後文章會整理放到個人的部落格上 http://chechia.net/
工程師應該注意 infrastructure 的安全性,然而並非人人都是資安專業背景,不一定都能捉到設定上資安風險。這時就要依賴外部的檢查資料庫,根據常見的安全性錯誤進行檢查。tfsec 是一個很好的免費開源工具,針對 terraform 的 .tf 檔案,針對 plan 直接進行分析,挑出安全性錯誤。底下介紹如何搭配 terragrunt 使用 tfsec。
sudo port install tfsec
sudo brew install tfsec
tfsec --version
0.57.0
找尋 root module 直接運行 tfsec
tfsec .
tfsec --exclude-downloaded-modules
為了避免以上的問題,可以使用 terragrunt before hook。這裡我們隨意拿一個 root module 作為範例
# azure/foundation/compute_network/terragrunt.hcl
terraform {
...
before_hook "tfsec" {
commands = ["apply", "plan"]
execute = ["tfsec", "."]
}
}
實際的效果
# azure/foundation/compute_network/terragrunt.hcl
cd azure/foundation/compute_network
terragrunt apply
Initializing modules...
Initializing the backend...
Initializing provider plugins...
Terraform has been successfully initialized!
INFO[0010] Executing hook: before_hook prefix=[/Users/che-chia/my-workspace/terraform-30-days/azure/foundation/compute_network]
times
------------------------------------------
disk i/o 2.952161ms
parsing HCL 29.157µs
evaluating values 1.307087ms
running checks 1.486024ms
counts
------------------------------------------
files loaded 7
blocks 8
evaluated blocks 26
modules 1
module blocks 18
results
------------------------------------------
critical 0
high 0
medium 0
low 0
ignored 0
No problems detected!
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration
and found no differences, so no changes are needed.
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
只要每一次 apply 前,都會進行 tfsec
如果希望所有
使用注意 hook 與 git pre-commit hook,會需要時間,影響開發效率,可以依據團隊的狀況做調整
範例是 after hook,只要每一次 apply 完成後,做一次 tfsec,讓工程師測試時就可以檢查安全性問題
# azure/terragrunt.hcl
terraform {
...
after_hook "tfsec" {
commands = ["apply", "plan"]
execute = ["tfsec", "."]
}
}
tfsec 檢查清單可以到 tfsec.dev 查閱。所有的檢查內容都有附上原因,風險說明,問題範例以及改進範例。例如 azure storage 設定風險
tfsec 就是社群維護的安全守則,善用 tfsec 可以實現安全最佳實踐,也同時提升自己的資安知識。
當掃出問題時,我們不一定能馬上解決,也許是排時程稍後再修理,也許是被其他因素影響,暫時無法改正。然而每次掃瞄 tfsec 還是會跳出警告。收到警告,但大家又不會馬上修改,就會無謂的警告,浪費團隊的精神能量,消耗無謂的注意力。tfsec 提供 ignored 標記
在 Terraform 中,我們會 change directory 到一個一個 root module 中去執行 init, plan, apply 等工作。當 root module 數量很多的時候,這件事就變得很複雜。這時可以利用 Terragrunt 提供同時多 workspace 執行 的功能,一次控制多個 root module。例如以 azure/dev 為例,資料夾樹狀結構如下
tree azure/dev
.
├── env.tfvars
├── japanwest
└── southeastasia
├── container_registry
│ └── terragrunt.hcl
└── env.tfvars
cd foundation
terragrunt run-all init
#terragrunt run-all init --reconfigure
INFO[0000] Stack at /Users/che-chia/my-workspace/terraform-30-days/azure/foundation:
=> Module /Users/che-chia/my-workspace/terraform-30-days/azure/foundation/compute_network (excluded: false, dependencies: [])
=> Module /Users/che-chia/my-workspace/terraform-30-days/azure/foundation/service_principal (excluded: false, dependencies: [])
=> Module /Users/che-chia/my-workspace/terraform-30-days/azure/foundation/southeastasia/terraform_backend (excluded: false, dependencies: [])
Initializing modules...
Initializing the backend...
Initializing the backend...
Initializing the backend...
也可以進行 run-all plan
terragrunt run-all plan
INFO[0000] Stack at /Users/che-chia/my-workspace/terraform-30-days/azure/dev:
=> Module /Users/che-chia/my-workspace/terraform-30-days/azure/dev/japanwest/container_registry (excluded: false, dependencies: [])
=> Module /Users/che-chia/my-workspace/terraform-30-days/azure/dev/southeastasia/container_registry (excluded: false, dependencies: [])
...
Plan: 1 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ registry_login_server = (known after apply)
...
Plan: 1 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ registry_login_server = (known after apply)
然而,run-all 搭配 apply,要特別注意
terragrunt run-all apply
INFO[0000] Stack at /Users/che-chia/my-workspace/terraform-30-days/azure/dev:
=> Module /Users/che-chia/my-workspace/terraform-30-days/azure/dev/japanwest/container_registry (excluded: false, dependencies: [])
=> Module /Users/che-chia/my-workspace/terraform-30-days/azure/dev/southeastasia/container_registry (excluded: false, dependencies: [])
Are you sure you want to run 'terragrunt apply' in each folder of the stack described above? (y/n)
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Outputs:
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Outputs:
有些 module 其實是有依賴性,需要依照先後順序 apply 到公有雲上,後面的 module 才能夠正常 provision。例如 compute VM 其實依賴 compute network 的 subnet id,才能把 compute VM 的 ip 分配到 subnet 上。實際的例子請見 azure/dev/southeastasia/chechia_net/compute
# azure/dev/southeastasia/chechia_net/compute/terragrunt.hcl
dependency "network"{
config_path = find_in_parent_folders("azure/foundation/compute_network")
}
inputs = {
...
vnet_subnet_id = dependency.network.outputs.vnet_subnets[0] # dev-1
}
inputs 中有個參數是 vnet_subnet_id
意思是這台 VM 應該使用指定的 subnet
這一個先後的動作,就是元件的依賴性
使用 terraform ,terraform 有提供 module depends_on
的 meta-argument,讓 .tf 中可以描述 module 與 module 之間的關係
terragrunt 中提供的 dependency,進一步將這層依賴性,推廣到 root module 之間也能建立依賴性,Terragrunt modules dependency,具體是有什麼差異:
config_path
指向
find_in_parent_folders
來尋找azure/foundation/compute_network
module 中的 output
vnet_subnet_id
azure/foundation/compute_network
module 要能 output 需要的值建立起這層依賴後對於 terragrunt 工作流程的影響是
chechia_net/compute
前,會先去取得 foundation/compute_network
state 中的 output
foundation/compute_network
state 中有發現問題,則 chechia_net/compute
的 plan 與 apply 會終止
Pros
Cons
實務建議:dependency 請適量使用,不用全部有關的依賴都套用上去,也不要都不用