Tutorial: como saber sobre vulnerabilidades de imagem

Este tutorial mostra como usar o Container Analysis para verificar se uma imagem de contêiner armazenada no Container Registry tem vulnerabilidades e listar as vulnerabilidades de alta gravidade.

Objetivos

Este tutorial inclui as etapas a seguir:

  1. Criar uma imagem do Docker com vulnerabilidades conhecidas
  2. Enviar a imagem para o Container Registry do projeto
  3. Usar o Container Analysis para fazer uma varredura inicial e analisar a imagem
  4. Exibir vulnerabilidades identificadas pelo Container Analysis
  5. Listar as vulnerabilidades mais graves da imagem

Custos

Neste tutorial, há componentes faturáveis do Google Cloud. Consulte a página de preços para mais informações.

Observação: ao ativar a API Container Scanning, o faturamento começa imediatamente. Após ativar a API, o recurso Container Analysis verifica automaticamente cada imagem recém-enviada, mas não verifica automaticamente as imagens existentes. Para verificar uma imagem existente, é necessário enviá-la novamente.

Novos usuários do Google Cloud podem estar qualificados para uma avaliação gratuita.

Antes de começar

Para usar o Container Analysis, é necessário ativar e configurar o Container Analysis e o Container Registry.

  1. Faça login na sua Conta do Google.

    Se você ainda não tiver uma, inscreva-se.

  2. No Console do Cloud, na página de seletor de projetos, selecione ou crie um projeto do Cloud.

    Acesse a página do seletor de projetos

  3. Verifique se a cobrança está ativada para o seu projeto do Google Cloud. Saiba como confirmar se a cobrança está ativada para o seu projeto.

  4. Ative as APIs Container Registry and Container Scanning.

    Ative as APIs

  5. Instale e inicialize o SDK do Cloud..
  6. Se você ainda não fez isso, siga um destes procedimentos para conseguir as permissões do IAM necessárias. Se você for o proprietário do projeto, pule esta etapa.
    • Para ver ocorrências, é necessário ter a seguinte permissão:
      containeranalysis.notes.listOccurrences
    • Como alternativa, é possível atribuir o seguinte papel predefinido do IAM, que concede automaticamente as permissões necessárias:
      Container Analysis Occurrences Viewer
  7. Instale o Docker. Se você estiver usando um sistema operacional baseado em Linux, como Ubuntu ou Debian, adicione seu nome de usuário ao grupo docker para executar o Docker sem utilizar sudo:
    sudo usermod -a -G docker ${USER}

    Talvez seja necessário reiniciar o sistema depois de adicionar você mesmo ao grupo docker.

  8. Abra o Docker. Para garantir que o Docker esteja ativo, execute o seguinte comando do Docker, que retorna a hora e a data atuais:
  9. docker run busybox date

Criação de uma imagem do Docker

Para este tutorial, crie a seguinte imagem do Docker para que você tenha uma imagem para enviar ao Container Registry. Você usará um ambiente de execução do Python com vulnerabilidades conhecidas que serão identificadas pelo Container Analysis. Esta imagem do Docker contém um pequeno aplicativo da Web em Python. O aplicativo usa a biblioteca da web Flask para disponibilizar uma página da web que exibe a mensagem "Hello, World!"

Para criar a imagem do Docker, siga estas etapas:

  1. Crie um diretório para armazenar os três arquivos de imagem do Docker.

  2. Nesse diretório, crie três arquivos: Dockerfile, requirements.txt e app.py. Veja os exemplos abaixo de como o conteúdo de cada arquivo precisa ser:

Dockerfile

# The file Dockerfile defines the image's environment
    # Import Python runtime and set up working directory
    # This specified runtime has known vulnerabilities so that vulnerability
    # scanning can be tested.
    FROM python:3.5-slim
    WORKDIR /app
    ADD . /app

    # Install any necessary dependencies
    RUN pip install -r requirements.txt

    # Open port 80 for serving the webpage
    EXPOSE 80

    # Run app.py when the container launches
    CMD ["python", "app.py"]
    

requirements.txt

# The file requirements.txt defines the image's dependencies
    Flask
    

app.py

# The Docker image contains the following code in app.py
    from flask import Flask
    import os
    import socket

    app = Flask(__name__)

    @app.route("/")
    def hello():
        html = "<h3>Hello, World!</h3>"
        return html

    if __name__ == "__main__":
      app.run(host='0.0.0.0', port=80)
    

Para criar a imagem do Docker, execute o seguinte comando a partir do diretório que contém os arquivos dela:

docker build -t vulnerabilities-tutorial-image .
    

Você criou uma imagem do Docker na máquina local.

Adicionar a imagem ao Container Registry

Configurar docker para usar a ferramenta de linha de comando gcloud como um assistente de credencial

