イメージの脆弱性情報を取得

は、

Container Analysis は、Container Registry 内のコンテナ イメージの脆弱性情報を提供します

このページでは、Container Registry のイメージの脆弱性の表示、フィルタリング、通知の方法について説明します。

はじめに

  1. プロジェクトで Container Analysis API を有効にします。既存のプロジェクトについて API を有効化することも、新しいプロジェクトを作成してから API を有効化することもできます。

    Container Analysis API を有効にする

  2. Container Registry ページの設定で脆弱性スキャンを有効にします。

    脆弱性スキャンを有効にする

  3. Container Analysis の概要をお読みください。

コンテナ イメージの脆弱性オカレンスの表示

Container Registry 内のイメージの脆弱性オカレンスを表示するには、GCP Console、gcloud コマンドライン ツール、Container Analysis API を使用します。

IAM 権限

このタスクを実行するには、次の IAM 権限が必要です。

  • containeranalysis.notes.listOccurrences

または、必要な権限が自動的に付与されるように、次の事前定義された IAM の役割を付与することもできます。

  • Container Analysis 実行回数の閲覧者

イメージの脆弱性オカレンスを表示するには:

Console

  1. GCP Console で Container Registry ページを開きます。

    Container Registry ページを開く

  2. イメージ名をクリックします。

    イメージの脆弱性が [脆弱性] 列に表示されます。

    脆弱性のあるイメージのスクリーンショット

  3. 脆弱性をクリックすると、詳細が表示されます。

gcloud コマンド

脆弱性情報の概要を表示するには:

gcloud beta container images list-tags --show-occurrences \
    [HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]

ここで

  • [PROJECT_ID] は、イメージを含むプロジェクトの ID です。
  • [IMAGE_ID] は、脆弱性を表示するイメージの ID です。
  • [HOSTNAME] は、レジストリ名で説明されているオプションの 1 つです。

タグまたはレイヤに関する情報を表示するには:

 gcloud beta container images describe [HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]:[TAG]

  or

 gcloud beta container images describe [HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]@sha256:[HASH]

ここで

  • [PROJECT_ID] は、イメージを含むプロジェクトの ID です。
  • [IMAGE_ID] は、脆弱性を表示するイメージの ID です。
  • [TAG] は、情報を取得するイメージのタグです。
  • [HASH] は、イメージのダイジェストです。
  • [HOSTNAME] は、レジストリ名で説明されているオプションの 1 つです。

脆弱性オカレンスをフィルタするには:

 gcloud beta container images list-tags --show-occurrences \
     [HOSTNAME]/[PROJECT_ID]/[IMAGE_ID] --occurrence-filter=[FILTER_EXPRESSION]

ここで

  • [PROJECT_ID] は、イメージを含むプロジェクトの ID です。
  • [IMAGE_ID] は、脆弱性オカレンスを表示するイメージの ID です。
  • [FILTER_EXPRESSION] は、脆弱性オカレンスのフィルタで説明されている形式のサンプル フィルタ式です。
  • [HOSTNAME] は、レジストリ名で説明されているオプションの 1 つです。

API

cURL を使用する

発生個所を取得するには:

 curl -X GET -H "Content-Type: application/json" -H \
    "Authorization: Bearer $(gcloud auth print-access-token)" \
    https://containeranalysis.googleapis.com/v1beta1/projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID]

Java

Container Registry 用のクライアント ライブラリをインストールして使用する方法については、Container Registry のクライアント ライブラリをご覧ください。詳細については、Container Registry Java API のリファレンス ドキュメントをご覧ください。

/**
 * Retrieves and prints a specified Occurrence from the server
 * @param client The Grafeas client used to perform the API requests.
 * @param occurrenceName the name of the Occurrence to delete
 *                       format: "projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID]"
 * @return the requested Occurrence object
 */
public static Occurrence getOccurrence(GrafeasV1Beta1Client client, String occurrenceName) {
  Occurrence occ = client.getOccurrence(occurrenceName);
  System.out.println(occ);
  return occ;
}

Go

Container Registry 用のクライアント ライブラリをインストールして使用する方法については、Container Registry のクライアント ライブラリをご覧ください。詳細については、Container Registry Go API のリファレンス ドキュメントをご覧ください。

// getOccurrence retrieves and prints a specified Occurrence from the server.
// occurrenceName should be in the following format: "projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID]"
func getOccurrence(ctx context.Context, client *containeranalysis.GrafeasV1Beta1Client, occurrenceName string) (*grafeaspb.Occurrence, error) {
	req := &grafeaspb.GetOccurrenceRequest{Name: occurrenceName}
	occ, err := client.GetOccurrence(ctx, req)
	fmt.Println(occ)
	return occ, err
}

脆弱性オカレンスのフィルタリング

gcloud コマンドと Container Analysis API でフィルタ文字列を使用して、脆弱性オカレンスを絞り込んでから表示することができます。次のフィールドの値に基づいてオカレンスを照会することができます。

  • occurrenceId
  • noteId
  • noteProjectId
  • resourceUrl
  • kind
  • createTime
  • updateTime

たとえば、gcr.io ホスト内のリソース URL のすべての脆弱性オカレンスを一覧表示するには、次のフィルタ文字列を使用します。

kind="PACKAGE_VULNERABILITY" \
    AND has_prefix(resource_url, "https://gcr.io/path/to/resource")

検出オカレンスの表示

イメージが Container Registry に最初に push されるときに、コンテナ イメージの初期スキャンに関する情報を含めた検出オカレンスが作成されます。

IAM 権限

このタスクを実行するには、次の IAM 権限が必要です。

  • containeranalysis.notes.listOccurrences

または、必要な権限が自動的に付与されるように、次の事前定義された IAM の役割の 1 つを付与することもできます。

  • Container Analysis 実行回数の閲覧者

検出オカレンスを表示するには:

イメージの検出オカレンスを取得するには、次のフィルタ式を使用します。

kind="DISCOVERY" AND resourceUrl="[RESOURCE_URL]"

次のスニペットでは、上記のフィルタ式を使用してイメージの検出オカレンスを表示する方法を示しています。

API

検出オカレンスを取得するには、次のように上記のフィルタ式を URL エンコード型にして、GET リクエストに埋め込む必要があります。

GET https://containeranalysis.googleapis.com/v1beta1/projects/PROJECT_ID/occurrences?filter=kind%3D%22DISCOVERY%22%20AND%20resourceUrl%3D%22ENCODED_RESOURCE_URL%22

詳しくは、projects.occurrences.get API エンドポイントをご覧ください。

Java

Container Registry 用のクライアント ライブラリをインストールして使用する方法については、Container Registry のクライアント ライブラリをご覧ください。詳細については、Container Registry Java API のリファレンス ドキュメントをご覧ください。

/**
 * Retrieves and prints the Discovery Occurrence created for a specified image
 * The Discovery Occurrence contains information about the initial scan on the image
 * @param client The Grafeas client used to perform the API requests.
 * @param imageUrl the Container Registry URL associated with the image
 *                 example: "https://gcr.io/project/image@sha256:foo"
 * @param projectId the GCP project the image belongs to
 */
public static void getDiscoveryInfo(GrafeasV1Beta1Client client, String imageUrl,
    String projectId) {
  String filterStr = "kind=\"DISCOVERY\" AND resourceUrl=\"" + imageUrl + "\"";
  final String projectName = ProjectName.format(projectId);

  for (Occurrence o : client.listOccurrences(projectName, filterStr).iterateAll()) {
    System.out.println(o);
  }
}

Go

Container Registry 用のクライアント ライブラリをインストールして使用する方法については、Container Registry のクライアント ライブラリをご覧ください。詳細については、Container Registry Go API のリファレンス ドキュメントをご覧ください。

// getDiscoveryInfo retrieves and prints the Discovery Occurrence created for a specified image.
// The Discovery Occurrence contains information about the initial scan on the image.
func getDiscoveryInfo(ctx context.Context, client *containeranalysis.GrafeasV1Beta1Client, imageURL, projectID string) error {
	filterStr := `kind="DISCOVERY" AND resourceUrl="` + imageURL + `"`
	projectName := "projects/" + projectID

	req := &grafeaspb.ListOccurrencesRequest{
		Parent: projectName,
		Filter: filterStr,
	}
	it := client.ListOccurrences(ctx, req)
	for {
		occ, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return err
		}
		fmt.Println(occ)
	}
	return nil
}

イメージのすべてのオカレンスの表示

IAM 権限

このタスクを実行するには、次の IAM 権限が必要です。

  • containeranalysis.notes.listOccurrences

