Pular para o conteúdo

Concessões e via de emergência

No Airframe ninguém tem um direito permanente de mudar a produção. Quando uma pessoa realmente precisa, por um incidente ou por uma das poucas raízes que ainda são aplicadas à mão, ela pede uma concessão que dura uma ou duas horas, outra pessoa aprova, e o pedido, a aprovação e o motivo ficam escritos. Esta página é o guia prático: qual concessão pedir, os comandos, o que registrar, e a via de emergência separada para quando o controle de aprovação não pode aprovar um merge.

Identidades e acesso explica por que funciona assim. Uma concessão aqui é uma concessão do Privileged Access Manager: o Google Cloud adiciona os papéis à sua própria conta por um tempo fixo e depois os remove.

A maior parte do trabalho não precisa. A sua conta do dia a dia pode ler os projetos e os seus logs, e a equipe de um produto pode adicionar uma versão nova de um dos seus segredos. Toda mudança de infraestrutura passa por um merge request e um pipeline. Rodar de novo o pipeline de um produto na main, corrigir o desvio no código e voltar atrás com um merge request de reversão também não precisam de concessão. Peça uma concessão só quando um merge request não puder fazer o trabalho.

O Airframe define quatro concessões, como quatro permissões em roots/pam do landing-zone:

Você precisa Concessão, quem aprova, duração
Ler os logs, as métricas ou o estado de um projeto de não produção para investigar Nível 1: sem aprovação, 1 hora
Corrigir algo à mão nos projetos da organização de demonstração durante um incidente Nível 2: uma segunda pessoa, 2 horas
Aplicar uma raiz que continua sendo aplicada de um notebook, ou substituir o runner confiável Apply da plataforma: uma segunda pessoa, 2 horas
Mudar algo no nível da organização Organização: uma segunda pessoa, 2 horas

Hoje o nível 1 existe só no projeto de execução de não produção da plataforma. O guia de identidade diz que o projeto de não produção de cada produto faturado recebe um da sua fábrica de projetos; nenhuma fábrica o cria ainda, então essa parte está projetada. Um apply de um notebook da raiz de identidade precisa ao mesmo tempo da concessão de apply da plataforma e da de organização, porque também muda vínculos na organização.

Os membros do grupo de emergência, lk-breakglass@, podem pedir as três primeiras. A concessão de organização é pedida por um membro do grupo de plataforma, lk-platform@, e todas as aprovações vêm desse grupo. O Privileged Access Manager não deixa quem pede aprovar o próprio pedido (aplicado).

um pedidocom um motivooutra pessoaaprovapapéis na suaconta por horasuma raiz,de um notebooka auditoriae uma linhao plano diáriomostra a mudança

Quem: você, com a sessão do gcloud aberta com a sua própria conta do dia a dia, nunca com a conta de administração.

Indique a permissão, onde ela está, por quanto tempo você precisa e por quê. Para uma concessão de nível 2 na pasta da organização de demonstração:

Janela do terminal
gcloud pam grants create \
--entitlement=airframe-level2-admin \
--folder=<folder-id> \
--location=global \
--requested-duration=7200s \
--justification="<o que você vai mudar, e por quê>"

As outras três mudam só na permissão e no seu lugar: airframe-platform-apply na mesma pasta; airframe-organisation-admin com --organization=<organization-id>; airframe-level1-read com --project=<project-id> e no máximo 3600s. A página do Privileged Access Manager no console do Google Cloud faz o mesmo. Uma concessão de nível 1 é ativada na hora; as outras esperam uma aprovação. Enquanto uma concessão para o mesmo acesso estiver aberta, o Privileged Access Manager recusa uma segunda, então reutilize a que está aberta.

Quem: outro membro de lk-platform@, nunca quem pediu.

Quem aprova lista o que espera a sua aprovação, lê a justificativa e aprova com um motivo próprio:

Janela do terminal
gcloud pam grants search \
--entitlement=airframe-level2-admin \
--folder=<folder-id> --location=global \
--caller-relationship=can-approve
gcloud pam grants approve <grant-id> \
--entitlement=airframe-level2-admin \
--folder=<folder-id> --location=global \
--reason="<por que isto é aprovado>"

Hoje uma só pessoa opera a plataforma, e a segunda aprovação é a segunda conta do mantenedor: o mecanismo está aplicado, mas a separação entre duas pessoas ainda não é real.

3. Use a concessão para uma raiz e deixe que ela expire

