Tutorial: getting image vulnerabilities

This tutorial shows you how to use Container Analysis to scan a container image stored in Container Registry for vulnerabilities and then list high severity vulnerabilities for the image.

Objectives

This tutorial covers the following steps:

  1. Build a Docker image with known vulnerabilities
  2. Push the image to your project's Container Registry
  3. Poll Container Analysis for completion of the initial scan and analysis of the image
  4. View vulnerabilities identified by Container Analysis
  5. List high severity vulnerabilities for the image

Costs

This tutorial uses billable components of Google Cloud. See Pricing for pricing information.

Note: When you enable the Container Scanning API, billing begins immediately. Once you enable the API, Container Analysis automatically scans each newly pushed image, but does not automatically scan existing images. To scan an existing image, you must push it again.

New Google Cloud users might be eligible for a free trial.

Before you begin

To use Container Analysis, you must enable and set up Container Analysis and Container Registry.

  1. Sign in to your Google Account.

    If you don't already have one, sign up for a new account.

  2. In the GCP Console, on the project selector page, select or create a GCP project.

    Go to the project selector page

  3. Make sure that billing is enabled for your Google Cloud Platform project. Learn how to confirm billing is enabled for your project.

  4. Enable the Container Registry and Container Scanning APIs.

    Enable the APIs

  5. Install and initialize the Cloud SDK.
  6. If you have not already done so, do one of the following to obtain the required IAM permissions. If you are the project owner, skip this step.
    • To view occurrences, you must have the following permission:
      containeranalysis.notes.listOccurrences
    • Alternately, you can grant the following predefined IAM role, which will automatically provide the necessary permissions:
      Container Analysis Occurrences Viewer
  7. Install Docker. If you're using a Linux-based operating system, such as Ubuntu or Debian, add your username to the docker group so that you can run Docker without using sudo:
    sudo usermod -a -G docker ${USER}

    You may need to restart your system after adding yourself to the docker group.

  8. Open Docker. To ensure that Docker is running, run the following Docker command, which returns the current time and date:
  9. docker run busybox date

Building a Docker image

For this tutorial, build the following Docker image so that you have an image to push to Container Registry. You will use a Python runtime with known vulnerabilities that Container Analysis will identify. This Docker image contains a small Python web app. The app uses the Flask web framework to serve a web page which displays the message "Hello, World!"

To create the Docker image:

  1. Create a directory to store the three Docker image files.

  2. In this directory, create three files: Dockerfile, requirements.txt, and app.py. See the examples below for what you'll need to put in the contents of each file:

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:3.5-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)

To build the Docker image, run the following Docker command from the directory containing the image's files:

docker build -t vulnerabilities-tutorial-image .

You've now created a Docker image on your local machine.

Add the image to Container Registry

Configure docker to use the gcloud command-line tool as a credential helper

Before you can push or pull images, you must configure Docker to use the gcloud command-line tool to authenticate requests to Container Registry. To do so, run the following command (you are only required to do this once):

gcloud auth configure-docker

Tag the image with a registry name

Before you push the Docker image to Container Registry, you need to tag it with its registry name. Tagging the Docker image with a registry name configures the docker push command to push the image to a specific location. For this quickstart, the host location is gcr.io.

To tag the Docker image, run the following command:

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

where:

  • [PROJECT-ID] is your Google Cloud Console project ID, which you need to add to your command
  • gcr.io is the hostname
  • vulnerabilities-tutorial-image is the name of the Docker image
  • tag1 is a tag you're adding to the Docker image. If you didn't specify a tag, Docker will apply the default tag latest.

You are now ready to push the image to Container Registry.

Push the image to Container Registry

Once docker has been configured to use gcloud as a credential helper, and the local image is tagged with the registry name, you can push it to Container Registry.

To push the Docker image, run the following command:

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

where [PROJECT-ID] is your Google Cloud Console project ID. If your project ID contains a colon (:), see Domain-scoped projects.

When you push an image to a new host location, the service creates the underlying storage bucket unique to your project. You can view images hosted by Container Registry via the Cloud Console, or by visiting the image's registry name in your web browser: http://gcr.io/[PROJECT-ID]/vulnerabilities-tutorial-image.

