Obtenir les failles et métadonnées d'images

Container Analysis fournit des informations sur les failles et d'autres types de métadonnées pour les images de conteneur dans Container Registry. Les métadonnées sont stockées sous forme de notes. Une occurrence est créée pour chaque occurrence d'une note associée à une image.

Cette page explique comment afficher, filtrer et obtenir des notifications pour les notes et les occurrences.

Avant de commencer

  1. Activez l'API Container Analysis pour le projet. L'activation de cette API déclenche une analyse automatique des failles de toutes vos images stockées dans Container Registry.

    Vous pouvez activer l'API pour un projet existant ou créer un projet, puis activer l'API.

    Activer l'API Container Analysis

  2. Activez les autorisations IAM requises.

    • Pour afficher des occurrences, vous devez avoir les autorisations suivantes :

      • containeranalysis.notes.listOccurrences

      Vous pouvez également attribuer le rôle IAM prédéfini suivant, qui accordera automatiquement toutes les autorisations nécessaires :

      • Lecteur d'occurrences d'analyse de conteneurs
    • Pour recevoir des notifications d'occurrences, vous devez configurer les autorisations Pub/Sub appropriées. Consultez les informations sur les notifications pour plus de détails.

  3. Consultez la présentation de Container Analysis.

Afficher des failles et autres occurrences

Vous pouvez afficher les occurrences de vos images dans Container Registry à l'aide de la console GCP, de l'outil de ligne de commande gcloud ou de l'API Container Analysis.

Pour afficher les occurrences de failles des images :

Console

  1. Ouvrez la page Container Registry dans la console GCP.

    Ouvrir la page "Container Registry"

  2. Cliquez sur un nom d'image.

    Le nombre total de failles par image est affiché dans la colonne Vulnerabilities (Failles).

    Capture d'écran d'une image avec des failles

  3. Pour afficher la liste des failles d'une image, cliquez sur le lien dans la colonne Vulnerabilities (Failles).

    Les informations sur la gravité, la disponibilité d'un correctif et le nom du package contenant la faille sont affichées dans la liste des failles.

  4. Pour en savoir plus sur une faille spécifique à partir de la source de la faille, cliquez sur le lien dans la colonne Documentation.

COMMANDE GCLOUD

Pour afficher un aperçu des informations sur les failles :

gcloud beta container images list-tags --show-occurrences \
    [HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]

où :

  • [PROJECT_ID] est l'ID du projet qui contient les images.
  • [IMAGE_ID] est l'ID de l'image pour laquelle vous souhaitez afficher les failles.
  • [HOSTNAME] est l'une des options décrites dans Nom du registre.

Vous ne pouvez pas spécifier de tag d'image avec cette commande.

Pour afficher des informations sur un tag ou sur une couche :

 gcloud beta container images describe [HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]:[TAG]

  or

 gcloud beta container images describe [HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]@sha256:[HASH]

où :

  • [PROJECT_ID] est l'ID du projet qui contient les images.
  • [IMAGE_ID] est l'ID de l'image pour laquelle vous souhaitez afficher les failles.
  • [TAG] est le tag d'image sur lequel vous souhaitez obtenir des informations.
  • [HASH] est le condensé de l'image.
  • [HOSTNAME] est l'une des options décrites dans Nom du registre.

Pour filtrer les occurrences de failles :

 gcloud beta container images list-tags --show-occurrences \
     [HOSTNAME]/[PROJECT_ID]/[IMAGE_ID] --occurrence-filter=[FILTER_EXPRESSION]

où :

  • [PROJECT_ID] est l'ID du projet qui contient les images.
  • [IMAGE_ID] est l'ID de l'image pour laquelle vous souhaitez afficher les occurrences de failles.
  • [FILTER_EXPRESSION] est un exemple d'expression de filtre au format expliqué dans Filtrer les occurrences de failles.
  • [HOSTNAME] est l'une des options décrites dans Nom du registre.

API

Utiliser cURL

Pour obtenir une occurrence :

 curl -X GET -H "Content-Type: application/json" -H \
    "Authorization: Bearer $(gcloud auth print-access-token)" \
    https://containeranalysis.googleapis.com/v1beta1/projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID]

Java

Pour apprendre à installer et à utiliser la bibliothèque cliente pour Container Registry, consultez la page Bibliothèques clientes Container Registry. Pour en savoir plus, consultez la documentation de référence sur l'API Container Registry en langage Java.

/**
 * Retrieves and prints a specified Occurrence from the server
 * @param client The Grafeas client used to perform the API requests.
 * @param occurrenceName the name of the Occurrence to delete
 *                       format: "projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID]"
 * @return the requested Occurrence object
 */
public static Occurrence getOccurrence(GrafeasV1Beta1Client client, String occurrenceName) {
  Occurrence occ = client.getOccurrence(occurrenceName);
  System.out.println(occ);
  return occ;
}

Go

Pour apprendre à installer et à utiliser la bibliothèque cliente pour Container Registry, consultez la page Bibliothèques clientes Container Registry. Pour en savoir plus, consultez la documentation de référence sur l'API Container Registry en langage Go.

// getOccurrence retrieves and prints a specified Occurrence from the server.
// occurrenceName should be in the following format: "projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID]"
func getOccurrence(ctx context.Context, client *containeranalysis.GrafeasV1Beta1Client, occurrenceName string) (*grafeaspb.Occurrence, error) {
	req := &grafeaspb.GetOccurrenceRequest{Name: occurrenceName}
	occ, err := client.GetOccurrence(ctx, req)
	fmt.Println(occ)
	return occ, err
}

Filtrer des occurrences

Vous pouvez utiliser des chaînes de filtre dans les commandes gcloud et l'API Container Analysis pour filtrer les occurrences avant de les afficher. Les sections ci-dessous décrivent les filtres de recherche compatibles.

Afficher les occurrences d'un type spécifique

Le champ kind (type) identifie le type d'occurrence. Utilisez ce champ pour limiter la liste des occurrences à un type particulier, tel qu'une faille ou un déploiement.

L'expression de filtre permettant de récupérer des occurrences d'un type spécifique pour une image spécifique est la suivante :

kind="[NOTE_KIND]" AND resourceUrl="[RESOURCE_URL]"

où :

  • [NOTE_KIND] est le type de note.
    • Par exemple, utilisez le type DISCOVERY pour répertorier les occurrences de découverte. Celles-ci sont créées pour les images lorsqu'elles sont initialement placées dans Container Registry.
    • Pour répertorier les occurrences de failles, utilisez le type VULNERABILITY.
  • [RESOURCE_URL] est l'URL complète de l'image https://[HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]@sha256:[HASH].

L'expression de filtre permettant de récupérer des occurrences d'un type spécifique dans de nombreuses images est la suivante :

kind="[NOTE_KIND]" AND has_prefix(resourceUrl, "[RESOURCE_URL_PREFIX]")

où :

  • [RESOURCE_URL_PREFIX] est le préfixe de l'URL pour certaines images.
    • Pour répertorier toutes les versions d’une image : https://[HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]@
    • Pour répertorier toutes les images d’un projet : https://[HOSTNAME]/[PROJECT_ID]/

Afficher les occurrences de découverte

Lorsqu'une image est initialement transférée dans Container Registry, elle crée une occurrence de découverte qui contient des informations sur l'analyse initiale de l'image de conteneur.

Pour récupérer l'occurrence de découverte d'une image, utilisez l'expression de filtre suivante :

kind="DISCOVERY" AND resourceUrl="[RESOURCE_URL]"

L'extrait suivant montre comment utiliser l'expression de filtre ci-dessus pour afficher les occurrences de découverte d'une image :

API

Pour récupérer l'occurrence de découverte, l'expression de filtre ci-dessus doit être encodée en URL et intégrée dans une requête GET comme suit :

GET https://containeranalysis.googleapis.com/v1beta1/projects/PROJECT_ID/occurrences?filter=kind%3D%22DISCOVERY%22%20AND%20resourceUrl%3D%22ENCODED_RESOURCE_URL%22

Reportez-vous au point de terminaison d'API projects.occurrences.get pour en savoir plus.

Java

Pour apprendre à installer et à utiliser la bibliothèque cliente pour Container Registry, consultez la page Bibliothèques clientes Container Registry. Pour en savoir plus, consultez la documentation de référence sur l'API Container Registry en langage Java.

/**
 * Retrieves and prints the Discovery Occurrence created for a specified image
 * The Discovery Occurrence contains information about the initial scan on the image
 * @param client The Grafeas client used to perform the API requests.
 * @param imageUrl the Container Registry URL associated with the image
 *                 example: "https://gcr.io/project/image@sha256:foo"
 * @param projectId the GCP project the image belongs to
 */
public static void getDiscoveryInfo(GrafeasV1Beta1Client client, String imageUrl,
    String projectId) {
  String filterStr = "kind=\"DISCOVERY\" AND resourceUrl=\"" + imageUrl + "\"";
  final String projectName = ProjectName.format(projectId);

  for (Occurrence o : client.listOccurrences(projectName, filterStr).iterateAll()) {
    System.out.println(o);
  }
}

Go

Pour apprendre à installer et à utiliser la bibliothèque cliente pour Container Registry, consultez la page Bibliothèques clientes Container Registry. Pour en savoir plus, consultez la documentation de référence sur l'API Container Registry en langage Go.

// getDiscoveryInfo retrieves and prints the Discovery Occurrence created for a specified image.
// The Discovery Occurrence contains information about the initial scan on the image.
func getDiscoveryInfo(ctx context.Context, client *containeranalysis.GrafeasV1Beta1Client, imageURL, projectID string) error {
	req := &grafeaspb.ListOccurrencesRequest{
		Parent: fmt.Sprintf("projects/%s", projectID),
		Filter: fmt.Sprintf(`kind="DISCOVERY" AND resourceUrl=%q`, imageURL),
	}
	it := client.ListOccurrences(ctx, req)
	for {
		occ, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return err
		}
		fmt.Println(occ)
	}
	return nil
}

Afficher les occurrences de faille

Pour afficher les occurrences de faille pour une image spécifique, créez une requête avec une expression de filtre :

kind="VULNERABILITY" AND resourceUrl="[RESOURCE_URL]"

Pour afficher toutes les occurrences d'une image, utilisez l'expression de filtre suivante :

API

L'URL de la ressource souhaitée doit être une URL encodée et intégrée dans une requête GET comme suit :

GET https://containeranalysis.googleapis.com/v1beta1/projects/PROJECT_ID/occurrences?filter=resourceUrl%3D%22ENCODED_RESOURCE_URL%22

Reportez-vous au point de terminaison d'API projects.occurrences.get pour en savoir plus.

Java

Pour apprendre à installer et à utiliser la bibliothèque cliente pour Container Registry, consultez la page Bibliothèques clientes Container Registry. Pour en savoir plus, consultez la documentation de référence sur l'API Container Registry en langage Java.

/**
 * Retrieves all the Occurrences associated with a specified image
 * Here, all Occurrences are simply printed and counted
 * @param client The Grafeas client used to perform the API requests.
 * @param imageUrl the Container Registry URL associated with the image
 *                 example: "https://gcr.io/project/image@sha256:foo"
 * @param projectId the GCP project to search for Occurrences in
 * @return number of Occurrences found
 */
public static int getOccurrencesForImage(GrafeasV1Beta1Client client, String imageUrl,
    String projectId) {
  final String filterStr = "resourceUrl=\"" + imageUrl + "\"";
  final String projectName = ProjectName.format(projectId);
  int i = 0;

  for (Occurrence o : client.listOccurrences(projectName, filterStr).iterateAll()) {
    // Write custom code to process each Occurrence here
    System.out.println(o.getName());
    i = i + 1;
  }
  return i;
}

Go

Pour apprendre à installer et à utiliser la bibliothèque cliente pour Container Registry, consultez la page Bibliothèques clientes Container Registry. Pour en savoir plus, consultez la documentation de référence sur l'API Container Registry en langage Go.

// getOccurrencesForImage retrieves all the Occurrences associated with a specified image.
// Here, all Occurrences are simply printed and counted.
func getOccurrencesForImage(ctx context.Context, client *containeranalysis.GrafeasV1Beta1Client, imageURL, projectID string) (int, error) {
	req := &grafeaspb.ListOccurrencesRequest{
		Parent: fmt.Sprintf("projects/%s", projectID),
		Filter: fmt.Sprintf("resourceUrl=%q", imageURL),
	}
	it := client.ListOccurrences(ctx, req)
	count := 0
	for {
		occ, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return -1, err
		}
		// Write custom code to process each Occurrence here.
		fmt.Println(occ)
		count = count + 1
	}
	return count, nil
}

Visualiser des images associées à une note spécifique

Vous pouvez récupérer une liste de ressources associées à un ID de note spécifique. Par exemple, vous pouvez répertorier les images avec une faille CVE spécifique.

Pour répertorier toutes les images d'un projet associées à une note particulière, utilisez l'expression de filtre suivante :

noteProjectId="[PROVIDER_PROJECT_ID]" AND noteId="[NOTE_ID]"

Pour consulter une image spécifique pour une note spécifique, utilisez l'expression de filtre suivante :

resourceUrl="[RESOURCE_URL]" AND noteProjectId="[PROVIDER_PROJECT_ID]" \
    AND noteId="[NOTE_ID]"

où :

  • [PROVIDER_PROJECT_ID] est l'ID du projet du fournisseur. Par exemple, goog-vulnz fournit l'analyse de faille par défaut.
  • [NOTE_ID] est l'ID de la note. Les notes relatives à la sécurité sont souvent au format CVE-2019-12345.
  • [RESOURCE_URL] est l'URL complète de l'image https://[HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]@sha256:[HASH].

Par exemple, pour vérifier que toutes les images ayant une occurrence de CVE-2017-16231 ont été analysées par Google, utilisez l'expression de filtre suivante :

noteProjectId="goog-vulnz" AND noteId="CVE-2017-16231"

Afficher les déploiements

Vous pouvez répertorier les déploiements en cours d'exécution ou en cours d'exécution pendant une période spécifiée.

Pour afficher les déploiements en cours d'exécution, utilisez l'expression de filtre suivante :

kind="DEPLOYABLE" AND resourceUrl="[RESOURCE_URL]" AND \
    isNull(deployment.undeployTime)

Pour afficher les déploiements en cours d'exécution pendant une période spécifique, utilisez l'expression de filtre suivante :

kind="DEPLOYABLE" AND resourceUrl="[RESOURCE_URL]" AND \
    deployment.deployTime<"[DEPLOY_TIME]" AND \
    deployment.undeployTime>"[UNDEPLOY_TIME]"

où :

  • [RESOURCE_URL] est l'URL complète de l'image https://[HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]@sha256:[HASH].
  • [DEPLOY_TIME] est l'heure de début de la période de déploiement. Cet élément utilise un horodatage au format RFC 3339 UTC "Zulu", précis à la nanoseconde près. Exemple : "2014-10-02T15:01:23.045123456Z".
  • [UNDEPLOY_TIME] correspond à la fin de la période de déploiement. Cet élément utilise un horodatage au format RFC 3339 UTC "Zulu", précis à la nanoseconde près.

Notifications Cloud Pub/Sub

Pour recevoir des notifications, vous devez configurer les autorisations IAM appropriées. Pour plus d'informations sur les autorisations et les rôles requis, reportez-vous aux informations sur le contrôle d'accès Pub/Sub.

Cette section explique comment configurer les notifications pour les mises à jour de notes et d'occurrences.

Container Registry fournit des notifications via Cloud Pub/Sub chaque fois qu'il recherche des failles et d'autres métadonnées. Une fois l'API Container Analysis activée, les sujets Cloud Pub/Sub suivants sont créés pour vous dans votre projet :

  • container-analysis-notes-v1beta1
  • container-analysis-occurrences-v1beta1

Chaque fois qu'une note ou une occurrence est créée ou mise à jour, un message est publié dans le sujet correspondant.

Les charges utiles Cloud Pub/Sub sont en JSON et leur schéma se présente comme suit :

Notes :

{
    "name": "projects/[PROJECT_ID]/notes/[NOTE_ID]",
    "kind": "[NOTE_KIND]",
    "notificationTime": "[NOTIFICATION_TIME]",
}

Occurrences :

{
    "name": "projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID]",
    "kind": "[NOTE_KIND]",
    "notificationTime": "[NOTIFICATION_TIME]",
}

où :

  • [NOTE_KIND] est l'une des valeurs de NoteKind.
  • [NOTIFICATION_TIME] est un horodatage au format RFC 3339 UTC "Zulu", précis à la nanoseconde près.

Pour écouter ces événements, créez un abonnement Pub/Sub associé au sujet :

API

Pour recevoir des événements Cloud Pub/Sub, vous devez d'abord créer un abonnement associé au sujet container-analysis-occurrences-v1beta1 :

gcloud beta pubsub subscriptions create \
    --topic container-analysis-occurrences-v1beta1 occurrences

Vous pouvez ensuite récupérer des messages concernant vos occurrences à l'aide de votre nouvel abonnement :

gcloud beta pubsub subscriptions pull \
    --auto-ack occurrences

Java

Pour apprendre à installer et à utiliser la bibliothèque cliente pour Container Registry, consultez la page Bibliothèques clientes Container Registry. Pour en savoir plus, consultez la documentation de référence sur l'API Container Registry en langage Java.

/**
 * Handle incoming Occurrences using a Cloud Pub/Sub subscription
 * @param subId the user-specified identifier for the Pub/Sub subscription
 * @param timeout the amount of time to listen for Pub/Sub messages (in seconds)
 * @param projectId the GCP project the Pub/Sub subscription belongs to
 * @return number of Occurrence Pub/Sub messages received before exiting
 * @throws InterruptedException on errors with the subscription client
 */
