イメージの脆弱性とメタデータの取得

Container Analysis は、Container Registry に格納されているコンテナ イメージの脆弱性情報などのメタデータを提供します。メタデータはメモとして保存されます。イメージに関連付けられたメモが検出されるたびにオカレンスが作成されます。

このページでは、メモとオカレンスの表示、フィルタリング、通知の受信を行う方法について説明します。

始める前に

  1. Container Scanning API を有効にします。これにより、脆弱性スキャンと Container Analysis API が有効になります。既存のプロジェクトで API を有効にすることも、新しいプロジェクトを作成して API を有効にすることも可能です。あとで脆弱性スキャンを手動で無効にできます。

    Container Scanning API を有効にする

  2. まだ行っていない場合は、必要な IAM 権限を有効にします。すでにプロジェクト オーナーの役割が付与されている場合は、この手順をスキップします。

    • オカレンスを表示するには、事前定義された次の IAM の役割を付与する必要があります。これにより、必要な権限が自動的に付与されます。

      • Container Analysis 実行回数の閲覧者
    • オカレンスの通知を受け取るには、適切な Pub/Sub 権限を構成する必要があります。詳細については、通知をご覧ください。

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

脆弱性と他のオカレンスの表示

Container Registry にイメージのオカレンスを表示するには、GCP Console、gcloud コマンドライン ツールまたは Container Analysis API を使用します。イメージに脆弱性が存在する場合、その詳細を確認できます。

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

Console

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

    Container Registry ページを開く

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

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

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

  3. イメージで検出された脆弱性の一覧を表示するには、[脆弱性] 列のリンクをクリックします。

    脆弱性リストには、重大度、修正プログラムが入手可能かどうか、脆弱性が存在するパッケージの名前が表示されます。

  4. 脆弱性ソースから特定の脆弱性の詳細を確認するには、[ドキュメント] 列のリンクをクリックします。

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 describe [HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]:[TAG]  \
 --show-package-vulnerability

  or

 gcloud beta container images describe [HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]@sha256:[HASH] \
 --show-package-vulnerability

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

 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/v1/projects/[PROJECT_ID]/occurrences

プロジェクトの脆弱性の概要を取得するには:

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

オカレンスを取得するには:

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

Java

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

import com.google.cloud.devtools.containeranalysis.v1.ContainerAnalysisClient;
import io.grafeas.v1.GrafeasClient;
import io.grafeas.v1.Occurrence;
import io.grafeas.v1.ProjectName;
import java.io.IOException;
import java.lang.InterruptedException;

