本程式碼實驗室會示範如何使用 IAM 條件和自訂角色,為 Cloud DNS 中的個別 DNS 記錄集實作精細的存取權控管。
簡介
Cloud DNS 傳統上支援在專案和受管理區域層級設定 IAM 權限。這項權限可讓您廣泛存取區域內的所有記錄。不過,對大型企業而言,這不符合「最小權限原則」。
本程式碼實驗室會引導您在 Cloud DNS 中設定每個記錄集的 IAM 權限。這項功能可讓您將特定子網域或記錄類型的管理權,委派給單一共用管理區域內的不同團隊。
課程內容
- 如何使用 IAM 條件限制 DNS 記錄管理作業。
- 建立自訂角色的原因和方式。
- 如何委派子網域和特定記錄類型 (例如:A、MX)。
- 如何使用
--skip-soa-update旗標,透過條件式權限處理 DNS 交易。
必要條件
- Google 帳戶
- 已啟用計費功能的 Google Cloud 雲端專案
- 已安裝並設定最新版本的 Google Cloud CLI
- 對 DNS 和 IAM 概念有基本瞭解
開始設定
時間長度:03:00
啟用 Cloud DNS API
登入 gcloud CLI 並啟用 API。
gcloud auth login
gcloud services enable dns.googleapis.com
建立測試專案
如果沒有專案,請立即建立專案,並將 gcloud 設定為該專案,這樣所有指令都會以該專案為目標。
gcloud projects create my-dns-per-rrset-lab
gcloud config set project my-dns-per-rrset-lab
瞭解自訂角色方法
時間:02:00
您無法直接將 IAM 條件繫結至標準 roles/dns.admin 角色。
您必須使用兩個自訂角色,將記錄集管理作業與其他管理工作分開:
- DnsRecordSetAdmin:包含建立、刪除、取得及更新資源記錄集的權限。這個角色會有條件授予。
- DnsNonRecordSetAdmin:包含所有其他 DNS 管理權限 (例如管理可用區、列出記錄及查看專案詳細資料)。這個角色會無條件授予。
透過拆分這些角色,您可以確保 Cloud DNS 執行的先決條件檢查 (例如 dns.changes.create) 無條件滿足,而實際記錄修改作業則受到條件嚴格控管。
建立自訂角色
時間長度:05:00
執行下列指令,在專案中建立必要的自訂角色。
定義權限集
# Record set management permissions
rs_perms="dns.resourceRecordSets.create,dns.resourceRecordSets.delete,dns.resourceRecordSets.get,dns.resourceRecordSets.update"
# Complementary administrative permissions
comp_perms="compute.networks.get,compute.networks.list,dns.changes.create,dns.changes.get,dns.changes.list,dns.dnsKeys.get,dns.dnsKeys.list,dns.gkeClusters.bindDNSResponsePolicy,dns.gkeClusters.bindPrivateDNSZone,dns.managedZoneOperations.get,dns.managedZoneOperations.list,dns.managedZones.create,dns.managedZones.delete,dns.managedZones.get,dns.managedZones.getIamPolicy,dns.managedZones.list,dns.managedZones.update,dns.networks.bindDNSResponsePolicy,dns.networks.bindPrivateDNSPolicy,dns.networks.bindPrivateDNSZone,dns.networks.targetWithPeeringZone,dns.networks.useHealthSignals,dns.policies.create,dns.policies.createTagBinding,dns.policies.delete,dns.policies.deleteTagBinding,dns.policies.get,dns.policies.list,dns.policies.listEffectiveTags,dns.policies.listTagBindings,dns.policies.update,dns.projects.get,dns.resourceRecordSets.list,dns.responsePolicies.create,dns.responsePolicies.delete,dns.responsePolicies.get,dns.responsePolicies.list,dns.responsePolicies.update,dns.responsePolicyRules.create,dns.responsePolicyRules.delete,dns.responsePolicyRules.get,dns.responsePolicyRules.list,dns.responsePolicyRules.update,resourcemanager.projects.get"
在 Gcloud 中建立角色
gcloud iam roles create DnsRecordSetAdmin --project=$(gcloud config get-value project) \
--title="DNS Record Set Admin (Conditional)" --permissions="${rs_perms}"
gcloud iam roles create DnsNonRecordSetAdmin --project=$(gcloud config get-value project) \
--title="DNS Complimentary Admin" --permissions="${comp_perms}"
情境 1:完全比對記錄
時間長度:05:00
在這種情況下,您希望授予團隊權限,只管理 api.example.com. 的 A 記錄。
建立代管區域
gcloud dns managed-zones create example-zone \
--description="Lab zone for per-RRSet permissions" \
--dns-name=example.com. --visibility=private \
--networks=default
建立測試服務帳戶
您將使用這個服務帳戶驗證受限權限。
gcloud iam service-accounts create dns-restricted-sa \
--display-name="Restricted DNS SA"
SA_EMAIL="dns-restricted-sa@$(gcloud config get-value project).iam.gserviceaccount.com"
套用有條件的 IAM 政策
無條件授予 DnsNonRecordSetAdmin,以及有條件授予 DnsRecordSetAdmin。
cat << EOF > policy.json
{
"bindings": [
{
"role": "projects/$(gcloud config get-value project)/roles/DnsRecordSetAdmin",
"members": ["serviceAccount:${SA_EMAIL}"],
"condition": {
"expression": "resource.type == 'dns.googleapis.com/ResourceRecordSet' && resource.name.endsWith('/rrsets/api.example.com./A')",
"title": "Exact Record Match"
}
},
{
"role": "projects/$(gcloud config get-value project)/roles/DnsNonRecordSetAdmin",
"members": ["serviceAccount:${SA_EMAIL}"]
}
],
"version": 3
}
EOF
gcloud dns managed-zones set-iam-policy example-zone --policy-file=policy.json
驗證限制
請嘗試建立允許的記錄,然後再嘗試建立未授權的記錄。
# ALLOWED: Create the specific A record
gcloud dns record-sets create api.example.com. --zone=example-zone --type=A --rrdatas="1.2.3.4" --ttl=300 --impersonate-service-account=${SA_EMAIL}
# DENIED: Create an unauthorized name
gcloud dns record-sets create www.example.com. --zone=example-zone --type=A --rrdatas="5.6.7.8" --ttl=300 --impersonate-service-account=${SA_EMAIL}
情境 2:子網域委派
時間長度:05:00
現在,我們來授予管理 p.example.com. 子網域中任何記錄的權限。
更新 IAM 政策
修改條件,使用 resource.name.extract() 比對子網域後置字串。
cat << EOF > policy_subdomain.json
{
"bindings": [
{
"role": "projects/$(gcloud config get-value project)/roles/DnsRecordSetAdmin",
"members": ["serviceAccount:${SA_EMAIL}"],
"condition": {
"expression": "resource.type == 'dns.googleapis.com/ResourceRecordSet' && resource.name.extract('/rrsets/{name}/').endsWith('.p.example.com.')",
"title": "Subdomain Delegation"
}
},
{
"role": "projects/$(gcloud config get-value project)/roles/DnsNonRecordSetAdmin",
"members": ["serviceAccount:${SA_EMAIL}"]
}
],
"version": 3
}
EOF
gcloud dns managed-zones set-iam-policy example-zone --policy-file=policy_subdomain.json
驗證委派
# ALLOWED: Create any record in the subdomain
gcloud dns record-sets create test.p.example.com. --zone=example-zone --type=A --rrdatas="192.168.1.1" --ttl=300 --impersonate-service-account=${SA_EMAIL}
# DENIED: Create a record outside the subdomain
gcloud dns record-sets create news.example.com. --zone=example-zone --type=A --rrdatas="192.168.1.2" --ttl=300 --impersonate-service-account=${SA_EMAIL}
情境 3:批次變更和交易
時間長度:03:00
使用條件式權限時,交易有一項重要細節。根據預設,DNS 交易會嘗試更新 SOA 記錄。如果 IAM 條件只允許使用者管理特定記錄 (例如 api.example.com.),交易就會失敗,因為使用者無權修改 SOA 記錄。
--skip-soa-update 旗標
如要在交易中修改允許的記錄,您應修改條件 (resource.name.endsWith('/SOA')),允許 SOA 更新,或使用 --skip-soa-update 標記。
gcloud dns record-sets transaction start --zone=example-zone --skip-soa-update
gcloud dns record-sets transaction add --zone=example-zone --name="api.example.com." --type=A --ttl=300 "10.0.0.1"
gcloud dns record-sets transaction execute --zone=example-zone --impersonate-service-account=${SA_EMAIL}
注意:如果交易包含任何未經授權的記錄修改,整筆交易都會遭到拒絕。
清除所用資源
時間長度:01:00
刪除本實驗室中建立的資源,以免產生費用。
# Delete record sets
gcloud dns record-sets delete api.example.com. --zone=example-zone --type=A
gcloud dns record-sets delete test.p.example.com. --zone=example-zone --type=A
# Delete managed zone
gcloud dns managed-zones delete example-zone
# Delete custom roles
gcloud iam roles delete DnsRecordSetAdmin --project=$(gcloud config get-value project)
gcloud iam roles delete DnsNonRecordSetAdmin --project=$(gcloud config get-value project)
# Delete service account
gcloud iam service-accounts delete ${SA_EMAIL}
恭喜
恭喜!您已成功瞭解如何在 Cloud DNS 中,實作精細的每筆記錄集 IAM 權限。
涵蓋內容摘要
- 建立自訂角色,將記錄集權限與區域層級管理工作分開。
- 針對特定記錄名稱和類型實作「完全比對」條件。
- 使用 IAM 條件中的字串擷取功能,實作子網域委派。
- 使用
--skip-soa-update旗標,允許符合條件的使用者執行批次變更。