En este codelab, se muestra cómo implementar un control de acceso detallado para conjuntos de registros DNS individuales en Cloud DNS con condiciones de IAM y roles personalizados.
Introducción
Tradicionalmente, Cloud DNS admite 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".
En este codelab, se te guiará para configurar 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 y MX)
- Cómo controlar las transacciones de DNS con permisos condicionales usando 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 Google Cloud CLI instalada y configurada
- Conocimientos básicos de los conceptos de DNS y de 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 para el proyecto, de modo 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
Información sobre el enfoque de funciones personalizadas
Duración: 02:00
No puedes vincular condiciones de IAM directamente al rol estándar roles/dns.admin.
En cambio, debes 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á incondicionalmente.
Si divides estos roles, te aseguras de que las verificaciones de requisitos previos que realiza Cloud DNS (como dns.changes.create) se cumplan de forma incondicional, mientras que las modificaciones reales de los registros están estrictamente controladas por tus condiciones.
Crea los roles personalizados
Duración: 05:00
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: Coincidencia exacta de registros
Duración: 05:00
En esta situación, quieres 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
Otorga DnsNonRecordSetAdmin de forma incondicional y DnsRecordSetAdmin con una condición.
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
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 subdominio
Duración: 05:00
Ahora, otorguemos permiso para administrar cualquier registro dentro del subdominio p.example.com..
Actualiza la política de IAM
Modifica la condición para usar resource.name.extract() y que coincida con el sufijo del subdominio.
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
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}
Caso 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 la condición según corresponda (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 que creaste 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
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}
Felicitaciones
¡Felicitaciones! Aprendiste a implementar correctamente permisos de IAM detallados por conjunto de registros en Cloud DNS.
Resumen de lo que vimos
- Se crearon roles personalizados para separar los permisos de los conjuntos de registros de las tareas administrativas a nivel de la zona.
- Se implementó una condición de concordancia exacta para nombres y tipos de registros específicos.
- Se implementó la delegación de subdominios con la extracción de cadenas en las condiciones de IAM.
- Se usó la marca
--skip-soa-updatepara permitir que los usuarios condicionales realicen cambios por lotes.