Permisos de IAM detallados de Cloud DNS para conjuntos de registros


En este codelab, se muestra cómo implementar el control de acceso detallado para conjuntos de registros DNS individuales en Cloud DNS con las condiciones de IAM y los roles personalizados.

Introducción

Cloud DNS admite tradicionalmente la configuración de permisos de IAM a nivel del proyecto y de la zona administrada. Esto proporciona un acceso amplio a todos los registros dentro de una zona. Sin embargo, para las grandes empresas, esto no cumple con el "principio de privilegio mínimo".

Este codelab te guiará para configurar los permisos de IAM por conjunto de registros en Cloud DNS. Esta función te permite delegar la administración de subdominios o tipos de registros específicos a diferentes equipos dentro de una sola zona administrada compartida.

Qué aprenderás

  • Cómo usar las condiciones de IAM para restringir la administración de registros DNS
  • Por qué y cómo crear roles personalizados
  • Cómo delegar subdominios y tipos de registros específicos (por ejemplo, A, MX)
  • Cómo controlar las transacciones de DNS con permisos condicionales mediante la marca --skip-soa-update

Requisitos previos

  • Una Cuenta de Google
  • Un proyecto de Google Cloud con la facturación habilitada.
  • La versión más reciente de la Google Cloud CLI instalada y configurada
  • Conocimientos básicos de los conceptos de DNS y IAM

Cómo prepararte

Duración: 03:00

Habilita la API de Cloud DNS

Accede a gcloud CLI y habilita la API.

gcloud auth login
gcloud services enable dns.googleapis.com

Crea un proyecto de prueba

Si no tienes un proyecto listo, crea uno ahora y configura tu configuración de gcloud en el proyecto para que todos los comandos se dirijan a ese proyecto.

gcloud projects create my-dns-per-rrset-lab
gcloud config set project my-dns-per-rrset-lab

Comprende los enfoques

Duración: 02:00

Para modificar correctamente los registros DNS, la entidad principal debe tener permiso para realizar la modificación del registro y las operaciones asociadas en los recursos de cambio.

Puedes configurar esto de una de las siguientes maneras:

Puedes vincular la condición de IAM directamente al rol estándar roles/dns.admin. Para admitir las modificaciones de registros y las operaciones en los recursos de cambio, usa una condición CEL más completa que otorgue acceso a los recursos necesarios que no sean conjuntos de registros.

  • Permisivo: Permite todas las demás acciones administrativas de DNS. Esto equivale a la opción 2 si el rol complementario contiene todos los demás permisos administrativos estándar. cel (resource.type == 'dns.googleapis.com/ResourceRecordSet' && <RRSET_CONDITION>) || (resource.type != 'dns.googleapis.com/ResourceRecordSet')
  • Restrictivo: Solo permite modificaciones de conjuntos de registros y operaciones en recursos de cambio. Se bloquean otras acciones administrativas, como enumerar conjuntos de registros (dns.resourceRecordSets.list) y describir la zona administrada. cel (resource.type == 'dns.googleapis.com/ResourceRecordSet' && <RRSET_CONDITION>) || (resource.type == 'dns.googleapis.com/Change')

Se recomienda este enfoque porque no requiere la creación ni la administración de roles personalizados.

Opción 2: Enfoque de rol personalizado

Si prefieres condiciones más simples, puedes separar la administración de conjuntos de registros de otras tareas administrativas con dos roles personalizados:

  1. DnsRecordSetAdmin: Contiene permisos para crear, borrar, obtener y actualizar conjuntos de registros de recursos. Este rol se otorgará de forma condicional.
  2. DnsNonRecordSetAdmin: Contiene todos los demás permisos administrativos de DNS (como administrar zonas, enumerar registros y ver detalles del proyecto). Este rol se otorgará de forma incondicional.

Crea los roles personalizados

Duración: 05:00

[!NOTE] Este paso solo es obligatorio si usas la opción 2: Enfoque de rol personalizado. Si usas la opción 1: Enfoque de rol estándar, puedes omitir este paso.

Ejecuta los siguientes comandos para crear los roles personalizados necesarios en tu proyecto.

Define los conjuntos de permisos

# 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"

Crea los roles en 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}"

Situación 1: Concordancia exacta de registros

Duración: 05:00

En esta situación, deseas otorgar permiso a un equipo para administrar solo el registro A de api.example.com..