または、必要な権限が自動的に付与されるように、次の事前定義された IAM の役割の 1 つを付与することもできます。

  • Container Analysis 実行回数の閲覧者

イメージのすべてのオカレンスを表示するには:

特定のコンテナ イメージに対して検出されたすべてのオカレンスを表示するには、フィルタ式を使用してクエリを作成します。

kind="PACKAGE_VULNERABILITY" \
    AND has_prefix(resource_url, "https://[HOSTNAME]/path/to/resource")

次のスニペットでは、上記のフィルタ式を使用してイメージのすべてのオカレンスを表示する方法を示しています。

API

必要なリソース URL は、次のように URL エンコード型にして、GET リクエストに埋め込む必要があります。

GET https://containeranalysis.googleapis.com/v1beta1/projects/PROJECT_ID/occurrences?filter=resourceUrl%3D%22ENCODED_RESOURCE_URL%22

詳しくは、projects.occurrences.get API エンドポイントをご覧ください。

Java

Container Registry 用のクライアント ライブラリをインストールして使用する方法については、Container Registry のクライアント ライブラリをご覧ください。詳細については、Container Registry Java API のリファレンス ドキュメントをご覧ください。

/**
 * Retrieves all the Occurrences associated with a specified image
 * Here, all Occurrences are simply printed and counted
 * @param client The Grafeas client used to perform the API requests.
 * @param imageUrl the Container Registry URL associated with the image
 *                 example: "https://gcr.io/project/image@sha256:foo"
 * @param projectId the GCP project to search for Occurrences in
 * @return number of Occurrences found
 */
public static int getOccurrencesForImage(GrafeasV1Beta1Client client, String imageUrl,
    String projectId) {
  final String filterStr = "resourceUrl=\"" + imageUrl + "\"";
  final String projectName = ProjectName.format(projectId);
  int i = 0;

  for (Occurrence o : client.listOccurrences(projectName, filterStr).iterateAll()) {
    // Write custom code to process each Occurrence here
    System.out.println(o.getName());
    i = i + 1;
  }
  return i;
}

Go

Container Registry 用のクライアント ライブラリをインストールして使用する方法については、Container Registry のクライアント ライブラリをご覧ください。詳細については、Container Registry Go API のリファレンス ドキュメントをご覧ください。

// getOccurrencesForImage retrieves all the Occurrences associated with a specified image.
// Here, all Occurrences are simply printed and counted.
func getOccurrencesForImage(ctx context.Context, client *containeranalysis.GrafeasV1Beta1Client, imageURL, projectID string) (int, error) {
	filterStr := `resourceUrl="` + imageURL + `"`
	project := "projects/" + projectID

	req := &grafeaspb.ListOccurrencesRequest{
		Parent: project,
		Filter: filterStr,
	}
	it := client.ListOccurrences(ctx, req)
	count := 0
	for {
		occ, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return -1, err
		}
		// Write custom code to process each Occurrence here.
		fmt.Println(occ)
		count = count + 1
	}
	return count, nil
}

Cloud Pub/Sub の通知

IAM 権限: このタスクを実行するには、適切な IAM 権限が必要です。必要な権限と役割の詳細については、PUB/ SUB で使用する IAM 権限をご覧ください。

Container Registry は、脆弱性のスキャン時に Cloud Pub/Sub 経由で通知を送信します。Container Analysis API を有効にすると、次の Cloud Pub/Sub トピックがプロジェクトに作成されます。

  • container-analysis-notes-v1beta1
  • container-analysis-occurrences-v1beta1

注記または発生個所が作成または更新されるたびに、それぞれのトピックにメッセージがパブリッシュされます。

Pub/Sub ペイロードは JSON 形式で、スキーマは次のとおりです。

注:

{
    "name": "projects/[PROJECT_ID]/notes/[NOTE_ID]",
    "kind": [NOTE_KIND]
}

発生個所:

{
    "name": "projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID]",
    "kind": [NOTE_KIND]
}

ここで、[NOTE_KIND] は、NoteKind の値の 1 つです。

これらのイベントをリッスンするには、そのトピックに関連付けられた Pub/Sub サブスクリプションを作成します。

API

Cloud Pub/Sub イベントを受信するには、まず container-analysis-occurrences-v1beta1 トピックに関連付けられたサブスクリプションを作成する必要があります。

gcloud beta pubsub subscriptions create \
    --topic container-analysis-occurrences-v1beta1 occurrences

