昨天我們將 root account IAM user import 到 terraform 中
今天要完成 root account 中 IAM Group + Policy,順便聊聊 aws IAM policy 管理原則
賽後文章會整理放到個人的部落格上 http://chechia.net/
承接昨天的 plan 結果,我們今天要把 IAM policy 與 group 開出來
首先 review aws_iam_user
的 resource
# module.iam_user["Administrator"].aws_iam_user.this[0] will be updated in-place
~ resource "aws_iam_user" "this" {
+ force_destroy = true
id = "Administrator"
name = "Administrator"
tags = {}
# (4 unchanged attributes hidden)
}`
force_destroy
這個參數我們需要嗎?可以一找以下的步驟查文件判斷
今天要來調整 Iam Group & Policy
首先 full-access 的 iam_group
plan 後的結果如下
module.iam_group_with_policies_full_access
裡面有 group 也有 policy.aws_iam_group.this[0]
是主要的 group # module.iam_group_with_policies_full_access.aws_iam_group.this[0] will be created
+ resource "aws_iam_group" "this" {
+ arn = (known after apply)
+ id = (known after apply)
+ name = "full-access"
+ path = "/"
+ unique_id = (known after apply)
}
# module.iam_group_with_policies_full_access.aws_iam_group_membership.this[0] will be created
+ resource "aws_iam_group_membership" "this" {
+ group = (known after apply)
+ id = (known after apply)
+ name = "full-access"
+ users = [
+ "Administrator",
]
}
有了 group,接下來就是要配 policy
arn:aws:iam::aws:policy/AdministratorAccess
# module.iam_group_with_policies_full_access.aws_iam_group_policy_attachment.custom_arns[0] will be created
+ resource "aws_iam_group_policy_attachment" "custom_arns" {
+ group = (known after apply)
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
有哪些 aws 已經預先定義好的 policy 可以使用?
這些預先定義的 policy,是 aws 依照最常出現的使用情境,事先建立的 policy
不使用預先定義的 policy 的話,我們可以自己寫 policy
權限愈大,安全性風險越高,所以最佳實踐會希望所有 policy 都是配得剛剛好夠用就好
通常寫 policy 很難配到非常完美剛剛好,通常都會多開 permission
AWS web console 提供根據使用紀錄,提建議修改 policy
https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html
aws 會統計各個 IAM 元件,存取 AWS API 使用/沒使用的權限
這些長時間都沒有用到的 policy,我們就應該定期 review,然後移除這些不必要的權限
由於我們在 module input 中開啟了 attach_iam_self_management_policy = true
參數,在 module 中便連帶產生
.aws_iam_policy.iam_self_management[0]
,裡面定義的要做 self management 所需要的 permission.aws_iam_group_policy_attachment.iam_self_management[0]
綁到 group 上 # module.iam_group_with_policies_full_access.aws_iam_policy.iam_self_management[0] will be created
+ resource "aws_iam_policy" "iam_self_management" {
...
}
# module.iam_group_with_policies_full_access.aws_iam_group_policy_attachment.iam_self_management[0] will be created
+ resource "aws_iam_group_policy_attachment" "iam_self_management" {
+ group = (known after apply)
+ id = (known after apply)
+ policy_arn = (known after apply)
}
上面就是我們的 root account group/full-access 與對應的 policy
接著是 root account group/full-access 與對應的 policy
我們搜尋 billing 有看到四個 policy,每個 policy 都有附上 description 說明使用的目的
這裡就要依據使用的需求選擇
我們這邊選擇 AWSBillingConductorFullAccess,做個示範
上面的變更我們的 PR 如下
由於我們 module 中有新增 module "iam_group_with_policies_billing"
,記得要先執行 init
aws-vault exec terraform-30day-root-iam-user --no-session -- terragrunt plan
╷
│ Error: Module not installed
│
│ on group.tf line 29:
│ 29: module "iam_group_with_policies_billing" {
│
│ This module is not yet installed. Run "terraform init" to install all
│ modules required by this configuration.
╵
aws-vault exec terraform-30day-root-iam-user --no-session -- terragrunt init
aws-vault exec terraform-30day-root-iam-user --no-session -- terragrunt plan
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# module.iam_group_with_policies_billing.aws_iam_group.this[0] will be created
+ resource "aws_iam_group" "this" {
+ arn = (known after apply)
+ id = (known after apply)
+ name = "billing"
+ path = "/"
+ unique_id = (known after apply)
}
# module.iam_group_with_policies_billing.aws_iam_group_membership.this[0] will be created
+ resource "aws_iam_group_membership" "this" {
+ group = (known after apply)
+ id = (known after apply)
+ name = "billing"
+ users = [
+ "Accounting",
]
}
# module.iam_group_with_policies_billing.aws_iam_group_policy_attachment.custom_arns[0] will be created
+ resource "aws_iam_group_policy_attachment" "custom_arns" {
+ group = (known after apply)
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/AWSBillingConductorFullAccess"
}
# module.iam_group_with_policies_billing.aws_iam_group_policy_attachment.iam_self_management[0] will be created
+ resource "aws_iam_group_policy_attachment" "iam_self_management" {
+ group = (known after apply)
+ id = (known after apply)
+ policy_arn = (known after apply)
}
# module.iam_group_with_policies_billing.aws_iam_policy.iam_self_management[0] will be created
+ resource "aws_iam_policy" "iam_self_management" {
+ arn = (known after apply)
+ id = (known after apply)
+ name = (known after apply)
+ name_prefix = "IAMSelfManagement-"
+ path = "/"
+ policy = jsonencode(
{
+ Statement = [
+ {
+ Action = [
+ "iam:UploadSigningCertificate",
+ "iam:UploadSSHPublicKey",
+ "iam:UpdateUser",
+ "iam:UpdateLoginProfile",
+ "iam:UpdateAccessKey",
+ "iam:ResyncMFADevice",
+ "iam:List*",
+ "iam:Get*",
+ "iam:GenerateServiceLastAccessedDetails",
+ "iam:GenerateCredentialReport",
+ "iam:EnableMFADevice",
+ "iam:DeleteVirtualMFADevice",
+ "iam:DeleteLoginProfile",
+ "iam:DeleteAccessKey",
+ "iam:CreateVirtualMFADevice",
+ "iam:CreateLoginProfile",
+ "iam:CreateAccessKey",
+ "iam:ChangePassword",
]
+ Effect = "Allow"
+ Resource = [
+ "arn:aws:iam::706136188012:user/*/${aws:username}",
+ "arn:aws:iam::706136188012:user/${aws:username}",
+ "arn:aws:iam::706136188012:mfa/${aws:username}",
]
+ Sid = "AllowSelfManagement"
},
+ {
+ Action = [
+ "iam:List*",
+ "iam:Get*",
]
+ Effect = "Allow"
+ Resource = "*"
+ Sid = "AllowIAMReadOnly"
},
+ {
+ Action = "iam:DeactivateMFADevice"
+ Condition = {
+ Bool = {
+ "aws:MultiFactorAuthPresent" = "true"
}
+ NumericLessThan = {
+ "aws:MultiFactorAuthAge" = "3600"
}
}
+ Effect = "Allow"
+ Resource = [
+ "arn:aws:iam::706136188012:user/*/${aws:username}",
+ "arn:aws:iam::706136188012:user/${aws:username}",
+ "arn:aws:iam::706136188012:mfa/${aws:username}",
]
+ Sid = "AllowDeactivateMFADevice"
},
]
+ Version = "2012-10-17"
}
)
+ policy_id = (known after apply)
+ tags_all = (known after apply)
}
# module.iam_group_with_policies_full_access.aws_iam_group.this[0] will be created
+ resource "aws_iam_group" "this" {
+ arn = (known after apply)
+ id = (known after apply)
+ name = "full-access"
+ path = "/"
+ unique_id = (known after apply)
}
# module.iam_group_with_policies_full_access.aws_iam_group_membership.this[0] will be created
+ resource "aws_iam_group_membership" "this" {
+ group = (known after apply)
+ id = (known after apply)
+ name = "full-access"
+ users = [
+ "Administrator",
]
}
# module.iam_group_with_policies_full_access.aws_iam_group_policy_attachment.custom_arns[0] will be created
+ resource "aws_iam_group_policy_attachment" "custom_arns" {
+ group = (known after apply)
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
# module.iam_group_with_policies_full_access.aws_iam_group_policy_attachment.iam_self_management[0] will be created
+ resource "aws_iam_group_policy_attachment" "iam_self_management" {
+ group = (known after apply)
+ id = (known after apply)
+ policy_arn = (known after apply)
}
# module.iam_group_with_policies_full_access.aws_iam_policy.iam_self_management[0] will be created
+ resource "aws_iam_policy" "iam_self_management" {
+ arn = (known after apply)
+ id = (known after apply)
+ name = (known after apply)
+ name_prefix = "IAMSelfManagement-"
+ path = "/"
+ policy = jsonencode(
{
+ Statement = [
+ {
+ Action = [
+ "iam:UploadSigningCertificate",
+ "iam:UploadSSHPublicKey",
+ "iam:UpdateUser",
+ "iam:UpdateLoginProfile",
+ "iam:UpdateAccessKey",
+ "iam:ResyncMFADevice",
+ "iam:List*",
+ "iam:Get*",
+ "iam:GenerateServiceLastAccessedDetails",
+ "iam:GenerateCredentialReport",
+ "iam:EnableMFADevice",
+ "iam:DeleteVirtualMFADevice",
+ "iam:DeleteLoginProfile",
+ "iam:DeleteAccessKey",
+ "iam:CreateVirtualMFADevice",
+ "iam:CreateLoginProfile",
+ "iam:CreateAccessKey",
+ "iam:ChangePassword",
]
+ Effect = "Allow"
+ Resource = [
+ "arn:aws:iam::706136188012:user/*/${aws:username}",
+ "arn:aws:iam::706136188012:user/${aws:username}",
+ "arn:aws:iam::706136188012:mfa/${aws:username}",
]
+ Sid = "AllowSelfManagement"
},
+ {
+ Action = [
+ "iam:List*",
+ "iam:Get*",
]
+ Effect = "Allow"
+ Resource = "*"
+ Sid = "AllowIAMReadOnly"
},
+ {
+ Action = "iam:DeactivateMFADevice"
+ Condition = {
+ Bool = {
+ "aws:MultiFactorAuthPresent" = "true"
}
+ NumericLessThan = {
+ "aws:MultiFactorAuthAge" = "3600"
}
}
+ Effect = "Allow"
+ Resource = [
+ "arn:aws:iam::706136188012:user/*/${aws:username}",
+ "arn:aws:iam::706136188012:user/${aws:username}",
+ "arn:aws:iam::706136188012:mfa/${aws:username}",
]
+ Sid = "AllowDeactivateMFADevice"
},
]
+ Version = "2012-10-17"
}
)
+ policy_id = (known after apply)
+ tags_all = (known after apply)
}
# module.iam_user["Accounting"].aws_iam_user.this[0] will be created
+ resource "aws_iam_user" "this" {
+ arn = (known after apply)
+ force_destroy = false
+ id = (known after apply)
+ name = "Accounting"
+ path = "/"
+ tags_all = (known after apply)
+ unique_id = (known after apply)
}
Plan: 11 to add, 0 to change, 0 to destroy.
aws-vault exec terraform-30day-root-iam-user --no-session -- terragrunt apply
眼尖的同學應該有注意到我們把 create_login_profile = false
先關掉