Crea una zona administrada

gcloud dns managed-zones create example-zone \
    --description="Lab zone for per-RRSet permissions" \
    --dns-name=example.com. --visibility=private \
    --networks=default

Crea una cuenta de servicio de prueba

Usarás esta cuenta de servicio para verificar los permisos restringidos.

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"

Aplica la política de IAM condicional

Elige una de las siguientes opciones para aplicar la política.

Esta opción usa el rol estándar dns.admin con una condición permisiva.

cat << EOF > policy.json
{
  "bindings": [
    {
      "role": "roles/dns.admin",
      "members": ["serviceAccount:${SA_EMAIL}"],
      "condition": {
        "expression": "(resource.type == 'dns.googleapis.com/ResourceRecordSet' && resource.name.endsWith('/rrsets/api.example.com./A')) || (resource.type != 'dns.googleapis.com/ResourceRecordSet')",
        "title": "Exact Record Match (Standard Role)"
      }
    }
  ],
  "version": 3
}
EOF

gcloud dns managed-zones set-iam-policy example-zone --policy-file=policy.json

Opción 2: Enfoque de rol personalizado

Esta opción usa los roles personalizados que creaste en el paso anterior.

cat << EOF > policy_custom.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 (Custom Roles)"
      }
    },
    {
      "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_custom.json

Verifica la restricción

Intenta crear el registro permitido y, luego, uno no autorizado.

# 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}

Situación 2: Delegación de subdominios

Duración: 05:00

Ahora, otorguemos permiso para administrar cualquier registro dentro del subdominio p.example.com..

Actualiza la política de IAM

Elige una de las siguientes opciones para actualizar la política.

cat << EOF > policy_subdomain.json
{
  "bindings": [
    {
      "role": "roles/dns.admin",
      "members": ["serviceAccount:${SA_EMAIL}"],
      "condition": {
        "expression": "(resource.type == 'dns.googleapis.com/ResourceRecordSet' && resource.name.extract('/rrsets/{name}/').endsWith('.p.example.com.')) || (resource.type != 'dns.googleapis.com/ResourceRecordSet')",
        "title": "Subdomain Delegation (Standard Role)"
      }
    }
  ],
  "version": 3
}
EOF

gcloud dns managed-zones set-iam-policy example-zone --policy-file=policy_subdomain.json

Opción 2: Enfoque de rol personalizado

cat << EOF > policy_subdomain_custom.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 (Custom Roles)"
      }
    },
    {
      "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_custom.json

Verifica la delegación

# 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}

Situación 3: Cambios y transacciones por lotes

Duración: 03:00

Cuando se usan permisos condicionales, hay un detalle importante para las transacciones. De forma predeterminada, las transacciones de DNS intentan actualizar el registro SOA. Si tu condición de IAM solo permite que los usuarios administren registros específicos (como api.example.com.), la transacción fallará porque el usuario no está autorizado para modificar el registro SOA.

La marca --skip-soa-update

Para modificar los registros permitidos dentro de una transacción, debes permitir las actualizaciones de SOA modificando tu condición en consecuencia (resource.name.endsWith('/SOA')) o usar la marca --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}

Nota: Si una transacción contiene incluso una modificación de registro no autorizada, se rechazará toda la transacción.

Limpia

Duración: 01:00

Borra los recursos creados en este lab para evitar cargos.

# 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 (only if you created them in Option 2)
gcloud iam roles delete DnsRecordSetAdmin --project=$(gcloud config get-value project) || true
gcloud iam roles delete DnsNonRecordSetAdmin --project=$(gcloud config get-value project) || true

# Delete service account
gcloud iam service-accounts delete ${SA_EMAIL}

Felicitaciones

¡Felicitaciones! Aprendiste a implementar permisos de IAM detallados por conjunto de registros en Cloud DNS.

Resumen de lo que abordamos

  • Creaste roles personalizados para separar los permisos de conjuntos de registros de las tareas administrativas a nivel de la zona.
  • Implementaste una condición de concordancia exacta para nombres y tipos de registros específicos.
  • Implementaste la delegación de subdominios con la extracción de cadenas en las condiciones de IAM.
  • Usaste la marca --skip-soa-update para permitir que los usuarios condicionales realicen cambios por lotes.

Lecturas adicionales