顯示具有 iam 標籤的文章。 顯示所有文章
顯示具有 iam 標籤的文章。 顯示所有文章

2024年6月6日 星期四

AWS - IAM Role with Policy

AWS 的 IAM Role 跟 Policy 有兩種連接方式:
- Role 內嵌 Policy.
- Role 和 Policy 是各自建立, 然後再接起來(attach)用.

以 Policy 編修來說, 前者就只能在 portal 上面 CRUD, 後者在 Policy 本身的 portal 介面還可以看 permission 檢查, 歷次編修版本與控管, 相同的 Policy 還可以接到多個 Role 共用, 後來我也盡量都用後者.

不過後者在 Terraform 的寫作上有需要注意的地方, 一般寫法如下:

resource "aws_iam_policy" "this" {}
resource "aws_iam_role" "this" {}
resource "aws_iam_role_policy_attachment" "this" {
  depends_on = [
    aws_iam_role.this,
    aws_iam_policy.this
  ]
}

在 terraform apply 的時候不成問題, 但是在 terraform destroy 會發生 race condition: Policy 還沒從 Role 拆出來, 上面這個寫法會造成 aws_iam_policy 跟 aws_iam_role 同時進行 destroy, 在刪除 aws_iam_policy 就會噴錯誤訊息, 說 Policy 還接在 Role 上面所以不能被砍掉.

雖然再執行一次 terraform destroy 就過了(錯誤是在砍 aws_iam_policy 的時候噴的, 但同時砍 aws_iam_role 的動作有被完成), 但是這樣對於砍站跑路就不夠絲滑.

簡單解決的方式就是在 aws_iam_role 裡面加一個 depends_on aws_iam_policy:

resource "aws_iam_role" "this" {
  ...

  depends_on = [
    aws_iam_policy.this
  ]
}

這樣子在 destroy 的時候, aws_iam_role 就會先被刪除(無論 Policy 拆出來了沒), 再刪除 aws_iam_policy 就不會卡住了.

然後第一個方式在 Terraform 有個地雷, 在 Role 裡面內嵌 Policy 大概是這樣寫:

resource "aws_iam_role" "this" {
  ...

  inline_policy {
    name = "Role-foobar-Policy"
    ...
  }
}

當不要用 inline_pocily 的時候, 把這段刪除成這樣:

resource "aws_iam_role" "this" {
  ...
}

然後 terraform apply 的時候, diff 並沒有出現 - 掉 inline_policy 這塊的訊息, 實際上 Terraform 真的沒做這個刪除, 在 portal 是還看得到 inline_policy 的存在, 得在這邊手動砍掉才算沒了.


隱欌地雷: AWS IAM 有好幾個拆連接的動作會產生 race condition, 表面上 API 回應 ok, 但是實際上裡面還在慢慢斷開, 沒那麼快拆完...

2022年11月30日 星期三

GCP - copy IAM custom role R from project A to project B

Role ID: projects/A/roles/R

0. gcloud auth login (with enough permission)

1. gcloud iam roles describe R --project=A > R.txt

2. gcloud iam roles create R --project=B --file=R.txt

2021年6月21日 星期一

Terraform - GCP IAM apply / destroy race condition

這是一個用 terraform 處理 GCP project / pubsub subscription / pubsub topic / storage bucket / etc 的 IAM role 常會遇到的 race condition, 目前高達八成確定原因是在 GCP 的相關 API 不是 single action, 而是 atomic action, 而且設後不理沒確認是否執行完成就直接 return.

目前只能用 workaround 解法: 再執行/多執行幾次 terraform 指令. (原因後敘)

假設狀況如下: (真實狀況可能不是/不只這樣)
- bucket foobar 原本就有 role: roles/storage.legacyBucketReader
- 現在要改成 role: roles/storage.legacyBucketOwner
- 執行 terraform apply (無關的部分就省略了):
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: -/+ destroy and then create replacement Terraform will perform the following actions: # module.basement.google_storage_bucket_iam_member.bucket must be replaced -/+ resource "google_storage_bucket_iam_member" "bucket" { ~ role = "roles/storage.legacyBucketReader" -> "roles/storage.legacyBucketOwner" # forces replacement } Plan: 1 to add, 0 to change, 1 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value:
表示這個 bucket 的 iam role 會被先拆後建. - 輸入 yes 再按 enter 下去之後, 噴錯誤訊息出來說無法設定之類的.... (省略) - 通常只要再執行一次 terraform apply 再 yes 下去之後就可以正常執行完. - 還是噴一樣錯誤訊息的話, 那就再等一下再執行一次... - The End.

有人會問, 是不是可以用 time_sleep 的寫法讓 destroy 先執行完再 apply ?

首先, 這是一個 resource 被 replace (destroy -> apply) 的動作, 並不是分開的 resource 運作, 所以不適用上面這種方式來處理.

其次, 在 terraform 裡面這應該是個呼叫 GCP API 進行 remove 之後再 add 的行為, 中間沒有也不應該有 delay 動作影響執行效率(這也可能產生別的 race condition), 問題點是在 remove 跟 add 大概是 atomic action, 沒有全部確定執行完就 return 回來, 產生後續的 race condition 問題.

最後, 利用 time_sleep 那個寫法實在是累贅也有問題, 因為使用者通常不會知道 create 要花多久時間(create_duration), 也不會知道 destroy_duration 多久, 只能用預估或是猜的來設定. 若是 GCP 不忙的時候可能 1s 就全部跑完, 卻還要等完剩下的 29s, 或是 1m 才跑完, 設定 30s 照樣還是發生 race condition.

倒不如還是人工 delay 再人工執行同樣的 terraform 指令還比較簡單實用.

2021年5月31日 星期一

GCP - Basic.Owner is not full Owner of project

一般來說, GCP project 使用者最大的權限應該是 Basic.Owner, 幾乎所有情況都能通行無阻.

但是...

最好再加上一個 Storage Admin 的 Owner, 才不會在 Cloud Storage 之類的相關功能遇到莫名其妙的卡住. 尤其是有用 terraform 操控 bucket + iam 的時候...

如果 project 上面還有一層 organization, 最好也設定個 Organization 的 Owner 上身, 避免靈異現象...