Configure notificações do Pub/Sub

Este documento descreve como configurar notificações para atualizações de notas e ocorrências.

A análise de artefactos envia notificações através do Pub/Sub para vulnerabilidades encontradas pela análise automatizada e para outros metadados. Quando uma nota ou uma ocorrência é criada ou atualizada, é publicada uma mensagem no tópico correspondente para cada versão da API. Use o tópico para a versão da API que está a usar.

Antes de começar

  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. Se estiver a usar um fornecedor de identidade (IdP) externo, primeiro, tem de iniciar sessão na CLI gcloud com a sua identidade federada.

  6. Para inicializar a CLI gcloud, execute o seguinte 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. Se estiver a usar um fornecedor de identidade (IdP) externo, primeiro, tem de iniciar sessão na CLI gcloud com a sua identidade federada.

  11. Para inicializar a CLI gcloud, execute o seguinte comando:

    gcloud init
  12. Saiba como configurar o controlo de acesso para os metadados no seu projeto. Ignore este passo se apenas consumir metadados de ocorrências de vulnerabilidades criadas pela análise de contentores do Artifact Analysis.
  13. Crie tópicos do Pub/Sub

    Depois de ativar a API Artifact Analysis, a Artifact Analysis cria automaticamente tópicos do Pub/Sub com os seguintes IDs de tópicos:

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

    Se os tópicos foram eliminados acidentalmente ou estão em falta, pode adicioná-los manualmente. Por exemplo, os tópicos podem estar em falta se a sua Google Cloud organização tiver uma restrição de política da organização que exija a encriptação com chaves de encriptação geridas pelo cliente (CMEK). Quando a API Pub/Sub está na lista de recusa desta restrição, os serviços não podem criar automaticamente tópicos comGoogle-owned and Google-managed encryption keys.

    Para criar os tópicos com a Google-owned and Google-managed encryption keys:

    Consola

    1. Aceda à página de tópicos do Pub/Sub na Google Cloud consola.

      Abra a página de tópicos do Pub/Sub

    2. Clique em Criar tópico.

    3. Introduza um ID do tópico:

      container-analysis-notes-v1
      

      para que o nome corresponda ao URI:

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

      onde PROJECT_ID é o seu Google Cloud ID do projeto.

    4. Clique em Criar.

    5. Introduza um ID do tópico:

      container-analysis-occurrences-v1
      

      para que o nome corresponda ao URI:

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

    gcloud

    Execute os seguintes comandos na shell ou na janela 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 saber mais sobre o comando gcloud pubsub topics, consulte a topics documentação.

    Para criar os tópicos com encriptação CMEK, consulte as instruções para encriptar tópicos do Pub/Sub.

    Sempre que uma nota ou uma ocorrência é criada ou atualizada, é publicada uma mensagem no tópico respetivo. No entanto, também tem de criar uma subscrição do Pub/Sub para ouvir eventos e receber mensagens do serviço Pub/Sub.

    Crie subscrições do Pub/Sub

    Para ouvir eventos, crie uma subscrição do Pub/Sub associada ao tópico:

    Consola

    1. Aceda à página de subscrições do Pub/Sub na Google Cloud consola.

      Abra a página de subscrições do Pub/Sub

    2. Clique em Criar subscrição.

    3. Escreva um nome para a subscrição. Por exemplo, notas.

    4. Introduza o URI do tópico para notas:

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

      onde PROJECT_ID é o seu Google Cloud ID do projeto.

    5. Clique em Criar.

    6. Crie outra subscrição para ocorrências com o URI:

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

    gcloud

    Para receber eventos do Pub/Sub, primeiro tem de criar uma subscrição associada ao tópico container-analysis-occurrences-v1:

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

    A partir de agora, pode obter mensagens relativas às suas ocorrências através da sua nova subscrição:

    gcloud pubsub subscriptions pull \
        --auto-ack occurrences
    

    Java

    Para saber como instalar e usar a biblioteca de cliente para a análise de artefactos, consulte o artigo Bibliotecas de cliente da análise de artefactos. Para mais informações, consulte a documentação de referência da API Artifact Analysis.Java

    Para se autenticar na Análise de artefactos, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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 como instalar e usar a biblioteca de cliente para a análise de artefactos, consulte o artigo Bibliotecas de cliente da análise de artefactos. Para mais informações, consulte a documentação de referência da API Artifact Analysis.Go

    Para se autenticar na Análise de artefactos, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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 como instalar e usar a biblioteca de cliente para a análise de artefactos, consulte o artigo Bibliotecas de cliente da análise de artefactos. Para mais informações, consulte a documentação de referência da API Artifact Analysis.Node.js

    Para se autenticar na Análise de artefactos, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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 como instalar e usar a biblioteca de cliente para a análise de artefactos, consulte o artigo Bibliotecas de cliente da análise de artefactos. Para mais informações, consulte a documentação de referência da API Artifact Analysis.Ruby

    Para se autenticar na Análise de artefactos, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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 como instalar e usar a biblioteca de cliente para a análise de artefactos, consulte o artigo Bibliotecas de cliente da análise de artefactos. Para mais informações, consulte a documentação de referência da API Artifact Analysis.Python

    Para se autenticar na Análise de artefactos, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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
    
    

    As aplicações subscritoras só recebem mensagens publicadas no tópico depois de a subscrição ser criada.

    Os payloads do Pub/Sub estão em JSON e o respetivo esquema é o seguinte:

    Notas:

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

    Ocorrências:

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

    where:

    • NOTE_KIND é um dos valores em NoteKind
    • NOTIFICATION_TIME é uma data/hora no formato "Zulu" UTC RFC 3339, precisa ao nível dos nanosegundos.

    Ver detalhes

    Para saber mais sobre uma nota ou uma ocorrência, pode aceder aos metadados armazenados na análise de artefactos. Por exemplo, pode pedir todos os detalhes de uma ocorrência específica. Consulte as instruções em Investigar vulnerabilidades.

    O que se segue?

    • Para obter instruções sobre como usar a análise de artefactos para armazenar e gerir os seus metadados personalizados, consulte Crie notas e ocorrências personalizadas.

    • Pode usar atestações com a análise de vulnerabilidades para impedir a execução de imagens com problemas de segurança conhecidos no seu ambiente de implementação. Para ver instruções sobre como o fazer, consulte o artigo, Crie atestações com o Kritis Signer.