Cloud DNS 記錄集精細 IAM 權限


本程式碼實驗室會示範如何使用 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 角色。 您必須使用兩個自訂角色,將記錄集管理作業與其他管理工作分開:

  1. DnsRecordSetAdmin:包含建立、刪除、取得及更新資源記錄集的權限。這個角色會有條件授予。
  2. 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 旗標,允許符合條件的使用者執行批次變更。

其他資訊