diff --git a/docs/_data/changelog.yml b/docs/_data/changelog.yml index 0b4f83b..b3b2510 100644 --- a/docs/_data/changelog.yml +++ b/docs/_data/changelog.yml @@ -1,3 +1,10 @@ +- date: '2025-12-31' # TODO + updates: + notation_plugin: + version: 1.1.1 + new_features: + - text: | + Initial Release of the [SignPath Notation plugin](/crypto-providers/notation). - date: '2025-10-23' updates: application: diff --git a/docs/_data/changelog_definitions.yml b/docs/_data/changelog_definitions.yml index 937e302..1bdbf2a 100644 --- a/docs/_data/changelog_definitions.yml +++ b/docs/_data/changelog_definitions.yml @@ -41,6 +41,9 @@ components: - id: scim_connector label: 'SCIM Connector' categories: [connectors] + - id: notation_plugin + label: 'Notation Plugin' + categories: [crypto_providers] categories: - id: application diff --git a/docs/_data/menus/documentation.yml b/docs/_data/menus/documentation.yml index cee5d16..581cf33 100644 --- a/docs/_data/menus/documentation.yml +++ b/docs/_data/menus/documentation.yml @@ -13,12 +13,18 @@ - text: Signing Container Images path: signing-containers items: + - text: Notary (Notation) + path: notary + - text: Sigstore Cosign path: cosign - text: Docker Content Trust (DCT) path: docker-content-trust + - text: GPG + path: gpg + - separator: true - text: Artifact Configuration @@ -89,6 +95,9 @@ - text: macOS CryptoTokenKit path: macos + - text: Notation + path: notation + - text: REST API path: rest-api diff --git a/docs/_data/tables/signing-containers.yml b/docs/_data/tables/signing-containers.yml index 3922308..471e218 100644 --- a/docs/_data/tables/signing-containers.yml +++ b/docs/_data/tables/signing-containers.yml @@ -1,37 +1,165 @@ -methods-differences: +methods-comparison: headers: topic: - cosign: Sigstore Cosign + notary: Notary (Notation) + cosign_fulcio: Cosign (with Fulcio) + cosign_keys: Cosign (Public/Private Keys) dct: Docker Content Trust (DCT) + gpg: GPG _attributes: - topic: {style: "width: 16%"} - cosign: {style: "width: 42%"} - dct: {style: "width: 42%"} + topic: { style: "width:15%" } + notary: { style: "width:17%" } + cosign_fulcio: { style: "width:17%" } + cosign_keys: { style: "width:17%" } + dct: { style: "width:17%" } + gpg: { style: "width:17%" } body: - - topic: OCI Registry Requirements - cosign: Works with any OCI registry. - dct: Requires [Notary](https://github.com/notaryproject/notary) server and signer (provided by _some_ OCI registries including Docker Hub and Azure Container Registry). - - topic: Validation Support - cosign: | - * Sigstore [Kubernetes Policy Controller](https://docs.sigstore.dev/policy-controller/overview/) - * [Connaisseur Cosign validator](https://sse-secure-systems.github.io/connaisseur/v3.3.2/validators/sigstore_cosign/) (third-party OSS) - dct: | - * [Docker CLI](https://docs.docker.com/engine/security/trust/) - * [Mirantis Kubernetes Engine (MKE)](https://docs.mirantis.com/containers/v3.0/dockeree-products/msr/msr-user/manage-images/sign-images/trust-with-a-remote-mke.html) - * [Connaisseur DCT validator](https://sse-secure-systems.github.io/connaisseur/v3.3.2/validators/notaryv1/) (third-party OSS) - * [trusted-compose](https://github.com/sse-secure-systems/trusted-compose) for Docker Compose (third party OSS) - - topic: Ecosystem - cosign: | - Integrated with other Sigstore components including - * [Fulcio](https://docs.sigstore.dev/certificate_authority/overview/), an OpenID-based certificate authority - * [Rekor](https://docs.sigstore.dev/logging/overview/), a transparency log + - _header: 'Feature Support' + - topic: Transfer signatures between registries + notary: 'Yes' + cosign_fulcio: 'No' + cosign_keys: 'No' + dct: 'No' + gpg: 'No' + - topic: Non-container artifacts + notary: 'Yes' + cosign_fulcio: 'Yes' + cosign_keys: 'Yes' + dct: 'No' + gpg: 'No' + - topic: Timestamping + notary: Yes (RFC 3161) + cosign_fulcio: Yes (through Rekor transparency log) + cosign_keys: Yes (through Rekor transparency log) + dct: Yes (through Notary "freshness") + gpg: 'No' + - topic: Invalidating signatures + notary: Yes (X.509 certificate revocation) + cosign_fulcio: Yes (Rekor log update) + cosign_keys: Yes (Rekor log update) + dct: Yes (via TUF) + gpg: 'No' + - topic: In-House X.509 PKI + notary: 'Yes' + cosign_fulcio: No (only with dedicated Fulcio server) + cosign_keys: 'No' + dct: 'No' + gpg: 'No' + - topic: Air-gapped systems + notary: 'Yes' + cosign_fulcio: 'No' + cosign_keys: 'Yes' + dct: 'No' + gpg: 'Yes' + - _header: Security attributes + - topic: Trust model + notary: PKI, X.509 + cosign_fulcio: Sigstore (Fulcio, Rekor) + cosign_keys: Public/Private Keys + dct: Notary v1, TUF + gpg: GPG Public Keys + - topic: Root of trust + notary: Root Certificate (X.509) + cosign_fulcio: OpenID Connect Issuer via Fulcio + cosign_keys: Public Key + dct: Trust on first use + gpg: GPG Keyring + - topic: Root key security + notary: Secure with SignPath + cosign_fulcio: Sigstore.dev (public Fulcio instance) keeps keys secure via TUF + cosign_keys: n/a + dct: Only file-based root key support + gpg: Via GPG ecosystem + - topic: Signing key security + notary: Secure with SignPath + cosign_fulcio: None (short-lived client side keys) + cosign_keys: Secure with SignPath + dct: Secure with SignPath + gpg: Secure with SignPath + - _header: Validation support + - topic: Kubernetes admission controllers + notary: Ratify for K8s (recommended by AWS and Azure) + cosign_fulcio: Sigstore, Ratify, Connaisseur (public key only) + cosign_keys: Sigstore, Ratify, Connaisseur + dct: Connaisseur + gpg: Only podman + - topic: Required infrastructure + notary: | + * OCI-compliant container registry + cosign_fulcio: | + * Fulcio CA + * Rekor transparency log (optional) + * OCI-compliant registry + cosign_keys: | + * OCI-compliant Container registry dct: | - Based on - * [The Update Framework (TUF)](https://theupdateframework.io/), an opinionated framework for code signing - * [Notary](https://github.com/notaryproject/notary), an online implementation of TUF - - topic: Industry Support - cosign: | - * Excellent adoption by OSS projects + * Docker registry + * Notary server + gpg: Podman runtime (no aditionl requirements) + - topic: Verification policy settings + notary: | + * Trusted root certificates + * Trusted timestamping certificates + * X.509 certificate fields + cosign_fulcio: | + * OpenID Connect issuer + * Subject + cosign_keys: | + * Key pinning dct: | - * Intially proposed by Docker (but never quite picked up) - * [Notation](https://github.com/notaryproject/specifications) (a.k.a. Notary 2) is supposed to eventually succeed DCT + * Key pinning + gpg: | + * Key pinning (per repository or registry) + - _header: Overview + - topic: Advantages + notary: | + * Simple setup + * Uses existing X.509 PKI infrastructure + * Mature trust model + * Recommended by Microsoft and Amazon + cosign_fulcio: | + * Existing infrastructure for open-source projects + * Public transparency log (optional) + * Podman support (public key only) + cosign_keys: | + * Public transparency log (optional) + dct: + gpg: | + * Podman support + - topic: Disadvantages + notary: + cosign_fulcio: | + * Verification only using repository and/or email addresses + * Signing without the public transparency log is discouraged + * Signature is not transferrable between registries + cosign_keys: | + * Verification only with public keys or special X.509 certificates + * Signing without the public transparency log is discouraged + * Signature is not transferrable between registries + dct: | + * Security concern: potential history rewrite + * No stable support in AKS + * Complex setup + * Legacy (no active development) + gpg: | + * Signature is not transferrable between registries + * Signature has to be provided out-of-band + - topic: Benefits with SignPath + notary: | + * Solves key security issue + cosign_fulcio: None + cosign_keys: | + * Solves key security issue + * Authenticates trusted build system instead of individual contributors for systems that are not natively supported + dct: | + * Solves key security issue + * Solves history rewrite issue + gpg: | + * Solves key security issue + * Solves GPG key handling + - topic: Recommended for + notary: Enterprises + cosign_fulcio: Open source projects + cosign_keys: + dct: + gpg: Podman diff --git a/docs/_includes/container_image_and_tag_panel.md b/docs/_includes/container_image_and_tag_panel.md new file mode 100644 index 0000000..f47a421 --- /dev/null +++ b/docs/_includes/container_image_and_tag_panel.md @@ -0,0 +1,12 @@ +{:.panel.info} +> **FQN and TAG** +> +> +> **Fully qualified name (FQN)** +> +> For images hosted on Docker Hub, the FQN is `docker.io/$namespace/$repository`, e.g. `docker.io/jetbrains/teamcity-server`. +> +> If you are using your own registry, specify the value you would use for Docker CLI commands, but without tag or digest values. E.g. when using `docker pull myreg.jfrog.io/> myrepo/myimage:latest`, the FQN would be `myreg.jfrog.io/myrepo/myimage`. +> +> +> `$TAG` refers the specific image tag (e.g. `latest`) \ No newline at end of file diff --git a/docs/_includes/render-table.html b/docs/_includes/render-table.html index b7f67a4..0a31d2c 100644 --- a/docs/_includes/render-table.html +++ b/docs/_includes/render-table.html @@ -25,17 +25,22 @@ {%- endunless -%} {%- endif -%} {%- if displayRow == true -%} - - {%- for cell in include.table.headers -%} - {%- assign columnId = cell[0] -%} - {%- unless columnId == "_attributes" or table-omit-columns contains columnId -%} - - + {%- if row._header -%} + + {{ row._header }} + + {%- else -%} + + {%- for cell in include.table.headers -%} + {%- assign columnId = cell[0] -%} + {%- unless columnId == "_attributes" or table-omit-columns contains columnId -%} + {{ row[columnId] }} - {%- endunless -%} - {%- endfor -%} - + {%- endunless -%} + {%- endfor -%} + + {%- endif -%} {%- endif -%} {%- endfor -%} diff --git a/docs/changelog/feeds/notation_plugin.xml b/docs/changelog/feeds/notation_plugin.xml new file mode 100644 index 0000000..0f6cdc1 --- /dev/null +++ b/docs/changelog/feeds/notation_plugin.xml @@ -0,0 +1,4 @@ +--- +layout: null +--- +{% include_relative changelog_feed.md category="notation_plugin" %} diff --git a/docs/crypto-providers/index.md b/docs/crypto-providers/index.md index 45937ff..bf2e86a 100644 --- a/docs/crypto-providers/index.md +++ b/docs/crypto-providers/index.md @@ -127,7 +127,7 @@ The following values Supported log levels: `none`, `fatal`, `error`, `warning`, `info`, `debug`, `verbose`. -#### Timeout settings +#### Timeout settings (Windows KSP, Cryptoki, GPG, MacOS) | JSON setting | Environment variable | Default Value | Description |-----------------------------|---------------------------------------|-------------------|------------------------- @@ -136,6 +136,15 @@ Supported log levels: `none`, `fatal`, `error`, `warning`, `info`, `debug`, `ver | `Timeouts.RetryCount` | `SIGNPATH_TIMEOUTS_RETRY_COUNT` | `10` | Maximum number of retries in case of failed API HTTP requests {: .break-column-2} +#### Timeout settings (Notation) + +| JSON setting | Environment variable | Default Value | Description +|--------------------------------------|----------------------------------------------------|---------------|------------------------- +| `ServiceUnavailableTimeoutInSeconds` | `SIGNPATH_SERVICE_UNAVAILABLE_TIMEOUT_IN_SECONDS ` | `600` | Total time in seconds that the command will wait for a single service call to succeed (across several retries). +| `HttpRequestTimeoutInSeconds` | `SIGNPATH_HTTP_REQUEST_TIMEOUT_IN_SECONDS` | `30` | Timeout for HTTP calls in seconds per attempt +{: .break-column-2} + + HTTP timeouts and 5xx server errors (e.g. 503 Service Unavailable errors) are treated as failed requests. The delay between retries increases exponentially. For the default values this sums up to a total delay time of 10 minutes. diff --git a/docs/crypto-providers/notation.md b/docs/crypto-providers/notation.md new file mode 100644 index 0000000..bc7ab16 --- /dev/null +++ b/docs/crypto-providers/notation.md @@ -0,0 +1,48 @@ +--- +header: Notation Plugin +layout: resources +toc: true +show_toc: 3 +description: SignPath Notation Plugin +--- + +## General instructions + +[notation] is a command line tool to creating and verifying signatures of artifacts stored in an OCI registry. It is most commonly used for container images. See the [section on signing container images with notation](/documentation/signing-containers/notation) for more details. + +### Installation + +The notation plugin can be installed using the following command: + +~~~bash +notation plugin install --url https://download.signpath.io/cryptoproviders/notation/1.0/linux/x64/notation-signpath.tar.gz --sha256sum +# or +notation plugin install --file /path/to/downloaded/notation-signpath +~~~ + +### Configuration + +See [SignPath Crypto Providers](/crypto-providers/#crypto-provider-configuration) for general configuration options. + +### Usage + +* The available [configuration values](/documentation/crypto-providers#crypto-provider-configuration) can also be passed in via the command line arguments `--plugin-config "Key="`. +* The notation _key id_ is comprised of the _project slug_ and _signing policy slug_, separated by a forward slash, e.g. `"MyProject/release-signing"` + +{% raw %} +~~~bash +export IMAGE_DIGEST=`docker inspect --format='{{index .RepoDigests 0}}' "$FQN:$TAG"` + +export SIGNPATH_API_KEY=...your-api-key... +notation sign \ + --signature-format cose \ + --id "$SIGNPATH_PROJECT_SLUG/$SIGNPATH_SIGNING_POLICY_SLUG" \ + --plugin signpath \ + --plugin-config "OrganizationId=$YOUR_ORGANIZATION_ID" \ + $IMAGE_DIGEST +~~~ +{% endraw %} + +{% include container_image_and_tag_panel.md %} + +[notation]: https://github.com/notaryproject/notation \ No newline at end of file diff --git a/docs/signing-containers/cosign.md b/docs/signing-containers/cosign.md index e682f84..6482cca 100644 --- a/docs/signing-containers/cosign.md +++ b/docs/signing-containers/cosign.md @@ -83,18 +83,7 @@ cosign generate $IMAGE_DIGEST > payload.json zip payload.json.zip payload.json ~~~ -{:.panel.info} -> **FQN and TAG** -> -> -> **Fully qualified name (FQN)** -> -> For images hosted on Docker Hub, the FQN is `docker.io/$namespace/$repository`, e.g. `docker.io/jetbrains/teamcity-server`. -> -> If you are using your own registry, specify the value you would use for Docker CLI commands, but without tag or digest values. E.g. when using `docker pull myreg.jfrog.io/> myrepo/myimage:latest`, the FQN would be `myreg.jfrog.io/myrepo/myimage`. -> -> -> `$TAG` refers the specific image tag (e.g. `latest`) +{% include container_image_and_tag_panel.md %} ### Step 2: create a signature for the metadata diff --git a/docs/signing-containers/gpg.md b/docs/signing-containers/gpg.md new file mode 100644 index 0000000..0f87ed4 --- /dev/null +++ b/docs/signing-containers/gpg.md @@ -0,0 +1,19 @@ +--- +header: GPG +layout: resources +toc: true +show_toc: 3 +description: Container signing with GPG +--- + +## Overview + +Standard GPG signatures can be used to sign container images and verify them using [podman](https://podman.io/). See [Red Hat's official documentation](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/8/html/building_running_and_managing_containers/assembly_signing-container-images_building-running-and-managing-containers) on how to perform the signing. + +There is no standard way of distributing GPG-based container image signatures (e.g. in an OCI-compliant registry), they have to be transferred out-of-band to the target system. + +## Signing with SignPath + +See the [GPG CryptoProvider documentation](/crypto-providers/gpg) for details. + +_Note: The signing happens on the client side. Only the image hash is transferred to SignPath._ \ No newline at end of file diff --git a/docs/signing-containers/index.md b/docs/signing-containers/index.md index 716bbbb..10862f6 100644 --- a/docs/signing-containers/index.md +++ b/docs/signing-containers/index.md @@ -8,27 +8,29 @@ redirect_from: /docker-signing datasource: tables/signing-containers --- + {% include editions.md feature="file_based_signing.docker" %} ## Overview +There are multiple technologies available for signing container images and they all differ from classic code signing methods as used by most platforms. The different technologies follow their individual philosophies and have their specific advantages and shortcomings. + +## Different technologies + SignPath supports these technologies for signing container images: +* **[Notary (Notation)](/signing-containers/notary)**: Sign containers using Notary - recommended by Microsoft (AKS) and Amazon (EKS) * **[Sigstore Cosign](/signing-containers/cosign)**: Sign containers using Cosign by Sigstore (a Linux foundation project) * **[Docker Content Trust (DCT)](/signing-containers/docker-content-trust)**: Sign containers using DCT, directly supported by the Docker CLI and Mirantis +* **[GPG](/signing-containers/gpg)**: Signing containers using GPG keys for RedHat OpenShift -## Comparing Cosign and DCT - -Both Cosign and DCT use concepts that differ widely from classic code signing methods as used by most platforms. Both follow their individual philosophies and have their specific advantages and shortcomings. We generally recommend the more modern Cosign, but according to your requirements you might prefer DCT. If DCT is a requirement by some customers, you might want to consider using both methods. - -### Similarities +### Recommendation -* **No classic Certificate Authorities:** Manual key/certificate trust configuration ("pinning") required -* **Signing items in OCI repositories rather than files:** Signatures are not transferable to other repositories, e.g. in replication scenarios +SignPath recommends using [Notary (Notation)](/signing-containers/notary) for Enterprises and [Cosign](/signing-containers/cosign) for open source projects. -### Differences +### Detailed comparison -{%- include render-table.html table=site.data.tables.signing-containers.methods-differences -%} +{%- include render-table.html table=site.data.tables.signing-containers.methods-comparison -%} {: .row-headers } ## Why use SignPath for container signing? @@ -36,7 +38,7 @@ Both Cosign and DCT use concepts that differ widely from classic code signing me SignPath provides the following advantages: * You can use the full power of SignPath **signing policies**, including permission, approval, and origin verification -* You can use all **CI integration** features of SignPath +* You can use all **CI integration** features of SignPath * Configuration and policy management is **aligned with other signing methods**, such as Authenticode or Java signing * SignPath maintains a **full audit log** of all signing activities including metadata such as the registry URL and signed image tag * You can **sign multiple images in a single signing request**, making audits/reviews of multi-image releases a lot easier diff --git a/docs/signing-containers/notary.md b/docs/signing-containers/notary.md new file mode 100644 index 0000000..c256e8b --- /dev/null +++ b/docs/signing-containers/notary.md @@ -0,0 +1,20 @@ +--- +header: Notary (Notation) +layout: resources +toc: true +show_toc: 3 +description: Documentation for signing Docker images with SignPath using Notary (Notation) +--- + +## Overview + +The _[Notary project](https://notaryproject.dev/)_ (aka Notary v2) is the successor of Docker Content Trust. It is developed by the [Cloud Native Computing Foundatio](https://cncf.io/). Both Microsoft and Amazon recommend Notation for signing container images deployed in their respective Kubernetes offerings. + +Notation uses standard PKI, is easy to set up and has a mature trust model. SignPath recommends Notation for signing container images in Enterprise environments. + +## Signing with SignPath + +Notary signatures are created using the [Notation CLI tool](https://github.com/notaryproject/notation). SignPath provides a plugin for signing. See the [SignPath Notation Plugin](/crypto-providers/notation) page for details. + +_Note: The signing happens on the client side. Only the image hash is transferred to SignPath._ +