Como proteger builds de contêiner

1. Introdução

ead1609267034bf7.png

Vulnerabilidades de software são fraquezas que podem causar uma falha acidental do sistema ou fornecer a usuários de má-fé um meio de comprometer seu software. O Container Analysis oferece dois tipos de verificação do SO para encontrar vulnerabilidades em contêineres:

  • A API On-Demand Scanning permite verificar manualmente as imagens de contêiner em busca de vulnerabilidades do SO, seja localmente no seu computador ou remotamente no Container Registry ou no Artifact Registry.
  • A API Container Scanning permite automatizar a detecção de vulnerabilidades do SO, verificando cada vez que você envia uma imagem para o Container Registry ou o Artifact Registry. A ativação dessa API também ativa a verificação de pacotes de linguagem para vulnerabilidades em Go e Java.

A API On-Demand Scanning permite verificar imagens armazenadas localmente no seu computador ou remotamente no Container Registry ou no Artifact Registry. Isso oferece controle granular sobre os contêineres em que você quer verificar vulnerabilidades. É possível usar a verificação sob demanda para verificar imagens no pipeline de CI/CD antes de decidir se quer armazená-las em um registro.

O que você vai aprender

Neste laboratório, você aprenderá a:

  • Criar imagens com o Cloud Build
  • Usar o Artifact Registry para contêineres
  • Usar a verificação automatizada de vulnerabilidades
  • Configurar a verificação sob demanda
  • Adicionar verificação de imagem em CI/CD no Cloud Build

2. Configuração e requisitos

Configuração de ambiente personalizada

  1. 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.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • 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 Você pode atualizar 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. normalmente você não se importa com o que seja. Na maioria dos codelabs, é necessário fazer referência ao ID do projeto, que normalmente é identificado como PROJECT_ID. Se você não gostar do ID gerado, poderá gerar outro ID aleatório. Como alternativa, você pode tentar o seu próprio e ver se ele está disponível. Ela não pode ser alterada após essa etapa e permanecerá durante a duração do projeto.
  • Para sua informação, há um terceiro valor, um Número de projeto, que algumas APIs usam. Saiba mais sobre esses três valores na documentação.
  1. 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 não gerar faturamento 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.

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 

3. como criar imagens com o Cloud Build

Nesta seção, você vai criar um pipeline de build automatizado que vai gerar sua imagem de contêiner, fazer a verificação dela e avaliar os resultados. Se nenhuma vulnerabilidade CRÍTICA for encontrada, a imagem será enviada ao repositório. Se forem encontradas vulnerabilidades CRÍTICAS, o build falhará e será encerrado.

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 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 conteúdo abaixo.

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 conteúdo a seguir

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 o pipeline do Cloud Build

O comando a seguir cria um arquivo cloudbuild.yaml no seu diretório que será usado no processo automatizado. Neste exemplo, as etapas são limitadas ao processo de criação do contêiner. No entanto, na prática, 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: ['-']


EOF

execute o pipeline de CI

Enviar o build para processamento

gcloud builds submit

Revisar os detalhes do build

Depois que o processo de build for iniciado, analise o progresso no painel do Cloud Build.

  1. Abra o Cloud Build no console do Cloud.
  2. Clique no build para acessar o conteúdo

4. Artifact Registry para contêineres

Criar repositório do Artifact Registry

Neste laboratório, você vai usar o Artifact Registry para armazenar e verificar imagens. Crie o repositório com o comando a seguir.

gcloud artifacts repositories create artifact-scanning-repo \
  --repository-format=docker \
  --location=us-central1 \
  --description="Docker repository"

Configure o Docker para utilizar suas credenciais da gcloud ao acessar o Artifact Registry.

gcloud auth configure-docker us-central1-docker.pkg.dev

Atualizar o pipeline do Cloud Build

Modifique o pipeline do build para enviar a imagem resultante ao Artifact Registry

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: ['-']

