Instructivo: Obtener información sobre las vulnerabilidades de las imágenes

En este instructivo, se muestra cómo usar Container Analysis a fin de analizar una imagen de contenedor almacenada en Container Registry para buscar vulnerabilidades y, luego, enumerar las vulnerabilidades graves para la imagen.

Objetivos

En este instructivo, se abarcan los siguientes pasos:

  1. Crear una imagen de Docker con vulnerabilidades conocidas
  2. Enviar la imagen al Container Registry de tu proyecto
  3. Consultar Container Analysis para completar el análisis inicial y de la imagen
  4. Ver las vulnerabilidades que identificó Container Analysis
  5. Enumerar las vulnerabilidades graves de la imagen

Costos

En este instructivo, se usan los componentes facturables de Google Cloud. Consulta Precios para obtener información sobre los precios.

Nota: Cuando habilitas la API de Container Scanning, la facturación comienza de inmediato. Luego, Container Analysis analizará de forma automática cada imagen nueva que envíes. Sin embargo, no analizará las imágenes existentes. Para que lo haga, debes volver a enviarlas.

Los usuarios nuevos de Google Cloud pueden ser aptos para una prueba gratuita.

Antes de comenzar

Para usar Container Analysis, debes habilitar y configurar Container Analysis y Container Registry.

  1. Accede a tu Cuenta de Google.

    Si todavía no tienes una cuenta, regístrate para obtener una nueva.

  2. En la página de selección de proyectos de Cloud Console, selecciona o crea un proyecto de Cloud.

    Ir a la página de selección de proyectos

  3. Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud. Obtén información sobre cómo confirmar que tienes habilitada la facturación para tu proyecto.

  4. Habilita las API de Container Registry and Container Scanning.

    Habilita las API

  5. Instala e inicializa el SDK de Cloud.
  6. Si aún no lo hiciste, realiza una de las siguientes acciones para obtener los permisos de IAM que necesitas. Si eres el propietario del proyecto, omite este paso.
    • Para ver los casos, debes tener los siguientes permisos:
      containeranalysis.notes.listOccurrences
    • Como alternativa, puedes otorgar la siguiente función de IAM predefinida, que proporcionará automáticamente los permisos necesarios:
      Container Analysis Occurrences Viewer
  7. Instala Docker. Si usas un sistema operativo basado en Linux, como Ubuntu o Debian, agrega tu nombre de usuario al grupo docker para que puedas ejecutar Docker sin usar sudo:
    sudo usermod -a -G docker ${USER}

    Es posible que debas reiniciar tu sistema después de agregarte al grupo docker.

  8. Abre Docker. Para asegurarte de que Docker esté funcionando, ejecuta el siguiente comando de Docker, que muestra la hora y la fecha actuales:
  9. docker run busybox date

Compila una imagen de Docker

Para este instructivo, compila la siguiente imagen de Docker a fin de que tengas una imagen que enviar a Container Registry. Utilizarás un entorno de ejecución de Python con vulnerabilidades conocidas que Container Analysis identificará. Esta imagen de Docker contiene una pequeña aplicación web de Python. La aplicación utiliza el marco de trabajo web Flask para entregar una página web que muestre el mensaje "Hello, World!".

Haz lo siguiente para crear la imagen de Docker:

  1. Crea un directorio para almacenar los tres archivos de imagen de Docker.

  2. En este directorio, crea tres archivos: Dockerfile, requirements.txt y app.py. Consulta los siguientes ejemplos para saber qué debes incluir en el contenido de cada archivo:

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 compilar la imagen de Docker, ejecuta el siguiente comando de Docker desde el directorio que contiene los archivos de la imagen:

docker build -t vulnerabilities-tutorial-image .

Ya creaste una imagen de Docker en tu máquina local.

Agrega la imagen a Container Registry

Configura docker para usar la herramienta de línea de comandos de gcloud como un auxiliar de credenciales

Antes de poder enviar o extraer imágenes, debes configurar Docker para que use la herramienta de línea de comandos de gcloud a fin de autenticar las solicitudes a Container Registry. Para ello, ejecuta el siguiente comando (solo debes hacerlo una vez):

gcloud auth configure-docker

Etiqueta la imagen con un nombre de registro

Antes de enviar la imagen de Docker a Container Registry, debes etiquetarla con su nombre de registro. Etiquetar la imagen de Docker con un nombre de registro configura el comando docker push para enviar la imagen a una ubicación específica. Para esta guía de inicio rápido, la ubicación del host es gcr.io.

A fin de etiquetar la imagen de Docker, ejecuta el siguiente comando:

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

donde:

  • [PROJECT-ID] es tu ID del proyecto de Google Cloud Console, que debes agregar a tu comando.
  • gcr.io es el nombre de host.
  • vulnerabilities-tutorial-image es el nombre de la imagen de Docker.
  • tag1 es una etiqueta que agregas a la imagen de Docker. Si no especificaste una etiqueta, Docker aplicará la etiqueta predeterminada latest.

Ahora estás listo para enviar la imagen a Container Registry.

Envía la imagen a Container Registry

Una vez que docker esté configurado para usar gcloud como auxiliar de credencial y la imagen local esté etiquetada con el nombre del registro, puedes enviarla a Container Registry.

Para enviar la imagen de Docker, ejecuta el siguiente comando:

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

donde [PROJECT-ID] es el ID del proyecto de Google Cloud Console. Si el ID de tu proyecto contiene dos puntos (:), consulta Proyectos con alcance de dominio.

Cuando envías una imagen a una nueva ubicación de host, el servicio crea el depósito de almacenamiento subyacente único para tu proyecto. Puedes ver las imágenes alojadas en Container Registry mediante Cloud Console o en tu navegador web mediante la URL del nombre de registro de la imagen: http://gcr.io/[PROJECT-ID]/vulnerabilities-tutorial-image.

Verifica el resumen de la imagen

En el siguiente paso, necesitarás el resumen SHA256 de la imagen. Este es un hash de la imagen generada cuando se envía a un registro.

Si bien puedes usar una etiqueta para marcar diferentes versiones en diferentes momentos, un resumen siempre es único para una versión de imagen.

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

La respuesta que se muestra es un objeto JSON que contiene información sobre las diferentes versiones de la imagen que subiste, junto con las etiquetas asociadas.

{
  "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"
  ]
}

Puedes analizarlo, por ejemplo, con la herramienta de 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'

Consulta el análisis inicial y los resultados

Container Analysis realiza automáticamente un análisis inicial de la imagen. Crea un caso de descubrimiento que incluye la información recopilada a partir de ese análisis inicial. Container Analysis también actualiza el caso de descubrimiento con el estado actual del análisis.

La siguiente muestra de código consulta el estado actual del análisis inicial para que sepas cuándo se puede ver la información de vulnerabilidad.

Java

Para obtener información sobre cómo instalar y usar la biblioteca cliente de Container Registry, consulta las Bibliotecas cliente de Container Registry. Si deseas obtener más información, consulta la documentación de referencia de la API de Java para Container Registry.

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 obtener información sobre cómo instalar y usar la biblioteca cliente de Container Registry, consulta las Bibliotecas cliente de Container Registry. Si deseas obtener más información, consulta la documentación de referencia de la API de Go para Container Registry.


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 obtener información sobre cómo instalar y usar la biblioteca cliente de Container Registry, consulta las Bibliotecas cliente de Container Registry. Si deseas obtener más información, consulta la documentación de referencia de la API de Node.js para Container Registry.

/**
 * 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 obtener información sobre cómo instalar y usar la biblioteca cliente de Container Registry, consulta las Bibliotecas cliente de Container Registry. Si deseas obtener más información, consulta la documentación de referencia de la API de Ruby para Container Registry.

# 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 obtener información sobre cómo instalar y usar la biblioteca cliente de Container Registry, consulta las Bibliotecas cliente de Container Registry. Si deseas obtener más información, consulta la documentación de referencia de la API de Python para Container Registry.

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

Cuando el estado del análisis es FINISHED_SUCCESS, puedes ver la lista de vulnerabilidades.

Muestra todas las vulnerabilidades asociadas con una imagen

Las vulnerabilidades conocidas se almacenan como notas. Container Analysis crea un caso para cada instancia de una nota que encuentra durante el análisis de la imagen. A medida que Container Analysis recopila información nueva sobre vulnerabilidades, actualiza la lista de casos automáticamente.

Puedes recuperar información sobre notas y casos con GCP Console, la herramienta de línea de comandos de gcloud o la API de Container Analysis. Además, la API es compatible con varias expresiones de filtro para recuperar información específica sobre notas o casos.

La siguiente muestra de código recupera las vulnerabilidades encontradas para una imagen.

Java

Para obtener información sobre cómo instalar y usar la biblioteca cliente de Container Registry, consulta las Bibliotecas cliente de Container Registry. Si deseas obtener más información, consulta la documentación de referencia de la API de Java para Container Registry.

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 obtener información sobre cómo instalar y usar la biblioteca cliente de Container Registry, consulta las Bibliotecas cliente de Container Registry. Si deseas obtener más información, consulta la documentación de referencia de la API de Go para Container Registry.


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 obtener información sobre cómo instalar y usar la biblioteca cliente de Container Registry, consulta las Bibliotecas cliente de Container Registry. Si deseas obtener más información, consulta la documentación de referencia de la API de Node.js para Container Registry.

/**
 * 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 obtener información sobre cómo instalar y usar la biblioteca cliente de Container Registry, consulta las Bibliotecas cliente de Container Registry. Si deseas obtener más información, consulta la documentación de referencia de la API de Ruby para Container Registry.

# 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 obtener información sobre cómo instalar y usar la biblioteca cliente de Container Registry, consulta las Bibliotecas cliente de Container Registry. Si deseas obtener más información, consulta la documentación de referencia de la API de Python para Container Registry.

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))

Genera una lista de vulnerabilidades graves

Cada vulnerabilidad se asocia con un nivel de gravedad. Container Analysis utiliza la información sobre el nivel de gravedad proporcionada por las distribuciones de Linux compatibles. Si los niveles de gravedad específicos de la distribución no están disponibles, los niveles asignados se basan en las puntuaciones de CVSS.

Si deseas priorizar planes para abordar las vulnerabilidades, puedes definir mejor tu lista de vulnerabilidades solo para las graves.

La siguiente muestra de código recupera una lista de vulnerabilidades de una imagen a la que se le asignó un nivel grave o crítico.

Java

Para obtener información sobre cómo instalar y usar la biblioteca cliente de Container Registry, consulta las Bibliotecas cliente de Container Registry. Si deseas obtener más información, consulta la documentación de referencia de la API de Java para Container Registry.

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().getEffectiveSeverity();
      if (severity == Severity.HIGH || severity == Severity.CRITICAL) {
        vulnerabilitylist.add(o);
      }
    }
    return vulnerabilitylist;
  }
}

Go

Para obtener información sobre cómo instalar y usar la biblioteca cliente de Container Registry, consulta las Bibliotecas cliente de Container Registry. Si deseas obtener más información, consulta la documentación de referencia de la API de Go para Container Registry.


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 obtener información sobre cómo instalar y usar la biblioteca cliente de Container Registry, consulta las Bibliotecas cliente de Container Registry. Si deseas obtener más información, consulta la documentación de referencia de la API de Node.js para Container Registry.

/**
 * 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.effective_severity === 'HIGH' ||
      occurrence.vulnerability.effective_severity === 'CRITICAL'
    ) {
      console.log(`${occurrence.name}:`);
    }
  });
} else {
  console.log('No occurrences found.');
}

Ruby

Para obtener información sobre cómo instalar y usar la biblioteca cliente de Container Registry, consulta las Bibliotecas cliente de Container Registry. Si deseas obtener más información, consulta la documentación de referencia de la API de Ruby para Container Registry.

# 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.effective_severity == :HIGH || item.vulnerability.effective_severity == :CRITICAL
end

Python

Para obtener información sobre cómo instalar y usar la biblioteca cliente de Container Registry, consulta las Bibliotecas cliente de Container Registry. Si deseas obtener más información, consulta la documentación de referencia de la API de Python para Container Registry.

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.effective_severity == Severity.HIGH or v.effective_severity == Severity.CRITICAL:
            filtered_list.append(v)
    return filtered_list

Limpieza

Para evitar que se apliquen cargos a tu cuenta de Google Cloud Platform por los recursos que usaste en este instructivo, haz lo siguiente:

Borra la imagen

Si solo deseas quitar la imagen de Docker que agregaste, ejecuta el siguiente comando y bórrala de Docker de Container Registry.

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

donde: [PROJECT-ID] es el ID del proyecto de Google Cloud Console. Si el ID de tu proyecto contiene dos puntos (:), consulta Proyectos con alcance de dominio.

Borra el proyecto

La manera más fácil de eliminar la facturación es borrar el proyecto que creaste para el instructivo.

Para borrar el proyecto, sigue estos pasos:

  1. En Cloud Console, ve a la página Administrar recursos.

    Ir a la página Administrar recursos

  2. En la lista de proyectos, selecciona el proyecto que deseas borrar y haz clic en Borrar .
  3. En el cuadro de diálogo, escribe el ID del proyecto y haz clic en Cerrar para borrar el proyecto.

Qué sigue