Polling for initial scan and analysis results

Container Analysis automatically performs an initial scan and analysis of the image. It creates a discovery occurrence that includes information collected from that initial scan. Container Analysis also updates the discovery occurrence with the current status of the scan.

The following code sample polls for the current status of the initial scan so that you know when vulnerability information is available to view.

Java

To learn how to install and use the client library for Container Registry, see the Container Registry Client Libraries . For more information, see the Container Registry Java API reference documentation .

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

To learn how to install and use the client library for Container Registry, see the Container Registry Client Libraries . For more information, see the Container Registry Go API reference documentation .


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

To learn how to install and use the client library for Container Registry, see the Container Registry Client Libraries . For more information, see the Container Registry Node.js API reference documentation .

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

To learn how to install and use the client library for Container Registry, see the Container Registry Client Libraries . For more information, see the Container Registry Ruby API reference documentation .

# 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

To learn how to install and use the client library for Container Registry, see the Container Registry Client Libraries . For more information, see the Container Registry Python API reference documentation .

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

When the status of the scan is FINISHED_SUCCESS, you are ready to view the list of vulnerabilities.

Listing all vulnerabilities associated with an image

Known vulnerabilities are stored as notes. Container Analysis creates an occurrence for each instance of a note that it finds during analysis of the image. As Container Analysis collects new information about vulnerabilities, it updates the list of occurrences automatically.

You can retrieve information about notes and occurrences using the GCP Console, gcloud command-line tool, or the Container Analysis API. Additionally, the API supports a number of filter expressions for retrieving specific information about notes or occurrences.

The following code sample retrieves vulnerabilities found for an image.

Java

To learn how to install and use the client library for Container Registry, see the Container Registry Client Libraries . For more information, see the Container Registry Java API reference documentation .

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

To learn how to install and use the client library for Container Registry, see the Container Registry Client Libraries . For more information, see the Container Registry Go API reference documentation .


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

To learn how to install and use the client library for Container Registry, see the Container Registry Client Libraries . For more information, see the Container Registry Node.js API reference documentation .

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

To learn how to install and use the client library for Container Registry, see the Container Registry Client Libraries . For more information, see the Container Registry Ruby API reference documentation .

# 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

To learn how to install and use the client library for Container Registry, see the Container Registry Client Libraries . For more information, see the Container Registry Python API reference documentation .

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))

Listing high-severity vulnerabilities

A severity level is associated with each vulnerability. Container Analysis uses severity level information provided by supported Linux distributions. If distribution-specific severity levels are unavailable, assigned levels are based on CVSS scores.

To prioritize plans to address vulnerabilities, you can refine your list of vulnerabilities to high severity ones only.

The following code sample retrieves a list of vulnerabilities for an image that is assigned high or critical severity.

Java

To learn how to install and use the client library for Container Registry, see the Container Registry Client Libraries . For more information, see the Container Registry Java API reference documentation .

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

To learn how to install and use the client library for Container Registry, see the Container Registry Client Libraries . For more information, see the Container Registry Go API reference documentation .


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

To learn how to install and use the client library for Container Registry, see the Container Registry Client Libraries . For more information, see the Container Registry Node.js API reference documentation .

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

To learn how to install and use the client library for Container Registry, see the Container Registry Client Libraries . For more information, see the Container Registry Ruby API reference documentation .

# 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

To learn how to install and use the client library for Container Registry, see the Container Registry Client Libraries . For more information, see the Container Registry Python API reference documentation .

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

Cleaning up

To avoid incurring charges to your Google Cloud Platform account for the resources used in this tutorial:

Deleting the image

If you only want to remove the Docker image you added, run the following command to delete the Docker image from Container Registry.

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

where:[PROJECT-ID] is your Google Cloud Console project ID. If your project ID contains a colon (:), see Domain-scoped projects.

Deleting the project

The easiest way to eliminate billing is to delete the project that you created for the tutorial.

To delete the project:

  1. In the GCP Console, go to the Manage resources page.

    Go to the Manage resources page

  2. In the project list, select the project you want to delete and click Delete .
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

What's next

Kunde den här sidan hjälpa dig? Berätta:

Skicka feedback om ...

Container Registry