public static int pubSub(String subId, int timeout, String projectId)
    throws InterruptedException {
  Subscriber subscriber = null;
  MessageReceiverExample receiver = new MessageReceiverExample();

  try {
    // Subscribe to the requested Pub/Sub channel
    ProjectSubscriptionName subName = ProjectSubscriptionName.of(projectId, subId);
    subscriber = Subscriber.newBuilder(subName, receiver).build();
    subscriber.startAsync().awaitRunning();
    // Listen to messages for 'timeout' seconds
    for (int i = 0; i < timeout; i++) {
      sleep(1000);
    }
  } finally {
    // Stop listening to the channel
    if (subscriber != null) {
      subscriber.stopAsync();
    }
  }
  // Print and return the number of Pub/Sub messages received
  System.out.println(receiver.messageCount);
  return receiver.messageCount;
}

/**
 * Custom class to handle incoming Pub/Sub messages
 * In this case, the class will simply log and count each message as it comes in
 */
static class MessageReceiverExample implements MessageReceiver {
  public int messageCount = 0;

  @Override
  public synchronized void receiveMessage(PubsubMessage message, AckReplyConsumer consumer) {
    // Every time a Pub/Sub message comes in, print it and count it
    System.out.println("Message " + messageCount + ": " + message.getData().toStringUtf8());
    messageCount += 1;
    // Acknowledge the message
    consumer.ack();
  }
}

/**
 * Creates and returns a Pub/Sub subscription object listening to the Occurrence topic
 * @param subId the identifier you want to associate with the subscription
 * @param projectId the GCP project to create the subscription under
 * @throws IOException thrown on errors with the subscription client
 * @throws StatusRuntimeException if subscription already exists
 *
 */
public static Subscription createOccurrenceSubscription(String subId, String projectId)
    throws IOException, StatusRuntimeException {
  // This topic id will automatically receive messages when Occurrences are added or modified
  String topicId = "container-analysis-occurrences-v1beta1";
  SubscriptionAdminClient client = SubscriptionAdminClient.create();
  PushConfig config = PushConfig.getDefaultInstance();
  ProjectTopicName topicName = ProjectTopicName.of(projectId, topicId);
  ProjectSubscriptionName subName = ProjectSubscriptionName.of(projectId, subId);
  Subscription sub = client.createSubscription(subName, topicName, config, 0);
  return sub;
} 

Go

Pour apprendre à installer et à utiliser la bibliothèque cliente pour Container Registry, consultez la page Bibliothèques clientes Container Registry. Pour en savoir plus, consultez la documentation de référence sur l'API Container Registry en langage Go.

// occurrencePubsub handles incoming Occurrences using a Cloud Pub/Sub subscription.
func occurrencePubsub(ctx context.Context, subscriptionID string, timeout int, projectID string) (int, error) {
	var mu sync.Mutex
	client, err := pubsub.NewClient(ctx, projectID)
	if err != nil {
		return -1, err
	}
	// Subscribe to the requested Pub/Sub channel.
	sub := client.Subscription(subscriptionID)
	count := 0

	// Listen to messages for 'timeout' seconds.
	toctx, cancel := context.WithTimeout(ctx, time.Duration(timeout)*time.Second)
	defer cancel()
	err = sub.Receive(toctx, func(ctx context.Context, msg *pubsub.Message) {
		mu.Lock()
		count = count + 1
		fmt.Printf("Message %d: %q\n", count, string(msg.Data))
		msg.Ack()
		mu.Unlock()
	})
	if err != nil {
		return -1, err
	}
	// Print and return the number of Pub/Sub messages received.
	fmt.Println(count)
	return count, nil
}

// createOccurrenceSubscription creates and returns a Pub/Sub subscription object listening to the Occurrence topic.
func createOccurrenceSubscription(ctx context.Context, subscriptionID, projectID string) error {
	client, err := pubsub.NewClient(ctx, projectID)
	if err != nil {
		return err
	}

	// This topic id will automatically receive messages when Occurrences are added or modified
	topicID := "container-analysis-occurrences-v1beta1"
	topic := client.Topic(topicID)
	config := pubsub.SubscriptionConfig{Topic: topic}
	_, err = client.CreateSubscription(ctx, subscriptionID, config)
	return err
}

Seuls les messages publiés dans le sujet après la création de l'abonnement sont disponibles pour les applications d'abonnés.

Étapes suivantes

  • Pour obtenir des instructions sur l'utilisation de Container Analysis afin de stocker et gérer les métadonnées de vos clients, consultez la page Fournir des métadonnées pour les images.

  • Vous pouvez intégrer Binary Authorization à l'analyse des failles afin d'éviter que les images présentant des problèmes de sécurité connus ne s'exécutent dans votre environnement de déploiement. Pour obtenir des instructions à ce sujet, consultez la page Intégration de l'analyse des failles.

Cette page vous a-t-elle été utile ? Évaluez-la :

Envoyer des commentaires concernant…

Container Registry