public class OccurrencesForImage {
  // Retrieves all the Occurrences associated with a specified image
  // Here, all Occurrences are simply printed and counted
  public static int getOccurrencesForImage(String resourceUrl, String projectId)
      throws IOException, InterruptedException {
    // String resourceUrl = "https://gcr.io/project/image@sha256:123";
    // String projectId = "my-project-id";
    final String projectName = ProjectName.format(projectId);
    final String filterStr = String.format("resourceUrl=\"%s\"", resourceUrl);

    // Initialize client that will be used to send requests. After completing all of your requests,
    // call the "close" method on the client to safely clean up any remaining background resources.
    GrafeasClient client = ContainerAnalysisClient.create().getGrafeasClient();
    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 のリファレンス ドキュメントをご覧ください。


import (
	"context"
	"fmt"
	"io"

	containeranalysis "cloud.google.com/go/containeranalysis/apiv1"
	"google.golang.org/api/iterator"
	grafeaspb "google.golang.org/genproto/googleapis/grafeas/v1"
)

// getOccurrencesForImage retrieves all the Occurrences associated with a specified image.
// Here, all Occurrences are simply printed and counted.
func getOccurrencesForImage(w io.Writer, resourceURL, projectID string) (int, error) {
	// resourceURL := fmt.Sprintf("https://gcr.io/my-project/my-image")
	ctx := context.Background()
	client, err := containeranalysis.NewClient(ctx)
	if err != nil {
		return -1, fmt.Errorf("NewClient: %v", err)
	}
	defer client.Close()

	req := &grafeaspb.ListOccurrencesRequest{
		Parent: fmt.Sprintf("projects/%s", projectID),
		Filter: fmt.Sprintf("resourceUrl=%q", resourceURL),
	}
	it := client.GetGrafeasClient().ListOccurrences(ctx, req)
	count := 0
	for {
		occ, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return -1, fmt.Errorf("occurrence iteration error: %v", err)
		}
		// Write custom code to process each Occurrence here.
		fmt.Fprintln(w, occ)
		count = count + 1
	}
	return count, nil
}

Node.js

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

/**
 * TODO(developer): Uncomment these variables before running the sample
 */
// const projectId = 'your-project-id', // Your GCP Project ID
// const imageUrl = 'https://gcr.io/my-project/my-image:123' // Image to attach metadata to

// Import the library and create a client
const {ContainerAnalysisClient} = require('@google-cloud/containeranalysis');
const client = new ContainerAnalysisClient();

const formattedParent = client.getGrafeasClient().projectPath(projectId);

// Retrieves all the Occurrences associated with a specified image
const [occurrences] = await client.getGrafeasClient().listOccurrences({
  parent: formattedParent,
  filter: `resourceUrl = "${imageUrl}"`,
});

if (occurrences.length) {
  console.log(`Occurrences for ${imageUrl}`);
  occurrences.forEach(occurrence => {
    console.log(`${occurrence.name}:`);
  });
} else {
  console.log('No occurrences found.');
}

Ruby

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

# resource_url = "The URL of the resource associated with the occurrence.
#                 e.g. https://gcr.io/project/image@sha256:123"
# project_id    = "The Google Cloud project ID of the occurrences to
#                  retrieve"

require "grafeas"

# Initialize the client
client = Grafeas.new

formatted_parent = Grafeas::V1::GrafeasClient.project_path project_id
filter = "resourceUrl = \"#{resource_url}\""
count = 0
client.list_occurrences(formatted_parent, filter: filter).each do |occurrence|
  # Process occurrence here
  puts occurrence
  count += 1
end
puts "Found #{count} occurrences"

Python

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

def get_occurrences_for_image(resource_url, project_id):
    """Retrieves all the occurrences associated with a specified image.
    Here, all occurrences are simply printed and counted."""
    # resource_url = 'https://gcr.io/my-project/my-image@sha256:123'
    # project_id = 'my-gcp-project'

    from google.cloud.devtools import containeranalysis_v1

    filter_str = 'resourceUrl="{}"'.format(resource_url)
    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    project_name = grafeas_client.project_path(project_id)

    response = grafeas_client.list_occurrences(project_name,
                                               filter_=filter_str)
    count = 0
    for o in response:
        # do something with the retrieved occurrence
        # in this sample, we will simply count each one
        count += 1
    return count

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

gcloud コマンドや Container Analysis API のフィルタ文字列を使用すれば、表示するオカレンスを絞り込むことができます。以降では、サポートされている検索フィルタについて説明します。

特定の種類のオカレンスを表示する

kind フィールドは、オカレンスの種類を特定します。このフィールドを使用して、オカレンスのリストを特定の種類(脆弱性やデプロイメントなど)に限定します。

1 つのイメージを対象に特定の種類のオカレンスを取得するには、次のフィルタ式を使用します。

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

ここで

  • [NOTE_KIND] はメモの種類です。
    • たとえば、検出オカレンスを表示するには、DISCOVERY を使用します。これらは、イメージが最初に Container Registry に push されたときに作成されます。
    • 脆弱性オカレンスを表示するには、VULNERABILITY を使用します。
  • [RESOURCE_URL] はイメージの完全な URL です。次に例を示します。https://[HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]@sha256:[HASH]

複数のイメージを対象に特定の種類のオカレンスを取得するには、次のフィルタ式を使用します。

kind="[NOTE_KIND]" AND has_prefix(resourceUrl, "[RESOURCE_URL_PREFIX]")

ここで

