{"id":17747670,"url":"https://github.com/docker/attest","last_synced_at":"2025-04-01T16:31:02.824Z","repository":{"id":259351982,"uuid":"786979563","full_name":"docker/attest","owner":"docker","description":"Library to create, verify, and evaluate policy for attestations on container images","archived":false,"fork":false,"pushed_at":"2024-10-24T09:05:51.000Z","size":1086,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-24T19:01:58.639Z","etag":null,"topics":["attestation","in-toto","oci","rego","slsa","supply-chain-security","the-update-framework"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/docker.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE-OF-CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-04-15T16:57:09.000Z","updated_at":"2024-10-24T09:05:54.000Z","dependencies_parsed_at":"2024-10-24T19:10:33.954Z","dependency_job_id":"1c106176-0835-4ee8-84f2-adb391d3b1af","html_url":"https://github.com/docker/attest","commit_stats":null,"previous_names":["docker/attest"],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/docker%2Fattest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/docker%2Fattest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/docker%2Fattest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/docker%2Fattest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/docker","download_url":"https://codeload.github.com/docker/attest/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246623797,"owners_count":20807405,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["attestation","in-toto","oci","rego","slsa","supply-chain-security","the-update-framework"],"created_at":"2024-10-26T10:00:21.206Z","updated_at":"2025-04-01T16:31:02.450Z","avatar_url":"https://github.com/docker.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `attest`\n\n\u003cdiv align=\"center\"\u003e\nLibrary to create attestation signatures on container images, and verify images against policy.\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/docker/attest.svg)](https://pkg.go.dev/github.com/docker/attest)\n[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/docker/attest/test.yml?branch=main)](https://github.com/docker/attest/actions/workflows/test.yml)\n[![codecov](https://codecov.io/gh/docker/attest/graph/badge.svg?token=cGT0f1ACKg)](https://codecov.io/gh/docker/attest)\n\n\u003c/div\u003e\n\n# Table of Contents\n\n- [`attest`](#attest)\n- [Table of Contents](#table-of-contents)\n- [What is this?](#what-is-this)\n- [Features](#features)\n- [Installation](#installation)\n- [Usage](#usage)\n  - [Verifying Image Attestations](#verifying-image-attestations)\n  - [Signing Attestations](#signing-attestations)\n- [Rego Policy](#rego-policy)\n  - [Writing Policy](#writing-policy)\n    - [Input](#input)\n    - [Builtin Functions](#builtin-functions)\n  - [Policy Mapping](#policy-mapping)\n- [Public Key IDs](#public-key-ids)\n- [Transparency Logging](#transparency-logging)\n- [Verification Summary Attestation (VSA)](#verification-summary-attestation-vsa)\n  - [Example VSA](#example-vsa)\n- [API Reference](#api-reference)\n- [Project Layout](#project-layout)\n- [Versioning](#versioning)\n\n# What is this?\n\n`attest` is a library for signing and verifying [in-toto](https://in-toto.io/) attestations on container images.\nExamples of attestations include statements about the provenance and SBOM of an image.\n\nThis library can be used to verify these attestations using Rego policy.\nPolicy can be used to check whether an attestation is correctly signed, and that the contents of the attestation are correct.\n\n# Features\n\n- Sign in-toto attestations\n- Push attestations to container registries using OCI 1.1 compatible artifacts\n- Verify attestations on container images using Rego policy and attestations fetched using OCI 1.1 referrers\n\n# Installation\n\n```shell\n$ go get github.com/docker/attest\n```\n\n# Usage\n\n## Verifying Image Attestations\n\nAn image's attestations can be verified against a policy using the `attest.Verify` function.\nThis function takes an [oci.ImageSpec](https://github.com/docker/attest/blob/781a738b54b9549c1dabfd7ea3f7ea582514ddec/pkg/oci/types.go#L35-L41) for the image to verify, and a set of options for policy resolution.\nBy default, the policy is resolved from the [the Docker TUF repository](https://github.com/docker/tuf), but the options can be used to specify an alternative TUF repository, a local policy directory, and/or a policy ID to use.\nSee [Policy Mapping](#policy-mapping) for more details.\n\nThe `attest.Verify` function returns a `VerificationSummary` object, which contains the results of the policy evaluation.\n\nSee [example_verify_test.go](./example_verify_test.go) for an example of how to verify an image against a policy.\n\n## Signing Attestations\n\nin-toto statements can be signed directly using the `attestation.SignInTotoStatement` function.\nThis function takes a statement and DSSE signer, and returns a signed DSSE envelope containing a copy of the original statement.\n\nFor the common use case of signing a statement and adding it to a manifest, e.g. for pushing to a registry as a referrer to the image being attested, the `attestation.AttestationManifest` type can be used.\nSee [example_attestation_manifest_test.go](./pkg/attestation/example_attestation_manifest_test.go)\n\nSee also [example_sign_test.go](./example_sign_test.go) for an example of how to sign all attached in-toto statements on an image, e.g. those produced by buildkit.\n\n# Rego Policy\n\nAn image policy consists of one or more `rego` files and, optionally, `json` or `yaml` data files.\n\nThe policies for trusted namespaces `docker.io/docker` and `docker.io/library` are stored in [the Docker TUF root](https://github.com/docker/tuf) under the `docker` and `doi` target sub-directories respectively.\n\n## Writing Policy\n\n`attest` uses [Open Policy Agent](https://www.openpolicyagent.org/) (OPA) for policy evaluation, and policies are written in Rego.\nA full guide to writing Rego policies is available in the [Rego documentation](https://www.openpolicyagent.org/docs/latest/policy-language/).\n\nFor attest, a policy must contain at a minimum a `result` rule in a package called `attest` that returns an object matching the schema defined by the [`policy.Result`](https://github.com/docker/attest/blob/bd2c4d7d8aa497754b674412b09628be8d02fab5/pkg/policy/types.go#L23-L27) struct.\nFor example:\n\n```rego\npackage attest\n\nimport rego.v1\n\nresult := {\n\t\"success\": true,\n\t\"violations\": set(),\n\t\"summary\": {\n\t\t\"subjects\": subjects,\n\t\t\"slsa_levels\": [\"SLSA_BUILD_LEVEL_3\"],\n\t\t\"verifier\": \"docker-official-images\",\n\t\t\"policy_uri\": \"https://docker.com/official/policy/v0.1\",\n\t},\n}\n```\n\nThe meanings of the fields in the `result` object are as follows:\n\n- `success` (bool): whether the policy passes\n- `violations` (set): a set of strings describing any policy violations\n- `summary` (object): a summary of the policy evaluation, used to construct a Verification Summary Attestation (VSA)\n  - `subjects` (set): a set of strings representing the subjects of each attestation that was evaluated\n  - `slsa_levels` (list): a list of strings representing the SLSA levels that the policy complies with\n  - `verifier` (string): the entity that verified the policy\n  - `policy_uri` (string): the URI of the policy\n\nThe `violations` set may contain policy violations even if `success` is `true`.\nThis can be useful if there are attestations that are invalid, but are not required by the policy.\n\n### Input\n\nThe input to the policy is an object with the following fields:\n\n- `digest` (string): the digest of the image being verified\n- `purl` (string): the package URL of the image being verified\n- `platform` (string): the platform of the image being verified\n- `normalized_name` (string): defaults are filled out. e.g. if the image is `alpine`, this would be `library/alpine`\n- `familiar_name` (string): short version of above (e.g. `alpine`)\n- `tag`: (string): tag of the image being verified (if present)\n\n### Builtin Functions\n\nThere are two builtin functions provided by `attest` that can be used to help with policy evaluation:\n\n- `attest.fetch(predicate_type)`: fetches all attestations for the input image with the given predicate type.\n  For example, `attest.fetch(\"https://spdx.dev/Document\")` will fetch all SPDX SBOM attestations for the input image.\n- `attest.verify(attestation, options)`: verifies the DSSE envelope of the given attestation, and returns the statement.\n  The options object can contain the following fields:\n  - `keys` (array): keys to use for signature verification. Each key contains the following fields:\n    - `id` (string): the key ID as specified in [Public Key IDs](#public-key-ids)\n    - `key` (string): the PEM-encoded public key\n    - `from` (string): the time from which the key is valid, or `null` if the key was always valid (default: `null`)\n    - `status` (string): `active` if the key is active, otherwise the reason the key is inactive.\n      This is only used in error messages if the `from` date is in the past\n    - `distrust` (bool): whether the key should be distrusted (default: `false`).\n      If `true`, the key will be considered invalid\n    - `signing-format` (string): the format of the signing key, must be `dssev1`\n  - `skip_tl` (bool): whether to skip transparency log entry verification (see [Transparency Logging](#transparency-logging)) (default: `false`)\n\nBoth `attest.fetch` and `attest.verify` return an object with the following fields:\n\n- `value`: the return value of the function if successful\n- `error`: an error message if the function failed\n\nThis is to allow the policy to easily construct a violation if an error occurs, which isn't usually possible with custom functions in Rego.\n\nThe return value of `attest.fetch` is an attestation which can be passed to `attest.verify`.\n\n## Policy Mapping\n\nA `mapping.yaml` file is stored at the root of TUF targets and contains the mapping from repository name to files containing the corresponding policy.\n\nA simple mapping file might look like this:\n\n```yaml\nversion: v1\nkind: policy-mapping\npolicies:\n  - id: docker-official-images\n    description: Docker Official Images\n    files:\n      - path: doi/policy.rego\nrules:\n  - pattern: \"^docker[.]io/library/(.*)$\"\n    policy-id: docker-official-images\n```\n\nThe `policies` section contains a list of policies, each with an `id` and a `description`, and a list of `files` containing the policy.\nThe `rules` section contains a list of rules that map regex expressions to policies.\nIf the `pattern` regex matches the repository name, the policy with the `policy-id` is used to evaluate the image.\nIn the above example, any repository in the `docker.io/library` namespace will be evaluated against the policy in `doi/policy.rego`.\n\nSometimes it is necessary to rewrite the repository name before evaluating the policy.\nThis can be useful when the repository name which is used to reference the image is different from the repository name in the attestations.\nFor example, when mirroring images from a public registry to a private registry, the repository name in the attestations will be the public registry, but the image will be referenced by the name of the private registry.\n\nAn example of a mapping file with rewrite rules might look like this:\n\n```yaml\nversion: v1\nkind: policy-mapping\npolicies:\n  - id: docker-official-images\n    description: Docker Official Images\n    files:\n      - path: doi/policy.rego\nrules:\n  - pattern: \"^docker[.]io/library/(.*)$\"\n    policy-id: docker-official-images\n  - pattern: \"^public[.]ecr[.]aws/docker/library/(.*)$\"\n    platforms: [\"linux/amd64\"] # optional: restrict image platforms for matching policies (default: all)\n    rewrite: docker.io/library/$1\n```\n`platforms` in the second rule above is optional and can be used to restrict the platforms for which the policy\n is evaluated. If the `platforms` field is not present, the policy will be applied to all platforms.\n It's important to note that the `platforms` field is a filter, and is applied before the `pattern`\n field is processed, so both `platforms` and `pattern` need to match in order for the policy to be selected\n (or the rewrite to be processed if present).\n\nAs before, any repository in the `docker.io/library` namespace will be evaluated against the policy in `doi/policy.rego`.\nThe second rule will rewrite any repository in the `public.ecr.aws/docker/library` namespace to `docker.io/library`.\nThis means two things:\n\n1. The rules are evaluated again using the rewritten repository name until a policy is found (in this case the first rule will match); and\n2. The rewritten name is passed into the actual policy when it is evaluated.\n\nThe `rewrite` field is not a simple string replacement, but a regex replacement.\nThis means that the `rewrite` field can contain capture groups that are referenced in the `pattern` field.\nFor example, the `rewrite` field in the example above contains `$1`, which is a reference to the first capture group in the `pattern` field.\n\n\u003e [!IMPORTANT]\n\u003e It's important to remember to escape the `.` character in the `pattern` field, as it is a special character in regex.\n\u003e This is why the `.` character is surrounded by `[]` in the example above.\n\u003e\n\u003e It's also important to make use of the `^` and `$` characters in the `pattern` field to ensure that the regex matches the entire repository name.\n\u003e This is to prevent the regex from matching a subset of the repository name, e.g. `docker.io/library` matching `notdocker.io/library`.\n\nLocal policy can also be specified via a local `mapping.yaml`, which can be used to create new mirrors of policies described in the Docker TUF root, as well as describing entirely independent policies. For example:\n\n```golang\n// configure policy options\nopts := \u0026policy.PolicyOptions{\n  TufClient:       tufClient,\n  LocalPolicyDir:  \"\u003cpolicy-dir\u003e\", // overrides TUF policy for local policy files if set\n  PolicyId:        \"\u003cpolicy-id\u003e\", // set to ignore policy mapping and select a policy by id\n}\n\nsrc, err := oci.ParseImageSpec(image, oci.WithPlatform(platform))\nif err != nil {\n  panic(err)\n}\n// verify attestations\nresult, err := attest.Verify(context.Background(), src, opts)\nif err != nil {\n  panic(err)\n}\n```\n\nwhere `\u003cpolicy-dir\u003e` is a directory containing a `mapping.yaml` file, and any policy files referenced in the `mapping.yaml`. For example:\n\n```\n├── myimages\n│   ├── data.yaml\n|   ├── keys.yaml\n│   └── policy.rego\n└── mapping.yaml\n```\n\n\u003e [!NOTE]\n\u003e\n\u003e `PolicyId` can also be set to select a policy by ID, completely ignoring the `rules` section of the mapping file.\n\nThe rules section of a local `mapping.yaml` can refer to the policies described in the `mapping.yaml` file in the Docker TUF root to specify additional mirrors to which the referenced policy can be applied.\n\nFor example, it might be desirable to mirror `docker.io/library` to a local registry for testing:\n\n```yaml\nversion: v1\nkind: policy-mapping\nrules:\n  - pattern: \"^localhost:5001/(.*)$\"\n    rewrite: docker.io/library/$1\n```\n\nThe rewritten repository name will match the `docker-official-images` polict in the TUF managed `mapping.yaml`.\n\n\u003e [!WARNING]\n\u003e Local `mapping.yaml` policies take precendence over TUF managed policies, so for example, it's possible to apply a custom policy to `docker.io/library` namespace:\n\u003e\n\u003e ```yaml\n\u003e version: v1\n\u003e kind: policy-mapping\n\u003e policies:\n\u003e   - id: mydoi\n\u003e     description: my doi policy\n\u003e     files:\n\u003e       - path: \"mypolicy.rego\"\n\u003e\n\u003e rules:\n\u003e   - pattern: \"^docker[.]io/library/(.*)$\"\n\u003e     policy-id: mydoi\n\u003e ```\n\n# Public Key IDs\n\nWhen signing attestations, a key-id is generated from the public key and added to envelope.\nThis is used at verification time to look up the public key.\n\nTo generate a key-id from a public key, use `openssl` as follows:\n\n```shell\nopenssl pkey -in \u003cpublic-key.pem\u003e -pubin -outform DER | openssl dgst -sha256\n```\n\n# Transparency Logging\n\n`attest` supports transparency logging for attestation signatures.\nThis serves two purposes:\n\n1. the transparency log is a mechanism to ensure that all attestations are logged in a tamper-evident way, and that the logs are publicly auditable; and\n2. the transparency log is a trusted source of timestamps for attestations, which allows signatures to be verified even if the key used to sign the attestation has expired.\n\nBy default, transparency logging is enabled and the logs are stored in the [public-good Rekor](https://docs.sigstore.dev/logging/overview/) instance.\nAnother transparency log can be used by creating an implementation of the [tl.TL](https://github.com/docker/attest/blob/781a738b54b9549c1dabfd7ea3f7ea582514ddec/pkg/tlog/tl.go#L57-L62) interface and using [`tl.WithTL`](https://github.com/docker/attest/blob/781a738b54b9549c1dabfd7ea3f7ea582514ddec/pkg/tlog/tl.go#L37) to set in on a context.\nAlternatively, transparency logging can be disabled when signing by using `SkipTL` in the `SigningOptions`, and when verifying by using `skip_tl` in the options to `attest.verify` in the Rego policy.\n\n# Verification Summary Attestation (VSA)\n\nVerification of attestations can be expensive, especially when the attestations are large.\nFor example, an SBOM attestation can be several megabytes in size.\nAn alternative to consumers verifying the full attestation is to have a trusted entity verify the attestation and publish a [SLSA Verification Summary Attestation](https://slsa.dev/spec/v1.0/verification_summary) (VSA) to the registry.\nThe VSA can then be verified by the consumer without needing to verify the full attestation, as long as the consumer trusts the entity that signed the VSA.\nThis is useful when the consumer only needs to know that the attestation was verified by a trusted entity, and does not need to know the details of the attestation.\n\nA useful pattern is to have apply a policy to a third-party image at initial ingress, then publish a VSA when publishing the image to an internal registry to attest that the image complies with the policy.\nThe VSA can be verified very quickly, for example in a Kubernetes admission controller.\n\n`attest` always generates a [SLSA VSA](https://slsa.dev/spec/v1.0/verification_summary) when verifying attestations on an image.\nThe VSA can be signed and published to the registry using the signing functions mentioned in [Signing Attestations](#signing-attestations).\n\n## Example VSA\n\n```json\n{\n  \"_type\": \"https://in-toto.io/Statement/v1\",\n  \"subject\": [\n    {\n      \"name\": \"pkg:docker/example.org/example-image@1.0?platform=linux%2Famd64\",\n      \"digest\": {\n        \"sha256\": \"49f717386e5462e945232569a97a05831cb83bef8c3369be3bb7ea1793686960\"\n      }\n    }\n  ],\n  \"predicateType\": \"https://slsa.dev/verification_summary/v1\",\n  \"predicate\": {\n    \"verifier\": {\n      \"id\": \"https://example.org/internal-verifier\"\n    },\n    \"timeVerified\": \"2024-04-19T08:00:00.01Z\",\n    \"resourceUri\": \"pkg:docker/example.org/example-image@1.0?platform=linux%2Famd64\u0026digest=sha256%3A49f717386e5462e945232569a97a05831cb83bef8c3369be3bb7ea1793686960\",\n    \"policy\": {\n      \"uri\": \"https://example.org/internal-policy/v1\",\n      \"downloadLocation\": \"https://docker.github.io/tuf-staging/targets/docker/d71d6b8f49fcba1295b16f5394dd5863a14e4277eb663d66d8c48e392509afe0.policy.rego\",\n      \"digest\": {\n        \"sha256\": \"d71d6b8f49fcba1295b16f5394dd5863a14e4277eb663d66d8c48e392509afe0\"\n      }\n    },\n    \"verificationResult\": \"PASSED\",\n    \"verifiedLevels\": [\"SLSA_BUILD_LEVEL_3\"]\n  }\n}\n```\n\n# API Reference\n\nFull API reference can be found at [pkg.go.dev/github.com/docker/attest](https://pkg.go.dev/github.com/docker/attest).\n\n# Project Layout\n\n- [pkg/](https://pkg.go.dev/github.com/docker/image-signer-verifier/pkg) =\u003e packages that are okay to import for other projects\n- [internal/](https://pkg.go.dev/github.com/docker/image-signer-verifier/pkg) =\u003e packages that are only for project internal purposes\n- [scripts/](scripts/) =\u003e build scripts\n- [test/](test/) =\u003e data for use in tests\n\n# Versioning\n\n`attest` uses [Semantic Versioning](https://semver.org/).\nAs such, until `attest` reaches version 1.0.0, breaking changes may be introduced in minor versions.\n\n\u003e Anything MAY change at any time. The public API SHOULD NOT be considered stable.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdocker%2Fattest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdocker%2Fattest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdocker%2Fattest/lists"}