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.
O que nunca precisa de uma concessão
Seção intitulada “O que nunca precisa de uma concessão”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.
Qual concessão serve
Seção intitulada “Qual concessão serve”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).
1. Peça a concessão
Seção intitulada “1. Peça a concessão”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:
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.
2. Aprove a concessão
Seção intitulada “2. Aprove a concessão”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:
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.
-
Em um clone limpo, pegue o commit aprovado e use a versão do Terraform que o
.terraform-versiondo repositório nomeia. -
Faça o provedor do Google do Terraform agir como a sua própria conta:
gcloud auth application-default login. -
No diretório da raiz, inicialize-a contra o seu estado. O
backend.tftem um blocogcsvazio, então passe o bucket de estado da plataforma, que a variávelstate_bucketda 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>" -
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 -
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.
4. Registre a concessão
Seção intitulada “4. Registre a concessão”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.
Etapa 1: recupere o controle
Seção intitulada “Etapa 1: recupere o controle”- Leia o sintoma:
https://gate.projectairframe.dev/healthe as linhas de log do controle no Grafana. Nenhum dos dois precisa de uma concessão. - 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.
- 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.
- 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çãorequired ownership gatee 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. - 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.
- 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.
Encerrar a janela
Seção intitulada “Encerrar a janela”- O controle serve de novo:
/healthresponde 200. Se a etapa 1 fixou o tráfego em uma revisão anterior, direcione-o de volta para a última. - Faça o merge do merge request inverso. O arquivo de políticas fica idêntico ao que era antes da janela.
- 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.
- 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.
O que foi ensaiado
Seção intitulada “O que foi ensaiado”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:
- roots/pam/: as quatro permissões
- docs/adr/0008: concessões para as raízes aplicadas de um notebook
- docs/guides/identity.md: quem pode fazer o quê
- docs/bootstrap-log.md: o registro de cada intervenção à mão
- docs/rehearsals/2026-10-02-the-gate-unreachable.md: o ensaio da via de emergência
No repositório security-policies:
No repositório control-plane:
