Configure Pub/Sub notifications
Stay organized with collections
Save and categorize content based on your preferences.
This document describes how to set up notifications for updates to notes and occurrences.
Artifact Analysis provides notifications via Pub/Sub for vulnerabilities found by automated scanning and for other metadata. When a note or occurrence is created or updated, a message is published to the corresponding topic for each API version. Use the topic for the API version you are using.
Before you begin
- 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.
-
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
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
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 theserviceusage.services.enablepermission. Learn how to grant roles. -
Install the Google Cloud CLI.
-
If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.
-
To initialize the gcloud CLI, run the following command:
gcloudinit
-
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
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
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 theserviceusage.services.enablepermission. Learn how to grant roles. -
Install the Google Cloud CLI.
-
If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.
-
To initialize the gcloud CLI, run the following command:
gcloudinit
- Learn how to set up access control for metadata in your project. Skip this step if you only consume metadata from vulnerability occurrences created by Artifact Analysis container scanning.
Create Pub/Sub topics
After you activate the Artifact Analysis API, Artifact Analysis automatically creates Pub/Sub topics with the following topic IDs:
container-analysis-notes-v1container-analysis-occurrences-v1
If the topics were accidentally deleted or are missing, you can add them yourself. For example, the topics might be missing if your Google Cloud organization has an organization policy constraint that requires encryption with customer-managed encryption keys (CMEK). When the Pub/Sub API is in the deny list of this constraint, services cannot automatically create topics with Google-owned and Google-managed encryption keys.
To create the topics with Google-owned and Google-managed encryption keys:
Console
Go to the Pub/Sub topics page in the Google Cloud console.
Click Create Topic.
Enter a Topic ID:
container-analysis-notes-v1so that the name matches URI:
projects/PROJECT_ID/topics/container-analysis-notes-v1where PROJECT_ID is your Google Cloud project ID.
Click Create.
Enter a Topic ID:
container-analysis-occurrences-v1so that the name matches URI:
projects/PROJECT_ID/topics/container-analysis-occurrences-v1
gcloud
Run the following commands in your shell or terminal window:
gcloudpubsubtopicscreateprojects/PROJECT_ID/topics/container-analysis-notes-v1
gcloudpubsubtopicscreateprojects/PROJECT_ID/topics/container-analysis-occurrences-v1
To learn more about the gcloud pubsub topics command, see the
topics documentation.
To create the topics with CMEK encryption, see the Pub/Sub instructions for encrypting topics.
Anytime a note or an occurrence is created or updated, a message is published to the respective topic, though you must also create a Pub/Sub subscription to listen for events and receive messages from the Pub/Sub service.
Create Pub/Sub subscriptions
To listen to events, create a Pub/Sub subscription associated with the topic:
Console
Go to the Pub/Sub subscriptions page in the Google Cloud console.
Click Create Subscription.
Type a name for the subscription. For example, notes.
Enter the URI of the topic for notes:
projects/PROJECT_ID/topics/container-analysis-notes-v1where PROJECT_ID is your Google Cloud project ID.
Click Create.
Create another subscription for occurrences with the URI:
projects/PROJECT_ID/topics/container-analysis-occurrences-v1
gcloud
To receive Pub/Sub events, you must first create a subscription
associated with the container-analysis-occurrences-v1 topic:
gcloudpubsubsubscriptionscreate\
--topiccontainer-analysis-occurrences-v1occurrences
Going forward, you can pull messages concerning your occurrences using your new subscription:
gcloudpubsubsubscriptionspull\
--auto-ackoccurrences
Java
To learn how to install and use the client library for Artifact Analysis, see Artifact Analysis client libraries. For more information, see the Artifact Analysis Java API reference documentation.
To authenticate to Artifact Analysis, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
importcom.google.cloud.pubsub.v1.AckReplyConsumer ;
importcom.google.cloud.pubsub.v1.MessageReceiver ;
importcom.google.cloud.pubsub.v1.Subscriber ;
importcom.google.cloud.pubsub.v1.SubscriptionAdminClient ;
importcom.google.pubsub.v1.ProjectSubscriptionName ;
importcom.google.pubsub.v1.PubsubMessage ;
importcom.google.pubsub.v1.PushConfig ;
importcom.google.pubsub.v1.Subscription ;
importcom.google.pubsub.v1.SubscriptionName ;
importcom.google.pubsub.v1.TopicName ;
importio.grpc.StatusRuntimeException;
importjava.io.IOException;
importjava.lang.InterruptedException;
importjava.util.concurrent.TimeUnit;
publicclass Subscriptions{
// Handle incoming Occurrences using a Cloud Pub/Sub subscription
publicstaticintpubSub(StringsubId,longtimeoutSeconds,StringprojectId)
throwsInterruptedException{
// String subId = "my-occurrence-subscription";
// long timeoutSeconds = 20;
// String projectId = "my-project-id";
Subscriber subscriber=null;
MessageReceiverExamplereceiver=newMessageReceiverExample();
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);
returnreceiver.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
staticclass MessageReceiverExampleimplementsMessageReceiver {
publicintmessageCount=0;
@Override
publicsynchronizedvoidreceiveMessage(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
publicstaticSubscription createOccurrenceSubscription(StringsubId,StringprojectId)
throwsIOException,StatusRuntimeException,InterruptedException{
// This topic id will automatically receive messages when Occurrences are added or modified
StringtopicId="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);
returnsub;
}
}Go
To learn how to install and use the client library for Artifact Analysis, see Artifact Analysis client libraries. For more information, see the Artifact Analysis Go API reference documentation.
To authenticate to Artifact Analysis, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
import(
"context"
"fmt"
"io"
"sync"
"time"
pubsub"cloud.google.com/go/pubsub"
)
// occurrencePubsub handles incoming Occurrences using a Cloud Pub/Sub subscription.
funcoccurrencePubsub(wio.Writer,subscriptionIDstring,timeouttime.Duration,projectIDstring)(int,error){
// subscriptionID := fmt.Sprintf("my-occurrences-subscription")
// timeout := time.Duration(20) * time.Second
ctx:=context.Background()
varmusync.Mutex
client,err:=pubsub.NewClient (ctx,projectID)
iferr!=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)
defercancel()
err=sub.Receive(ctx,func(ctxcontext.Context,msg*pubsub.Message){
mu.Lock()
count=count+1
fmt.Fprintf(w,"Message %d: %q\n",count,string(msg.Data))
msg.Ack()
mu.Unlock()
})
iferr!=nil{
return-1,fmt.Errorf("sub.Receive: %w",err)
}
// Print and return the number of Pub/Sub messages received.
fmt.Fprintln(w,count)
returncount,nil
}
// createOccurrenceSubscription creates a new Pub/Sub subscription object listening to the Occurrence topic.
funccreateOccurrenceSubscription(subscriptionID,projectIDstring)error{
// subscriptionID := fmt.Sprintf("my-occurrences-subscription")
ctx:=context.Background()
client,err:=pubsub.NewClient (ctx,projectID)
iferr!=nil{
returnfmt.Errorf("pubsub.NewClient: %w",err)
}
deferclient.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)
returnfmt.Errorf("client.CreateSubscription: %w",err)
}
Node.js
To learn how to install and use the client library for Artifact Analysis, see Artifact Analysis client libraries. For more information, see the Artifact Analysis Node.js API reference documentation.
To authenticate to Artifact Analysis, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
/**
* 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');
constpubsub=newPubSub ({projectId});
constsubscription=pubsub.subscription(subscriptionId);
// Handle incoming Occurrences using a Cloud Pub/Sub subscription
letcount=0;
constmessageHandler=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
To learn how to install and use the client library for Artifact Analysis, see Artifact Analysis client libraries. For more information, see the Artifact Analysis Ruby API reference documentation.
To authenticate to Artifact Analysis, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
# 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
sleeptimeout_seconds
listener.stop.wait!
subscription_admin.delete_subscriptionsubscription:subscription.name
# Print and return the total number of Pub/Sub messages received
puts"Total Messages Received: #{count}"
countPython
To learn how to install and use the client library for Artifact Analysis, see Artifact Analysis client libraries. For more information, see the Artifact Analysis Python API reference documentation.
To authenticate to Artifact Analysis, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
importtime
fromgoogle.api_core.exceptionsimport AlreadyExists
fromgoogle.cloud.pubsubimport SubscriberClient
fromgoogle.cloud.pubsub_v1.subscriber.messageimport Message
defpubsub(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
classMessageReceiver:
"""Custom class to handle incoming Pub/Sub messages."""
def__init__(self) -> None:
# initialize counter to 0 on initialization
self.msg_count = 0
defpubsub_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 ()
defcreate_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
Subscriber applications only receive messages that are published to the topic after the subscription is created.
Pub/Sub payloads are in JSON and their schema is as follows:
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", }
where:
- NOTE_KIND is one of the values in
NoteKind - NOTIFICATION_TIME is a timestamp in RFC 3339 UTC "Zulu" format, accurate to nanoseconds.
View details
To learn more about a note or occurrence, you can access metadata stored in Artifact Analysis. For example, you can request all the details for a specific occurrence. See instructions in Investigating Vulnerabilities.
What's next
For instructions on how to use Artifact Analysis to store and manage your custom metadata, see Create custom notes and occurrences.
You can use attestations with vulnerability scanning to prevent images with known security issues from running in your deployment environment. For instructions on doing this see, Create attestations with Kritis Signer.