Notifications Pub/Sub

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

Container Registry fournit des notifications via Pub/Sub chaque fois qu'il recherche des failles et d'autres métadonnées. Lorsqu'une note ou une occurrence est créée ou mise à jour, un message est publié dans le sujet correspondant pour chaque version de l'API. Utilisez le sujet correspondant à la version actuelle de votre API.

Avant de commencer

  1. Activez l'API Container Scanning.

  2. Lisez la présentation de Container Analysis.

Créer des sujets Pub/Sub

Une fois l'API Container Analysis activée, les sujets Pub/Sub suivants sont créés pour vous dans votre projet :

  • container-analysis-notes-v1 + container-analysis-occurrences-v1

Si les sujets ont été supprimés par accident ou sont manquants, vous pouvez les ajouter vous-même.

Console

  1. Accédez à la page "Sujets Pub/Sub" dans Cloud Console.

    Ouvrir la page "Sujets Pub/Sub"

  2. Cliquez sur Créer un sujet.

  3. Saisissez un sujet pour les notes avec l'URI :

    projects/[PROJECT-ID]/topics/container-analysis-notes-v1
        

    [PROJECT-ID] correspond à votre ID de projet Google Cloud.

  4. Cliquez sur Créer.

  5. Créez un autre sujet pour les occurrences avec l'URI :

     projects/[PROJECT-ID]/topics/container-analysis-occurrences-v1
        

Commande gcloud

Exécutez les commandes suivantes dans la fenêtre de votre interface système ou de votre terminal :

gcloud pubsub topics create projects/[PROJECT-ID]/topics/container-analysis-notes-v1
    gcloud pubsub topics create projects/[PROJECT-ID]/topics/container-analysis-occurrences-v1
    

Pour en savoir plus sur la commande gcloud pubsub topics, consultez la documentation sur topics.

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 Pub/Sub sont au format 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.

Créer un abonnement Pub/Sub

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

Console

  1. Accédez à la page "Abonnements Pub/Sub" dans Cloud Console.

    Ouvrir la page "Abonnements Pub/Sub"

  2. Cliquez sur Créer un abonnement.

  3. Saisissez un nom pour l'abonnement. Exemple : notes.

  4. Saisissez l'URI du sujet pour les notes :

    projects/[PROJECT-ID]/topics/container-analysis-notes-v1
        

    [PROJECT-ID] correspond à votre ID de projet Google Cloud.

  5. Cliquez sur Créer.

  6. Créez un autre abonnement pour les occurrences avec l'URI :

     projects/[PROJECT-ID]/topics/container-analysis-occurrences-v1
        

Commande gcloud

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

    gcloud pubsub subscriptions create \
        --topic container-analysis-occurrences-v1 occurrences
    

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

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

import com.google.cloud.pubsub.v1.AckReplyConsumer;
    import com.google.cloud.pubsub.v1.MessageReceiver;
    import com.google.cloud.pubsub.v1.Subscriber;
    import com.google.cloud.pubsub.v1.SubscriptionAdminClient;
    import com.google.pubsub.v1.ProjectSubscriptionName;
    import com.google.pubsub.v1.ProjectTopicName;
    import com.google.pubsub.v1.PubsubMessage;
    import com.google.pubsub.v1.PushConfig;
    import com.google.pubsub.v1.Subscription;
    import io.grpc.StatusRuntimeException;
    import java.io.IOException;
    import java.lang.InterruptedException;
    import java.util.concurrent.TimeUnit;

    public class Subscriptions {
      // Handle incoming Occurrences using a Cloud Pub/Sub subscription
      public static int pubSub(String subId, long timeoutSeconds, String projectId)
          throws InterruptedException {
        // String subId = "my-occurrence-subscription";
        // long timeoutSeconds = 20;
        // String projectId = "my-project-id";
        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();
          // Sleep to listen for messages
          TimeUnit.SECONDS.sleep(timeoutSeconds);
        } 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
      public static Subscription createOccurrenceSubscription(String subId, String projectId)
          throws IOException, StatusRuntimeException, InterruptedException {
        // This topic id will automatically receive messages when Occurrences are added or modified
        String topicId = "container-analysis-occurrences-v1";
        ProjectTopicName topicName = ProjectTopicName.of(projectId, topicId);
        ProjectSubscriptionName subName = ProjectSubscriptionName.of(projectId, subId);

        SubscriptionAdminClient client = SubscriptionAdminClient.create();
        PushConfig config = PushConfig.getDefaultInstance();
        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.


    import (
    	"context"
    	"fmt"
    	"io"
    	"sync"
    	"time"

    	pubsub "cloud.google.com/go/pubsub"
    )

    // occurrencePubsub handles incoming Occurrences using a Cloud Pub/Sub subscription.
    func occurrencePubsub(w io.Writer, subscriptionID string, timeout time.Duration, projectID string) (int, error) {
    	// subscriptionID := fmt.Sprintf("my-occurrences-subscription")
    	// timeout := time.Duration(20) * time.Second
    	ctx := context.Background()

    	var mu sync.Mutex
    	client, err := pubsub.NewClient(ctx, projectID)
    	if err != nil {
    		return -1, fmt.Errorf("pubsub.NewClient: %v", err)
    	}
    	// Subscribe to the requested Pub/Sub channel.
    	sub := client.Subscription(subscriptionID)
    	count := 0

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

    // createOccurrenceSubscription creates a new Pub/Sub subscription object listening to the Occurrence topic.
    func createOccurrenceSubscription(subscriptionID, projectID string) error {
    	// subscriptionID := fmt.Sprintf("my-occurrences-subscription")
    	ctx := context.Background()
    	client, err := pubsub.NewClient(ctx, projectID)
    	if err != nil {
    		return fmt.Errorf("pubsub.NewClient: %v", err)
    	}
    	defer client.Close()

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

Node.js

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 Node.js.

/**
     * TODO(developer): Uncomment these variables before running the sample
     */
    // const projectId = 'your-project-id', // Your GCP Project ID
    // const subscriptionId = 'my-sub-id', // A user-specified subscription to the 'container-analysis-occurrences-v1' topic
    // const timeoutSeconds = 30 // The number of seconds to listen for the new Pub/Sub Messages

    // Import the pubsub library and create a client, topic and subscription
    const {PubSub} = require('@google-cloud/pubsub');
    const pubsub = new PubSub({projectId});
    const subscription = pubsub.subscription(subscriptionId);

    // Handle incoming Occurrences using a Cloud Pub/Sub subscription
    let count = 0;
    const messageHandler = message => {
      count++;
      message.ack();
    };

    // Listen for new messages until timeout is hit
    subscription.on(`message`, messageHandler);

    setTimeout(() => {
      subscription.removeListener(`message`, messageHandler);
      console.log(`Polled ${count} occurrences`);
    }, timeoutSeconds * 1000);

Ruby

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

# subscription_id = "A user-specified identifier for the new subscription"
    # timeout_seconds = "The number of seconds to listen for new Pub/Sub
    #                    messages"
    # project_id      = "Your Google Cloud project ID"

    require "google/cloud/pubsub"

    pubsub = Google::Cloud::Pubsub.new project: project_id
    topic = pubsub.topic "container-analysis-occurrences-v1"
    subscription = topic.subscribe subscription_id

    count = 0
    subscriber = subscription.listen do |received_message|
      count += 1
      # Process incoming occurrence here
      puts "Message #{count}: #{received_message.data}"
      received_message.acknowledge!
    end
    subscriber.start
    # Wait for incomming occurrences
    sleep timeout_seconds
    subscriber.stop.wait!
    subscription.delete
    # Print and return the total number of Pub/Sub messages received
    puts "Total Messages Received: #{count}"
    count

Python

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

def pubsub(subscription_id, timeout_seconds, project_id):
        """Respond to incoming occurrences using a Cloud Pub/Sub subscription."""
        # subscription_id := 'my-occurrences-subscription'
        # timeout_seconds = 20
        # project_id = 'my-gcp-project'

        import time
        from google.cloud.pubsub import SubscriberClient

        client = SubscriberClient()
        subscription_name = client.subscription_path(project_id, subscription_id)
        receiver = MessageReceiver()
        client.subscribe(subscription_name, receiver.pubsub_callback)

        # listen for 'timeout' seconds
        for _ in range(timeout_seconds):
            time.sleep(1)
        # print and return the number of pubsub messages received
        print(receiver.msg_count)
        return receiver.msg_count

    class MessageReceiver:
        """Custom class to handle incoming Pub/Sub messages."""
        def __init__(self):
            # initialize counter to 0 on initialization
            self.msg_count = 0

        def pubsub_callback(self, message):
            # every time a pubsub message comes in, print it and count it
            self.msg_count += 1
            print('Message {}: {}'.format(self.msg_count, message.data))
            message.ack()

    def create_occurrence_subscription(subscription_id, project_id):
        """Creates a new Pub/Sub subscription object listening to the
        Container Analysis Occurrences topic."""
        # subscription_id := 'my-occurrences-subscription'
        # project_id = 'my-gcp-project'

        from google.api_core.exceptions import AlreadyExists
        from google.cloud.pubsub import SubscriberClient

        topic_id = 'container-analysis-occurrences-v1'
        client = SubscriberClient()
        topic_name = client.topic_path(project_id, topic_id)
        subscription_name = client.subscription_path(project_id, subscription_id)
        success = True
        try:
            client.create_subscription(subscription_name, topic_name)
        except AlreadyExists:
            # if subscription already exists, do nothing
            pass
        else:
            success = False
        return success

Les applications d'abonnés ne reçoivent que les messages publiés dans le sujet après la création de l'abonnement.

Étape suivante

  • 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 la fonctionnalité d'autorisation binaire à 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.