Antes de enviar ou extrair imagens, é necessário configurar o Docker para usar a ferramenta de linha de comando gcloud para autenticar solicitações para o Container Registry. Para isso, execute o seguinte comando (você só precisa fazer isso uma vez):

gcloud auth configure-docker
    

Marcar a imagem com um nome de registro

Antes de enviar a imagem do Docker ao Container Registry, marque-a com seu nome de registro. Marcar a imagem do Docker com um nome de registro configura o comando docker push para enviar a imagem a um local específico. Para este guia de início rápido, o local do host é gcr.io.

Para marcar a imagem do Docker, execute este comando:

docker tag vulnerabilities-tutorial-image gcr.io/[PROJECT-ID]/vulnerabilities-tutorial-image:tag1
    

em que:

  • [PROJECT-ID] é o ID do projeto do Console do Google Cloud , que você precisa adicionar ao seu comando
  • gcr.io é o nome do host
  • vulnerabilities-tutorial-image é o nome da imagem do Docker
  • tag1 é uma tag que você está adicionando à imagem do Docker. Se você não especificou uma tag, o Docker aplicará a tag padrão latest.

Agora você está pronto para enviar a imagem ao Container Registry.

Enviar a imagem ao Container Registry

Depois que o docker tiver sido configurado para usar o gcloud como um auxiliar de credencial e a imagem local estiver marcada com o nome do registro, você poderá enviá-la para o Container Registry.

Basta executar o comando a seguir:

docker push gcr.io/[PROJECT-ID]/vulnerabilities-tutorial-image:tag1
    

em que [PROJECT-ID] é o ID do projeto do seu Console do Google Cloud. Caso o ID do projeto contenha dois pontos (:), consulte Projetos com escopo de domínio.

Quando você envia uma imagem para um novo local de host, o serviço cria um intervalo de armazenamento subjacente exclusivo para seu projeto. Para visualizar imagens hospedadas pelo Container Registry através do Console do Cloud, ou acessar o nome do registro da imagem no navegador da Web: http://gcr.io/[PROJECT-ID]/vulnerabilities-tutorial-image.

Verificar o resumo da imagem

Na próxima etapa, você precisará do resumo SHA256 da imagem. Este é um hash da imagem gerada quando você a envia para um registro.

Embora você possa usar uma tag para marcar diferentes versões em diferentes pontos no tempo, um resumo é sempre exclusivo para uma versão de imagem.

curl -H "Authorization: Bearer $(gcloud auth print-access-token)" https://gcr.io/v2/[PROJECT-ID]/vulnerabilities-tutorial-image/tags/list
    

A resposta retornada é um objeto JSON que contém informações sobre diferentes versões da imagem enviada, juntamente com as tags associadas.

{
      "child": [],
      "manifest": {
        "sha256:1e70b945e7266268e35b3db3ddc5c13e88fe4e42ee6ffbfa8962ec0b1562b51a": {
          "imageSizeBytes": "2803075",
          "layerId": "",
          "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
          "tag": [],
          "timeCreatedMs": "1583923219860",
          "timeUploadedMs": "1583923231051"
        },
        "sha256:95d270793da3f9eb77ae6c0ebe84beaaa84a66c331c3fb2205f8645646568a98": {
          "imageSizeBytes": "61212796",
          "layerId": "",
          "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
          "tag": [
            "tag1"
          ],
          "timeCreatedMs": "1583923518920",
          "timeUploadedMs": "1583923552668"
        }
      },
      "name": "[PROJECT-ID]/vulnerabilities-tutorial-image",
      "tags": [
        "tag1"
      ]
    }
    

Você pode analisá-lo, por exemplo, usando a ferramenta JQ:

curl -H "Authorization: Bearer $(gcloud auth print-access-token)" https://gcr.io/v2/[PROJECT-ID]/vulnerabilities-tutorial-image/tags/list | jq  '.manifest | to_entries[] | select(.value.tag | contains(["tag1"])) | .key'
    

Como realizar a varredura inicial e visualizar os resultados da análise

O Container Analysis executa automaticamente uma varredura inicial e uma análise da imagem. Ele cria uma ocorrência de descoberta, que inclui as informações coletadas dessa varredura inicial. O Container Analysis também atualiza a ocorrência de descoberta com o status atual da varredura.

A amostra de código a seguir pesquisa o status atual da varredura inicial para saber quando as informações de vulnerabilidade estão disponíveis para visualização.

Java

Para saber como instalar e usar a biblioteca de cliente do Container Registry, consulte Bibliotecas de cliente do Container Registry. Para mais informações, consulte a documentação de referência da API Container Registry Java.

