1. Introdução
O Container Analysis oferece verificação de vulnerabilidades e armazenamento de metadados para contêineres. Esse serviço realiza verificações de vulnerabilidade em imagens no Artifact Registry e no Container Registry. Depois, armazena os metadados resultantes e os disponibiliza para consumo por meio de uma API. O armazenamento de metadados permite armazenar informações de diferentes fontes, incluindo a verificação de vulnerabilidades, serviços do Google Cloud e provedores de terceiros.
A verificação de vulnerabilidades pode ocorrer de forma automática ou sob demanda:
- Quando a verificação automática está ativada, a verificação é acionada automaticamente sempre que você envia uma nova imagem para o Artifact Registry ou o Container Registry. As informações de vulnerabilidade são atualizadas continuamente quando novas vulnerabilidades são descobertas.
- Quando a verificação sob demanda está ativada, é necessário executar um comando para verificar uma imagem local ou uma imagem no Artifact Registry ou no Container Registry. A verificação sob demanda oferece flexibilidade para verificar contêineres. Por exemplo, é possível verificar uma imagem criada localmente e corrigir vulnerabilidades antes de armazená-la em um registro. Os resultados da verificação ficam disponíveis por até 48 horas após a conclusão da verificação, e as informações de vulnerabilidade não são atualizadas após a verificação.
Com o Container Analysis integrado ao pipeline de CI/CD, é possível tomar decisões com base nesses metadados. Por exemplo, é possível usar a autorização binária para criar políticas de implantação que permitam apenas implantações de imagens compatíveis de registros confiáveis.
O que você vai aprender
- Como ativar a leitura automática
- Como realizar a verificação sob demanda
- Como integrar a verificação em um pipeline de build
- Como assinar imagens aprovadas
- Como usar os controladores de admissão do GKE para bloquear imagens
- Como configurar o GKE para permitir apenas imagens assinadas aprovadas
2. Configuração e requisitos
Configuração de ambiente personalizada
- Faça login no Console do Google Cloud e crie um novo projeto ou reutilize um existente. Crie uma conta do Gmail ou do Google Workspace, se ainda não tiver uma.
- O Nome do projeto é o nome de exibição para os participantes do projeto. É uma string de caracteres não usada pelas APIs do Google É possível atualizar o local a qualquer momento.
- O ID do projeto precisa ser exclusivo em todos os projetos do Google Cloud e não pode ser mudado após a definição. O console do Cloud gera automaticamente uma string exclusiva. Em geral, não importa o que seja. Na maioria dos codelabs, é necessário fazer referência ao ID do projeto, normalmente identificado como
PROJECT_ID
. Se você não gostar do ID gerado, crie outro aleatório. Se preferir, teste o seu e confira se ele está disponível. Ele não pode ser mudado após essa etapa e permanece durante o projeto. - Para sua informação, há um terceiro valor, um Número do projeto, que algumas APIs usam. Saiba mais sobre esses três valores na documentação.
- Em seguida, ative o faturamento no console do Cloud para usar os recursos/APIs do Cloud. A execução deste codelab não será muito cara, se tiver algum custo. Para encerrar os recursos e evitar cobranças além deste tutorial, exclua os recursos criados ou exclua o projeto inteiro. Novos usuários do Google Cloud estão qualificados para o programa de US$ 300 de avaliação sem custos.
Iniciar o editor do Cloud Shell
Este laboratório foi criado e testado para uso com o editor do Google Cloud Shell. Para acessar o editor,
- Acesse seu projeto do Google em https://console.cloud.google.com.
- No canto superior direito, clique no ícone do editor do Cloud Shell.
- Um novo painel será aberto na parte de baixo da janela.
Configuração do ambiente
No Cloud Shell, defina o ID e o número do projeto. Salve-as como variáveis PROJECT_ID
e PROJECT_ID
.
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
--format='value(projectNumber)')
Ativar serviços
Ative todos os serviços necessários:
gcloud services enable \
cloudkms.googleapis.com \
cloudbuild.googleapis.com \
container.googleapis.com \
containerregistry.googleapis.com \
artifactregistry.googleapis.com \
containerscanning.googleapis.com \
ondemandscanning.googleapis.com \
binaryauthorization.googleapis.com
Criar repositório do Artifact Registry
Neste laboratório, você vai usar o Artifact Registry para armazenar e verificar suas imagens. Crie o repositório com o comando abaixo.
gcloud artifacts repositories create artifact-scanning-repo \
--repository-format=docker \
--location=us-central1 \
--description="Docker repository"
Configure o Docker para usar suas credenciais do gcloud ao acessar o Artifact Registry.
gcloud auth configure-docker us-central1-docker.pkg.dev
3. Verificação automatizada
A verificação de artefatos é acionada automaticamente sempre que você envia uma nova imagem para o Artifact Registry ou o Container Registry. As informações de vulnerabilidade são atualizadas continuamente quando novas vulnerabilidades são descobertas. Nesta seção, você vai enviar uma imagem para o Artifact Registry e conferir os resultados.
Criar e mudar para um diretório de trabalho
mkdir vuln-scan && cd vuln-scan
Definir uma imagem de amostra
Crie um arquivo chamado Dockerfile com o seguinte conteúdo.
cat > ./Dockerfile << EOF
FROM gcr.io/google-appengine/debian9@sha256:ebffcf0df9aa33f342c4e1d4c8428b784fc571cdf6fbab0b31330347ca8af97a
# System
RUN apt update && apt install python3-pip -y
# App
WORKDIR /app
COPY . ./
RUN pip3 install Flask==1.1.4
RUN pip3 install gunicorn==20.1.0
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app
EOF
Crie um arquivo chamado main.py com o seguinte conteúdo:
cat > ./main.py << EOF
import os
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello_world():
name = os.environ.get("NAME", "Worlds")
return "Hello {}!".format(name)
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
EOF
Criar e enviar a imagem para RA
Use o Cloud Build para criar e enviar automaticamente o contêiner ao Artifact Registry. Observe a tag bad
na imagem. Isso vai ajudar você a identificar o arquivo para as etapas posteriores.
gcloud builds submit . -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:bad
Revisar detalhes da imagem
Depois que o processo de build for concluído, analise a imagem e os resultados de vulnerabilidade no painel do Artifact Registry.
- Abra o Artifact Registry no console do Cloud.
- Clique em artifact-scanning-repo para conferir o conteúdo.
- Clique nos detalhes da imagem
- Clique no resumo mais recente da sua imagem.
- Quando a verificação terminar, clique na guia "Vulnerabilidades" da imagem.
Na guia "Vulnerabilidades", você vai encontrar os resultados da verificação automática da imagem que acabou de criar.
A automação da verificação é ativada por padrão. Confira as configurações do Artifact Registry para saber como ativar/desativar a verificação automática.
4. Verificação sob demanda
Há vários cenários em que você pode precisar executar uma verificação antes de enviar a imagem para um repositório. Por exemplo, um desenvolvedor de contêineres pode verificar uma imagem e corrigir os problemas antes de enviar o código para o controle de origem. No exemplo abaixo, você vai criar e analisar a imagem localmente antes de agir com base nos resultados.
Criar uma imagem
Nesta etapa, você vai usar o Docker local para criar a imagem no cache local.
docker build -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image .
Digitalizar a imagem
Depois que a imagem for criada, solicite uma verificação dela. Os resultados da verificação são armazenados em um servidor de metadados. O job é concluído com um local dos resultados no servidor de metadados.
gcloud artifacts docker images scan \
us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
--format="value(response.scan)" > scan_id.txt
Analisar arquivo de saída
Analise a saída da etapa anterior, que foi armazenada no arquivo scan_id.txt. Observe o local do relatório dos resultados da verificação no servidor de metadados.
cat scan_id.txt
Analisar os resultados detalhados da verificação
Para conferir os resultados reais da verificação, use o comando list-vulnerabilities
no local do relatório indicado no arquivo de saída.
gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt)
A saída contém uma quantidade significativa de dados sobre todas as vulnerabilidades na imagem.
Sinalizar problemas críticos
As pessoas raramente usam os dados armazenados no relatório diretamente. Normalmente, os resultados são usados por um processo automatizado. Use os comandos abaixo para ler os detalhes do relatório e registrar se foram encontradas vulnerabilidades CRITÉRICAS.
export SEVERITY=CRITICAL
gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt) --format="value(vulnerability.effectiveSeverity)" | if grep -Fxq ${SEVERITY}; then echo "Failed vulnerability check for ${SEVERITY} level"; else echo "No ${SEVERITY} Vulnerabilities found"; fi
A saída desse comando será
Failed vulnerability check for CRITICAL level
5. Verificação do pipeline de build
Nesta seção, você vai criar um pipeline de build automatizado que vai criar a imagem do contêiner, fazer a verificação e avaliar os resultados. Se nenhuma vulnerabilidade CRITICAL for encontrada, a imagem será enviada para o repositório. Se vulnerabilidades CRITICAL forem encontradas, o build vai falhar e sair.
Conceder acesso à conta de serviço do Cloud Build
O Cloud Build vai precisar de direitos para acessar a API de verificação sob demanda. Forneça acesso com os comandos a seguir.
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/iam.serviceAccountUser"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/ondemandscanning.admin"
Criar o pipeline do Cloud Build
O comando a seguir cria um arquivo cloudbuild.yaml no diretório que será usado para o processo automatizado. Neste exemplo, as etapas são limitadas ao processo de build do contêiner. Na prática, no entanto, você incluiria instruções e testes específicos do aplicativo, além das etapas do contêiner.
Crie o arquivo com o comando a seguir.
cat > ./cloudbuild.yaml << EOF
steps:
# build
- id: "build"
name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', '.']
waitFor: ['-']
#Run a vulnerability scan at _SECURITY level
- id: scan
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- |
(gcloud artifacts docker images scan \
us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
--location us \
--format="value(response.scan)") > /workspace/scan_id.txt
#Analyze the result of the scan
- id: severity check
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- |
gcloud artifacts docker images list-vulnerabilities \$(cat /workspace/scan_id.txt) \
--format="value(vulnerability.effectiveSeverity)" | if grep -Fxq CRITICAL; \
then echo "Failed vulnerability check for CRITICAL level" && exit 1; else echo "No CRITICAL vulnerability found, congrats !" && exit 0; fi
#Retag
- id: "retag"
name: 'gcr.io/cloud-builders/docker'
args: ['tag', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']
#pushing to artifact registry
- id: "push"
name: 'gcr.io/cloud-builders/docker'
args: ['push', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']
images:
- us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
EOF
Executar o pipeline de CI
Envie o build para processamento para verificar se o build é interrompido quando uma vulnerabilidade de gravidade CRITICAL é encontrada.
gcloud builds submit
Falha na análise do build
O build que você acabou de enviar vai falhar porque a imagem contém vulnerabilidades CRITÉRICAS.
Analise a falha de build na página Histórico do Cloud Build.
Corrigir a vulnerabilidade
Atualize o Dockerfile para usar uma imagem base que não contenha vulnerabilidades CRITÉRICAS.
Substitua o Dockerfile para usar a imagem do Debian 10 com o seguinte comando
cat > ./Dockerfile << EOF
from python:3.8-slim
# App
WORKDIR /app
COPY . ./
RUN pip3 install Flask==2.1.0
RUN pip3 install gunicorn==20.1.0
CMD exec gunicorn --bind :\$PORT --workers 1 --threads 8 main:app
EOF
Execute o processo de CI com a imagem boa
Envie o build para processamento e verifique se o build vai ser bem-sucedido quando nenhuma vulnerabilidade de gravidade CRÍTICA for encontrada.
gcloud builds submit
Revisar a conclusão da build
O build que você acabou de enviar vai ser bem-sucedido porque a imagem atualizada não contém vulnerabilidades CRITÉRICAS.
Confira o sucesso do build na página Histórico do Cloud Build.
Analisar os resultados da verificação
Analisar a imagem boa no Artifact Registry
- Abra o Artifact Registry no console do Cloud.
- Clique em artifact-scanning-repo para conferir o conteúdo.
- Clique nos detalhes da imagem
- Clique no resumo mais recente da sua imagem.
- Clique na guia "Vulnerabilidades" da imagem.
6. Assinatura de imagens
Criar uma nota do atestador
Uma nota de testemunha é apenas um pequeno conjunto de dados que funciona como um rótulo para o tipo de assinatura que está sendo aplicado. Por exemplo, uma nota pode indicar a verificação de vulnerabilidade, enquanto outra pode ser usada para a aprovação de controle de qualidade. A nota será mencionada durante o processo de assinatura.
Criar uma nota
cat > ./vulnz_note.json << EOM
{
"attestation": {
"hint": {
"human_readable_name": "Container Vulnerabilities attestation authority"
}
}
}
EOM
Armazenar a nota
NOTE_ID=vulnz_note
curl -vvv -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
--data-binary @./vulnz_note.json \
"https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"
Verificar a nota
curl -vvv \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}"
Como criar um atestador
Os atestadores são usados para realizar o processo de assinatura de imagem e anexam uma ocorrência da nota à imagem para verificação posterior. Crie o atestador para uso futuro.
Criar atestador
ATTESTOR_ID=vulnz-attestor
gcloud container binauthz attestors create $ATTESTOR_ID \
--attestation-authority-note=$NOTE_ID \
--attestation-authority-note-project=${PROJECT_ID}
Verificar atestado
gcloud container binauthz attestors list
A última linha indica NUM_PUBLIC_KEYS: 0
, que você vai fornecer chaves em uma etapa posterior.
O Cloud Build também cria automaticamente o atestador built-by-cloud-build
no seu projeto quando você executa um build que gera imagens. Assim, o comando acima retorna dois certificadores, vulnz-attestor
e built-by-cloud-build
. Depois que as imagens são criadas, o Cloud Build assina e cria atestados automaticamente.
Como adicionar um papel do IAM
A conta de serviço Autorização binária precisa ter direitos para visualizar as notas de atestado. Forneça o acesso com a seguinte chamada de API
PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" --format="value(projectNumber)")
BINAUTHZ_SA_EMAIL="service-${PROJECT_NUMBER}@gcp-sa-binaryauthorization.iam.gserviceaccount.com"
cat > ./iam_request.json << EOM
{
'resource': 'projects/${PROJECT_ID}/notes/${NOTE_ID}',
'policy': {
'bindings': [
{
'role': 'roles/containeranalysis.notes.occurrences.viewer',
'members': [
'serviceAccount:${BINAUTHZ_SA_EMAIL}'
]
}
]
}
}
EOM
Use o arquivo para criar a política do IAM
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
--data-binary @./iam_request.json \
"https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}:setIamPolicy"
Como adicionar uma chave do KMS
O Attestor precisa de chaves criptográficas para anexar a nota e fornecer assinaturas verificáveis. Nesta etapa, você vai criar e armazenar chaves no KMS para que o Cloud Build possa acessá-las mais tarde.
Primeiro, adicione algumas variáveis de ambiente para descrever a nova chave.
KEY_LOCATION=global
KEYRING=binauthz-keys
KEY_NAME=codelab-key
KEY_VERSION=1
Criar um chaveiro para guardar um conjunto de chaves
gcloud kms keyrings create "${KEYRING}" --location="${KEY_LOCATION}"
Criar um novo par de chaves de assinatura assimétrica para o atestador
gcloud kms keys create "${KEY_NAME}" \
--keyring="${KEYRING}" --location="${KEY_LOCATION}" \
--purpose asymmetric-signing \
--default-algorithm="ec-sign-p256-sha256"
Sua chave vai aparecer na página do KMS no console do Google Cloud.
Agora, associe a chave ao seu atestador usando o comando gcloud binauthz:
gcloud beta container binauthz attestors public-keys add \
--attestor="${ATTESTOR_ID}" \
--keyversion-project="${PROJECT_ID}" \
--keyversion-location="${KEY_LOCATION}" \
--keyversion-keyring="${KEYRING}" \
--keyversion-key="${KEY_NAME}" \
--keyversion="${KEY_VERSION}"
Se você mostrar a lista de autoridades novamente, uma chave registrada vai aparecer:
gcloud container binauthz attestors list
Como criar um atestado assinado
Agora você tem os recursos configurados para assinar imagens. Use o atestador que você criou anteriormente para assinar a imagem do contêiner com que você está trabalhando
CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:latest \
--format='get(image_summary.digest)')
Agora você pode usar a gcloud para criar seu atestado. O comando simplesmente recebe os detalhes da chave que você quer usar para assinatura e a imagem de contêiner específica que você quer aprovar.
gcloud beta container binauthz attestations sign-and-create \
--artifact-url="${CONTAINER_PATH}@${DIGEST}" \
--attestor="${ATTESTOR_ID}" \
--attestor-project="${PROJECT_ID}" \
--keyversion-project="${PROJECT_ID}" \
--keyversion-location="${KEY_LOCATION}" \
--keyversion-keyring="${KEYRING}" \
--keyversion-key="${KEY_NAME}" \
--keyversion="${KEY_VERSION}"
Em termos de análise de contêineres, isso vai criar uma nova ocorrência e anexá-la à nota do atestador. Para garantir que tudo funcione como esperado, liste seus atestados.
gcloud container binauthz attestations list \
--attestor=$ATTESTOR_ID --attestor-project=${PROJECT_ID}
7. Assinatura com o Cloud Build
Você ativou a assinatura de imagem e usou manualmente o Attestor para assinar a imagem de amostra. Na prática, você vai querer aplicar as declarações durante processos automatizados, como pipelines de CI/CD.
Nesta seção, você vai configurar o Cloud Build para atestar imagens automaticamente.
Papéis
Adicione o papel Visualizador de atestador de autorização binária à conta de serviço do Cloud Build:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/binaryauthorization.attestorsViewer
Adicione o papel Signatário/Verificador de CryptoKey do Cloud KMS à conta de serviço do Cloud Build (assinatura baseada em KMS):
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/cloudkms.signerVerifier
Adicione o papel Anexador de notas do Container Analysis à conta de serviço do Cloud Build:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/containeranalysis.notes.attacher
Preparar a etapa personalizada do Cloud Build
Você vai usar uma etapa de build personalizada no Cloud Build para simplificar o processo de atestado. O Google oferece esta etapa de build personalizado, que contém funções auxiliares para simplificar o processo. Antes do uso, o código da etapa de build personalizada precisa ser integrado a um contêiner e enviado ao Cloud Build. Para fazer isso, execute os seguintes comandos:
git clone https://github.com/GoogleCloudPlatform/cloud-builders-community.git
cd cloud-builders-community/binauthz-attestation
gcloud builds submit . --config cloudbuild.yaml
cd ../..
rm -rf cloud-builders-community
Adicionar uma etapa de assinatura ao cloudbuild.yaml
Nesta etapa, você vai adicionar a etapa de atestado ao pipeline do Cloud Build criado anteriormente.
- Revise a nova etapa que você vai adicionar.
Somente revisão. Não copiar
#Sign the image only if the previous severity check passes - id: 'create-attestation' name: 'gcr.io/${PROJECT_ID}/binauthz-attestation:latest' args: - '--artifact-url' - 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image' - '--attestor' - 'projects/${PROJECT_ID}/attestors/$ATTESTOR_ID' - '--keyversion' - 'projects/${PROJECT_ID}/locations/$KEY_LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY_NAME/cryptoKeyVersions/$KEY_VERSION'
- Substitua o arquivo cloudbuild.yaml pelo pipeline completo atualizado.
cat > ./cloudbuild.yaml << EOF
steps:
# build
- id: "build"
name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', '.']
waitFor: ['-']
#Run a vulnerability scan at _SECURITY level
- id: scan
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- |
(gcloud artifacts docker images scan \
us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
--location us \
--format="value(response.scan)") > /workspace/scan_id.txt
#Analyze the result of the scan
- id: severity check
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- |
gcloud artifacts docker images list-vulnerabilities \$(cat /workspace/scan_id.txt) \
--format="value(vulnerability.effectiveSeverity)" | if grep -Fxq CRITICAL; \
then echo "Failed vulnerability check for CRITICAL level" && exit 1; else echo "No CRITICAL vulnerability found, congrats !" && exit 0; fi
#Retag
- id: "retag"
name: 'gcr.io/cloud-builders/docker'
args: ['tag', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']
#pushing to artifact registry
- id: "push"
name: 'gcr.io/cloud-builders/docker'
args: ['push', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']
#Sign the image only if the previous severity check passes
- id: 'create-attestation'
name: 'gcr.io/${PROJECT_ID}/binauthz-attestation:latest'
args:
- '--artifact-url'
- 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good'
- '--attestor'
- 'projects/${PROJECT_ID}/attestors/$ATTESTOR_ID'
- '--keyversion'
- 'projects/${PROJECT_ID}/locations/$KEY_LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY_NAME/cryptoKeyVersions/$KEY_VERSION'
images:
- us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good
EOF
Executar o build
gcloud builds submit
Analisar a versão no histórico do Cloud Build
Abra o Console do Cloud na página "Histórico do Cloud Build" e analise o build mais recente e a execução bem-sucedida das etapas de build.
8. Políticas de controle de admissão
A autorização binária é um recurso do GKE e do Cloud Run que permite validar regras antes que uma imagem de contêiner seja executada. A validação é executada em qualquer solicitação para executar uma imagem, seja de um pipeline de CI/CD confiável ou de um usuário que tenta implantar uma imagem manualmente. Esse recurso permite proteger seus ambientes de execução de maneira mais eficaz do que as verificações de pipeline de CI/CD.
Para entender esse recurso, você vai modificar a política padrão do GKE para aplicar uma regra de autorização rígida.
Criar o cluster do GKE
Crie o cluster do GKE:
gcloud beta container clusters create binauthz \
--zone us-central1-a \
--binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE
Permita que o Cloud Build seja implantado neste cluster:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/container.developer"
Política de permissão para todos
Primeiro, verifique o estado da política padrão e sua capacidade de implantar qualquer imagem.
- Analisar a política atual
gcloud container binauthz policy export
- A política de aplicação está definida como
ALWAYS_ALLOW
.
evaluationMode: ALWAYS_ALLOW
- Implantar a amostra para verificar se você pode implantar qualquer coisa
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
- Verificar se a implantação funcionou
kubectl get pods
A saída a seguir será exibida:
- Excluir implantação
kubectl delete pod hello-server
Política de negação total
Agora, atualize a política para proibir todas as imagens.
- Exportar a política atual para um arquivo editável
gcloud container binauthz policy export > policy.yaml
- Alterar a política
Em um editor de texto, mude o evaluationMode de ALWAYS_ALLOW para ALWAYS_DENY.
edit policy.yaml
O arquivo YAML da política será exibido da seguinte maneira:
globalPolicyEvaluationMode: ENABLE defaultAdmissionRule: evaluationMode: ALWAYS_DENY enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG name: projects/PROJECT_ID/policy
- Abra o Terminal, aplique a nova política e aguarde alguns segundos para que a mudança seja propagada.
gcloud container binauthz policy import policy.yaml
- Tentar a implantação de carga de trabalho de amostra
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
- A implantação falha com a seguinte mensagem
Error from server (VIOLATES_POLICY): admission webhook "imagepolicywebhook.image-policy.k8s.io" denied the request: Image gcr.io/google-samples/hello-app:1.0 denied by Binary Authorization default admission rule. Denied by always_deny admission rule
Reverter a política para permitir tudo
Antes de passar para a próxima seção, reverta as mudanças na política.
- Alterar a política
Em um editor de texto, mude o evaluationMode de ALWAYS_DENY para ALWAYS_ALLOW.
edit policy.yaml
O arquivo YAML da política será exibido da seguinte maneira:
globalPolicyEvaluationMode: ENABLE defaultAdmissionRule: evaluationMode: ALWAYS_ALLOW enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG name: projects/PROJECT_ID/policy
- Aplicar a política revertida
gcloud container binauthz policy import policy.yaml
9. Bloquear vulnerabilidades no GKE
Nesta seção, você vai combinar o que aprendeu até agora implementando um pipeline de CI/CD com o Cloud Build que verifica as imagens e, em seguida, procura vulnerabilidades antes de assinar a imagem e tentar implantar. O GKE vai usar a autorização binária para validar se a imagem tem uma assinatura da verificação de vulnerabilidade antes de permitir que ela seja executada.
Atualizar a política do GKE para exigir atestado
Exija que as imagens sejam assinadas pelo Attestor adicionando clusterAdmissionRules à sua política de BinAuth do GKE.
Substitua a política pela configuração atualizada usando o comando abaixo.
COMPUTE_ZONE=us-central1-a
cat > binauth_policy.yaml << EOM
defaultAdmissionRule:
enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
evaluationMode: ALWAYS_DENY
globalPolicyEvaluationMode: ENABLE
clusterAdmissionRules:
${COMPUTE_ZONE}.binauthz:
evaluationMode: REQUIRE_ATTESTATION
enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
requireAttestationsBy:
- projects/${PROJECT_ID}/attestors/vulnz-attestor
EOM
Aplicar a política
gcloud beta container binauthz policy import binauth_policy.yaml
Tentar implantar a imagem não assinada
Crie um descritor de implantação para o aplicativo criado anteriormente usando o comando a seguir. A imagem usada aqui é a que você criou anteriormente, que contém vulnerabilidades críticas e NÃO contém o atestado assinado.
Os controladores de admissão do GKE precisam saber a imagem exata a ser implantada para validar a assinatura de forma consistente. Para isso, você precisa usar o resumo da imagem em vez de uma tag simples.
Receber o resumo da imagem inválida
CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:bad \
--format='get(image_summary.digest)')
Usar o resumo na configuração do Kubernetes
cat > deploy.yaml << EOM
apiVersion: v1
kind: Service
metadata:
name: deb-httpd
spec:
selector:
app: deb-httpd
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deb-httpd
spec:
replicas: 1
selector:
matchLabels:
app: deb-httpd
template:
metadata:
labels:
app: deb-httpd
spec:
containers:
- name: deb-httpd
image: ${CONTAINER_PATH}@${DIGEST}
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
EOM
Tentar implantar o app no GKE
kubectl apply -f deploy.yaml
Analise a carga de trabalho no console e observe o erro que indica que a implantação foi negada:
No attestations found that were valid and signed by a key trusted by the attestor
Implantar uma imagem assinada
Receber o resumo da imagem inválida
CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:good \
--format='get(image_summary.digest)')
Usar o resumo na configuração do Kubernetes
cat > deploy.yaml << EOM
apiVersion: v1
kind: Service
metadata:
name: deb-httpd
spec:
selector:
app: deb-httpd
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deb-httpd
spec:
replicas: 1
selector:
matchLabels:
app: deb-httpd
template:
metadata:
labels:
app: deb-httpd
spec:
containers:
- name: deb-httpd
image: ${CONTAINER_PATH}@${DIGEST}
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
EOM
Implantar o app no GKE
kubectl apply -f deploy.yaml
Revise a carga de trabalho no console e observe a implantação bem-sucedida da imagem.
10. Parabéns!
Parabéns, você concluiu o codelab.
O que aprendemos:
- Como ativar a leitura automática
- Como realizar a verificação sob demanda
- Como integrar a verificação em um pipeline de build
- Como assinar imagens aprovadas
- Como usar os controladores de admissão do GKE para bloquear imagens
- Como configurar o GKE para permitir apenas imagens assinadas aprovadas
O que vem em seguida:
- Como proteger implantações de imagens no Cloud Run e no Google Kubernetes Engine | Documentação do Cloud Build
- Guia de início rápido: configurar uma política de autorização binária com o GKE | Google Cloud
Limpar
Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto ou mantenha o projeto e exclua cada um dos recursos.
Excluir o projeto
O jeito mais fácil de evitar cobranças é excluindo o projeto que você criou para este tutorial.