Seção intitulada “3. Use a concessão para uma raiz e deixe que ela expire”

A concessão não entrega uma chave separada: enquanto ela dura, a sua própria conta tem os papéis da permissão. Nenhum documento dos repositórios dá a sequência exata de comandos para um apply de um notebook; o roteiro abaixo foi montado a partir dos próprios arquivos das raízes e das linhas do docs/bootstrap-log.md.

Onde: landing-zone para as raízes de organização, auditoria e identidade (roots/organisation, roots/audit, roots/wif); roots/runner do control-plane para substituir o runner confiável.

  1. Em um clone limpo, pegue o commit aprovado e use a versão do Terraform que o .terraform-version do repositório nomeia.

  2. Faça o provedor do Google do Terraform agir como a sua própria conta: gcloud auth application-default login.

  3. No diretório da raiz, inicialize-a contra o seu estado. O backend.tf tem um bloco gcs vazio, então passe o bucket de estado da plataforma, que a variável state_bucket da raiz nomeia, e o prefixo da linha “State” do README da raiz:

    Janela do terminal
    terraform init \
    -backend-config="bucket=<platform state bucket>" \
    -backend-config="prefix=<the State row of the README>"
  4. Planeje para um arquivo, leia-o, aplique exatamente esse arquivo e planeje de novo; o último plano deve estar vazio:

    Janela do terminal
    terraform plan -out=<file>
    terraform apply <file>
    terraform plan
  5. Pare. Os papéis saem da sua conta quando a concessão expira.

O diagrama e estes passos seguem uma concessão de apply da plataforma ou de organização. Uma concessão de nível 1 não tem aprovação e não muda nada: enquanto ela dura, leia os logs, as métricas e o estado do projeto. Uma concessão de nível 2 é para uma correção à mão durante um incidente, muitas vezes alguns comandos do gcloud em vez de um apply, como mostram as linhas do docs/bootstrap-log.md. Uma correção assim é desvio por definição: o plano diário o informa, e ele termina quando a correção é escrita no código ou o próximo apply a reverte. Veja Desvio.

Onde: docs/bootstrap-log.md do landing-zone, uma linha por merge request, aprovada pela equipe de plataforma.

Dois registros existem sem que ninguém os escreva: o Privileged Access Manager guarda cada concessão com quem pediu, a justificativa, quem aprovou e o motivo, e o registro de auditoria guarda cada mudança feita com ela, e as leituras dos serviços cujos logs de acesso a dados a raiz de auditoria ativa: Secret Manager, Cloud SQL, Cloud Storage, IAM e Cloud KMS (aplicado). A linha do registro é uma convenção, escrita e ensinada, mas nada recusa uma concessão sem ela. Ela nomeia os identificadores das concessões, quem as pediu e quem as aprovou, a raiz e o commit aplicado, o que mudou e o plano vazio depois. Nunca cole nela uma credencial, um segredo ou um token.

Via de emergência quando o controle de aprovação não pode aprovar ou não pode ser alcançado

Seção intitulada “Via de emergência quando o controle de aprovação não pode aprovar ou não pode ser alcançado”

Todos os repositórios menos um precisam da aprovação do controle de aprovação antes do merge, e todo pipeline, menos os desse repositório, começa com o gate:integrity, que falha de forma fechada quando o controle não responde. Então um controle fora do ar bloqueia toda correção, inclusive uma correção do próprio controle. O ADR-0032 do control-plane fixa a saída em duas etapas. Ele vale quando o gate:integrity falha com gate unreachable: fail closed em mais de um repositório, ou quando o controle deixa de aprovar merge requests que o seu modelo aceita. Uma queda do GitLab.com não é uma queda do controle, e nada disto ajuda com ela.

A pessoa que percebe abre um issue no control-plane com o link do job que falha e mantém nele uma linha do tempo.

  1. Leia o sintoma: https://gate.projectairframe.dev/health e as linhas de log do controle no Grafana. Nenhum dos dois precisa de uma concessão.
  2. Se a causa é a última revisão, peça uma concessão de nível 2 com o issue como justificativa, faça outro membro do grupo de plataforma aprová-la e direcione o tráfego do Cloud Run para a última revisão que funcionou. Nenhuma revisão nova é criada, então o Binary Authorization não é consultado de novo. No ensaio isso levou cerca de 22 segundos em cada sentido.
  3. Se a causa é uma credencial, um mantenedor adiciona uma versão nova do segredo que o controle lê, sob a mesma concessão. O valor nunca vai para o issue.

