Overview

This document introduces Grafeas: a common API and language to store, query and retrieve metadata about software components.

Grafeas defines metadata API spec for computing components (e.g., VM images, container images, jar files, scripts) that can assist with aggregations over your metadata. Grafeas uses two API concepts, a note and an occurrence. This division allows 3rd party metadata providers to create and manage metadata on behalf of many customers. Additionally, the division also allows implementation of access control settings that allow fine grain access control.

Definition of terms

Notes: A note is an item or condition that can be found via an analysis or something that is used multiple times in a process. For example, a CVE could be the result of a vulnerability analysis of a Linux package. In a build process, we would store information about our builder in a note.

A note name should take the format /projects/<project_id>/notes/<note_id> where the project_id would typically be different from the project where the occurrence is created and the note_id would be unique per note-project, and informative if possible.

Access to notes should be read-only for users who have access to occurrences referencing them, and editable only by the note owner.

Occurrences: An occurrence can be thought of as an instantiation of a note and describes how the note was found in a specific cloud resource or project (e.g., location, specific remediation steps, etc.), or what the results of a specific note were (e.g., the container images that resulted from a build). For example, an occurrence might report that the heartbleed OpenSSL bug (a possible Note) was found in a specific package of a container image, and include information about how to remedy the heartbleed bug based on the customer’s package.

An occurrence name should take the format /projects/<project_id>/occurrences/<occurrence_id> where the project_id would typically be different from the project where the note is created and the occurrence_id would be unique per occurrence-project, and would often be random.

Write access to occurrences should only be granted to users who have access to link a note to the occurrence. Any users can have read access to occurrences.

Kind Specific Schemas

In order to properly aggregate over metadata stored in Grafeas, each kind of information stored has a strict schema. These schemas allow normalization of data from multiple providers, giving users the ability to see meaningful insights in their components over time. Defined below are the currently supported kinds, and a brief summary of what the notes and occurrences for each of them will contain. Specifying a kind in our notes and occurrences makes Grafeas extensible. As new metadata types need support, new kinds can be added, each with their own schema.

TODO:Document the process for adding a new kind to the spec and generating the model, documents, and client libraries to include that kind.

KindNote SummaryOccurrence Summary
PACKAGE_VULNERABILITYCVE or vulnerability description and details including severity, versionsAffected packages/versions in a specific resource
BUILD_DETAILSBuilder version and signatureDetails of this specific build including inputs and outputs
IMAGE_BASISBase Image for a containerAn image that uses the base image, and layers included on top of base image
PACKAGE_MANAGERPackage DescriptionsFilesystem locations of where the package is installed in a specific resource
DEPLOYMENT_HISTORYA resource that can be deployedDetails of each deployment of the resource
ATTESTATIONAnchor for attestations for this authorityAn attestation on a specific component

Examples

A vulnerability scanning provider would create a note under their project with the following json for CVE-2017-14159