  • [RESOURCE_URL_PREFIX] は、イメージの URL 接頭辞です。
    • 1 つのイメージのすべてのバージョンを表示する場合: https://[HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]@
    • プロジェクト内のすべてのイメージを表示する場合: https://[HOSTNAME]/[PROJECT_ID]/

検出オカレンスの表示

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

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

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

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

gcloud コマンド

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

gcloud beta container images list-tags --show-occurrences \
  --occurrence-filter='kind="DISCOVERY"' --format=json [HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]

API

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

GET https://containeranalysis.googleapis.com/v1/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 のリファレンス ドキュメントをご覧ください。

import com.google.cloud.devtools.containeranalysis.v1.ContainerAnalysisClient;
import io.grafeas.v1.GrafeasClient;
import io.grafeas.v1.Occurrence;
import io.grafeas.v1.ProjectName;
import java.io.IOException;
import java.lang.InterruptedException;

public class GetDiscoveryInfo {
  // Retrieves and prints the Discovery Occurrence created for a specified image
  // The Discovery Occurrence contains information about the initial scan on the image
  public static void getDiscoveryInfo(String resourceUrl, String projectId)
      throws IOException, InterruptedException {
    // String resourceUrl = "https://gcr.io/project/image@sha256:123";
    // String projectId = "my-project-id";
    String filterStr = "kind=\"DISCOVERY\" AND resourceUrl=\"" + resourceUrl + "\"";
    final String projectName = ProjectName.format(projectId);

    // Initialize client that will be used to send requests. After completing all of your requests,
    // call the "close" method on the client to safely clean up any remaining background resources.
    GrafeasClient client = ContainerAnalysisClient.create().getGrafeasClient();
    for (Occurrence o : client.listOccurrences(projectName, filterStr).iterateAll()) {
      System.out.println(o);
    }
  }
}

Go

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


import (
	"context"
	"fmt"
	"io"

	containeranalysis "cloud.google.com/go/containeranalysis/apiv1"
	"google.golang.org/api/iterator"
	grafeaspb "google.golang.org/genproto/googleapis/grafeas/v1"
)

// 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(w io.Writer, resourceURL, projectID string) error {
	// resourceURL := fmt.Sprintf("https://gcr.io/my-project/my-image")
	ctx := context.Background()
	client, err := containeranalysis.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("NewClient: %v", err)
	}
	defer client.Close()

	req := &grafeaspb.ListOccurrencesRequest{
		Parent: fmt.Sprintf("projects/%s", projectID),
		Filter: fmt.Sprintf(`kind="DISCOVERY" AND resourceUrl=%q`, resourceURL),
	}
	it := client.GetGrafeasClient().ListOccurrences(ctx, req)
	for {
		occ, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return fmt.Errorf("occurrence iteration error: %v", err)
		}
		fmt.Fprintln(w, occ)
	}
	return nil
}

Node.js

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

/**
 * TODO(developer): Uncomment these variables before running the sample
 */
// const projectId = 'your-project-id', // Your GCP Project ID
// const imageUrl = 'https://gcr.io/my-project/my-image:123' // Image to attach metadata to

// Import the library and create a client
const {ContainerAnalysisClient} = require('@google-cloud/containeranalysis');
const client = new ContainerAnalysisClient();

const formattedParent = client.getGrafeasClient().projectPath(projectId);
// Retrieves and prints the Discovery Occurrence created for a specified image
// The Discovery Occurrence contains information about the initial scan on the image
const [occurrences] = await client.getGrafeasClient().listOccurrences({
  parent: formattedParent,
  filter: `kind = "DISCOVERY" AND resourceUrl = "${imageUrl}"`,
});

if (occurrences.length > 0) {
  console.log(`Discovery Occurrences for ${imageUrl}`);
  occurrences.forEach(occurrence => {
    console.log(`${occurrence.name}:`);
  });
} else {
  console.log('No occurrences found.');
}

Ruby

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

# resource_url = "The URL of the resource associated with the occurrence.
#                 e.g. https://gcr.io/project/image@sha256:123"
# project_id   = "The Google Cloud project ID of the occurrences to retrieve"

require "grafeas"

# Initialize the client
client = Grafeas.new

formatted_parent = Grafeas::V1::GrafeasClient.project_path project_id
filter = "kind = \"DISCOVERY\" AND resourceUrl = \"#{resource_url}\""
client.list_occurrences(formatted_parent, filter: filter).each do |occurrence|
  # Process discovery occurrence here
  puts occurrence
end

Python

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

def get_discovery_info(resource_url, project_id):
    """Retrieves and prints the discovery occurrence created for a specified
    image. The discovery occurrence contains information about the initial
    scan on the image."""
    # resource_url = 'https://gcr.io/my-project/my-image@sha256:123'
    # project_id = 'my-gcp-project'

    from google.cloud.devtools import containeranalysis_v1

    filter_str = 'kind="DISCOVERY" AND resourceUrl="{}"'.format(resource_url)
    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    project_name = grafeas_client.project_path(project_id)
    response = grafeas_client.list_occurrences(project_name,
                                               filter_=filter_str)
    for occ in response:
        print(occ)

脆弱性オカレンスの表示

特定のイメージの脆弱性オカレンスを表示するには、次のフィルタ式を使用してクエリを作成します。

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

次のスニペットは、イメージの脆弱性オカレンスのリストを取得する方法を示しています。

gcloud コマンド

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

gcloud beta container images list-tags --show-occurrences \
  --occurrence-filter='kind="VULNERABILITY"' --format=json [HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]

API

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

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

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

Java

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

import com.google.cloud.devtools.containeranalysis.v1.ContainerAnalysisClient;
import io.grafeas.v1.GrafeasClient;
import io.grafeas.v1.Occurrence;
import io.grafeas.v1.ProjectName;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

public class VulnerabilityOccurrencesForImage {
  // Retrieve a list of vulnerability occurrences assoviated with a resource
  public static List<Occurrence> findVulnerabilityOccurrencesForImage(String resourceUrl,
      String projectId) throws IOException {
    // String resourceUrl = "https://gcr.io/project/image@sha256:123";
    // String projectId = "my-project-id";
    final String projectName = ProjectName.format(projectId);
    String filterStr = String.format("kind=\"VULNERABILITY\" AND resourceUrl=\"%s\"", resourceUrl);

    // Initialize client that will be used to send requests. After completing all of your requests,
    // call the "close" method on the client to safely clean up any remaining background resources.
    GrafeasClient client = ContainerAnalysisClient.create().getGrafeasClient();
    LinkedList<Occurrence> vulnerabilitylist = new LinkedList<Occurrence>();
    for (Occurrence o : client.listOccurrences(projectName, filterStr).iterateAll()) {
      vulnerabilitylist.add(o);
    }
    return vulnerabilitylist;
  }
}

Go

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


import (
	"context"
	"fmt"

	containeranalysis "cloud.google.com/go/containeranalysis/apiv1"
	"google.golang.org/api/iterator"
	grafeaspb "google.golang.org/genproto/googleapis/grafeas/v1"
)

// findVulnerabilityOccurrencesForImage retrieves all vulnerability Occurrences associated with a resource.
func findVulnerabilityOccurrencesForImage(resourceURL, projectID string) ([]*grafeaspb.Occurrence, error) {
	// resourceURL := fmt.Sprintf("https://gcr.io/my-project/my-image")
	ctx := context.Background()
	client, err := containeranalysis.NewClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("NewClient: %v", err)
	}
	defer client.Close()

	req := &grafeaspb.ListOccurrencesRequest{
		Parent: fmt.Sprintf("projects/%s", projectID),
		Filter: fmt.Sprintf("resourceUrl = %q kind = %q", resourceURL, "VULNERABILITY"),
	}

	var occurrenceList []*grafeaspb.Occurrence
	it := client.GetGrafeasClient().ListOccurrences(ctx, req)
	for {
		occ, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, fmt.Errorf("occurrence iteration error: %v", err)
		}
		occurrenceList = append(occurrenceList, occ)
	}

	return occurrenceList, nil
}

Node.js

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

/**
 * TODO(developer): Uncomment these variables before running the sample
 */
// const projectId = 'your-project-id', // Your GCP Project ID
// const imageUrl = 'https://gcr.io/my-project/my-image:123' // Image to attach metadata to

// Import the library and create a client
const {ContainerAnalysisClient} = require('@google-cloud/containeranalysis');
const client = new ContainerAnalysisClient();

const formattedParent = client.getGrafeasClient().projectPath(projectId);

// Retrieve a list of vulnerability occurrences assoviated with a resource
const [occurrences] = await client.getGrafeasClient().listOccurrences({
  parent: formattedParent,
  filter: `kind = "VULNERABILITY" AND resourceUrl = "${imageUrl}"`,
});

if (occurrences.length) {
  console.log(`All Vulnerabilities for ${imageUrl}`);
  occurrences.forEach(occurrence => {
    console.log(`${occurrence.name}:`);
  });
} else {
  console.log('No occurrences found.');
}

Ruby

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

# resource_url = "The URL of the resource associated with the occurrence
#                e.g. https://gcr.io/project/image@sha256:123"
# project_id   = "The Google Cloud project ID of the vulnerabilities to find"

require "grafeas"

# Initialize the client
client = Grafeas.new

formatted_parent = Grafeas::V1::GrafeasClient.project_path project_id
filter = "resourceUrl = \"#{resource_url}\" AND kind = \"VULNERABILITY\""
client.list_occurrences formatted_parent, filter: filter

Python

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

def find_vulnerabilities_for_image(resource_url, project_id):
    """"Retrieves all vulnerability occurrences associated with a resource."""
    # resource_url = 'https://gcr.io/my-project/my-image@sha256:123'
    # project_id = 'my-gcp-project'

    from google.cloud.devtools import containeranalysis_v1

    client = containeranalysis_v1.ContainerAnalysisClient()
    grafeas_client = client.get_grafeas_client()
    project_name = grafeas_client.project_path(project_id)

    filter_str = 'kind="VULNERABILITY" AND resourceUrl="{}"'\
        .format(resource_url)
    return list(grafeas_client.list_occurrences(project_name, filter_str))

特定のメモに関連付けられているイメージを表示する

特定のメモ ID に関連付けられているリソースのリストを取得できます。たとえば、特定の CVE の脆弱性を含むイメージを一覧表示できます。

プロジェクト内で特定のメモに関連付けられているすべてのイメージを一覧表示するには、次のフィルタ式を使用します。

noteProjectId="[PROVIDER_PROJECT_ID]" AND noteId="[NOTE_ID]"

特定のイメージのメモを確認するには、次のフィルタ式を使用します。

resourceUrl="[RESOURCE_URL]" AND noteProjectId="[PROVIDER_PROJECT_ID]" \
    AND noteId="[NOTE_ID]"

ここで

  • [PROVIDER_PROJECT_ID] は、プロバイダ プロジェクトの ID です。たとえば、goog-vulnz はデフォルトの脆弱性分析を提供します。
  • [NOTE_ID] はメモの ID です。多くの場合、セキュリティ関連のメモは CVE-2019-12345 という形式になります。
  • [RESOURCE_URL] はイメージの完全な URL です。次に例を示します。https://[HOSTNAME]/[PROJECT_ID]/[IMAGE_ID]@sha256:[HASH]

たとえば、Google による分析で CVE-2017-16231 のオカレンスがあるすべてのイメージを確認するには、次のフィルタ式を使用します。

noteProjectId="goog-vulnz" AND noteId="CVE-2017-16231"

Cloud Pub/Sub の通知

このセクションでは、メモとオカレンスの更新通知を設定する方法について説明します。

Container Registry は、脆弱性や他のメタデータをスキャンするたびに、Cloud Pub/Sub 経由で通知を送信します。メモやオカレンスが作成または更新されると、それぞれの API バージョンの対応トピックにメッセージがパブリッシュされます。現在の API バージョンに対応するトピックを使用します。

