Skip to content

Latest commit

 

History

History
378 lines (276 loc) · 15.9 KB

README.md

File metadata and controls

378 lines (276 loc) · 15.9 KB

Voucher Server

Installation

Install voucher_server by running:

$ go install github.com/grafeas/voucher/v2/cmd/voucher_server

This will download and install the voucher server binary into $GOPATH/bin directory.

Note: omitting "v2" from the path will download Voucher Server v1.

Configuration

See the Tutorial for more thorough setup instructions.

An example configuration file can be found in the config directory.

The configuration can be written as a toml, json, or yaml file, and you can specify the path to the configuration file using "-c".

Below are the configuration options for Voucher Server:

Group Key Description
dryrun When set, don't create attestations.
scanner The vulnerability scanner to use ("metadata").
failon The minimum vulnerability to fail on. Discussed below.
valid_repos A list of repos that are owned by your team/organization.
trusted_builder_identities A list of email addresses. Owners of these emails are considered "trusted" (and will pass Provenance)
trusted_projects A list of projects that are considered "trusted" (and will pass Provenance)
binauth_project The project in the metadata server that the binauth information is stored.
checks (test name here) A test that is active when running "all" tests.
server port The port that the server can be reached on.
server timeout The number of seconds to spend checking an image, before failing.
server require_auth Require the use of Basic Auth, with the username and password from the configuration.
server username The username that Voucher server users must use.
server password A password hashed with the bcrypt algorithm, for use with the username.
ejson dir The path to the ejson keys directory.
ejson secrets The path to the ejson secrets.
sops file The path to the SOPS secrets.
repository.[alias] org-url The URL used to determine if a repository is owned by an organization.
required.[env] (test name here) A test that is active when running "env" tests.
metrics backend The destination for reporting metrics, can be statsd for local aggregation, datadog for direct Datadog API, or opentelemetry for an otel collector.
metrics tags List of tags in key:value format that apply to every metric. Example: env:production.
statsd addr The UDP endpoint to use when metrics.backend == "statsd"
statsd sample_rate Configurable sample rate to limit metrics overhead.
opentelemetry interval The interval at which to flush metrics to the opentelemetry collector.
opentelemetry addr The http://, https:// or grpc:// address for the opentelemetry collector.
opentelemetry insecure Disable transport security like HTTPS for the opentelemetry collector.

Configuration options can be overridden at runtime by setting the appropriate flag. For example, if you set the "port" flag when running voucher_server, that value will override whatever is in the configuration.

Note that Repositories can be set multiple times. This is discussed futher below.

Secret values are stored encrypted in an ejson or SOPS file, and can not be overwritten at the command line. Below are the configuration secrets for Voucher Server. Ejson and SOPS secrets follow the same schema:

Group Key Description
openpgpkeys (test name here) The PGP key to use for signing attestations of a specific test.
datadog api_key API key for direct submission when configuration statsd.backend == "datadog".
datadog app_key App key for direct submission when configuration statsd.backend == "datadog".
repositories (repository owner name here) Credentials for repository authentication.

Scanner

The scanner option in the configuration is used to select the Vulnerability scanner.

This option supports one value:

  • metadata to use Google Container Analysis. (Note that g and gca are being deprecated in favor of metadata.)

Fail-On: Failing on vulnerabilities

The failon option allows you to set the minimum vulnerability to consider an image insecure.

This option supports the following:

  • "negligible"
  • "low"
  • "medium"
  • "unknown"
  • "high"
  • "critical"

For example, if you set failon to "high", only "high" and "critical" vulnerabilities will prevent the image from being attested. A value of "low" will cause "low", "medium", "unknown", "high", and "critical" vulnerabilities to prevent the image from being attested failure.

Valid Repos

The valid_repos option in the configuration is used to limit which repositories images must be from to pass the DIY check.

This option takes a list of repos, which are compared against the repos that images live in. An image will pass if it starts with any of the items in the list.

For example:

valid_repos = [
    "gcr.io/team-images/",
    "gcr.io/external-images/specific-project"
]

Will allow images that start with gcr.io/team-images/ and gcr.io/external-images/specific-project/ to pass the DIY check, while blocking other gcr.io/external-images/.

Trusted Builder Identities and Trusted Builder Projects

The provenance check works by obtaining the build metadata for an image from the metadata service, and verifying that it both comes from a trusted project and was built by a trusted builder.

You can use this to ensure that only images built by your continuous integration pipeline can be deployed to the cloud, with exceptions for images built by trusted administrators.

For example:

trusted_builder_identities = [
    "catherine@example.com",
    "idcloudbuild.gserviceaccount.com"
]
trusted_projects = [
    "team-images"
]

This would require that images be built in the team-images project, by either catherine@example.com or idcloudbuild.gserviceaccount.com. Images not built in the team-images project will fail Provenance regardless of who built them.

Repository Checks

Repository Groups

Repository Groups are used to determine which Repository client should be used to connect to a Repository.

They are defined as an alias (usually matching the name of the organization in the repository system) and a URL. Note that the alias can contain only lower cases letters, dashes, and underscores ([a-z_-]).

The URL is used to determine if a repository is owned by a repository group.