import com.google.cloud.devtools.containeranalysis.v1.ContainerAnalysisClient;
    import io.grafeas.v1.DiscoveryOccurrence;
    import io.grafeas.v1.DiscoveryOccurrence.AnalysisStatus;
    import io.grafeas.v1.GrafeasClient;
    import io.grafeas.v1.Occurrence;
    import io.grafeas.v1.ProjectName;
    import java.io.IOException;
    import java.lang.InterruptedException;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.TimeoutException;

    public class PollDiscoveryOccurrenceFinished {
      // Repeatedly query the Container Analysis API for the latest discovery occurrence until it is
      // either in a terminal state, or the timeout value has been exceeded
      public static Occurrence pollDiscoveryOccurrenceFinished(String resourceUrl, String projectId,
          long timeoutSeconds) throws IOException, TimeoutException, InterruptedException {
        // String resourceUrl = "https://gcr.io/project/image@sha256:123";
        // String projectId = "my-project-id";
        // long timeoutSeconds = 30;
        final String projectName = ProjectName.format(projectId);
        long deadline = System.currentTimeMillis() + timeoutSeconds * 1000;

        // Initialize client that will be used to send requests. After completing all of your requests,
        // call the "close" method on the client to safely clean up any remaining background resources.
        GrafeasClient client = ContainerAnalysisClient.create().getGrafeasClient();

        // find the discovery occurrence using a filter string
        Occurrence discoveryOccurrence = null;
        // vulbnerability discovery occurrences are always associated with the
        // PACKAGE_VULNERABILITY note in the "goog-analysis" GCP project
        String filter =  String.format("resourceUrl=\"%s\" AND noteProjectId=\"%s\" AND noteId=\"%s\"",
            resourceUrl, "goog-analysis",  "PACKAGE_VULNERABILITY");
        while (discoveryOccurrence == null) {
          for (Occurrence o : client.listOccurrences(projectName, filter).iterateAll()) {
            if (o.getDiscovery() != null) {
              // there should be only one valid discovery occurrence returned by the given filter
              discoveryOccurrence = o;
            }
          }
          TimeUnit.SECONDS.sleep(1);
          // check for timeout
          if (System.currentTimeMillis() > deadline) {
            throw new TimeoutException("discovery occurrence not found");
          }
        }

        // wait for discovery occurrence to enter a terminal state
        AnalysisStatus status = AnalysisStatus.PENDING;
        while (status != AnalysisStatus.FINISHED_SUCCESS
            && status != AnalysisStatus.FINISHED_FAILED
            && status != AnalysisStatus.FINISHED_UNSUPPORTED) {
          // update the occurrence state
          discoveryOccurrence = client.getOccurrence(discoveryOccurrence.getName());
          status = discoveryOccurrence.getDiscovery().getAnalysisStatus();
          TimeUnit.SECONDS.sleep(1);
          // check for timeout
          if (System.currentTimeMillis() > deadline) {
            throw new TimeoutException("discovery occurrence not in terminal state");
          }
        }
        return discoveryOccurrence;
      }
    }

Go

Para saber como instalar e usar a biblioteca de cliente do Container Registry, consulte Bibliotecas de cliente do Container Registry. Para mais informações, consulte a documentação de referência da API Container Registry Go.


    import (
    	"context"
    	"fmt"
    	"time"

    	containeranalysis "cloud.google.com/go/containeranalysis/apiv1"
    	"google.golang.org/api/iterator"
    	grafeaspb "google.golang.org/genproto/googleapis/grafeas/v1"
    )

    // pollDiscoveryOccurrenceFinished returns the discovery occurrence for a resource once it reaches a finished state.
    func pollDiscoveryOccurrenceFinished(resourceURL, projectID string, timeout time.Duration) (*grafeaspb.Occurrence, error) {
    	// resourceURL := fmt.Sprintf("https://gcr.io/my-project/my-image")
    	// timeout := time.Duration(5) * time.Second
    	ctx, cancel := context.WithTimeout(context.Background(), timeout)
    	defer cancel()

    	client, err := containeranalysis.NewClient(ctx)
    	if err != nil {
    		return nil, fmt.Errorf("NewClient: %v", err)
    	}
    	defer client.Close()

    	// ticker is used to poll once per second.
    	ticker := time.NewTicker(1 * time.Second)
    	defer ticker.Stop()

    	// Find the discovery occurrence using a filter string.
    	var discoveryOccurrence *grafeaspb.Occurrence
    	for discoveryOccurrence == nil {
    		select {
    		case <-ctx.Done():
    			return nil, fmt.Errorf("timeout while retrieving discovery occurrence")
    		case <-ticker.C:
    			req := &grafeaspb.ListOccurrencesRequest{
    				Parent: fmt.Sprintf("projects/%s", projectID),
    				// Vulnerability discovery occurrences are always associated with the
    				// PACKAGE_VULNERABILITY note in the "goog-analysis" GCP project.
    				Filter: fmt.Sprintf(`resourceUrl=%q AND noteProjectId="goog-analysis" AND noteId="PACKAGE_VULNERABILITY"`, resourceURL),
    			}
    			it := client.GetGrafeasClient().ListOccurrences(ctx, req)
    			// Only one occurrence should ever be returned by ListOccurrences
    			// and the given filter.
    			result, err := it.Next()
    			if err == iterator.Done {
    				break
    			}
    			if err != nil {
    				return nil, fmt.Errorf("it.Next: %v", err)
    			}
    			if result.GetDiscovery() != nil {
    				discoveryOccurrence = result
    			}
    		}
    	}

    	// Wait for the discovery occurrence to enter a terminal state.
    	for {
    		select {
    		case <-ctx.Done():
    			return nil, fmt.Errorf("timeout waiting for terminal state")
    		case <-ticker.C:
    			// Update the occurrence.
    			req := &grafeaspb.GetOccurrenceRequest{Name: discoveryOccurrence.GetName()}
    			updated, err := client.GetGrafeasClient().GetOccurrence(ctx, req)
    			if err != nil {
    				return nil, fmt.Errorf("GetOccurrence: %v", err)
    			}
    			switch updated.GetDiscovery().GetAnalysisStatus() {
    			case grafeaspb.DiscoveryOccurrence_FINISHED_SUCCESS,
    				grafeaspb.DiscoveryOccurrence_FINISHED_FAILED,
    				grafeaspb.DiscoveryOccurrence_FINISHED_UNSUPPORTED:
    				return discoveryOccurrence, nil
    			}
    		}
    	}
    }
    