# push 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']

images:
  - us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
EOF

execute o pipeline de CI

Enviar o build para processamento

gcloud builds submit

5. Verificação de vulnerabilidades automatizada

A verificação de artefatos é acionada automaticamente toda vez que você envia uma nova imagem para o Artifact Registry ou o Container Registry. As informações sobre vulnerabilidades são atualizadas continuamente quando novas vulnerabilidades são descobertas. Nesta seção, você vai revisar a imagem que acabou de criar e enviar para o Artifact Registry, além de analisar os resultados da vulnerabilidade.

Revisar detalhes da imagem

Após a conclusão do processo de build anterior, a imagem e os resultados de vulnerabilidade serão exibidos no painel do Artifact Registry.

  1. Abra o Artifact Registry no Console do Cloud
  2. Clique em artifact-scanning-repo para ver o conteúdo
  3. Clique nos detalhes da imagem
  4. Clique no resumo mais recente da sua imagem.
  5. Quando a verificação terminar, clique na guia "Vulnerabilidades" da imagem.

Na guia "Vulnerabilidades", você verá os resultados da verificação automática da imagem que acabou de criar.

361be7b3bf293fca.png

A verificação automática está ativada por padrão. Explore as configurações do Artifact Registry para saber como ativar ou desativar a verificação automática.

6. Busca sob demanda

Existem vários cenários em que você pode precisar realizar uma verificação antes de enviar a imagem para um repositório. Por exemplo, um desenvolvedor de contêiner pode verificar uma imagem e corrigir os problemas antes de enviar o código ao 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 .

Digitalize 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 o arquivo de saída

Reserve um momento para rever 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 ver 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 da imagem.

Sinalizar problemas críticos

Os humanos raramente usam os dados armazenados diretamente no relatório. 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 CRÍTICAS

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

7. como verificar na CICD com o Cloud Build

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"

Atualizar o pipeline do Cloud Build

O comando a seguir cria um arquivo cloudbuild.yaml no seu diretório que será usado no processo automatizado. Neste exemplo, as etapas são limitadas ao processo de criação do contêiner. No entanto, na prática, 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

execute o pipeline de CI

Envie o build para processamento a fim de verificar as falhas de build quando uma vulnerabilidade de gravidade CRÍTICA for encontrada.

gcloud builds submit

Analisar falhas no build

A versão que você acabou de enviar falhará porque a imagem contém vulnerabilidades CRÍTICAS.

Revise a falha de build na página Histórico do Cloud Build

Corrigir a vulnerabilidade

Atualize o Dockerfile para usar uma imagem de base que não contenha vulnerabilidades CRÍTICAS.

Substitua o Dockerfile para usar a imagem do Debian 10 com o comando a seguir:

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

Executar o processo de CI com a imagem boa

Envie o build para processamento e verifique se ele será bem-sucedido quando nenhuma vulnerabilidade de gravidade CRÍTICA for encontrada.

gcloud builds submit

Revisar o sucesso do build

O build que você acabou de enviar será concluído porque a imagem atualizada não contém vulnerabilidades CRÍTICAS.

Revise o sucesso do build na página Histórico do Cloud Build.

Analisar os resultados da verificação

Revise a imagem boa no Artifact Registry

  1. Abra o Artifact Registry no Console do Cloud
  2. Clique em artifact-scanning-repo para ver o conteúdo
  3. Clique nos detalhes da imagem
  4. Clique no resumo mais recente da sua imagem.
  5. Clique na guia "Vulnerabilidades" da imagem.

8. Parabéns!

Parabéns, você concluiu o codelab.

O que aprendemos:

  • Como criar imagens com o Cloud Build
  • Artifact Registry para contêineres
  • Verificação de vulnerabilidades automatizada
  • Busca sob demanda
  • como verificar na CICD com o Cloud Build

O que vem em seguida:

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.

Última atualização: 21/03/2023