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:
Opción 1: Enfoque de rol estándar (recomendado)
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:
- DnsRecordSetAdmin: Contiene permisos para crear, borrar, obtener y actualizar conjuntos de registros de recursos. Este rol se otorgará de forma condicional.
- 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.
Opción 1: Enfoque de rol estándar (recomendado)
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.
Opción 1: Enfoque de rol estándar (recomendado)
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-updatepara permitir que los usuarios condicionales realicen cambios por lotes.