Node.js

Para saber como instalar e usar a biblioteca de cliente do Container Registry, consulte Bibliotecas de cliente do Container Registry. Para mais informações, consulte a documentação de referência da API Container Registry Node.js (em inglês).

/**
     * TODO(developer): Uncomment these variables before running the sample
     */
    // const projectId = 'your-project-id', // Your GCP Project ID
    // const imageUrl = 'https://gcr.io/my-project/my-image:123', // Image to attach metadata to
    // const retries = 5 // The number of retries to listen for the new Pub/Sub messages

    // Import the library and create a client
    const {ContainerAnalysisClient} = require('@google-cloud/containeranalysis');
    const client = new ContainerAnalysisClient();

    const formattedParent = client.getGrafeasClient().projectPath(projectId);

    let filter = `resourceUrl="${imageUrl}" AND noteProjectId="goog-analysis" AND noteId="PACKAGE_VULNERABILITY"`;

    // Repeatedly query the Container Analysis API for the latest discovery occurrence until it is
    // either in a terminal state, or the timeout value has been exceeded
    const pRetry = require('p-retry');
    const discoveryOccurrence = await pRetry(
      async () => {
        const [occurrences] = await client.getGrafeasClient().listOccurrences({
          parent: formattedParent,
          filter: filter,
        });
        if (occurrences.length < 0) {
          throw new Error('No occurrences found for ' + imageUrl);
        }
        return occurrences[0];
      },
      {
        retries: retries,
      }
    );

    // Wait for discovery occurrence to enter a terminal state or the timeout value has been exceeded
    const finishedOccurrence = await pRetry(
      async () => {
        let status = 'PENDING';
        const [updated] = await client.getGrafeasClient().getOccurrence({
          name: discoveryOccurrence.name,
        });
        status = updated.discovery.analysisStatus;
        if (
          status !== 'FINISHED_SUCCESS' &&
          status !== 'FINISHED_FAILED' &&
          status !== 'FINISHED_UNSUPPORTED'
        ) {
          throw new Error('Timeout while retrieving discovery occurrence');
        }
        return updated;
      },
      {
        retries: retries,
      }
    );
    console.log(
      `Found discovery occurrence ${finishedOccurrence.name}.  Status: ${finishedOccurrence.discovery.analysisStatus}`
    );

Ruby

Para saber como instalar e usar a biblioteca de cliente do Container Registry, consulte Bibliotecas de cliente do Container Registry. Para mais informações, consulte a documentação de referência da API Container Registry Ruby (em inglês).

# resource_url    = "The URL of the resource associated with the occurrence.
    #                    e.g. https://gcr.io/project/image@sha256:123"
    # timeout_seconds = "The number of seconds to wait for the discovery
    #                    occurrence"
    # project_id      = "Your Google Cloud project ID"

    require "grafeas"

    deadline = Time.now + timeout_seconds

    # Initialize the client
    client = Grafeas.new
    formatted_parent = Grafeas::V1::GrafeasClient.project_path project_id

    # Find the discovery occurrence using a filter string
    discovery_occurrence = nil
    while discovery_occurrence.nil?
      begin
        filter = 'resourceUrl="#{resource_url}" ' \
                 'AND noteProjectId="goog-analysis" ' \
                 'AND noteId="PACKAGE_VULNERABILITY"'
        # Only the discovery occurrence should be returned for the given filter
        discovery_occurrence = client.list_occurrences(formatted_parent, filter: filter).first
      rescue StandardError # If there is an error, keep trying until the deadline
        puts "discovery occurrence not yet found"
      ensure
        # check for timeout
        sleep 1
        if Time.now > deadline
          raise "Timeout while retrieving discovery occurrence."
        end
      end
    end

    # Wait for the discovery occurrence to enter a terminal state
    status = Grafeas::V1::DiscoveryOccurrence::AnalysisStatus::PENDING
    while status != :FINISHED_SUCCESS &&
          status != :FINISHED_FAILED &&
          status != :FINISHED_UNSUPPORTED
      # Update occurrence
      begin
        updated = client.get_occurrence discovery_occurrence.name
        status = updated.discovery.analysis_status
      rescue StandardError # If there is an error, keep trying until the deadline
        puts "discovery occurrence not yet in terminal state"
      ensure
        # check for timeout
        sleep 1
        if Time.now > deadline
          raise "Timeout while retrieving discovery occurrence."
        end
      end
    end
    puts "Found discovery occurrence #{updated.name}."
    puts "Status: #{updated.discovery.analysis_status}"

Python

Para saber como instalar e usar a biblioteca de cliente do Container Registry, consulte Bibliotecas de cliente do Container Registry. Para mais informações, consulte a documentação de referência da API Container Registry Python (em inglês).

def poll_discovery_finished(resource_url, timeout_seconds, project_id):
        """Returns the discovery occurrence for a resource once it reaches a
        terminal state."""
        # resource_url = 'https://gcr.io/my-project/my-image@sha256:123'
        # timeout_seconds = 20
        # project_id = 'my-gcp-project'

        import time
        from grafeas.grafeas_v1.gapic.enums import DiscoveryOccurrence
        from google.cloud.devtools import containeranalysis_v1

        deadline = time.time() + timeout_seconds

        client = containeranalysis_v1.ContainerAnalysisClient()
        grafeas_client = client.get_grafeas_client()
        project_name = grafeas_client.project_path(project_id)

        discovery_occurrence = None
        while discovery_occurrence is None:
            time.sleep(1)
            filter_str = 'resourceUrl="{}" \
                          AND noteProjectId="goog-analysis" \
                          AND noteId="PACKAGE_VULNERABILITY"'.format(resource_url)
            result = grafeas_client.list_occurrences(project_name, filter_str)
            # only one occurrence should ever be returned by ListOccurrences
            # and the given filter
            for item in result:
                discovery_occurrence = item
            if time.time() > deadline:
                raise RuntimeError('timeout while retrieving discovery occurrence')

        status = DiscoveryOccurrence.AnalysisStatus.PENDING
        while status != DiscoveryOccurrence.AnalysisStatus.FINISHED_UNSUPPORTED \
                and status != DiscoveryOccurrence.AnalysisStatus.FINISHED_FAILED \
                and status != DiscoveryOccurrence.AnalysisStatus.FINISHED_SUCCESS:
            time.sleep(1)
            updated = grafeas_client.get_occurrence(discovery_occurrence.name)
            status = updated.discovery.analysis_status
            if time.time() > deadline:
                raise RuntimeError('timeout while waiting for terminal state')
        return discovery_occurrence

Quando o status da verificação é FINISHED_SUCCESS, a lista de vulnerabilidades pode ser exibida.

Como listar todas as vulnerabilidades associadas a uma imagem

Vulnerabilidades conhecidas são armazenadas como notas. O Container Analysis cria uma ocorrência para cada instância de uma nota que encontra durante a análise da imagem. À medida que o Container Analysis coleta novas informações sobre vulnerabilidades, ele atualiza a lista de ocorrências automaticamente.

É possível recuperar informações sobre notas e ocorrências usando o Console do GCP, a ferramenta de linha de comando gcloud ou a API Container Analysis. Além disso, a API é compatível com várias expressões de filtro para recuperar informações específicas sobre notas ou ocorrências.

O código a seguir recupera as vulnerabilidades encontradas para uma imagem.

Java

Para saber como instalar e usar a biblioteca de cliente do Container Registry, consulte Bibliotecas de cliente do Container Registry. Para mais informações, consulte a documentação de referência da API Container Registry Java.

import com.google.cloud.devtools.containeranalysis.v1.ContainerAnalysisClient;
    import io.grafeas.v1.GrafeasClient;
    import io.grafeas.v1.Occurrence;
    import io.grafeas.v1.ProjectName;
    import java.io.IOException;
    import java.util.LinkedList;
    import java.util.List;

    public class VulnerabilityOccurrencesForImage {
      // Retrieve a list of vulnerability occurrences assoviated with a resource
      public static List<Occurrence> findVulnerabilityOccurrencesForImage(String resourceUrl,
          String projectId) throws IOException {
        // String resourceUrl = "https://gcr.io/project/image@sha256:123";
        // String projectId = "my-project-id";
        final String projectName = ProjectName.format(projectId);
        String filterStr = String.format("kind=\"VULNERABILITY\" AND resourceUrl=\"%s\"", resourceUrl);

        // Initialize client that will be used to send requests. After completing all of your requests,
        // call the "close" method on the client to safely clean up any remaining background resources.
        GrafeasClient client = ContainerAnalysisClient.create().getGrafeasClient();
        LinkedList<Occurrence> vulnerabilitylist = new LinkedList<Occurrence>();
        for (Occurrence o : client.listOccurrences(projectName, filterStr).iterateAll()) {
          vulnerabilitylist.add(o);
        }
        return vulnerabilitylist;
      }
    }

Go

Para saber como instalar e usar a biblioteca de cliente do Container Registry, consulte Bibliotecas de cliente do Container Registry. Para mais informações, consulte a documentação de referência da API Container Registry Go.


    import (
    	"context"
    	"fmt"

    	containeranalysis "cloud.google.com/go/containeranalysis/apiv1"
    	"google.golang.org/api/iterator"
    	grafeaspb "google.golang.org/genproto/googleapis/grafeas/v1"
    )

    // findVulnerabilityOccurrencesForImage retrieves all vulnerability Occurrences associated with a resource.
    func findVulnerabilityOccurrencesForImage(resourceURL, projectID string) ([]*grafeaspb.Occurrence, error) {
    	// resourceURL := fmt.Sprintf("https://gcr.io/my-project/my-image")
    	ctx := context.Background()
    	client, err := containeranalysis.NewClient(ctx)
    	if err != nil {
    		return nil, fmt.Errorf("NewClient: %v", err)
    	}
    	defer client.Close()

    	req := &grafeaspb.ListOccurrencesRequest{
    		Parent: fmt.Sprintf("projects/%s", projectID),
    		Filter: fmt.Sprintf("resourceUrl = %q kind = %q", resourceURL, "VULNERABILITY"),
    	}

    	var occurrenceList []*grafeaspb.Occurrence
    	it := client.GetGrafeasClient().ListOccurrences(ctx, req)
    	for {
    		occ, err := it.Next()
    		if err == iterator.Done {
    			break
    		}
    		if err != nil {
    			return nil, fmt.Errorf("occurrence iteration error: %v", err)
    		}
    		occurrenceList = append(occurrenceList, occ)
    	}

    	return occurrenceList, nil
    }
    

Node.js

Para saber como instalar e usar a biblioteca de cliente do Container Registry, consulte Bibliotecas de cliente do Container Registry. Para mais informações, consulte a documentação de referência da API Container Registry Node.js (em inglês).

/**
     * TODO(developer): Uncomment these variables before running the sample
     */
    // const projectId = 'your-project-id', // Your GCP Project ID
    // const imageUrl = 'https://gcr.io/my-project/my-image:123' // Image to attach metadata to

    // Import the library and create a client
    const {ContainerAnalysisClient} = require('@google-cloud/containeranalysis');
    const client = new ContainerAnalysisClient();

    const formattedParent = client.getGrafeasClient().projectPath(projectId);

    // Retrieve a list of vulnerability occurrences assoviated with a resource
    const [occurrences] = await client.getGrafeasClient().listOccurrences({
      parent: formattedParent,
      filter: `kind = "VULNERABILITY" AND resourceUrl = "${imageUrl}"`,
    });

    if (occurrences.length) {
      console.log(`All Vulnerabilities for ${imageUrl}`);
      occurrences.forEach(occurrence => {
        console.log(`${occurrence.name}:`);
      });
    } else {
      console.log('No occurrences found.');
    }

Ruby

Para saber como instalar e usar a biblioteca de cliente do Container Registry, consulte Bibliotecas de cliente do Container Registry. Para mais informações, consulte a documentação de referência da API Container Registry Ruby (em inglês).

# resource_url = "The URL of the resource associated with the occurrence
    #                e.g. https://gcr.io/project/image@sha256:123"
    # project_id   = "The Google Cloud project ID of the vulnerabilities to find"

    require "grafeas"

    # Initialize the client
    client = Grafeas.new

    formatted_parent = Grafeas::V1::GrafeasClient.project_path project_id
    filter = "resourceUrl = \"#{resource_url}\" AND kind = \"VULNERABILITY\""
    client.list_occurrences formatted_parent, filter: filter

Python

Para saber como instalar e usar a biblioteca de cliente do Container Registry, consulte Bibliotecas de cliente do Container Registry. Para mais informações, consulte a documentação de referência da API Container Registry Python (em inglês).

def find_vulnerabilities_for_image(resource_url, project_id):
        """"Retrieves all vulnerability occurrences associated with a resource."""
        # resource_url = 'https://gcr.io/my-project/my-image@sha256:123'
        # project_id = 'my-gcp-project'

        from google.cloud.devtools import containeranalysis_v1

        client = containeranalysis_v1.ContainerAnalysisClient()
        grafeas_client = client.get_grafeas_client()
        project_name = grafeas_client.project_path(project_id)

        filter_str = 'kind="VULNERABILITY" AND resourceUrl="{}"'\
            .format(resource_url)
        return list(grafeas_client.list_occurrences(project_name, filter_str))

Como listar vulnerabilidades de alta gravidade

Cada vulnerabilidade tem um nível de gravidade associado. O Container Analysis usa informações de nível de gravidade fornecidas pelas distribuições Linux compatíveis. Se os níveis de gravidade específicos da distribuição estiverem indisponíveis, os níveis atribuídos serão baseados nas pontuações do CVSS.

Para priorizar planos de correção de vulnerabilidades, é possível refinar a lista de vulnerabilidades para que ela mostre apenas as mais graves.

A amostra de código a seguir recupera uma lista de vulnerabilidades de uma imagem que recebeu a classificação de gravidade alta ou crítica.

Java

Para saber como instalar e usar a biblioteca de cliente do Container Registry, consulte Bibliotecas de cliente do Container Registry. Para mais informações, consulte a documentação de referência da API Container Registry Java.

import com.google.cloud.devtools.containeranalysis.v1.ContainerAnalysisClient;
    import io.grafeas.v1.GrafeasClient;
    import io.grafeas.v1.Occurrence;
    import io.grafeas.v1.ProjectName;
    import io.grafeas.v1.Severity;
    import java.io.IOException;
    import java.util.LinkedList;
    import java.util.List;

    public class HighVulnerabilitiesForImage {
      // Retrieve a list of vulnerability occurrences with a severity level of 'HIGH' or greater
      public static List<Occurrence> findHighSeverityVulnerabilitiesForImage(String resourceUrl,
          String projectId) throws IOException {
        // String resourceUrl = "https://gcr.io/project/image@sha256:123";
        // String projectId = "my-project-id";
        final String projectName = ProjectName.format(projectId);
        String filterStr = String.format("kind=\"VULNERABILITY\" AND resourceUrl=\"%s\"", resourceUrl);

        // Initialize client that will be used to send requests. After completing all of your requests,
        // call the "close" method on the client to safely clean up any remaining background resources.
        GrafeasClient client = ContainerAnalysisClient.create().getGrafeasClient();
        LinkedList<Occurrence> vulnerabilitylist = new LinkedList<Occurrence>();
        for (Occurrence o : client.listOccurrences(projectName, filterStr).iterateAll()) {
          Severity severity = o.getVulnerability().getSeverity();
          if (severity == Severity.HIGH || severity == Severity.CRITICAL) {
            vulnerabilitylist.add(o);
          }
        }
        return vulnerabilitylist;
      }
    }

Go

Para saber como instalar e usar a biblioteca de cliente do Container Registry, consulte Bibliotecas de cliente do Container Registry. Para mais informações, consulte a documentação de referência da API Container Registry Go.


    import (
    	"context"
    	"fmt"

    	containeranalysis "cloud.google.com/go/containeranalysis/apiv1"
    	"google.golang.org/api/iterator"
    	grafeaspb "google.golang.org/genproto/googleapis/grafeas/v1"
    )

    // findHighSeverityVulnerabilitiesForImage retrieves a list of only high vulnerability occurrences associated with a resource.
    func findHighSeverityVulnerabilitiesForImage(resourceURL, projectID string) ([]*grafeaspb.Occurrence, error) {
    	// resourceURL := fmt.Sprintf("https://gcr.io/my-project/my-image")
    	ctx := context.Background()
    	client, err := containeranalysis.NewClient(ctx)
    	if err != nil {
    		return nil, fmt.Errorf("NewClient: %v", err)
    	}
    	defer client.Close()

    	req := &grafeaspb.ListOccurrencesRequest{
    		Parent: fmt.Sprintf("projects/%s", projectID),
    		Filter: fmt.Sprintf("resourceUrl = %q kind = %q", resourceURL, "VULNERABILITY"),
    	}

    	var occurrenceList []*grafeaspb.Occurrence
    	it := client.GetGrafeasClient().ListOccurrences(ctx, req)
    	for {
    		occ, err := it.Next()
    		if err == iterator.Done {
    			break
    		}
    		if err != nil {
    			return nil, fmt.Errorf("occurrence iteration error: %v", err)
    		}

    		severityLevel := occ.GetVulnerability().GetEffectiveSeverity()
    		if severityLevel == grafeaspb.Severity_HIGH || severityLevel == grafeaspb.Severity_CRITICAL {
    			occurrenceList = append(occurrenceList, occ)
    		}
    	}

    	return occurrenceList, nil
    }
    

