Limites de confiança
A segurança do Airframe se apoia em poucos limites. O código que ninguém revisou roda onde não alcança nada, o código que as pessoas certas aprovaram roda com identidades que servem cada uma para um só trabalho, e controles no próprio Google Cloud se mantêm mesmo que cada pipeline fosse contornado. Esta página traça esses limites, diz o que garante cada um e marca o que está projetado mas não construído. Afirmações e mecanismos lista depois cada afirmação, uma por uma.
Os exemplos vêm de uma organização de demonstração, um comércio on-line fictício, cujos projetos ficam todos sob uma pasta no Google Cloud.
Não confiável e confiável
Seção intitulada “Não confiável e confiável”A plataforma roda seus jobs de pipeline em dois runners próprios, o runner não confiável e o confiável, e os mantém separados.
O runner não confiável roda o pipeline de cada merge request, e as verificações na main que não precisam de identidade, como a validação, o pacote de políticas e os testes da aplicação. Ele fica no projeto de integração contínua da plataforma, fora dos perímetros, em uma rede própria sem rota para as redes da plataforma, e seus jobs não alcançam o servidor de metadados, onde estariam as credenciais de uma máquina. Nada do que ele roda consegue obter uma identidade na nuvem: cada identidade que um job pode obter está vinculada a uma branch ou tag protegida, e o pipeline de um merge request não tem nenhuma das duas. Assim, quem pode enviar uma branch recebe um pipeline que não tem nada.
O runner confiável fica dentro da rede de produção da plataforma e só aceita os jobs marcados para ele, a partir de refs protegidas. Dois tipos de trabalho rodam ali: as execuções do executor, e o pipeline na branch main protegida de cada repositório depois de um merge. Ele só roda imagens do registro próprio da plataforma.
O controle entre os dois
Seção intitulada “O controle entre os dois”O controle de aprovação decide quando uma mudança pode passar de um lado para o outro. Ele lê o modelo de responsáveis a partir da branch main protegida do catálogo, nunca da mudança que julga, não conta nenhuma aprovação do autor nem de quem fez um commit, e dá sua própria aprovação vinculada ao commit que verificou. Só então ele inicia o executor, com um token de disparo que só o controle tem, e o executor verifica tudo de novo antes de ter uma credencial.
Uma política de aprovação do GitLab torna a aprovação do controle uma condição para o merge em todos os repositórios menos o security-policies, que guarda as regras de aprovação e é a saída quando o controle não pode aprovar. Outra política exige a aprovação de uma pessoa nomeada do catálogo que não escreveu a mudança nem fez commits nela. Hoje uma só pessoa opera a plataforma, e cada aprovador nomeado é uma das contas próprias do mantenedor: o mecanismo é aplicado, mas a separação entre duas pessoas ainda não é real. O controle de aprovação e o executor explica a sequência completa.
As identidades de cada lado
Seção intitulada “As identidades de cada lado”- Antes de um merge, o executor pode usar a identidade de plan de cada produto, que lê e não muda nada, e cada identidade de apply de não produção, para as prévias. Ele não tem nenhuma identidade de apply de produção, então nada do que roda antes de um merge pode mudar a produção.
- Depois de um merge, o job de cada raiz na main protegida obtém a identidade de apply própria dessa raiz, e nenhuma outra. O vínculo nomeia o caminho do repositório, o ambiente e a ref protegida, então um job de outro repositório, de outro ambiente ou de uma branch sem proteção não obtém nada.
- As pessoas têm papéis de leitura, e a equipe de um produto pode adicionar uma versão de um dos seus segredos de produção, nunca lê-la. Qualquer coisa além disso é uma concessão: a de nível 1, uma hora de leitura de um projeto de não produção, que quem pede aprova com um motivo, ou uma concessão administrativa de até duas horas, aprovada por outro membro do grupo da plataforma, que hoje é a segunda conta do mantenedor.
Três raízes da plataforma, as políticas da organização, a configuração de auditoria e o provedor de identidade, são aplicadas em vez disso a partir de um notebook com uma concessão, e um plan diário só de leitura mostra qualquer mudança nelas como desvio.
Abaixo de toda identidade fica a base: controles no Google Cloud que se mantêm mesmo que um pipeline fosse contornado, definidos na pasta da organização de demonstração pela raiz da organização, e a política de firewall pela raiz de rede.
- Políticas da organização (aplicadas). Elas proíbem criar ou enviar chaves de conta de serviço, as redes padrão, os buckets públicos e os endereços públicos do Cloud SQL, e exigem Shielded VM e OS Login. Só os principais da própria organização podem aparecer em uma política de acesso, só o runner confiável pode ter um endereço externo, e os recursos vão só para
us-central1onde um serviço aceita a restrição. - Uma política de negação (aplicada). Ela nega a todos a criação de chaves, as mudanças nas políticas da organização, as mudanças no IAM da pasta e qualquer mudança em um sink de logs da pasta. Suas únicas exceções são o grupo de emergência, a conta de administrador da inicialização e o próprio agente de serviço do Privileged Access Manager, e, só para o IAM da pasta, a identidade que configura as concessões. Assim, uma mudança no acesso à pasta só existe como uma concessão registrada e com tempo limitado.
- Uma política de firewall hierárquica (aplicada). O tráfego que entra e sai das redes da plataforma é negado por padrão; passam as APIs do Google, as verificações de integridade dos balanceadores de carga e a permissão estreita de cada runner, e o tráfego entre as faixas da plataforma é decidido por regras que a raiz de rede gera.
- Nenhum owner ou editor abaixo da pasta (aplicado). Uma restrição personalizada da política da organização recusa uma concessão de qualquer um dos dois papéis por qualquer caminho, o console incluído, exceto em um projeto ainda na janela de inicialização da sua fábrica e para o próprio agente de serviço das APIs do Google, a quem o Google dá editor quando as APIs de um projeto são ativadas. As fábricas de projetos removem o papel owner que o Google lhes dá em cada projeto que criam.
- Três perímetros (projetados). Os perímetros do VPC Service Controls de produção, não produção e auditoria existem como especificações em modo de teste: registram o que bloqueariam e não bloqueiam nada. Aplicá-los é uma variável, quando os pipelines próprios da plataforma rodarem sem problemas sob eles. As leituras diárias da raiz da organização que um perímetro recusaria vêm de dentro do perímetro de produção, do runner de confiança na VPC da rede de produção, porque a lista de serviços alcançáveis a partir dessa VPC não os inclui.
A base da arquitetura vai além do que está construído:
- Binary Authorization para cada serviço (projetado). A arquitetura a conta na base e a inclui, junto com a política de firewall, entre as permissões da política de negação; a política de negação não cobre nenhuma das duas. O que está construído é uma adesão por serviço: o módulo de Cloud Run do golden path faz cada serviço aderir à política do seu projeto, que no projeto de produção de um produto faturado só admite uma imagem que a plataforma construiu e promoveu. Um serviço implantado sem o módulo, como o gateway de telemetria da plataforma, roda sem ela.
Um job diário do Policy Analyzer no repositório landing-zone também falha, e gera um alerta, se alguma pessoa além da única conta de administrador, ou algum grupo, tem um papel na organização.
A cadeia de auditoria
Seção intitulada “A cadeia de auditoria”Cada mudança pode ser seguida até o merge request, a aprovação e a pessoa.
O que é registrado. Os logs de auditoria do Google Cloud guardam cada ação administrativa, e os logs de Data Access estão ativos na pasta para os serviços cujas leituras importam: Secret Manager, Cloud SQL, Cloud Storage, IAM, Cloud KMS e a troca de tokens pela qual passa a identidade de um pipeline. Os próprios eventos de auditoria do GitLab, como as aprovações, as associações e a criação de tokens, são transmitidos ao controle e ao receptor de auditoria, um serviço separado, e cada um escreve todos os eventos como uma linha de log. O GitLab não reenvia um evento que um destino não conseguiu receber, então o bucket abaixo guarda cada evento duas vezes enquanto os dois estão ativos e perde um somente quando os dois estão inacessíveis; um evento que o GitLab só transmite se perde então.
Para onde vai. Um único sink agregado na pasta envia os logs de auditoria de cada projeto, e essas linhas do GitLab, para um bucket no projeto de auditoria, criptografado com uma chave que a plataforma tem. A política de negação recusa qualquer mudança em um sink da pasta, então nem um pipeline nem alguém sem uma concessão pode desviar o registro. Ela também protege a política de IAM da pasta, que guarda a configuração de auditoria, com mais uma exceção: a identidade que configura as concessões, que só age a partir de código revisado. A condição dessa identidade exige que uma mudança modifique pelo menos uma concessão, então uma chamada que muda apenas a configuração de auditoria é recusada. Uma chamada que muda ao mesmo tempo uma concessão permitida e a configuração de auditoria ainda passa; na pasta uma regra do Grafana avisa, e na organização nenhum sink a vê.
O sink deixa de fora as entradas que o VPC Service Controls escreve em modo de teste, que registram o que um perímetro teria recusado e não uma recusa. O log próprio de cada projeto as guarda, e o bucket bloqueado não as mantém por um ano.
Quanto tempo fica (aplicado). Uma política de retenção guarda cada objeto por 365 dias, e ninguém pode apagá-lo ou sobrescrevê-lo antes disso. A política está bloqueada, o que o Google torna irreversível: ninguém, nem um administrador com uma concessão, pode encurtá-la ou removê-la.
O que a une. O controle registra cada veredito com as afirmações do token que o pediu, o executor registra cada execução com seu merge request, seu commit e seu pipeline, um job de plan guarda seu plan e o veredito das políticas como artefatos que só os desenvolvedores do repositório podem ler, e cada entrada do log de auditoria nomeia a identidade que agiu, que responde a um só repositório, ambiente e ref protegida.
O que o vigia (aplicado). Um segundo sink, estreito, na pasta envia ao Grafana, pelo gateway de logs de produção, as entradas que uma equipe de segurança vigiaria: uma tentativa de criar uma chave, uma recusa de uma política de negação ou da organização, um token recusado, uma mudança nos sinks, nas políticas de negação ou na configuração de auditoria da pasta, uma concessão, e os eventos de auditoria do GitLab. As regras acionam a plataforma com urgência pelos cinco primeiros e abrem um ticket por uma concessão ou uma rajada de mudanças no GitLab. Um evento na própria organização, como uma concessão no nível da organização, fica fora dos sinks da pasta.
A arquitetura também projeta um job de auditoria que compara cada acesso com o catálogo; ele ainda não existe (projetado).
Onde fica
No repositório landing-zone:
- roots/organisation/: as políticas da organização, a restrição e a política de negação
- roots/audit/: os sinks, o bucket e os logs de Data Access
- roots/perimeters/: os três perímetros em modo de teste
- roots/network/: a política de firewall hierárquica
- docs/guides/security.md: o guia de segurança da plataforma
No repositório control-plane:
