Configurar notificaciones de Pub/Sub

En este documento se describe cómo configurar notificaciones para recibir novedades sobre notas y repeticiones.

Artifact Analysis envía notificaciones a través de Pub/Sub sobre las vulnerabilidades detectadas por el análisis automático y otros metadatos. Cuando se crea o se actualiza una nota o una ocurrencia, se publica un mensaje en el tema correspondiente de cada versión de la API. Usa el tema de la versión de la API que estés usando.

Antes de empezar

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Enable the Container Analysis API.

    Enable the API

  4. Install the Google Cloud CLI.

  5. Si utilizas un proveedor de identidades (IdP) externo, primero debes iniciar sesión en la CLI de gcloud con tu identidad federada.

  6. Para inicializar gcloud CLI, ejecuta el siguiente comando:

    gcloud init
  7. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  8. Enable the Container Analysis API.

    Enable the API

  9. Install the Google Cloud CLI.

  10. Si utilizas un proveedor de identidades (IdP) externo, primero debes iniciar sesión en la CLI de gcloud con tu identidad federada.

  11. Para inicializar gcloud CLI, ejecuta el siguiente comando:

    gcloud init
  12. Consulta cómo configurar el control de acceso para los metadatos de tu proyecto. Omita este paso si solo utiliza metadatos de repeticiones de vulnerabilidades creadas por el análisis de contenedores de Artifact Analysis.
  13. Crear temas de Pub/Sub

    Después de activar la API Artifact Analysis, esta crea automáticamente temas de Pub/Sub con los siguientes IDs de tema:

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

    Si los temas se han eliminado por error o faltan, puedes añadirlos tú mismo. Por ejemplo, puede que falten temas si tu Google Cloud organización tiene una restricción de política de organización que requiera el encriptado con claves de encriptado gestionadas por el cliente (CMEK). Si la API Pub/Sub está en la lista de denegación de esta restricción, los servicios no podrán crear automáticamente temas conGoogle-owned and Google-managed encryption keys.

    Para crear los temas con Google-owned and Google-managed encryption keys, sigue estos pasos:

    Consola

    1. Ve a la página Temas de Pub/Sub en la Google Cloud consola.

      Abre la página Temas de Pub/Sub.

    2. Haz clic en Crear tema.

    3. Introduce un ID de tema:

      container-analysis-notes-v1
      

      para que el nombre coincida con el URI:

      projects/PROJECT_ID/topics/container-analysis-notes-v1
      

      donde PROJECT_ID es el Google Cloud ID del proyecto.

    4. Haz clic en Crear.

    5. Introduce un ID de tema:

      container-analysis-occurrences-v1
      

      para que el nombre coincida con el URI:

      projects/PROJECT_ID/topics/container-analysis-occurrences-v1
      

    gcloud

    Ejecuta los siguientes comandos en tu shell o ventana de 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
    

    Para obtener más información sobre el comando gcloud pubsub topics, consulta la documentación de topics.

    Para crear los temas con el cifrado CMEK, consulta las instrucciones para cifrar temas de Pub/Sub.

    Cada vez que se crea o se actualiza una nota o una ocurrencia, se publica un mensaje en el tema correspondiente, aunque también debes crear una suscripción de Pub/Sub para detectar eventos y recibir mensajes del servicio Pub/Sub.

    Crear suscripciones de Pub/Sub

    Para recibir eventos, crea una suscripción de Pub/Sub asociada al tema:

    Consola

    1. Ve a la página de suscripciones de Pub/Sub en la Google Cloud consola.

      Abre la página Suscripciones de Pub/Sub.

    2. Haz clic en Crear suscripción.

    3. Escribe un nombre para la suscripción. Por ejemplo, notas.

    4. Introduce el URI del tema de las notas:

      projects/PROJECT_ID/topics/container-analysis-notes-v1
      

      donde PROJECT_ID es el Google Cloud ID del proyecto.

    5. Haz clic en Crear.

    6. Crea otra suscripción para las ocurrencias con el URI:

      projects/PROJECT_ID/topics/container-analysis-occurrences-v1
      

    gcloud

    Para recibir eventos de Pub/Sub, primero debes crear una suscripción asociada al tema container-analysis-occurrences-v1:

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

    A partir de ahora, puedes extraer mensajes relacionados con tus repeticiones usando tu nueva suscripción:

    gcloud pubsub subscriptions pull \
        --auto-ack occurrences
    

    Java

    Para saber cómo instalar y usar la biblioteca de cliente de Artifact Analysis, consulta Bibliotecas de cliente de Artifact Analysis. Para obtener más información, consulta la documentación de referencia de la API Artifact Analysis Java.

    Para autenticarte en Artifact Analysis, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

    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.PubsubMessage;
    import com.google.pubsub.v1.PushConfig;
    import com.google.pubsub.v1.Subscription;
    import com.google.pubsub.v1.SubscriptionName;
    import com.google.pubsub.v1.TopicName;
    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";
        TopicName topicName = TopicName.of(projectId, topicId);
        SubscriptionName subName = SubscriptionName.of(projectId, subId);
    
        SubscriptionAdminClient client = SubscriptionAdminClient.create();
        PushConfig config = PushConfig.getDefaultInstance();
        Subscription sub = client.createSubscription(subName, topicName, config, 0);
        return sub;
      }
    }

    Go

    Para saber cómo instalar y usar la biblioteca de cliente de Artifact Analysis, consulta Bibliotecas de cliente de Artifact Analysis. Para obtener más información, consulta la documentación de referencia de la API Artifact Analysis Go.

    Para autenticarte en Artifact Analysis, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

    
    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: %w", 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: %w", 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: %w", 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: %w", err)
    }
    

    Node.js

    Para saber cómo instalar y usar la biblioteca de cliente de Artifact Analysis, consulta Bibliotecas de cliente de Artifact Analysis. Para obtener más información, consulta la documentación de referencia de la API Artifact Analysis Node.js.

    Para autenticarte en Artifact Analysis, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

    /**
     * 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

    Para saber cómo instalar y usar la biblioteca de cliente de Artifact Analysis, consulta Bibliotecas de cliente de Artifact Analysis. Para obtener más información, consulta la documentación de referencia de la API Artifact Analysis Ruby.

    Para autenticarte en Artifact Analysis, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

    # 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_id: project_id
    subscription_admin = pubsub.subscription_admin
    subscription = subscription_admin.create_subscription \
      name: pubsub.subscription_path(subscription_id),
      topic: pubsub.topic_path("container-analysis-occurrences-v1")
    
    subscriber = pubsub.subscriber subscription.name
    count = 0
    listener = subscriber.listen do |received_message|
      count += 1
      # Process incoming occurrence here
      puts "Message #{count}: #{received_message.data}"
      received_message.acknowledge!
    end
    
    listener.start
    # Wait for incoming occurrences
    sleep timeout_seconds
    listener.stop.wait!
    
    subscription_admin.delete_subscription subscription: subscription.name
    
    # Print and return the total number of Pub/Sub messages received
    puts "Total Messages Received: #{count}"
    count

    Python

    Para saber cómo instalar y usar la biblioteca de cliente de Artifact Analysis, consulta Bibliotecas de cliente de Artifact Analysis. Para obtener más información, consulta la documentación de referencia de la API Artifact Analysis Python.

    Para autenticarte en Artifact Analysis, configura las credenciales predeterminadas de la aplicación. Para obtener más información, consulta el artículo Configurar la autenticación en un entorno de desarrollo local.

    import time
    
    from google.api_core.exceptions import AlreadyExists
    from google.cloud.pubsub import SubscriberClient
    from google.cloud.pubsub_v1.subscriber.message import Message
    
    
    def pubsub(subscription_id: str, timeout_seconds: int, project_id: str) -> int:
        """Respond to incoming occurrences using a Cloud Pub/Sub subscription."""
        # subscription_id := 'my-occurrences-subscription'
        # timeout_seconds = 20
        # project_id = 'my-gcp-project'
    
        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) -> None:
            # initialize counter to 0 on initialization
            self.msg_count = 0
    
        def pubsub_callback(self, message: Message) -> None:
            # every time a pubsub message comes in, print it and count it
            self.msg_count += 1
            print(f"Message {self.msg_count}: {message.data}")
            message.ack()
    
    
    def create_occurrence_subscription(subscription_id: str, project_id: str) -> bool:
        """Creates a new Pub/Sub subscription object listening to the
        Container Analysis Occurrences topic."""
        # subscription_id := 'my-occurrences-subscription'
        # project_id = 'my-gcp-project'
    
        topic_id = "container-analysis-occurrences-v1"
        client = SubscriberClient()
        topic_name = f"projects/{project_id}/topics/{topic_id}"
        subscription_name = client.subscription_path(project_id, subscription_id)
        success = True
        try:
            client.create_subscription({"name": subscription_name, "topic": topic_name})
        except AlreadyExists:
            # if subscription already exists, do nothing
            pass
        else:
            success = False
        return success
    
    

    Las aplicaciones de suscriptor solo reciben los mensajes que se publican en el tema después de crear la suscripción.

    Las cargas útiles de Pub/Sub están en formato JSON y su esquema es el siguiente:

    Notas:

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

    Repeticiones:

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

    donde:

    • NOTE_KIND es uno de los valores de NoteKind
    • NOTIFICATION_TIME es una marca de tiempo en formato RFC 3339 UTC "Zulu", con una precisión de nanosegundos.

    Ver detalles

    Para obtener más información sobre una nota o una incidencia, puede acceder a los metadatos almacenados en Análisis de artefactos. Por ejemplo, puedes solicitar todos los detalles de un evento concreto. Consulta las instrucciones en Investigar vulnerabilidades.

    Siguientes pasos

    • Para obtener instrucciones sobre cómo usar Análisis de artefactos para almacenar y gestionar sus metadatos personalizados, consulte Crear notas y ocurrencias personalizadas.

    • Puedes usar las certificaciones con el análisis de vulnerabilidades para evitar que se ejecuten imágenes con problemas de seguridad conocidos en tu entorno de implementación. Para obtener instrucciones sobre cómo hacerlo, consulta Crear atestaciones con Kritis Signer.