Node.js

Para saber como instalar e usar a biblioteca de cliente do Container Registry, consulte Bibliotecas de cliente do Container Registry. Para mais informações, consulte a documentação de referência da API Container Registry Node.js (em inglês).

/**
     * TODO(developer): Uncomment these variables before running the sample
     */
    // const projectId = 'your-project-id', // Your GCP Project ID
    // const imageUrl = 'https://gcr.io/my-project/my-image:123' // Image to attach metadata to

    // Import the library and create a client
    const {ContainerAnalysisClient} = require('@google-cloud/containeranalysis');
    const client = new ContainerAnalysisClient();

    const formattedParent = client.getGrafeasClient().projectPath(projectId);

    // Retrieve a list of vulnerability occurrences with a severity level of 'HIGH' or greater
    const [occurrences] = await client.getGrafeasClient().listOccurrences({
      parent: formattedParent,
      filter: `kind = "VULNERABILITY" AND resourceUrl = "${imageUrl}"`,
    });

    if (occurrences.length) {
      console.log(`High Severity Vulnerabilities for ${imageUrl}`);
      occurrences.forEach(occurrence => {
        if (
          occurrence.vulnerability.severity === 'HIGH' ||
          occurrence.vulnerability.severity === 'CRITICAL'
        ) {
          console.log(`${occurrence.name}:`);
        }
      });
    } else {
      console.log('No occurrences found.');
    }

Ruby

Para saber como instalar e usar a biblioteca de cliente do Container Registry, consulte Bibliotecas de cliente do Container Registry. Para mais informações, consulte a documentação de referência da API Container Registry Ruby (em inglês).

# resource_url = "The URL of the resource associated with the occurrence,
    #                 e.g. https://gcr.io/project/image@sha256:123"
    # project_id   = "The Google Cloud project ID of the vulnerabilities to find"

    require "grafeas"

    # Initialize the client
    client = Grafeas.new

    formatted_parent = Grafeas::V1::GrafeasClient.project_path project_id
    filter = "resourceUrl = \"#{resource_url}\" AND kind = \"VULNERABILITY\""
    vulnerability_list = client
                         .list_occurrences(formatted_parent, filter: filter)
    # Filter the list to include only "high" and "critical" vulnerabilities
    vulnerability_list.select do |item|
      item.vulnerability.severity == :HIGH || item.vulnerability.severity == :CRITICAL
    end

Python

Para saber como instalar e usar a biblioteca de cliente do Container Registry, consulte Bibliotecas de cliente do Container Registry. Para mais informações, consulte a documentação de referência da API Container Registry Python (em inglês).

def find_high_severity_vulnerabilities_for_image(resource_url, project_id):
        """Retrieves a list of only high vulnerability occurrences associated
        with a resource."""
        # resource_url = 'https://gcr.io/my-project/my-image@sha256:123'
        # project_id = 'my-gcp-project'

        from grafeas.grafeas_v1.gapic.enums import Severity
        from google.cloud.devtools import containeranalysis_v1

        client = containeranalysis_v1.ContainerAnalysisClient()
        grafeas_client = client.get_grafeas_client()
        project_name = grafeas_client.project_path(project_id)

        filter_str = 'kind="VULNERABILITY" AND resourceUrl="{}"'\
            .format(resource_url)
        vulnerabilities = grafeas_client.list_occurrences(project_name, filter_str)
        filtered_list = []
        for v in vulnerabilities:
            if v.severity == Severity.HIGH or v.severity == Severity.CRITICAL:
                filtered_list.append(v)
        return filtered_list

Limpar

Para evitar que os recursos usados neste tutorial sejam cobrados na conta do Google Cloud Platform:

Como excluir a imagem

Caso você queira apenas remover a imagem do Docker que foi adicionada, execute o comando a seguir para excluir a imagem do Docker do Container Registry.

gcloud container images delete gcr.io/[PROJECT-ID]/vulnerabilities-tutorial-image:tag1 --force-delete-tags
    

em que:[PROJECT-ID] é o ID do projeto do seu Console do Google Cloud. Caso o ID do projeto contenha dois pontos (:), consulte Projetos com escopo de domínio.

Excluir o projeto

O jeito mais fácil de evitar cobranças é excluir o projeto criado para o tutorial.

Para excluir o projeto:

  1. No Console do Cloud, acesse a página Gerenciar recursos:

    Acessar a página Gerenciar recursos

  2. Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir .
  3. Na caixa de diálogo, digite o ID do projeto e clique em Encerrar para excluí-lo.

A seguir