Container Analysis API を有効にすると、次の Cloud Pub/Sub トピックがプロジェクトに作成されます。

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

誤って削除したトピックや見つからないトピックは自分で追加できます。

Console

  1. GCP Console の Cloud Pub/Sub トピックページに移動します。

    [Cloud Pub/Sub トピック] ページに移動

  2. [トピックを作成] をクリックします。

  3. メモのトピックを URI 付きで入力します。

    projects/[PROJECT-ID]/topics/container-analysis-notes-v1
    

    [PROJECT-ID] は GCP のプロジェクト ID です。

  4. [作成] をクリックします。

  5. 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 のドキュメントをご覧ください。

メモまたはオカレンスが作成または更新されるたびに、それぞれのトピックにメッセージがパブリッシュされます。

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

ここで

  • [NOTE_KIND] は、NoteKind の値の 1 つです。
  • [NOTIFICATION_TIME] は、RFC 3339 UTC Zulu 形式のタイムスタンプ(精度はナノ秒)です。

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

gcloud コマンド

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

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

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

gcloud pubsub subscriptions pull \
    --auto-ack occurrences

Java

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

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.ProjectTopicName;
import com.google.pubsub.v1.PubsubMessage;
import com.google.pubsub.v1.PushConfig;
import com.google.pubsub.v1.Subscription;
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";
    ProjectTopicName topicName = ProjectTopicName.of(projectId, topicId);
    ProjectSubscriptionName subName = ProjectSubscriptionName.of(projectId, subId);

    SubscriptionAdminClient client = SubscriptionAdminClient.create();
    PushConfig config = PushConfig.getDefaultInstance();
    Subscription sub = client.createSubscription(subName, topicName, config, 0);
    return sub;
  }
}

Go

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


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: %v", 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: %v", 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: %v", 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: %v", err)
}

Node.js

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

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

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

# 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: project_id
topic = pubsub.topic "container-analysis-occurrences-v1"
subscription = topic.subscribe subscription_id

count = 0
subscriber = subscription.listen do |received_message|
  count += 1
  # Process incoming occurrence here
  puts "Message #{count}: #{received_message.data}"
  received_message.acknowledge!
end
subscriber.start
# Wait for incomming occurrences
sleep timeout_seconds
subscriber.stop.wait!
subscription.delete
# Print and return the total number of Pub/Sub messages received
puts "Total Messages Received: #{count}"
count

Python

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

def pubsub(subscription_id, timeout_seconds, project_id):
    """Respond to incoming occurrences using a Cloud Pub/Sub subscription."""
    # subscription_id := 'my-occurrences-subscription'
    # timeout_seconds = 20
    # project_id = 'my-gcp-project'

    import time
    from google.cloud.pubsub import SubscriberClient

    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):
        # initialize counter to 0 on initialization
        self.msg_count = 0

    def pubsub_callback(self, message):
        # every time a pubsub message comes in, print it and count it
        self.msg_count += 1
        print('Message {}: {}'.format(self.msg_count, message.data))
        message.ack()

def create_occurrence_subscription(subscription_id, project_id):
    """Creates a new Pub/Sub subscription object listening to the
    Container Analysis Occurrences topic."""
    # subscription_id := 'my-occurrences-subscription'
    # project_id = 'my-gcp-project'

    from google.api_core.exceptions import AlreadyExists
    from google.cloud.pubsub import SubscriberClient

    topic_id = 'container-analysis-occurrences-v1'
    client = SubscriberClient()
    topic_name = client.topic_path(project_id, topic_id)
    subscription_name = client.subscription_path(project_id, subscription_id)
    success = True
    try:
        client.create_subscription(subscription_name, topic_name)
    except AlreadyExists:
        # if subscription already exists, do nothing
        pass
    else:
        success = False
    return success

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

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

脆弱性スキャンを無効にするには、次の操作を行います。

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

    設定ページを開く

  2. [脆弱性スキャンを無効にする] をクリックします。

次のステップ

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

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

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

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

Container Registry のドキュメント