À medida que mais empresas buscam construir infraestruturas confiáveis em torno do Kubernetes, o controle de acesso por si só se mostra insuficiente. Clusters modernos apresentam múltiplos vetores de ataque, desde a substituição de contêineres e exploração de vulnerabilidades de runtime até a execução de código não assinado dentro de pods. Para garantir que apenas o código pretendido seja executado e que todos os componentes permaneçam íntegros, são necessários mecanismos de controle mais rigorosos. Ao preparar a Deckhouse Kubernetes Platform para a certificação FSTEC da Rússia, nos deparamos com as limitações das soluções existentes. Muitas ferramentas abordam apenas aspectos isolados: algumas focam em imagens, outras em manifestos e outras ainda na fase de execução. Nenhuma oferece um controle ponta a ponta, "da compilação ao runtime".
Meu nome é Maxim Nabokih, e lidero o desenvolvimento da Deckhouse Kubernetes Platform. Neste artigo, detalharei como implementamos o controle de integridade dos três "K" (Контейнеры - Contêineres, Конфигурации - Configurações, Компоненты ОС - Componentes do SO) e construímos um sistema de verificação ponta a ponta sem comprometer a flexibilidade e a compatibilidade. Este conteúdo é valioso para equipes que precisam gerenciar a segurança do Kubernetes em face de ameaças reais, bem como para aquelas que buscam conformidade regulatória e desejam adotar práticas de execução confiável em seus clusters.
O Elo Fraco na Cadeia: Um Exemplo de Controle de Integridade na Vida Real
Comecemos com um exemplo prático. Recentemente, precisei de fones de ouvido novos e os encomendei em um marketplace, pois não tinha tempo para ir a uma loja física. O vendedor enviou a encomenda, e o entregador a trouxe até minha porta. No entanto, os fones de ouvido não estavam na caixa. Tanto eu quanto a loja queríamos que o produto correto estivesse na caixa. Acabei frustrado, e o vendedor sofreu perdas. Eu confiava no marketplace em geral e na loja específica. Mas alguém na cadeia de suprimentos foi não confiável: o elo fraco foi o armazém ou o entregador, é impossível saber. E, o mais importante, eu não tinha como verificar o item na caixa em cada etapa da entrega. Este é o problema do controle de integridade.
A entrega de código em um cluster Kubernetes é semelhante. Entre a escrita de uma nova lógica e a execução do código em um nó, existe uma cadeia longa, e cada elo pode ser comprometido. Vamos analisar como ela funciona, onde estão os pontos fracos e o que pode ser feito a respeito.
Cadeia de Suprimentos de Código no Kubernetes e Estatísticas de Ataques
A cadeia de suprimentos de novo código para um ambiente específico funciona da seguinte maneira: as equipes de desenvolvimento escrevem o código. No pipeline de build, ele se transforma em um artefato – uma imagem de contêiner – e é enviado para um registro de imagens de contêiner (container registry). Paralelamente, engenheiros ou os próprios desenvolvedores escrevem manifestos para o Kubernetes e os entregam ao ambiente desejado: testing, development ou production. Após isso, as imagens são baixadas do registro e executadas. No nosso caso, no final da cadeia não estão os ambientes de uma única empresa, mas sim clusters de diferentes clientes. Mas a essência não muda: o caminho do código para o contêiner em execução é o mesmo.
Esquematicamente, o processo se parece com isto:
[Diagrama da Cadeia de Suprimentos de Código no Kubernetes]
A parte do pipeline destacada em cor de fundo na figura abaixo deve ser o mais protegida possível. Idealmente, deve ser hermética: sem acesso SSH ou mesmo acesso à internet "selvagem". Não abordarei a segurança desta parte neste artigo. Também deixaremos de fora a segurança das estações de trabalho, engenharia social e outras influências sobre o desenvolvedor, que pode enviar código malicioso diretamente para o repositório. Onde, nesse caso, os invasores podem nos atacar? Existem dois vetores principais:
- Um invasor se insere no registro de imagens de contêineres ou no transporte entre ele e o cluster, entregando código malicioso.
- Um invasor entra diretamente no cluster Kubernetes e substitui algo internamente ou executa cargas maliciosas.
Esses vetores não são teóricos. Aqui estão dois incidentes públicos, um para cada vetor:
- Kong Ingress Controller (2024): Um invasor, explorando uma vulnerabilidade no pipeline CI/CD do projeto, publicou uma build não autorizada do Kong Ingress Controller 3.4.0 com um cryptominer no Docker Hub. O incidente foi detectado não por alertas de segurança, mas por uma carga de CPU anormalmente alta. A verificação da assinatura da imagem ao baixar não teria permitido que essa imagem chegasse ao nó. Detalhes do incidente estão no post oficial da Kong.
- Tesla (2018): Através de um console administrativo Kubernetes desprotegido, credenciais de nuvem foram expostas, permitindo a implantação de um cryptominer em um dos clusters de infraestrutura de nuvem da empresa. Mesmo com esse nível de comprometimento, a verificação das imagens de contêineres antes da execução não teria permitido a execução de um contêiner malicioso não assinado e teria sido a última barreira contra os atacantes. Mais detalhes sobre o incidente podem ser lidos na Ars Technica.
Esses casos fazem parte de uma tendência mais ampla. De acordo com o relatório State of the Software Supply Chain, até 2024, mais de 704.000 pacotes maliciosos foram registrados em repositórios abertos (acumulados desde 2019), com um crescimento acentuado no número desses pacotes nos últimos anos. Esses casos são considerados parte de ataques à cadeia de suprimentos de software.
E, minha seção favorita – "segundo a Gartner". Em geral, a Gartner afirma que não existe uma "bala de prata" na proteção da cadeia de suprimentos de código. O mercado de soluções é fragmentado, e para cobrir toda a cadeia é necessário um conjunto de ferramentas, cada uma cobrindo sua parte. Eles também preveem que, até 2028, 85% das equipes de desenvolvimento em grandes empresas implementarão tais ferramentas – elas se tornarão uma parte padrão da entrega de software. O Market Guide 2025 enfatiza separadamente que uma parte importante da abordagem é o controle de integridade: a verificação de artefatos em todo o caminho de entrega, incluindo assinatura e verificação, para reduzir o risco de sua substituição.
Gartner é bom, mas o que dizem os reguladores e a realidade russos? Na Rússia, o controle de integridade de software e componentes de infraestrutura não é mais uma recomendação, mas um requisito normativo para a proteção de informações para sistemas de informação estatais, sujeitos de infraestrutura crítica de informação (КИИ) e outros ambientes regulamentados. Os requisitos estão consagrados em vários documentos:
- Ordem FSTEC da Rússia nº 118 "Requisitos de segurança da informação para ferramentas de conteinerização", que, entre outras coisas, descreve os requisitos para controle de integridade.
- Ordem FSTEC da Rússia nº 187 "Requisitos de segurança da informação para ferramentas de virtualização" – similarmente, com requisitos para proteção e controle de integridade do ambiente.
- Documento Metodológico FSTEC da Rússia "Medidas de proteção de informações em sistemas de informação estatais", que inclui a medida ОЦЛ.1 – controle de integridade de software.
- Decreto Presidencial nº 166 "Sobre medidas para garantir a independência tecnológica e a segurança da infraestrutura crítica de informação da Federação Russa", que, em geral, define a direção para o uso de soluções confiáveis e certificadas com controle de integridade.
E parece que, mesmo que uma empresa não se enquadre formalmente nesses requisitos, o controle de integridade faz sentido como uma prática básica de segurança. Código comprometido em produção pode levar à falha de serviços, vazamento de dados, danos à reputação e perdas financeiras.
De todas as estatísticas, previsões e requisitos, podemos tirar uma conclusão concisa: no mundo moderno, o controle de integridade da entrega de software, da compilação à execução, é mais um mínimo básico do que um luxo máximo. É preciso implementá-lo.
O Que Requer Controle de Integridade no Kubernetes e Por Que Tudo se Resume a Contêineres
Se quisermos implementar o controle de integridade no Kubernetes, ele deve abranger:
- Contêineres: Isso inclui imagens de contêineres e sua execução. Componentes do control plane, add-ons e cargas úteis, se executados em contêineres.
- Configurações: Isso inclui recursos do Kubernetes, como Deployments, StatefulSets, Services e outros objetos definidos por meio de manifestos. Esses manifestos são aplicados ao cluster via Helm, GitOps ou qualquer outro método.
- Componentes do Sistema Operacional: Isso inclui tudo o que garante o funcionamento do Kubernetes no nível do nó. Por exemplo, containerd, kubelet, agentes e serviços do sistema.
Para simplificar, podemos falar sobre o controle de integridade dos três "K".
Vamos ver de onde cada um dos três "K" é entregue ao cluster. Com os contêineres, é simples – eles são baixados de um registro de imagens de contêineres (container registry). Configurações, como Helm charts, podem ser armazenadas em um ChartMuseum separado, mas na prática também podem ser empacotadas em um contêiner e colocadas no mesmo registro de imagens. Por exemplo, no caso da Deckhouse Kubernetes Platform, a configuração é implantada pelo operador deckhouse-controller, que é ele próprio um contêiner. Componentes do SO podem ser armazenados em um repositório de pacotes, mas também podem ser empacotados em imagens OCI e colocados em um armazenamento comum.
Se fizermos tudo o que foi mencionado acima, a nossa entrega inteira se tornará contêineres:
[Diagrama mostrando que tudo se resume a contêineres]
Quanto mais homogênea for a entrega, mais fácil será controlar sua integridade. Se tudo for armazenado como contêineres em um único registry, a tarefa de controle de integridade se resume a como controlar a integridade das imagens de contêineres.
Lembremos como uma imagem de contêiner é estruturada de acordo com a especificação OCI. Quando o ambiente de execução de contêineres carrega uma imagem, ele primeiro acessa o índice (image index). Mas o índice em si não contém os dados da imagem. Ele funciona como um sumário e aponta para os manifestos disponíveis. Por sua vez, cada manifesto contém links para:
- A configuração da imagem – seu entrypoint, variáveis de ambiente e tudo o que é necessário para executar o contêiner;
- O sistema de arquivos, que consiste em um conjunto de camadas (layer 1, …, layer n).
Como tudo isso é armazenado em disco? De acordo com a OCI Image Layout, uma imagem é um conjunto de arquivos interligados por hashes SHA-256. O índice é um arquivo JSON com uma lista de manifestos. O manifesto também é um arquivo JSON que contém o hash da configuração e os hashes das camadas. As próprias configurações e camadas residem no armazenamento como arquivos separados (blobs), cada um identificado por seu hash SHA-256.
Um manifesto define inequivocamente uma imagem de contêiner, pois une a configuração e todas as camadas do sistema de arquivos por meio de seus hashes SHA-256. Se qualquer componente da imagem for alterado, seu hash deixará de corresponder ao especificado no manifesto.
Mas resta a questão – como garantir a integridade do próprio manifesto? Para isso, ele precisa ser assinado: uma assinatura digital confirma que este é exatamente o manifesto que compilamos.
Como Implementar a Assinatura Digital de Manifestos
Explicarei como resolvemos o problema de assinar manifestos na Deckhouse e, em seguida, proporei alternativas Open Source que você pode usar como base para sua implementação.
Em nossa plataforma Kubernetes, há uma ferramenta de build que usa um buildah modificado e é chamada Deckhouse Delivery Kit. Ela compila contêineres e opera dentro do sistema CI. Juntas, elas formam um pipeline CI/CD.
Quando os contêineres são compilados, entra em cena o Deckhouse Stronghold – nossa solução para gerenciamento seguro do ciclo de vida de segredos. Neste caso, o usamos para assinaturas. Primeiro, o Deckhouse Delivery Kit envia a soma de verificação do manifesto via API compatível com Vault para o Deckhouse Stronghold e recebe uma assinatura digital como resultado. Os manifestos de contêineres assinados são armazenados no registro de imagens.
Junto com a assinatura, quatro anotações são adicionadas ao manifesto (veja em annotations):
json"config": { "digest": "ff82488acfcddd213198…", ... }, "layers": [ { "digest": "8acfcddd2131ff82488a…", ... }, ], "annotations": { "io.deckhouse.delivery-kit.build-timestamp": "1750791050", "io.deckhouse.delivery-kit.cert": "LS0tLS1 ...", "io.deckhouse.delivery-kit.chain": "LS0tLS1 ...", "io.deckhouse.delivery-kit.signature": "MEQCIEV..." }
A primeira anotação indica quando a assinatura foi feita. A segunda aponta para o certificado usado para assinar, neste caso, um certificado da "Flant". Em terceiro lugar está a cadeia de certificados. Ela é necessária se o manifesto não foi assinado pelo certificado raiz, mas por um intermediário, e representa vários X509. A última anotação é a assinatura, que fixa a soma de verificação do manifesto.
Um ponto importante: a assinatura em si não é proteção, mas a base para a verificação de confiança. A assinatura apenas registra quem criou o quê em cada etapa.
Soluções Alternativas
Como alternativa, você pode usar soluções Open Source. Para criar a assinatura em vez do Deckhouse Stronghold, você pode usar HashiCorp Vault ou OpenBao. Mas a Deckhouse Kubernetes Platform Community Edition também oferece os recursos da edição CE do Stronghold, que podem ser usados para replicar o esquema original.
Como clientes para assinatura, você pode usar Cosign ou Notary. Mas mais adiante no texto, apresentarei as razões pelas quais o Deckhouse Delivery Kit é melhor.
Níveis de Qualidade de Controle de Integridade
Antes de analisar nossa implementação de controle de integridade da entrega de código no Kubernetes, vamos examinar os níveis de qualidade existentes desse controle. São três, listados do melhor para o pior:
- Imutabilidade: O controle é projetado de forma que nada possa ser alterado dentro da cadeia de suprimentos.
- Compensação: Aplicação automática de medidas compensatórias. Por exemplo, se um invasor alterou algo, o sistema reverte essas alterações.
- Alarme: Quando um invasor altera algo, o sistema envia eventos de segurança do tipo "algo está acontecendo aqui, preste atenção".
[Imagem para facilitar a memorização]
Controle de Integridade de Contêineres
Portanto, os contêineres estão assinados, mas como controlar sua integridade? Perguntamo-nos se as interfaces de runtime de contêineres existentes já oferecem controle de integridade de primeiro ou segundo nível. Descobrimos que não. Por isso, iniciamos nossa própria implementação para a Deckhouse Kubernetes Platform.
Tomamos como base o containerd 2.0. No momento em que iniciamos nosso trabalho, esta era a versão mais recente. Precisávamos fazer:
- Download de fontes confiáveis;
- Execução apenas do que está presente na fonte confiável, ou seja, execução apenas do que assinamos;
- Verificação periódica de que tudo está funcionando.
O containerd 2.0 permite o uso de sistema de arquivos somente leitura aprimorado (EROFS) para contêineres. Por exemplo, temos uma imagem de contêiner – um manifesto, uma configuração e camadas de sistema de arquivos. E o containerd possui um armazenamento interno de snapshots (snapshot storage) em cada nó. Durante o pull (também conhecido como apply) para o nó, o containerd salva o manifesto neste armazenamento e converte as camadas para o formato EROFS. Isso é importante para entender nossas modificações.
Modificação 1: Verificação de Assinatura no Lado do Containerd
No momento do pull do manifesto, verificamos seu certificado embutido no containerd. Como resultado, nosso containerd baixa apenas contêineres de fontes confiáveis. Em seguida, de todas as camadas EROFS, um grande sistema de arquivos somente leitura é montado para o contêiner.
Como alternativa para verificar assinaturas, poderíamos ter usado o plugin ImageVerifier. Mas decidimos embutir o certificado diretamente no containerd, pois é mais confiável operar sem um binário adicional.
Modificação 2: Integração do dm-verity para Proteção de Camadas EROFS
Por padrão, o containerd não possui proteção contra a substituição de uma das camadas EROFS. Um invasor pode substituí-la diretamente no armazenamento interno de snapshots, e o sistema não saberá disso. Decidimos fechar essa vulnerabilidade usando dm-verity, um mecanismo de segurança do kernel Linux para sistemas de arquivos somente leitura. Ele constrói uma árvore de hashes (Merkle Tree) para blocos de disco e verifica a integridade de cada camada durante a leitura. Se os dados foram alterados, a leitura é bloqueada.
Funciona assim: um dispositivo mapper é criado, que via dm-verity aponta para outros dois dispositivos – um com os dados, outro com os hashes. Durante a leitura, o dm-verity compara os dados com os hashes e retorna um erro se eles não coincidirem. Isso nos dá controle de integridade durante a leitura.
Mas de onde vêm os hashes das camadas EROFS para o dm-verity? Voltando ao exemplo do manifesto assinado. Na verdade, além das quatro anotações já mencionadas, ele contém blocos para cada camada com suas próprias anotações. É nelas que reside o hash calculado para o dm-verity:
json"config": { "digest": "ff82488acfcddd213198…", ... }, "layers": [ { "digest": "8acfcddd2131ff82488a…", "annotations": { "io.deckhouse.delivery-kit.build-timestamp": "1750791050", "io.deckhouse.delivery-kit.dm-verity-root-hash": "1e9827da1457bc21b..." } ... }, ], "annotations": { "io.deckhouse.delivery-kit.build-timestamp": "1750791050", "io.deckhouse.delivery-kit.cert": "LS0tLS1 ...", "io.deckhouse.delivery-kit.chain": "LS0tLS1 ...", "io.deckhouse.delivery-kit.signature": "MEQCIEV..." }
O Deckhouse Delivery Kit calcula o hash para cada camada EROFS na fase de build. Os hashes são entregues junto com o manifesto assinado, que é salvo no armazenamento interno do containerd após verificação prévia da assinatura, e depois são obtidos diretamente do manifesto.
Isso significa que, mesmo que um invasor consiga substituir de alguma forma uma das camadas EROFS, o contêiner não perceberá isso até a reinicialização. E durante a reinicialização, nossa próxima modificação entra em ação: se a imagem não passar na verificação de integridade ao reiniciar, ela será marcada como corrompida, e a baixaremos novamente do armazenamento. O invasor ficará sem sucesso.
Modificação 3: Sistema de Arquivos Somente Leitura para Contêineres
Os problemas do containerd não terminam aí. O fato é que, sobre o sistema de arquivos somente leitura, o containerd também monta um OverlayFS. Ele é necessário para permitir a escrita em contêineres, mas um invasor também pode usá-lo. Recusamos o OverlayFS. Contêineres na Deckhouse Kubernetes Platform são sempre executados em modo somente leitura. Ao mesmo tempo, as pastas para montagem devem ser pré-criadas nos contêineres – caso contrário, nada funcionará. Para arquivos temporários, se realmente necessário, usa-se emptyDir, mas, em geral, tudo está disponível apenas para leitura. Um invasor não poderá escrever nada em um contêiner já em execução.
Resultados das Modificações para Controle de Integridade de Contêineres
Vamos resumir as modificações em nosso containerd para controle de integridade de contêineres:
- Ao baixar um contêiner, sua assinatura é verificada pelo certificado embutido no containerd.
- Para garantir a imutabilidade no contêiner, é utilizado um sistema de arquivos somente leitura.
- Na inicialização do contêiner, todos os snapshots são protegidos com dm-verity. Eles não podem ser alterados nem mesmo no host, e se isso acontecer, o contêiner não o perceberá até a reinicialização.
- Em caso de violação de integridade na inicialização do contêiner, a imagem inteira é baixada novamente do armazenamento confiável de imagens de contêineres.
- OverlayFS não é utilizado; nada pode ser adicionado a um contêiner já em execução.
- A verificação periódica apenas verifica a presença de dm-verity para todas as camadas EROFS.
Conseguimos um nível de qualidade de controle de integridade de primeiro nível para contêineres. Vamos para o segundo "K".
Controle de Integridade de Configurações
Configuração é tudo o que descreve o estado desejado do cluster e das aplicações. Ela determina o que deve ser executado, com quais parâmetros e onde. No Kubernetes, a configuração é armazenada no etcd e gerenciada através do control plane. O componente central do control plane é o kube-apiserver. Todos os requests para o cluster passam por ele: tanto de usuários (via CLI ou interface gráfica) quanto de componentes internos como scheduler e controller-manager. O API server é bem protegido: RBAC, admission controllers e outros mecanismos controlam quem pode fazer o quê. Todos os dados sobre o estado do cluster são armazenados pelo API server no etcd, e é o armazenamento que representa a parte mais fraca do esquema:
Acesso ao etcd é, na verdade, o mesmo que o modo deus no cluster. Se você tem acesso ao armazenamento, pode alterar segredos, substituir configurações ou executar alguma carga maliciosa contornando todo o sistema de verificação de permissões no API server.
Assinatura de Dados Antes de Salvar no etcd
A principal questão sobre controle de integridade é como podemos garantir que tudo o que é gravado no etcd foi gravado exatamente através do kube-apiserver e não foi alterado. E nossa solução aqui é a mesma – assinaturas digitais. Sim, novamente. Em teoria, poderíamos criptografar todo o banco de dados, mas então os dados não poderiam ser recuperados em caso de perda da chave, além de ser muito mais difícil detectar substituições. Assinaturas digitais oferecem um pouco mais de flexibilidade:
| Propriedade | Criptografia at rest | Assinatura Digital |
|---|---|---|
| Previne vazamento | ✅ | ❌ |
| Detecta substituição | ❌ | ✅ |
| Dados recuperáveis após perda de chave | ❌ | ✅ |
Decidimos adicionar um patch ao kube-apiserver que permite assinar os dados.
A transformação padrão dos dados que o kube-apiserver armazena no etcd ocorre da seguinte forma. Temos objetos de usuário (Deployment, StatefulSet, etc.). Primeiro, eles são codificados em JSON ou Protobuf, depois criptografados, por exemplo, usando KMS, e em seguida armazenados no etcd. Adicionamos mais um elo a essa cadeia. Antes de armazenar os dados no etcd, nós os assinamos:
Para a assinatura digital dos dados, usamos JOSE – JSON Object Signing and Encryption. Este é um padrão popular compatível com HSM, HashiCorp Vault e chaves em arquivos, o que permite usar chaves diferentes para verificação e assinatura. O JOSE também suporta curvas elípticas, incluindo o algoritmo comum ES256.
Onde Adicionamos Nossa Lógica
Nossa lógica está embutida na cadeia padrão de transformação de dados do kube-apiserver. Para isso, implementamos a estrutura SigningTransformer:
gotype SigningTransformer struct { transformer value.Transformer publicKeys *jose.JSONWebKeySet signer jose.Signer }
Aqui, transformer é a cadeia de transformação padrão, publicKeys são as chaves públicas para verificação da assinatura durante a leitura, e signer é o objeto que executa a assinatura durante a escrita.
O método TransformToStorage é responsável pela escrita no armazenamento. Ao salvar dados no etcd, primeiro passamos o objeto pela cadeia de transformação, depois assinamos o resultado e serializamos em nosso formato:
gofunc (t *SigningTransformer) TransformToStorage( data []byte, ctx context.Context, ) ([]byte, error) { transformedData, err := t.transformer.TransformToStorage(data) if err != nil {…} sig, err := t.signer.Sign(transformedData) if err != nil {…} return []byte(sig.FullSerialize()), nil }
Como resultado, o etcd recebe um JSON no formato Flattened JWS JSON Serialization com um conjunto definido de campos:
json{ "payload": "eyJpc3MiOiJqb2UiLA0KI…", "protected": "eyJhbGciOiJFUzI1NiJ9", "header": { "kid": "e9bc097a-ce51-4036-9562-d2ade882db0d" }, "signature": "DtEhU3ljbEg8L38VWAfUAqOyKAM6-X…" }
Aqui:
payload– dados criptografados;protectedeheader– metadados da chave com a qual os dados foram assinados;signature– a assinatura dos próprios dados.
O método TransformFromStorage é responsável pela leitura do armazenamento. Ao extrair dados do etcd, verificamos a assinatura usando várias chaves públicas – aqui já incluímos a possibilidade de rotação. Se a assinatura for válida, passamos os dados pela cadeia de transformação padrão do Kubernetes:
gofunc (t *SignatureTransformer) TransformFromStorage( ctx context.Context, data []byte, dataCtx value.Context, ) ([]byte, bool, error) { sig, err := jose.ParseSigned(string(data)) if err != nil {…} payload, err := sig.Verify(t.publicKeys) if err != nil {…} return transformer.TransformFromStorage(payload) }
Erro na Verificação de Assinatura Durante a Leitura
Consideramos o que acontece quando a assinatura é correta. Mas o que fazer se ocorrer um erro durante sua verificação? Na Deckhouse Kubernetes Platform, existem duas respostas para essa pergunta:
- Opção "para o dia a dia": Se a assinatura estiver incorreta, recusamos a emissão do objeto; ele não pode ser retirado do etcd. Este é o mecanismo de operação padrão.
- Opção para migração: Retornamos o objeto, mesmo que ele não tenha uma assinatura válida, mas adicionamos uma anotação especial ao audit log e uma métrica incremental. Esta opção é adequada se houver dados não migrados no etcd.
A opção "para o dia a dia" garante o primeiro nível de qualidade de controle de integridade, e a opção para migração – o terceiro nível de qualidade.
Resultados das Modificações para Controle de Integridade de Configurações
Como resultado das modificações, obtivemos:
- Um caminho confiável para gravação de dados no etcd;
- Detecção de substituição;
- Gravação auditável;
- Possibilidade de rotação de chaves;
- Compatibilidade de assinaturas digitais com a camada de criptografia. Ou seja, se desejar, os dados podem ser simultaneamente criptografados e assinados.
Vamos para o último "K" – componentes do sistema operacional.
Controle de Integridade de Componentes do Sistema Operacional
Componentes do sistema operacional incluem kubelet, containerd, nosso d8-client para Kubernetes, nc, resize2fs e muitos outros. Todos eles são arquivos binários ELF, e é essa propriedade que permite protegê-los com um mecanismo unificado.
Assinatura de Cabeçalhos ELF de Arquivos Binários
Arquivos ELF permitem adicionar uma assinatura em seu cabeçalho. Quando o Deckhouse Delivery Kit compila um contêiner, ele pode inspecionar seu sistema de arquivos final e encontrar os arquivos binários. Resta ir ao Deckhouse Stronghold, obter uma assinatura para cada binário e colocá-la nos cabeçalhos ELF. Em seguida, a cadeia padrão entra em ação: assinatura








