チュートリアル: イメージの脆弱性の取得

このチュートリアルでは、Container Analysis を使用して、Container Registry に格納されているイメージをスキャンして脆弱性がないか確認し、イメージに含まれる重大度の高い脆弱性を一覧表示する方法について説明します。

目標

このチュートリアルでは、次の手順について説明します。

  1. 既知の脆弱性が含まれる Docker イメージを作成する
  2. イメージをプロジェクトの Container Registry に push する
  3. Container Analysis をポーリングし、イメージの初期スキャンと分析を完了する
  4. Container Analysis によって識別された脆弱性を表示する
  5. イメージに含まれる重大度の高い脆弱性を一覧表示する

費用

このチュートリアルでは、Google Cloud Platform の課金対象となるコンポーネントを使用します。詳細は料金をご覧ください。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを出すことができます。

GCP を初めて使用する場合は、無料トライアルをご利用いただけます。

始める前に

Container Analysis を使用するには、Container Analysis と Container Registry を有効にして設定する必要があります。

  1. Google アカウントにログインします。

    Google アカウントをまだお持ちでない場合は、新しいアカウントを登録します。

  2. GCP Console のプロジェクト セレクタのページで、GCP プロジェクトを選択または作成します。

    プロジェクト セレクタのページに移動

  3. Google Cloud Platform プロジェクトに対して課金が有効になっていることを確認します。 詳しくは、課金を有効にする方法をご覧ください。

  4. Container Registry と Container Scanning API を有効にします。

    APIを有効にする

  5. Cloud SDK をインストールして初期化します。
  6. まだ行っていない場合は、次のいずれかを実行して、必要な IAM 権限を取得します。すでにプロジェクト オーナーの役割が付与されている場合は、この手順をスキップします。
    • オカレンスを表示するには、次の権限が必要です。
      containeranalysis.notes.listOccurrences
    • または、必要な権限が自動的に付与されるように、次の事前定義された IAM の役割を付与することもできます。
      Container Analysis Occurrences Viewer
  7. Docker をインストールします。 Ubuntu や Debian など、Linux ベースのオペレーティング システムを使用している場合は、ユーザー名を docker グループに追加して、sudo を使用しなくても Docker を実行できるようにします。
    sudo usermod -a -G docker ${USER}

    docker グループにユーザー名を追加した後、システムの再起動が必要となる場合があります。

  8. Docker を開きます。Docker が稼働中であることを確認するには、現在の時刻と日付を返す次の Docker コマンドを実行します。
  9. docker run busybox date

Docker イメージの作成

このチュートリアル用に、次の Docker イメージを作成して、Container Registry に push するイメージを用意します。Container Analysis によって識別される既知の脆弱性が含まれる Python ランタイムを使用します。この Docker イメージには、小さな Python ウェブアプリが含まれます。このアプリは Flask のウェブ フレームワークを使用して、「Hello, World!」というメッセージを表示するウェブページを提供します。

Docker イメージを作成するには:

  1. 3 つの Docker イメージ ファイルを格納するディレクトリを作成します。

  2. このディレクトリに、Dockerfilerequirements.txtapp.py の 3 つのファイルを作成します。各ファイルの内容に含める必要があるものについては、以下の例をご覧ください。

Dockerfile

# The Dockerfile defines the image's environment
# Import Python runtime and set up working directory
# This specified runtime has known vulnerabilities so that vulnerability
# scanning can be tested.
FROM python:2.7-slim
WORKDIR /app
ADD . /app

# Install any necessary dependencies
RUN pip install -r requirements.txt

# Open port 80 for serving the webpage
EXPOSE 80

# Run app.py when the container launches
CMD ["python", "app.py"]

requirements.txt

# This file defines the image's dependencies
Flask

app.py

# The Docker image contains the following code
from flask import Flask
import os
import socket

app = Flask(__name__)

@app.route("/")
def hello():
    html = "<h3>Hello, World!</h3>"
    return html

if __name__ == "__main__":
  app.run(host='0.0.0.0', port=80)

Docker イメージをビルドするには、イメージのファイルが含まれているディレクトリから、次の Docker コマンドを実行します。

docker build -t vulnerabilities-tutorial-image .

これで、ローカルマシンに Docker イメージが作成されました。

イメージを Container Registry に追加する

gcloud コマンドライン ツールを認証ヘルパーとして使用するように docker を構成する

イメージを push または pull するには、gcloud コマンドライン ツールを使用して Container Registry へのリクエストを認証するように Docker を構成する必要があります。これを行うには、次のコマンドを実行します(実行する必要があるのは一度だけです)。

gcloud auth configure-docker

イメージにレジストリ名をタグ付けする

Docker イメージを Container Registry に push する前に、そのイメージにレジストリ名をタグ付けする必要があります。これにより、イメージを特定の場所に push するように docker push コマンドが構成されます。このクイックスタートでは、ホストの場所は gcr.io です。

Docker イメージにタグを付けるには、次のコマンドを実行します。

docker tag vulnerabilities-tutorial-image gcr.io/[PROJECT-ID]/vulnerabilities-tutorial-image:tag1

ここで

  • [PROJECT-ID] は Google Cloud Platform Console プロジェクト ID です。対象の ID をコマンドに追加します。
  • gcr.io はホスト名です。
  • vulnerabilities-tutorial-image は Docker イメージの名前です。
  • tag1 は Docker イメージに追加するタグです。タグを指定しない場合は、Docker でデフォルトのタグ latest が適用されます。

イメージを Container Registry に push する準備ができました。

イメージを Container Registry に push する

gcloud を認証ヘルパーとして使用するように docker を構成し、ローカル イメージにレジストリ名をタグ付けしたら、そのイメージを Container Registry に push することができます。

Docker イメージを push するには、次のコマンドを実行します。

docker push gcr.io/[PROJECT-ID]/vulnerabilities-tutorial-image:tag1

[PROJECT-ID] は Google Cloud Platform Console プロジェクト ID です。プロジェクト ID にコロン(:)が含まれている場合は、ドメインをスコープとするプロジェクトをご覧ください。

