Permissões detalhadas do IAM do Cloud DNS para conjuntos de registros


Este codelab demonstra como implementar o controle de acesso granular para conjuntos de registros DNS individuais no Cloud DNS usando condições do IAM e papéis personalizados.

Introdução

O Cloud DNS tradicionalmente oferece suporte à definição de permissões do IAM nos níveis do projeto e da zona gerenciada. Isso fornece acesso amplo a todos os registros em uma zona. No entanto, para grandes empresas, isso não atende ao "princípio do privilégio mínimo".

Este codelab vai orientar você na configuração de permissões do IAM por conjunto de registros no Cloud DNS. Com esse recurso, é possível delegar o gerenciamento de subdomínios ou tipos de registros específicos a diferentes equipes em uma única zona gerenciada compartilhada.

O que você vai aprender

  • Como usar as condições do IAM para restringir o gerenciamento de registros DNS.
  • Por que e como criar papéis personalizados.
  • Como delegar subdomínios e tipos de registros específicos (por exemplo: A, MX).
  • Como processar transações de DNS com permissões condicionais usando a flag --skip-soa-update.

Pré-requisitos

  • Uma Conta do Google
  • Tenha um projeto do Google Cloud com o faturamento ativado.
  • A versão mais recente da CLI do Google Cloud instalada e configurada
  • Noções básicas sobre os conceitos de DNS e IAM

Etapas da configuração

Duração: 03:00

Ativar a API Cloud DNS

Faça login na CLI gcloud e ative a API.

gcloud auth login
gcloud services enable dns.googleapis.com

Criar um projeto de teste

Se você não tiver um projeto pronto, crie um agora e defina a configuração da gcloud para o projeto. Assim, todos os comandos vão direcionar para ele.

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

Entenda as abordagens

Duração: 02:00

Para modificar registros DNS, o principal precisa ter permissão para realizar a modificação do registro e as operações associadas em Recursos de mudança.

É possível configurar isso de duas maneiras:

É possível vincular a condição do IAM diretamente à função padrão roles/dns.admin. Para oferecer suporte às modificações de registros e às operações em recursos de mudança, use uma condição CEL mais abrangente que conceda acesso aos recursos necessários que não são conjuntos de registros.

  • Permissivo:permite todas as outras ações administrativas de DNS. É equivalente à opção 2 se o papel complementar tiver todas as outras permissões administrativas padrão. cel (resource.type == 'dns.googleapis.com/ResourceRecordSet' && <RRSET_CONDITION>) || (resource.type != 'dns.googleapis.com/ResourceRecordSet')
  • Restritiva:permite apenas modificações no conjunto de registros e operações em recursos de mudança. Outras ações administrativas, incluindo listar conjuntos de registros (dns.resourceRecordSets.list) e descrever a zona gerenciada, são bloqueadas. cel (resource.type == 'dns.googleapis.com/ResourceRecordSet' && <RRSET_CONDITION>) || (resource.type == 'dns.googleapis.com/Change')

Essa abordagem é recomendada porque não exige a criação e o gerenciamento de funções personalizadas.

Opção 2: abordagem de função personalizada

Se preferir condições mais simples, separe o gerenciamento de conjuntos de registros de outras tarefas administrativas usando duas funções personalizadas:

  1. DnsRecordSetAdmin: contém permissões para criar, excluir, receber e atualizar conjuntos de registros de recursos. Esse papel será concedido condicionalmente.
  2. DnsNonRecordSetAdmin: contém todas as outras permissões administrativas do DNS, como gerenciar zonas, listar registros e visualizar detalhes do projeto. Esse papel será concedido incondicionalmente.

Como criar papéis personalizados

Duração: 05:00

[!NOTE] Esta etapa só é necessária se você estiver usando a opção 2: abordagem de função personalizada. Se você estiver usando a opção 1: abordagem de função padrão, pule esta etapa.

Execute os comandos a seguir para criar os papéis personalizados necessários no seu projeto.

Definir os conjuntos de permissões

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

Criar as funções no 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}"

Cenário 1: correspondência exata de registro

Duração: 05:00

Nesse cenário, você quer conceder a uma equipe permissão para gerenciar apenas o registro A de api.example.com..

Criar uma zona gerenciada

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

Criar uma conta de serviço de teste

Você vai usar essa conta de serviço para verificar as permissões restritas.

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"

Aplicar a política condicional do IAM

Escolha uma das seguintes opções para aplicar a política.

Essa opção usa o papel padrão dns.admin com uma condição permissiva.

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

Opção 2: abordagem de função personalizada

Essa opção usa as funções personalizadas que você criou na etapa 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

Verificar a restrição

Tente criar o registro permitido e depois um não 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}

Cenário 2: delegação de subdomínio

Duração: 05:00

Agora, vamos conceder permissão para gerenciar qualquer registro no subdomínio p.example.com..

Atualize a política do IAM

Escolha uma das seguintes opções para atualizar a 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

Opção 2: abordagem de função personalizada

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

Verificar a delegação

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

Cenário 3: mudanças e transações em lote

Duração: 03:00

Ao usar permissões condicionais, há um detalhe importante para transações. Por padrão, as transações de DNS tentam atualizar o registro SOA. Se a condição do IAM permitir que os usuários gerenciem apenas registros específicos (como api.example.com.), a transação vai falhar porque o usuário não tem autorização para modificar o registro SOA.

A flag --skip-soa-update

Para modificar registros permitidos em uma transação, permita atualizações de SOA modificando sua condição de acordo com isso (resource.name.endsWith('/SOA')) ou use a flag --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}

Observação: se uma transação tiver pelo menos uma modificação de registro não autorizada, toda a transação será rejeitada.

Limpar

Duração: 01:00

Exclua os recursos criados neste laboratório para evitar cobranças.

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

Parabéns

Parabéns! Você aprendeu a implementar permissões granulares do IAM por conjunto de registros no Cloud DNS.

Resumo do que abordamos

  • Criou funções personalizadas para separar as permissões de conjunto de registros das tarefas administrativas no nível da zona.
  • Implementamos uma condição de correspondência exata para nomes e tipos de registros específicos.
  • Implementamos a delegação de subdomínio usando a extração de strings em condições do IAM.
  • Usamos a flag --skip-soa-update para permitir que usuários condicionais façam mudanças em lote.

Leia mais