הגדרת התראות ב-Pub/Sub

במאמר הזה מוסבר איך להגדיר התראות על עדכונים בהערות ובמופעים.

השירות Artifact Analysis שולח התראות באמצעות Pub/Sub לגבי פגיעויות שנמצאו על ידי סריקה אוטומטית ולגבי מטא-נתונים אחרים. כשנוצרת או מתעדכנת הערה או התרחשות, מתפרסמת הודעה בנושא המתאים לכל גרסת API. צריך להשתמש בנושא של גרסת ה-API שבה אתם משתמשים.

לפני שמתחילים

  1. נכנסים לחשבון Google Cloud . אם אתם משתמשים חדשים ב- Google Cloud, צרו חשבון כדי שתוכלו להעריך את הביצועים של המוצרים שלנו בתרחישים מהעולם האמיתי. לקוחות חדשים מקבלים בחינם גם קרדיט בשווי 300$ להרצה, לבדיקה ולפריסה של עומסי העבודה.
  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. התקינו את ה-CLI של Google Cloud.

  5. אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.

  6. כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:

    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. התקינו את ה-CLI של Google Cloud.

  10. אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.

  11. כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:

    gcloud init
  12. כך מגדירים בקרת גישה למטא-נתונים בפרויקט. אפשר לדלג על השלב הזה אם אתם צורכים מטא-נתונים רק ממופעים שנוצרו על ידי סריקת קונטיינרים של Artifact Analysis.

יצירת נושאים ב-Pub/Sub

אחרי שמפעילים את Artifact Analysis API,‏ Artifact Analysis יוצר באופן אוטומטי נושאי Pub/Sub עם מזהי הנושאים הבאים:

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

אם הנושאים נמחקו בטעות או שהם חסרים, אתם יכולים להוסיף אותם בעצמכם. לדוגמה, יכול להיות שהנושאים לא יופיעו אם Google Cloud בארגון שלכם יש אילוץ של מדיניות הארגון שדורש הצפנה באמצעות מפתחות הצפנה בניהול הלקוח (CMEK). אם Pub/Sub API נמצא ברשימת הדחייה של האילוץ הזה, השירותים לא יכולים ליצור נושאים באופן אוטומטי עםGoogle-owned and Google-managed encryption keys.

כדי ליצור את הנושאים באמצעות Google-owned and Google-managed encryption keys:

המסוף

  1. נכנסים לדף הנושאים של Pub/Sub במסוף Google Cloud .

    פתיחת הדף Pub/Sub topics

  2. לוחצים על יצירת נושא.

  3. מזינים מזהה נושא:

    container-analysis-notes-v1
    

    כך שהשם יתאים ל-URI:

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

    כאשר PROJECT_ID הוא מזהה הפרויקט. Google Cloud

  4. לוחצים על יצירה.

  5. מזינים מזהה נושא:

    container-analysis-occurrences-v1
    

    כך שהשם יתאים ל-URI:

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

gcloud

מריצים את הפקודות הבאות במעטפת או בחלון הטרמינל:

gcloud pubsub topics create projects/PROJECT_ID/topics/container-analysis-notes-v1
gcloud pubsub topics create projects/PROJECT_ID/topics/container-analysis-occurrences-v1

מידע נוסף על הפקודה gcloud pubsub topics זמין במסמכי התיעוד של topics.

כדי ליצור את הנושאים עם הצפנת CMEK, אפשר לעיין בהוראות להצפנת נושאים ב-Pub/Sub.

בכל פעם שיוצרים או מעדכנים הערה או מופע, מתפרסמת הודעה בנושא המתאים. עם זאת, צריך גם ליצור מינוי ל-Pub/Sub כדי להאזין לאירועים ולקבל הודעות משירות Pub/Sub.

יצירת מינויים ל-Pub/Sub

כדי להאזין לאירועים, צריך ליצור מינוי Pub/Sub שמשויך לנושא:

המסוף

  1. נכנסים לדף המינויים של Pub/Sub במסוףGoogle Cloud .

    פתיחת הדף Pub/Sub subscriptions

  2. לוחצים על יצירת מינוי.

  3. מקלידים שם למינוי. לדוגמה, notes.

  4. מזינים את ה-URI של הנושא להערות:

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

    כאשר PROJECT_ID הוא מזהה הפרויקט. Google Cloud

  5. לוחצים על יצירה.

  6. יוצרים מינוי נוסף למקרים עם ה-URI:

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

gcloud

כדי לקבל אירועים מ-Pub/Sub, צריך קודם ליצור מינוי שמשויך לנושא container-analysis-occurrences-v1:

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

מעכשיו, תוכלו לשלוף הודעות שקשורות למקרים באמצעות המינוי החדש:

gcloud pubsub subscriptions pull \
    --auto-ack occurrences

Java

מידע על התקנת ספריית הלקוח של Artifact Analysis ושימוש בה מופיע במאמר ספריות הלקוח של Artifact Analysis. מידע נוסף מופיע במאמרי העזרה של Artifact Analysis Java API.

כדי לבצע אימות ב-Artifact Analysis, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

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

מידע על התקנת ספריית הלקוח של Artifact Analysis ושימוש בה מופיע במאמר ספריות הלקוח של Artifact Analysis. מידע נוסף מופיע במאמרי העזרה של Artifact Analysis Go API.

כדי לבצע אימות ב-Artifact Analysis, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.


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

מידע על התקנת ספריית הלקוח של Artifact Analysis ושימוש בה מופיע במאמר ספריות הלקוח של Artifact Analysis. מידע נוסף מופיע במאמרי העזרה של Artifact Analysis Node.js API.

כדי לבצע אימות ב-Artifact Analysis, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

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

מידע על התקנת ספריית הלקוח של Artifact Analysis ושימוש בה מופיע במאמר ספריות הלקוח של Artifact Analysis. מידע נוסף מופיע במאמרי העזרה של Artifact Analysis Ruby API.

כדי לבצע אימות ב-Artifact Analysis, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

# 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

מידע על התקנת ספריית הלקוח של Artifact Analysis ושימוש בה מופיע במאמר ספריות הלקוח של Artifact Analysis. מידע נוסף מופיע במאמרי העזרה של Artifact Analysis Python API.

כדי לבצע אימות ב-Artifact Analysis, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

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

אפליקציות של מנויים מקבלות רק הודעות שפורסמו בנושא אחרי שהמינוי נוצר.

המטען הייעודי (payload) של Pub/Sub הוא בפורמט JSON והסכימה שלו היא כדלקמן:

הערות:

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

חזרות:

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

where:

  • NOTE_KIND הוא אחד מהערכים ב-NoteKind
  • NOTIFICATION_TIME היא חותמת זמן בפורמט RFC 3339 UTC ‏'Zulu', עם דיוק של ננו-שניות.

לפרטים

כדי לקבל מידע נוסף על הערה או על מופע, אפשר לגשת למטא-נתונים שמאוחסנים ב-Artifact Analysis. לדוגמה, אפשר לבקש את כל הפרטים של אירוע ספציפי. הוראות מפורטות זמינות במאמר בדיקת חולשות.

המאמרים הבאים