--- # **Agenda** - 前言 - Identity - Role - IAM policy - 整體架構 - IAM Resource Hierarchy - 實際演練 --- ## 1. 前言 CLOUD IAM 是 GCP 管理資源權限的服務,全名叫Identity and Access Management,中文意思即「身分識別與存取管理」,主要功能是讓GCP知道 **誰(Identity)** 可以對哪些 **資源(Resource)** 做 **哪些行為(Role)**。 --- ## 2. **Identity** - Google Account : 可能是開發者或是管理員的電子郵件地址,通常是 gmail.com,也可以是其他域名。 - Service Account : 提供給應用程式的帳號,例如應用程式要使用gcp的資源時,就會以被指定的服務帳號來驗證其身分,若有相關權限,即可對GCP資源做權限所允許的行為。 - Google Group : 是一個由多個 Google Account 或 Service Account 組成的集合,而每一個Google Group都會有唯一的電子郵件帳號,其用途在管理者可透過這個帳號,直接對集合中的帳號統一授權或是權限調整,提高管理上的便利性 ; 惟須留意,Google Group帳號是無法作為登入GCP時所使用的帳號的。 - Google Workspace : 主要是以一個域名來管理,例如某組織註冊域名 xxx.com,並用這個域名為底下員工註冊google帳戶,如 employee_1@xxx.com、employee_2@xxx.com,那麼設定iam的時候,就能一次性的使用xxx.com來管理組織下的權限。 - Cloud Identity Domain : 類似於Google Workspace,差別在於如果沒有要使用Workspace的服務,那使用 Cloud Identity Domain 即可。 --- ## 3. **Roles** Roles 與兩項目有相關,即 Resource、Permission,故先簡單描述兩者,接著再介紹Roles。 ### Resource : 即GCP提供的各種資源,例如 storage、cloudsql、memorystore等等。 ### Permission : 可以對gcp資源做什麼行為,例如刪除gce的vm,即需要如下圖的權限。  ### Roles Roles 是由一個或多個 Permission 所組成的角色,其類型有以下三種 : 1. **Basic Roles (基本角色)** : 有Owner/Editor/Viewer三種role,在啟用gcp project後就會存在了。其中Owner權限最大,擁有project內所有資源的存取權,而Editor是可以修改既已存在的資源並包含Viewer的權限,Viewer則只能對資源進行檢視。這種類型的role在管理權限上是非常不細致的,因此並不建議使用這種方式來管理權限。 2. **Predefined Roles (預定義角色)** : 由GCP提供並持續維護與更新的role,這種角色可以針對特定的資源去配置權限,相較於Basic Roles是對整個專案的資源都適用,Predefined Roles在權限控管上的精細度是有所提升的。實例如下圖紅框處,該權限僅限於GCS的建立、讀取、更新和刪除物件及分段上傳:  3. **Custom Roles (自定義角色)** : 此種 role 比 Predefined role 又更精細,如下圖紅框處,可以只針對特定權限授予,例如只想授予storage的建立權限,那只加入 storage.bucket.create 即可達到需求。  --- ## 4. **IAM policy** 當角色都制定好,再來就是要如何授權給使用者了,此時就會使用到 IAM policy。  以上圖來說明,IAM policy是由一個或多個Binding的集合,其中Binding就是將某種Roles綁定給使用者的概念。 --- ## 5. 整體架構  Cloud IAM 會根據 IAM policy 去查看**誰(Identity)** 可以對哪些 **資源(Resource)** 做 **哪些行為(Role)**,所以當使用者沒有被綁定到Roles,就無法執行該Roles所擁有的權限,此即為IAM的整體概念。 --- ## 6. IAM Resource Hierarchy 在 GCP 上,所有資源都是以階層的方式進行組織,從上到下依序為: 1. Organization: 根節點,資源的最上層 2. Folder: Organization 的子項目 3. Project: Organization 或是 Folder 的子項目 4. Resource: Project 下面的子項目  --- ## 7. 實際演練 以下會以GCS作為示範的資源,建置則以terraform方式建立。 簡單描述演練項目及步驟: 1. terraform前置準備 2. 創建自定義的角色 3. 創建服務帳號 4. 創建iam_policy 5. 驗證iam_policy 6. condition功能演示 <br> - **terraform前置準備 (此步驟只限terraform練習才要,用ui練習者可忽略)** - ui介面操作: (1) 先為terraform建置服務帳號  接著產出服務帳戶的金鑰:  (2)創建一個自訂義的角色,角色要擁有以下權限: ``` iam.roles.get iam.roles.create iam.roles.delete iam.roles.update iam.roles.undelete iam.serviceAccountKeys.create iam.serviceAccountKeys.delete iam.serviceAccountKeys.get iam.serviceAccounts.create iam.serviceAccounts.delete iam.serviceAccounts.get resourcemanager.projects.setIamPolicy resourcemanager.projects.getIamPolicy ```  (3) 建置好角色後,將角色綁訂至terraform的服務帳號  - terraform腳本: ```terraform= // provider.tf provider "google" { credentials = var.credentials project = var.project region = var.region } provider "google-beta" { credentials = var.credentials project = var.project region = var.region } // variable.tf variable "credentials" { type = string default = "terraform-test.json" } variable "project" { type = string default = "iamrich-lab" } variable "region" { type = string default = "asia-east1" } //terraform-test.json -> 將剛剛產出的金鑰內容貼到此份檔案 ``` - **創建自定義角色** - ui的設定位置在:  - terraform建置腳本: ```terraform= # main.tf resource "google_project_iam_custom_role" "custom_role"{ for_each = var.custom_role_list role_id = each.value.role_id title = each.value.title permissions = each.value.permissions description = each.value.description } # variable.tf variable "custom_role_list"{ type = map(object({ role_id = string title = string permissions = list(string) description = string })) default = { custom_role_1 = { role_id = "CustomRoleFortest1" title = "Custom Role Test 1" permissions = ["storage.buckets.create","storage.buckets.get"] description = "forIamTest-storage-create" } } } ``` - **創建服務帳號** - ui的設定位置在:  - terraform建置腳本: ```terraform= # *main.tf* #--創建服務帳號 resource "google_service_account" "for-test" { for_each = var.servcieaccount_list account_id = each.value.account_id display_name = each.value.display_name } #--產出服務帳號的金鑰 resource "google_service_account_key" "mykey" { for_each = var.key_list service_account_id = google_service_account.for-test[each.key].name public_key_type = each.value.public_key_type } #--將上面服務帳號的私鑰 匯出至本機指定的目錄 (等等切換帳號時需用到) resource "local_file" "download_key_json"{ for_each = var.keyjson_list content = base64decode(google_service_account_key.mykey[each.key].private_key) filename = each.value.filename } # variable.tf variable "servcieaccount_list"{ type = map(map(string)) default = { for_test = { account_id = "for-test" display_name = "Allow to editor storage." } } } variable "key_list" { type = map(map(string)) default = { for_test = { public_key_type = "TYPE_X509_PEM_FILE" } } } variable "keyjson_list"{ type = map(map(string)) default = { for_test ={ filename = "./serviceaccount_demo/for-test.json" } } } ``` - **創建iam_policy** - ui的設定位置在:  - terraform建置腳本: 分別有兩種不同情境: 1. 針對單一帳號設定 policy ```terraform= # main.tf resource "google_project_iam_member" "iam_policy" { for_each = var.google_project_iam_member_list project = var.project role = each.value.role member = each.value.member dynamic "condition" { for_each = each.value.condition_config content { title = condition.value["title"] description = condition.value["description"] expression = condition.value["expression"] } } } # variable.tf variable "google_project_iam_member_list" { type = map(object({ role = string member = string condition_config = list(object({ title = string description = string expression = string })) })) default = { for_iam_member_1 = { role = "projects/iamrich-lab/roles/CustomRoleFortest1" member = "serviceAccount:for-test@iamrich-lab.iam.gserviceaccount.com" condition_config = [] } } } ``` 2. 針對多組帳號設定 policy ```terraform= # main.tf resource "google_project_iam_binding" "iam_policy" { for_each = var.google_project_iam_binding_list project = var.project role = each.value.role member = each.value.muli_member dynamic "condition" { for_each = each.value.condition_config content { title = condition.value["title"] description = condition.value["description"] expression = condition.value["expression"] } } } # variable.tf variable "google_project_iam_binding_list" { type = map(object({ role = string muli_member = list(string) condition_config = list(object({ title = string description = string expression = string })) })) default = { for_iam_muliMember = { role = "projects/iamrich-lab/roles/CustomRoleFortest1" muli_member = [ "serviceAccount:for-test@iamrich-lab.iam.gserviceaccount.com", ] condition_config = [] } } } ``` 關於Permission有哪些 可參考[GCP文件](https://cloud.google.com/iam/docs/understanding-roles#cloud-storage-roles) - **驗證iam_policy (使用剛創建的服務帳號創建+刪除bucket)** - ui的設定位置在:  - terraform建置腳本: 到這邊我們需要切換資料夾,因為接下來要使用剛剛建好的服務帳號執行,來驗證iam_policy生效。新的資料夾會有以下: ```terraform= # main.tf resource "google_storage_bucket" "bucket"{ name = "test-20240605" location = "ASIA" force_destroy = false storage_class = "STANDARD" cors { origin = ["*"] method = ["GET"] response_header = ["Access-Control-Allow-Origin"] max_age_seconds = 3600 } } # variable.tf variable "credentials" { type = string default = "for-test.json" } variable "project" { type = string default = "iamrich-lab" } variable "region" { type = string default = "asia-east1" } # provider.tf provider "google" { credentials = var.credentials project = var.project region = var.region } provider "google-beta" { credentials = var.credentials project = var.project region = var.region } ``` - **condition功能演示** - ui的設定位置在:  (在創建iam_policy時可以順便設定的) - terraform腳本: ```terraform= variable "google_project_iam_member_list" { type = map(object({ role = string member = string condition_config = list(object({ title = string description = string expression = string })) })) default = { for_iam_member_1 = { role = "projects/iamrich-lab/roles/CustomRoleFortest1" member = "serviceAccount:for-test-1@iamrich-lab.iam.gserviceaccount.com" condition_config = [ { title = "condition_test" description = "for-condition-test" expression = "request.time.getHours('Asia/Taipei') >= 9 && request.time.getHours('Asia/Taipei') <= 15 && request.time.getDayOfWeek('Asia/Taipei') >= 1 && request.time.getDayOfWeek('Asia/Taipei') <= 5" } ] } } } ``` --- ## 參考文件 https://cloud.google.com/iam/docs/overview?hl=zh-cn https://cloud.google.com/iam/docs/conditions-overview?hl=zh-cn https://blog.cloud-ace.tw/identity-security/what-is-cloud-iam/ https://hackmd.io/@kevinhuangtw/SJ2KjoRKc terraform項目: [google_project_iam_custom_role](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam_custom_role) [google_service_account](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account) [google_service_account_key](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account_key) [local_file](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) [google_project_iam](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam) [google_storage_bucket](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket)
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up