{
  "name": "projects/security-scanner/notes/CVE-2017-14159",
  "shortDescription": "CVE-2017-14159",
  "longDescription": "NIST vectors: AV:L/AC:M/Au:N/C:N/I:N",
  "relatedUrl": [
    {
      "url": "https://security-tracker.debian.org/tracker/CVE-2017-14159",
      "label": "More Info"
    },
    {
      "url": "http://people.ubuntu.com/~ubuntu-security/cve/CVE-2017-14159",
      "label": "More Info"
    }
  ],
  "kind": "PACKAGE_VULNERABILITY",
  "createTime": "2017-09-05T21:44:52.071982Z",
  "updateTime": "2017-09-29T16:16:01.140652Z",
  "vulnerabilityType": {
    "cvssScore": 1.9,
    "severity": "LOW",
    "details": [
      {
        "cpeUri": "cpe:/o:debian:debian_linux:7",
        "severityName": "LOW",
        "fixedLocation": {
          "cpeUri": "cpe:/o:debian:debian_linux:7",
          "package": "openldap",
          "version": {
            "kind": "MAXIMUM"
          }
        },
        "minAffectedVersion": {
          "kind": "MINIMUM"
        },
        "package": "openldap",
        "description": "slapd in OpenLDAP 2.4.45 and earlier creates a PID file after dropping privileges to a non-root account, which might allow local users to kill arbitrary processes by leveraging access to this non-root account for PID file modification before a root script executes a \"kill `cat /pathname`\" command, as demonstrated by openldap-initscript."
      },
      {
        "cpeUri": "cpe:/o:debian:debian_linux:unstable",
        "severityName": "LOW",
        "fixedLocation": {
          "cpeUri": "cpe:/o:debian:debian_linux:unstable",
          "package": "openldap",
          "version": {
            "kind": "MAXIMUM"
          }
        },
        "minAffectedVersion": {
          "kind": "MINIMUM"
        },
        "package": "openldap",
        "description": "slapd in OpenLDAP 2.4.45 and earlier creates a PID file after dropping privileges to a non-root account, which might allow local users to kill arbitrary processes by leveraging access to this non-root account for PID file modification before a root script executes a \"kill `cat /pathname`\" command, as demonstrated by openldap-initscript."
      },
      {
        "cpeUri": "cpe:/o:debian:debian_linux:9",
        "severityName": "LOW",
        "fixedLocation": {
          "cpeUri": "cpe:/o:debian:debian_linux:9",
          "package": "openldap",
          "version": {
            "kind": "MAXIMUM"
          }
        },
        "minAffectedVersion": {
          "kind": "MINIMUM"
        },
        "package": "openldap",
        "description": "slapd in OpenLDAP 2.4.45 and earlier creates a PID file after dropping privileges to a non-root account, which might allow local users to kill arbitrary processes by leveraging access to this non-root account for PID file modification before a root script executes a \"kill `cat /pathname`\" command, as demonstrated by openldap-initscript."
      },
      {
        "cpeUri": "cpe:/o:debian:debian_linux:8",
        "severityName": "LOW",
        "fixedLocation": {
          "cpeUri": "cpe:/o:debian:debian_linux:8",
          "package": "openldap",
          "version": {
            "kind": "MAXIMUM"
          }
        },
        "minAffectedVersion": {
          "kind": "MINIMUM"
        },
        "package": "openldap",
        "description": "slapd in OpenLDAP 2.4.45 and earlier creates a PID file after dropping privileges to a non-root account, which might allow local users to kill arbitrary processes by leveraging access to this non-root account for PID file modification before a root script executes a \"kill `cat /pathname`\" command, as demonstrated by openldap-initscript."
      },
      {
        "cpeUri": "cpe:/o:canonical:ubuntu_linux:14.04",
        "severityName": "LOW",
        "fixedLocation": {
          "cpeUri": "cpe:/o:canonical:ubuntu_linux:14.04",
          "package": "openldap",
          "version": {
            "kind": "MAXIMUM"
          }
        },
        "minAffectedVersion": {
          "kind": "MINIMUM"
        },
        "package": "openldap",
        "description": "slapd in OpenLDAP 2.4.45 and earlier creates a PID file after dropping privileges to a non-root account, which might allow local users to kill arbitrary processes by leveraging access to this non-root account for PID file modification before a root script executes a \"kill `cat /pathname`\" command, as demonstrated by openldap-initscript."
      },
      {
        "cpeUri": "cpe:/o:canonical:ubuntu_linux:16.04",
        "severityName": "LOW",
        "fixedLocation": {
          "cpeUri": "cpe:/o:canonical:ubuntu_linux:16.04",
          "package": "openldap",
          "version": {
            "kind": "MAXIMUM"
          }
        },
        "minAffectedVersion": {
          "kind": "MINIMUM"
        },
        "package": "openldap",
        "description": "slapd in OpenLDAP 2.4.45 and earlier creates a PID file after dropping privileges to a non-root account, which might allow local users to kill arbitrary processes by leveraging access to this non-root account for PID file modification before a root script executes a \"kill `cat /pathname`\" command, as demonstrated by openldap-initscript."
      }
    ]
  }
}

On scanning and coming across this vulnerability, a security scanning provider would create the following in their customer’s project:

{
  "name": "projects/scanning-customer/occurrences/randomId1234",
  "resourceUrl": "https://gcr.io/scanning-customer/[email protected]:hash",
  "noteName": "projects/security-scanner/notes/CVE-2017-14159",
  "kind": "PACKAGE_VULNERABILITY",
  "createTime": "2017-09-29T02:58:23.376798Z",
  "updateTime": "2017-09-29T07:35:22.141762Z",
  "vulnerabilityDetails": {
    "severity": "LOW",
    "cvssScore": 1.9,
    "packageIssue": [
      {
        "affectedLocation": {
          "cpeUri": "cpe:/o:debian:debian_linux:8",
          "package": "openldap",
          "version": {
            "name": "2.4.40+dfsg",
            "revision": "1+deb8u2"
          }
        },
        "fixedLocation": {
          "cpeUri": "cpe:/o:debian:debian_linux:8",
          "package": "openldap",
          "version": {
            "kind": "MAXIMUM"
          }
        },
        "severityName": "LOW"
      }
    ]
  }
}

Resource Urls

Component resource Urls need to be unique per resource as well as immutable. This will mean that the metadata associated with a resourceUrl will always be associated with exactly one component, and what is pointed at should never change. Content addressable resource urls are preferred. In the case with resources that cannot be immutable, a timestamp should be appended.

The following table provides examples one could use as resource urls for several component types:

Component TypeIdentifierExample
Debiandeb://dist(optional):arch:name:versiondeb://lucid:i386:acl:2.2.49-2
Dockerhttps://Namespace/[email protected]:https://gcr.io/scanning-customer/[email protected]:244fd47e07d1004f0aed9c156aa09083c82bf8944eceb67c946ff7430510a77b
Generic filefile://sha256::namefile://sha256:244fd47e07d1004f0aed9c156aa09083c82bf8944eceb67c946ff7430510a77b:foo.jar
Mavengav://group:artifact:versiongav://ant:ant:1.6.5
NPMnpm://package:versionnpm://mocha:2.4.5
NuGetnuget://module:versionnuget://log4net:9.0.1
Pythonpip://package:versionpip://raven:5.13.0
RPMrpm://dist(optional):arch:name:versionrpm://el6:i386:ImageMagick:6.7.2.7-4