新しいホストの場所にイメージを push すると、プロジェクトに固有の基になるストレージ バケットが作成されます。Container Registry でホストされているイメージを確認するには、GCP Console を使用するか、ウェブブラウザでイメージのレジストリ名(http://gcr.io/[PROJECT-ID]/vulnerabilities-tutorial-image)にアクセスします。

初期スキャンのポーリングと分析結果

Container Analysis は、イメージの初期スキャンと分析を自動的に実行します。また、初期スキャンで収集された情報を含む検出オカレンスを作成します。さらに、Container Analysis は、スキャンの現在のステータスが含まれるように検出オカレンスを更新します。

次のサンプルコードは、初期スキャンの現在のステータスをポーリングします。これによって、脆弱性情報が表示できるようになるタイミングを判断できます。

Java

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

import com.google.cloud.devtools.containeranalysis.v1.ContainerAnalysisClient;
import io.grafeas.v1.DiscoveryOccurrence;
import io.grafeas.v1.DiscoveryOccurrence.AnalysisStatus;
import io.grafeas.v1.GrafeasClient;
import io.grafeas.v1.Occurrence;
import io.grafeas.v1.ProjectName;
import java.io.IOException;
import java.lang.InterruptedException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class PollDiscoveryOccurrenceFinished {
  // Repeatedly query the Container Analysis API for the latest discovery occurrence until it is
  // either in a terminal state, or the timeout value has been exceeded
  public static Occurrence pollDiscoveryOccurrenceFinished(String resourceUrl, String projectId,
      long timeoutSeconds) throws IOException, TimeoutException, InterruptedException {
    // String resourceUrl = "https://gcr.io/project/image@sha256:123";
    // String projectId = "my-project-id";
    // long timeoutSeconds = 30;
    final String projectName = ProjectName.format(projectId);
    long deadline = System.currentTimeMillis() + timeoutSeconds * 1000;

    // 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();

    // find the discovery occurrence using a filter string
    Occurrence discoveryOccurrence = null;
    // vulbnerability discovery occurrences are always associated with the
    // PACKAGE_VULNERABILITY note in the "goog-analysis" GCP project
    String filter =  String.format("resourceUrl=\"%s\" AND noteProjectId=\"%s\" AND noteId=\"%s\"",
        resourceUrl, "goog-analysis",  "PACKAGE_VULNERABILITY");
    while (discoveryOccurrence == null) {
      for (Occurrence o : client.listOccurrences(projectName, filter).iterateAll()) {
        if (o.getDiscovery() != null) {
          // there should be only one valid discovery occurrence returned by the given filter
          discoveryOccurrence = o;
        }
      }
      TimeUnit.SECONDS.sleep(1);
      // check for timeout
      if (System.currentTimeMillis() > deadline) {
        throw new TimeoutException("discovery occurrence not found");
      }
    }

    // wait for discovery occurrence to enter a terminal state
    AnalysisStatus status = AnalysisStatus.PENDING;
    while (status != AnalysisStatus.FINISHED_SUCCESS
        && status != AnalysisStatus.FINISHED_FAILED
        && status != AnalysisStatus.FINISHED_UNSUPPORTED) {
      // update the occurrence state
      discoveryOccurrence = client.getOccurrence(discoveryOccurrence.getName());
      status = discoveryOccurrence.getDiscovery().getAnalysisStatus();
      TimeUnit.SECONDS.sleep(1);
      // check for timeout
      if (System.currentTimeMillis() > deadline) {
        throw new TimeoutException("discovery occurrence not in terminal state");
      }
    }
    return discoveryOccurrence;
  }
}

Go

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


import (
	"context"
	"fmt"
	"time"

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

// pollDiscoveryOccurrenceFinished returns the discovery occurrence for a resource once it reaches a finished state.
func pollDiscoveryOccurrenceFinished(resourceURL, projectID string, timeout time.Duration) (*grafeaspb.Occurrence, error) {
	// resourceURL := fmt.Sprintf("https://gcr.io/my-project/my-image")
	// timeout := time.Duration(5) * time.Second
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()

	client, err := containeranalysis.NewClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("NewClient: %v", err)
	}
	defer client.Close()

	// ticker is used to poll once per second.
	ticker := time.NewTicker(1 * time.Second)
	defer ticker.Stop()

	// Find the discovery occurrence using a filter string.
	var discoveryOccurrence *grafeaspb.Occurrence
	for discoveryOccurrence == nil {
		select {
		case <-ctx.Done():
			return nil, fmt.Errorf("timeout while retrieving discovery occurrence")
		case <-ticker.C:
			req := &grafeaspb.ListOccurrencesRequest{
				Parent: fmt.Sprintf("projects/%s", projectID),
				// Vulnerability discovery occurrences are always associated with the
				// PACKAGE_VULNERABILITY note in the "goog-analysis" GCP project.
				Filter: fmt.Sprintf(`resourceUrl=%q AND noteProjectId="goog-analysis" AND noteId="PACKAGE_VULNERABILITY"`, resourceURL),
			}
			it := client.GetGrafeasClient().ListOccurrences(ctx, req)
			// Only one occurrence should ever be returned by ListOccurrences
			// and the given filter.
			result, err := it.Next()
			if err == iterator.Done {
				break
			}
			if err != nil {
				return nil, fmt.Errorf("it.Next: %v", err)
			}
			if result.GetDiscovery() != nil {
				discoveryOccurrence = result
			}
		}
	}

	// Wait for the discovery occurrence to enter a terminal state.
	for {
		select {
		case <-ctx.Done():
			return nil, fmt.Errorf("timeout waiting for terminal state")
		case <-ticker.C:
			// Update the occurrence.
			req := &grafeaspb.GetOccurrenceRequest{Name: discoveryOccurrence.GetName()}
			updated, err := client.GetGrafeasClient().GetOccurrence(ctx, req)
			if err != nil {
				return nil, fmt.Errorf("GetOccurrence: %v", err)
			}
			switch updated.GetDiscovery().GetAnalysisStatus() {
			case grafeaspb.DiscoveryOccurrence_FINISHED_SUCCESS,
				grafeaspb.DiscoveryOccurrence_FINISHED_FAILED,
				grafeaspb.DiscoveryOccurrence_FINISHED_UNSUPPORTED:
				return discoveryOccurrence, 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
// const retries = 5 // The number of retries to listen for the new Pub/Sub messages

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

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

let filter = `resourceUrl="${imageUrl}" AND noteProjectId="goog-analysis" AND noteId="PACKAGE_VULNERABILITY"`;

// Repeatedly query the Container Analysis API for the latest discovery occurrence until it is
// either in a terminal state, or the timeout value has been exceeded
const pRetry = require('p-retry');
const discoveryOccurrence = await pRetry(
  async () => {
    const [occurrences] = await client.getGrafeasClient().listOccurrences({
      parent: formattedParent,
      filter: filter,
    });
    if (occurrences.length < 0) {
      throw new Error('No occurrences found for ' + imageUrl);
    }
    return occurrences[0];
  },
  {
    retries: retries,
  }
);

// Wait for discovery occurrence to enter a terminal state or the timeout value has been exceeded
const finishedOccurrence = await pRetry(
  async () => {
    let status = 'PENDING';
    const [updated] = await client.getGrafeasClient().getOccurrence({
      name: discoveryOccurrence.name,
    });
    status = updated.discovery.analysisStatus;
    if (
      status !== 'FINISHED_SUCCESS' &&
      status !== 'FINISHED_FAILED' &&
      status !== 'FINISHED_UNSUPPORTED'
    ) {
      throw new Error('Timeout while retrieving discovery occurrence');
    }
    return updated;
  },
  {
    retries: retries,
  }
);
console.log(
  `Found discovery occurrence ${finishedOccurrence.name}.  Status: ${finishedOccurrence.discovery.analysisStatus}`
);

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"
# timeout_seconds = "The number of seconds to wait for the discovery
#                    occurrence"
# project_id      = "Your Google Cloud project ID"

require "grafeas"

deadline = Time.now + timeout_seconds

# Initialize the client
client = Grafeas.new
formatted_parent = Grafeas::V1::GrafeasClient.project_path project_id

# Find the discovery occurrence using a filter string
discovery_occurrence = nil
while discovery_occurrence.nil?
  begin
    filter = 'resourceUrl="#{resource_url}" ' \
             'AND noteProjectId="goog-analysis" ' \
             'AND noteId="PACKAGE_VULNERABILITY"'
    # Only the discovery occurrence should be returned for the given filter
    discovery_occurrence = client.list_occurrences(formatted_parent, filter: filter).first
  rescue StandardError # If there is an error, keep trying until the deadline
    puts "discovery occurrence not yet found"
  ensure
    # check for timeout
    sleep 1
    if Time.now > deadline
      raise "Timeout while retrieving discovery occurrence."
    end
  end
end

# Wait for the discovery occurrence to enter a terminal state
status = Grafeas::V1::DiscoveryOccurrence::AnalysisStatus::PENDING
while status != :FINISHED_SUCCESS &&
      status != :FINISHED_FAILED &&
      status != :FINISHED_UNSUPPORTED
  # Update occurrence
  begin
    updated = client.get_occurrence discovery_occurrence.name
    status = updated.discovery.analysis_status
  rescue StandardError # If there is an error, keep trying until the deadline
    puts "discovery occurrence not yet in terminal state"
  ensure
    # check for timeout
    sleep 1
    if Time.now > deadline
      raise "Timeout while retrieving discovery occurrence."
    end
  end
end
puts "Found discovery occurrence #{updated.name}."
puts "Status: #{updated.discovery.analysis_status}"

Python

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

def poll_discovery_finished(resource_url, timeout_seconds, project_id):
    """Returns the discovery occurrence for a resource once it reaches a
    terminal state."""
    # resource_url = 'https://gcr.io/my-project/my-image@sha256:123'
    # timeout_seconds = 20
    # project_id = 'my-gcp-project'

    import time
    from grafeas.grafeas_v1.gapic.enums import DiscoveryOccurrence
    from google.cloud.devtools import containeranalysis_v1

    deadline = time.time() + timeout_seconds

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

    discovery_occurrence = None
    while discovery_occurrence is None:
        time.sleep(1)
        filter_str = 'resourceUrl="{}" \
                      AND noteProjectId="goog-analysis" \
                      AND noteId="PACKAGE_VULNERABILITY"'.format(resource_url)
        result = grafeas_client.list_occurrences(project_name, filter_str)
        # only one occurrence should ever be returned by ListOccurrences
        # and the given filter
        for item in result:
            discovery_occurrence = item
        if time.time() > deadline:
            raise RuntimeError('timeout while retrieving discovery occurrence')

    status = DiscoveryOccurrence.AnalysisStatus.PENDING
    while status != DiscoveryOccurrence.AnalysisStatus.FINISHED_UNSUPPORTED \
            and status != DiscoveryOccurrence.AnalysisStatus.FINISHED_FAILED \
            and status != DiscoveryOccurrence.AnalysisStatus.FINISHED_SUCCESS:
        time.sleep(1)
        updated = grafeas_client.get_occurrence(discovery_occurrence.name)
        status = updated.discovery.analysis_status
        if time.time() > deadline:
            raise RuntimeError('timeout while waiting for terminal state')
    return discovery_occurrence

スキャンのステータスが FINISHED_SUCCESS になった時点で、脆弱性のリストを表示する準備が完了しています。

イメージに関連するすべての脆弱性の一覧表示

既知の脆弱性はメモとして保存されます。Container Analysis は、イメージの分析中に検出したメモのインスタンスごとにオカレンスを作成します。Container Analysis は、脆弱性に関する新しい情報を収集すると、オカレンスのリストを自動的に更新します。

GCP Console、gcloud コマンドライン ツール、Container Analysis API を使用して、メモとオカレンスに関する情報を取得できます。また、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))

重大度の高い脆弱性の一覧表示

ぞれぞれの脆弱性には重大度レベルが関連付けられています。Container Analysis では、サポート対象の Linux ディストリビューションによって提供される重大度レベルの情報が使用されます。ディストリビューションに固有の重大度レベルを使用できない場合は、CVSS スコアに基づくレベルが割り当てられます。

脆弱性の修正プランに優先順位を付けるには、脆弱性のリストを重大度の高い脆弱性のみに絞り込むことができます。

次のコードサンプルは、イメージで「高」または「重大」の重大度が割り当てられた脆弱性のリストを取得します。

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 io.grafeas.v1.Severity;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

public class HighVulnerabilitiesForImage {
  // Retrieve a list of vulnerability occurrences with a severity level of 'HIGH' or greater
  public static List<Occurrence> findHighSeverityVulnerabilitiesForImage(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()) {
      Severity severity = o.getVulnerability().getSeverity();
      if (severity == Severity.HIGH || severity == Severity.CRITICAL) {
        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"
)

// findHighSeverityVulnerabilitiesForImage retrieves a list of only high vulnerability occurrences associated with a resource.
func findHighSeverityVulnerabilitiesForImage(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)
		}

		severityLevel := occ.GetVulnerability().GetSeverity()
		if severityLevel == grafeaspb.Severity_HIGH || severityLevel == grafeaspb.Severity_CRITICAL {
			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 with a severity level of 'HIGH' or greater
const [occurrences] = await client.getGrafeasClient().listOccurrences({
  parent: formattedParent,
  filter: `kind = "VULNERABILITY" AND resourceUrl = "${imageUrl}"`,
});

if (occurrences.length) {
  console.log(`High Severity Vulnerabilities for ${imageUrl}`);
  occurrences.forEach(occurrence => {
    if (
      occurrence.vulnerability.severity === 'HIGH' ||
      occurrence.vulnerability.severity === 'CRITICAL'
    ) {
      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\""
vulnerability_list = client
                     .list_occurrences(formatted_parent, filter: filter)
# Filter the list to include only "high" and "critical" vulnerabilities
vulnerability_list.select do |item|
  item.vulnerability.severity == :HIGH || item.vulnerability.severity == :CRITICAL
end

Python

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

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

    from grafeas.grafeas_v1.gapic.enums import Severity
    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)
    vulnerabilities = grafeas_client.list_occurrences(project_name, filter_str)
    filtered_list = []
    for v in vulnerabilities:
        if v.severity == Severity.HIGH or v.severity == Severity.CRITICAL:
            filtered_list.append(v)
    return filtered_list

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud Platform アカウントに課金されないようにする手順は次のとおりです。

イメージの削除

追加した Docker イメージのみを削除する場合は、次のコマンドを実行して Container Registry から Docker イメージを削除します。

gcloud container images delete gcr.io/[PROJECT-ID]/vulnerabilities-tutorial-image:tag1 --force-delete-tags

[PROJECT-ID] は Google Cloud Platform Console プロジェクト ID です。プロジェクト ID にコロン(:)が含まれている場合は、ドメインをスコープとするプロジェクトをご覧ください。

プロジェクトの削除

課金をなくす最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。

プロジェクトを削除する手順は次のとおりです。

  1. GCP Console で [プロジェクト] ページに移動します。

    プロジェクト ページに移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

次のステップ

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

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