For example, a repository owned by Shopify, it's URL should contain github.com/Shopify. A repository owned by Grafeas, should contain github.com/grafeas, and so on.

Repository groups are required to use the Repository checks.

You can define repository groups as follows:

[repository.shopify]
org-url = "https://github.com/Shopify"

[repository.grafeas]
org-url = "https://github.com/grafeas"

Repository Authentication

For the repository groups to authenticate with a repository server, you will need to create secrets matching the alias name in your secrets file (ejson or SOPS).

For example, for the repository.shopify block, you would need a repositories block in your secrets with a shopify block inside of it:

{
  "repositories": {
    "shopify": {
      "token": "EJ[1:vt978NEKynsJhZlCvg5XdSE2S2PM1JBPK0tlC05cQAc=:4mDZCykfieedtHGoM0UT+Wr6zPO9J6XO:/AuGJ3I2QVnk52qOLo0sQ+EzEAk=]"
    }
  }
}

Note that like aliases, the name of the block must only contain lower cases letters, dashes, and underscores ([a-z_-]).

If your repository server supports personal access token, you can specify it by setting the token key (as in the example above).

If your repository server supports app based authentication (as Github does), you can specify the App ID, Installation ID, and the private key as follows:

{
  "repositories": {
    "shopify": {
      "_id": "1234",
      "_installation_id": "123456789",
      "private_key": "EJ[1:vt978NEKynsJhZlCvg5XdSE2S2PM1JBPK0tlC05cQAc=:4mDZCykfieedtHGoM0UT+Wr6zPO9J6XO:/AuGJ3I2QVnk52qOLo0sQ+EzEAk=]"
    }
  }
}

Organization Check

The organization check is a dynamic check which uses the name of an organization to determine if code came from that organization.

For example, if you have defined an organization as follows:

[[repositories]]
alias = "Shopify"
org-url = "https://github.com/Shopify"

You can enable a check that verifies that an image came from that organization:

[checks]
is_shopify = true

The name of the check is is_ followed by the name of the organization, converted to lowercase.

This check works by:

  • looking up the build metadata for an image from your metadata service
  • getting the repository information from that metadata
  • connecting to the API of that repository (in this example, Github)
  • verifying that the source code is associated with the organization that it says it is

Enabling Checks

You can enable certain checks for the "all" option by updating the checks block in the configuration.

For example:

[checks]
diy      = true
nobody   = true
provenance = false
snakeoil = true
is_shopify = true

With this configuration, the diy, nobody, snakeoil, and is_shopify checks would run when running all checks. The provenance check will be ignored unless called directly.

Check Groups

You can configure named groups of checks identically to how you would define an enable checks block, by replacing the block heading with required.[env] where [env] is a name of your choosing.

For example:

[required.myenv]
diy      = true
nobody   = true
provenance = false
snakeoil = true
is_shopify = true

With this configuration, the diy, nobody, snakeoil, and is_shopify checks would run when running myenv checks. The provenance check will be ignored unless called directly.

Signing Keys

OpenPGP Keys

You can use OpenPGP keys by encrypting them in your secrets file (ejson or SOPS).

First, ensure the signer is set to pgp in the configuration:

signer = "pgp"

Then add keys to your secrets file. This is documented more completely in the Tutorial.

Google KMS Keys

You can use Google KMS signing keys by switching the signer in the configuration:

signer = "kms"

Then you would specify the KMS keys in the configuration file, by adding [[kms_keys]] blocks.

For example, to have the DIY Check use a KMS key in the project binauth with the name diy-attestor, you would use the following:

[[kms_keys]]
check = "diy"
path  = "projects/binauth-staging/locations/global/keyRings/binauthz-keys/cryptoKeys/diy-attestor/cryptoKeyVersions/1"
algo  = "SHA512"

Usage

Using Voucher Server to check an image

You can run Voucher in server mode by launching voucher_server, using the following syntax:

$ voucher_server [--port <port number>]

voucher_server supports the following flags:

Flag Short Flag Description
--config -c The path to a configuration file that should be used.
--port -p Set the port to listen on.
--timeout The number of seconds to spend checking an image, before failing.

For example:

$ voucher_server --port 8000

This would launch the server, utilizing port 8000.

You can connect to Voucher over http.

For example, using curl:

$ curl -X POST -H "Content-Type: application/json" -d "{\"image_url\": \"gcr.io/path/to/image@sha256:ab7524b7375fbf09b3784f0bbd9cb2505700dd05e03ce5f5e6d262bf2f5ac51c\"}" http://localhost:8000/all

The response will be something along the following lines:

{
    "image": "gcr.io/path/to/image@sha256:ab7524b7375fbf09b3784f0bbd9cb2505700dd05e03ce5f5e6d262bf2f5ac51c",
    "success": false,
    "results": [
        {
            "name": "provenance",
            "error": "no occurrences returned for image",
            "success": false,
            "attested": false
        },
        {
            "name": "snakeoil",
            "success": true,
            "attested": true
        },
        {
            "name": "diy",
            "success": true,
            "attested": true
        },
        {
            "name": "nobody",
            "success": true,
            "attested": true
        }
    ]
}

More details about Voucher server can be read in the API documentation.