Configurar notificações do Pub/Sub

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

O Artifact Analysis fornece notificações via Pub/Sub para vulnerabilidades encontradas por verificações automáticas e para outros metadados. Quando uma nota ou ocorrência é criada ou atualizada, uma mensagem é publicada no tópico correspondente para cada versão da API. Use o tópico da versão da API que você está usando.

Antes de começar

  1. Faça login na sua Google Cloud conta do. Se você começou a usar o Google Cloud, crie uma conta para avaliar o desempenho dos nossos produtos em situações reais. Clientes novos também recebem US $300 em créditos para executar, testar e implantar cargas de trabalho.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Enable the Container Analysis API.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the API

  4. Instale a Google Cloud CLI.

  5. Ao usar um provedor de identidade (IdP) externo, primeiro faça login na gcloud CLI com 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.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  8. Enable the Container Analysis API.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the API

  9. Instale a Google Cloud CLI.

  10. Ao usar um provedor de identidade (IdP) externo, primeiro faça login na gcloud CLI com sua identidade federada.

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

    gcloud init
  12. Saiba como configurar o controle de acesso para metadados no seu projeto. Pule esta etapa se você consumir apenas metadados de ocorrências criadas pela verificação de contêineres do Artifact Analysis scanning.

Criar tópicos Pub/Sub

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

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

Se os tópicos foram excluídos acidentalmente ou estão ausentes, você mesmo pode adicioná-los. Por exemplo, os tópicos podem estar ausentes se a Google Cloud organização tiver uma restrição de política da organização que exige criptografia com chaves de criptografia gerenciadas pelo cliente (CMEK). Quando a API Pub/Sub está na lista de bloqueio dessa restrição, os serviços não podem criar tópicos automaticamente com Google-owned and Google-managed encryption keys.

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

Console

  1. Acesse a página de tópicos do Pub/Sub no Google Cloud console.

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

  2. Clique em Criar tópico.

  3. Insira um ID de tópico:

    container-analysis-notes-v1
    

    para que o nome corresponda ao URI:

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

    em que PROJECT_ID é o Google Cloud ID do projeto.

  4. Clique em Criar.

  5. Insira um ID de 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 no shell ou na janela do 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 criptografia CMEK, consulte as instruções do Pub/Sub para criptografar tópicos.

Sempre que uma nota ou ocorrência for criada ou atualizada, uma mensagem será publicada no respectivo tópico. No entanto, você também precisa criar uma assinatura do Pub/Sub para ouvir eventos e receber mensagens do serviço do Pub/Sub.

Criar assinaturas do Pub/Sub

Para ouvir eventos, crie uma assinatura do Pub/Sub associada ao tópico:

Console

  1. Acesse a página de assinaturas do Pub/Sub no Google Cloud console.

    Abrir a página de assinaturas do Pub/Sub

  2. Clique em Criar assinatura.

  3. Digite um nome para a assinatura. Por exemplo, notas.

  4. Insira o URI do tópico para as notas:

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

    em que PROJECT_ID é o Google Cloud ID do projeto.

  5. Clique em Criar.

  6. Crie outra assinatura para ocorrências com o URI:

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

gcloud

Para receber eventos Pub/Sub, você deve primeiro criar uma inscrição associada ao tópico container-analysis-occurrences-v1:

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

No futuro, você pode extrair mensagens sobre suas ocorrências usando sua nova assinatura:

gcloud pubsub subscriptions pull \
    --auto-ack occurrences

Java

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

Para autenticar no Artifact Analysis, configure o Application Default Credentials. Se quiser mais informações, consulte Configurar 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 do Artifact Analysis, consulte Bibliotecas de cliente do Artifact Analysis. Para mais informações, consulte a documentação de referência da APIGo do Artifact Analysis.

Para autenticar no Artifact Analysis, configure o Application Default Credentials. Se quiser mais informações, consulte Configurar 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 do Artifact Analysis, consulte Bibliotecas de cliente do Artifact Analysis. Para mais informações, consulte a documentação de referência da APINode.js do Artifact Analysis.

Para autenticar no Artifact Analysis, configure o Application Default Credentials. Se quiser mais informações, consulte Configurar 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 do Artifact Analysis, consulte Bibliotecas de cliente do Artifact Analysis. Para mais informações, consulte a documentação de referência da APIRuby do Artifact Analysis.

Para autenticar no Artifact Analysis, configure o Application Default Credentials. Se quiser mais informações, consulte Configurar 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 do Artifact Analysis, consulte Bibliotecas de cliente do Artifact Analysis. Para mais informações, consulte a documentação de referência da API Artifact Analysis Python.

Para autenticar no Artifact Analysis, configure o Application Default Credentials. Se quiser mais informações, consulte Configurar 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

Os aplicativos de assinante recebem apenas mensagens que são publicadas no tópico após a criação da assinatura.

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

Observações:

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

em que:

  • NOTE_KIND é um dos valores em NoteKind
  • NOTIFICATION_TIME é um carimbo de data/hora no formato UTC “Zulu” RFC 3339, medido com precisão de nanossegundos.

Ver detalhes

Para saber mais sobre uma observação ou ocorrência, acesse os metadados armazenados no Artifact Analysis. Por exemplo, você pode solicitar todos os detalhes de uma ocorrência específica. Consulte as instruções em Investigar vulnerabilidades.

A seguir