新しいサブスクリプションを使用して、オカレンスに関するメッセージを pull できるようになります。

gcloud beta pubsub subscriptions pull \
    --auto-ack occurrences

Java

Container Registry 用のクライアント ライブラリをインストールして使用する方法については、Container Registry のクライアント ライブラリをご覧ください。詳細については、Container Registry Java API のリファレンス ドキュメントをご覧ください。

/**
 * Handle incoming Occurrences using a Cloud Pub/Sub subscription
 * @param subId the user-specified identifier for the Pub/Sub subscription
 * @param timeout the amount of time to listen for Pub/Sub messages (in seconds)
 * @param projectId the GCP project the Pub/Sub subscription belongs to
 * @return number of Occurrence Pub/Sub messages received before exiting
 * @throws InterruptedException on errors with the subscription client
 */
public static int pubSub(String subId, int timeout, String projectId)
    throws InterruptedException {
  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();
    // Listen to messages for 'timeout' seconds
    for (int i = 0; i < timeout; i++) {
      sleep(1000);
    }
  } 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
 * @param subId the identifier you want to associate with the subscription
 * @param projectId the GCP project to create the subscription under
 * @throws IOException thrown on errors with the subscription client
 * @throws StatusRuntimeException if subscription already exists
 *
 */
public static Subscription createOccurrenceSubscription(String subId, String projectId)
    throws IOException, StatusRuntimeException {
  // This topic id will automatically receive messages when Occurrences are added or modified
  String topicId = "container-analysis-occurrences-v1beta1";
  SubscriptionAdminClient client = SubscriptionAdminClient.create();
  PushConfig config = PushConfig.getDefaultInstance();
  ProjectTopicName topicName = ProjectTopicName.of(projectId, topicId);
  ProjectSubscriptionName subName = ProjectSubscriptionName.of(projectId, subId);
  Subscription sub = client.createSubscription(subName, topicName, config, 0);
  return sub;
} 

Go

Container Registry 用のクライアント ライブラリをインストールして使用する方法については、Container Registry のクライアント ライブラリをご覧ください。詳細については、Container Registry Go API のリファレンス ドキュメントをご覧ください。

// occurrencePubsub handles incoming Occurrences using a Cloud Pub/Sub subscription.
func occurrencePubsub(ctx context.Context, subscriptionID string, timeout int, projectID string) (int, error) {
	var mu sync.Mutex
	client, err := pubsub.NewClient(ctx, projectID)
	if err != nil {
		return -1, err
	}
	// Subscribe to the requested Pub/Sub channel.
	sub := client.Subscription(subscriptionID)
	count := 0

	// Listen to messages for 'timeout' seconds.
	toctx, cancel := context.WithTimeout(ctx, time.Duration(timeout)*time.Second)
	defer cancel()
	err = sub.Receive(toctx, func(ctx context.Context, msg *pubsub.Message) {
		mu.Lock()
		count = count + 1
		fmt.Printf("Message %d: %q\n", count, string(msg.Data))
		msg.Ack()
		mu.Unlock()
	})
	if err != nil {
		return -1, err
	}
	// Print and return the number of Pub/Sub messages received.
	fmt.Println(count)
	return count, nil
}

// createOccurrenceSubscription creates and returns a Pub/Sub subscription object listening to the Occurrence topic.
func createOccurrenceSubscription(ctx context.Context, subscriptionID, projectID string) error {
	client, err := pubsub.NewClient(ctx, projectID)
	if err != nil {
		return err
	}

	// This topic id will automatically receive messages when Occurrences are added or modified
	topicID := "container-analysis-occurrences-v1beta1"
	topic := client.Topic(topicID)
	config := pubsub.SubscriptionConfig{Topic: topic}
	_, err = client.CreateSubscription(ctx, subscriptionID, config)
	return err
}

サブスクライバー アプリケーションで使用できるのは、サブスクリプションの作成後にトピックにパブリッシュしたメッセージだけです。

次のステップ

  • Container Analysis を使用して顧客のメタデータを格納および管理する方法については、イメージ用のメタデータの提供をご覧ください。

  • Binary Authorization と脆弱性スキャンを統合することで、既知のセキュリティ問題を伴うイメージがデプロイ環境で実行されないようにすることができます。これを行う手順については、脆弱性スキャンの統合をご覧ください。

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...