Com o controle fora do ar, o pipeline não é o caminho de volta: construir a imagem do controle precisa do controle. A reversão é o que o faz servir de novo, e a correção vem depois como um merge request normal.

Etapa 2: um repositório fora das duas políticas, por duas horas

Seção intitulada “Etapa 2: um repositório fora das duas políticas, por duas horas”

Só quando a etapa 1 não restabeleceu o controle em 30 minutos e uma mudança em um repositório não pode esperar.

  1. Onde: security-policies, .gitlab/security-policies/policy.yml. Um merge request, sem mais nada, faz duas mudanças para esse repositório: ele sai do alcance da política de aprovação required ownership gate e entra nas exclusões da política de execução de pipelines do grupo todo, ao lado do próprio security-policies. O security-policies fica fora dessa política para que este merge request não espere o controle para o qual ele existe.
  2. Quem aprova: uma pessoa nomeada do catálogo que não seja a autora nem tenha feito commits nele. Hoje as pessoas nomeadas que aprovam são todas contas do próprio mantenedor: o mecanismo está aplicado, mas a separação entre duas pessoas ainda não é real.
  3. O merge request inverso é aberto ao mesmo tempo e fica esperando a aprovação, de modo que encerrar a janela é uma aprovação e um merge.

No repositório, durante a janela, o merge request urgente é integrado com a aprovação de uma pessoa nomeada e a sua própria validação. O executor não planeja nada para ele, então quem revisa lê a mudança e a saída da validação, e o pipeline da main aplica só raízes que não usam imagem. Seus pipelines não levam o gate:integrity, então o que ainda se interpõe entre eles e as nuvens são os vínculos de federação de identidades de carga de trabalho com a ref protegida e o ambiente. Todos os outros repositórios mantêm os dois controles. O repositório de um produto não pode usar o procedimento, porque o seu merge também espera a verificação de status “Airframe cost”, que só o controle define.

  1. O controle serve de novo: /health responde 200. Se a etapa 1 fixou o tráfego em uma revisão anterior, direcione-o de volta para a última.
  2. Faça o merge do merge request inverso. O arquivo de políticas fica idêntico ao que era antes da janela.
  3. Deixe a concessão expirar. Quem pediu uma concessão não pode revogá-la, porque revogar precisa de um papel que ninguém tem de forma permanente.
  4. Feche o issue com a sua linha do tempo e os identificadores dos eventos de auditoria do GitLab da queda, lidos nas páginas de eventos de auditoria do grupo e de cada projeto que mudou. O receptor de auditoria, um segundo destino de transmissão, os guarda no bucket de auditoria bloqueado enquanto o controle está fora do ar; se ele também estava fora do ar, o GitLab não os reenvia, e os tipos que ele só transmite não são guardados em lugar nenhum: diga isso no issue. Depois escreva uma análise posterior em até cinco dias úteis.

O limite de duas horas é verificado e não imposto à força. No pipeline agendado do control-plane, que roda uma vez por dia, o breakglass:check compara o arquivo de políticas do security-policies com o estado normal, avisa enquanto uma diferença tem menos de duas horas e falha depois, nomeando os repositórios. O breakglass:report mantém aberto um issue até as políticas voltarem a coincidir. Só o merge request inverso encerra uma janela.

Em 2026-10-02 o procedimento rodou em um repositório da plataforma, em duas partes, registrado em docs/rehearsals/2026-10-02-the-gate-unreachable.md do landing-zone. Com o controle no ar, a regra de aprovação saiu do repositório 10 segundos depois do primeiro merge e voltou 16 segundos depois do inverso. Depois o controle ficou inalcançável por dois minutos: um pipeline de outro repositório falhou de forma fechada 10 segundos depois de começar, o pipeline do security-policies não foi afetado, e quem pediu a concessão não conseguiu revogá-la, então ela expirou sozinha. O ensaio também mostrou que o controle não consegue se reimplantar pelo próprio pipeline enquanto está fora do ar. O control-plane guarda uma cópia espelho do arquivo de políticas, e o seu job policy:schema falha enquanto as duas diferem, até o merge inverso torná-las iguais de novo.

Onde fica

No repositório landing-zone:

No repositório security-policies:

No repositório control-plane:

Licença MIT. Copyright dos colaboradores do Airframe.

Este site descreve a versão 2026.10.20-1 da plataforma.