diff --git a/specs/signature-envelope-cose.md b/specs/signature-envelope-cose.md index 6df10e5..4aafd7d 100644 --- a/specs/signature-envelope-cose.md +++ b/specs/signature-envelope-cose.md @@ -4,7 +4,7 @@ This specification implements the [Notary Project signature specification](signa CBOR Object Signing and Encryption (COSE). COSE ([RFC8152](https://datatracker.ietf.org/doc/html/rfc8152)) is a CBOR based envelope format for digital signatures over any type of payload (e.g. CBOR, JSON, binary). Notary Project specifically supports [COSE_Sign1_Tagged](https://datatracker.ietf.org/doc/html/rfc8152#section-4.2) as a signature envelope. -## OCI Signature Storage +## Signature Storage A COSE signature envelope will be stored in an OCI registry as a blob, and referenced in the signature manifest as a layer blob with `mediaType` of `"application/cose"`. @@ -36,15 +36,12 @@ Signature Manifest Example } } ``` -## Blob Signature Storage - -For detached signatures associated with arbitrary blobs, a COSE signature envelope will be stored on the file system as a binary file with `cose` as the file extension. ## COSE Payload The COSE envelope contains the [Notary Project signature Payload](./signature-specification.md#payload). -Example of the Notary Project OCI signature payload: +Example ```jsonc { @@ -59,21 +56,6 @@ Example of the Notary Project OCI signature payload: } ``` -Example of the Notary Project blob signature payload: - -```jsonc -{ - "targetArtifact": { - "mediaType": "application/octet-stream", - "digest": "sha256:2f3a23b6373afb134ddcd864be8e037e34a662d090d33ee849471ff73c873345", - "size": 1024, - "annotations": { - "io.wabbit-networks.buildId": "123" // user defined metadata - } - } -} -``` - ## Protected Header The COSE envelope for the Notary Project signature uses the following header parameters: diff --git a/specs/signature-envelope-jws.md b/specs/signature-envelope-jws.md index e50a0cd..5342b46 100644 --- a/specs/signature-envelope-jws.md +++ b/specs/signature-envelope-jws.md @@ -2,9 +2,9 @@ This specification implements the [Notary Project signature specification](./signature-specification.md) using JSON Web Signature (JWS). JWS ([RFC7515](https://datatracker.ietf.org/doc/html/rfc7515)) is a JSON based envelope format for digital signatures over any type of payload (e.g. JSON, binary). JWS is the Notary Project supported signature format and specifically uses the *JWS JSON Serialization* representation. -## OCI Signature Storage +## Signature Storage -A JWS signature envelope will be stored in an OCI registry as a layer, and referenced in the signature manifest as a layer blob with `mediaType` of `"application/jose+json"`. +A JWS signature envelope will be stored in an OCI registry as a blob, and referenced in the signature manifest as a layer blob with `mediaType` of `"application/jose+json"`. Signature Manifest Example @@ -35,15 +35,11 @@ Signature Manifest Example } ``` -## Blob Signature Storage - -For detached signatures associated with blobs, a JWS signature envelope will be stored on the file system with `jws` as the file extension. - ## JWS Payload The JWS envelope contains the [Notary Project signature payload](./signature-specification.md#payload). -Example of the Notary Project OCI signature payload +Example ```jsonc { @@ -58,21 +54,6 @@ Example of the Notary Project OCI signature payload } ``` -Example of the Notary Project blob signature payload: - -```jsonc -{ - "targetArtifact": { - "mediaType": "application/octet-stream", - "digest": "sha256:2f3a23b6373afb134ddcd864be8e037e34a662d090d33ee849471ff73c873345", - "size": 1024, - "annotations": { - "io.wabbit-networks.buildId": "123" // user defined metadata - } - } -} -``` - ## Protected Headers The JWS envelope for the Notary Project signature uses following headers diff --git a/specs/signature-specification.md b/specs/signature-specification.md index 1c158ae..6783e0f 100644 --- a/specs/signature-specification.md +++ b/specs/signature-specification.md @@ -3,8 +3,7 @@ This document provides the following details for Notary Project signature: - **[Signature Envelope](#signature-envelope)**: Describes the structure of the Notary Project signature. -- **[OCI Signatures](#oci-signatures)**: Describes how signatures for OCI artifacts are stored and retrieved from an OCI registry. -- **[Blob Signatures](#blob-signatures)**: Describes how signatures for signed Blobs are stored on file system. +- **[Signature](#signature)**: Describes how signatures are stored and retrieved from an OCI registry. ## Signature Envelope @@ -30,25 +29,15 @@ The Notary Project signature supports following envelope formats: The Notary Project signature payload is a JSON document with media type `application/vnd.cncf.notary.payload.v1+json` and has following properties. - `targetArtifact` : Required property whose value is the descriptor of the target artifact manifest that is being signed. -- For OCI artifacts, this MUST be a valid [OCI descriptor][oci-descriptor]. +- This MUST be a valid [OCI descriptor][oci-descriptor]. - Descriptor MUST contain `mediaType`, `digest`, and `size` fields. - Descriptor MAY contain `annotations` and if present it MUST follow the [annotation rules][annotation-rules]. - Descriptor MAY contain `artifactType` field for the `config.mediaType` of OCI image manifests. -- For Blob artifacts, the descriptor MUST describe the blob that is being signed - - Descriptor MUST contain `mediaType`, `digest`, and `size` fields. - - `digest` MUST be in the format of `:`. Example: `sha256:2f3a23b6373afb134ddcd864be8e037e34a662d090d33ee849471ff73c873345` - - `digest algorithm` MUST be deduced from signing certificate's public key. See [Algorithm Selection](#algorithm-selection) - - `mediaType` can be any arbitrary media type that the user provides to describe the blob. An example can be `application/octet-stream` - - `size` MUST be the raw size of the blob in bytes. - - Blob descriptors MAY optionally contain `annotations` and if present it MUST follow the [annotation rules][annotation-rules]. NOTE: The Notary Project signature uses annotations for storing both Notary Project specific and user defined metadata. The prefix `io.cncf.notary` in `annotations` key is reserved for use in Notary Project signature and MUST NOT be used outside this specification. - #### Examples -##### OCI Payload - ```jsonc { "targetArtifact": { @@ -58,7 +47,7 @@ NOTE: The Notary Project signature uses annotations for storing both Notary Proj } } ``` -##### OCI Payload with artifactType and annotations +##### Payload with artifactType and annotations ```jsonc { @@ -73,31 +62,6 @@ NOTE: The Notary Project signature uses annotations for storing both Notary Proj } } ``` -##### Blob Payload - -```jsonc -{ - "targetArtifact": { - "mediaType": "application/octet-stream", - "digest": "sha256:2f3a23b6373afb134ddcd864be8e037e34a662d090d33ee849471ff73c873345", - "size": 1024 - } -} -``` -##### Blob Payload with annotations - -```jsonc -{ - "targetArtifact": { - "mediaType": "application/octet-stream", - "digest": "sha256:2f3a23b6373afb134ddcd864be8e037e34a662d090d33ee849471ff73c873345", - "size": 1024, - "annotations": { - "io.wabbit-networks.buildId": "123" // user defined metadata - } - } -} -``` ### Signed Attributes @@ -152,10 +116,10 @@ These attributes are considered unsigned with respect to the signing key that ge - **Timestamp Signature**: An OPTIONAL countersignature generated by a trusted third party, such as a Timestamp Authority (TSA). Its purpose is to demonstrate that the primitive signature, computed on payload and signed attributes, was generated before the timestamp. Only [RFC 3161][ietf-rfc3161] compliant timestamp signatures are supported. If present, this claim is validated and used solely under the [`notary.x509`](./signing-scheme.md/#notaryx509) signing scheme. - **Signing Agent**: An OPTIONAL claim that provides the identifier of the software (e.g. Notation) that produced the signature on behalf of the user. It is an opaque string set by the software that produces the signature. It's intended primarily for diagnostic and troubleshooting purposes, this attribute is unsigned, the verifier MUST NOT validate formatting, or fail validation based on the content of this claim. The suggested format is one or more tokens of the form `{id}/{version}` containing identifier and version of the software, separated by spaces. E.g. "notation/1.0.0", "notation/1.0.0 myplugin/0.8". -## OCI Signatures +## Signature This section describes how a Notary Project signature is stored in an OCI Distribution conformant registry. -OCI image manifest is used to store signatures in the registry, see [OCI image spec v1.1.0-rc3][oci-image-manifest] for details. +OCI image manifest is used to store signatures in the registry, see [OCI image spec v1.1.0][oci-image-manifest] for details. The signature manifest has a configuration media type that specifies it's a Notary Project signature, a subject referencing the manifest of the artifact being signed, a layer referencing the signature, and a collection of annotations. ![Signature storage inside registry](../media/oci-signature-specification.svg) @@ -207,29 +171,18 @@ Besides the [image manifest property requirements][image-manifest-property-descr Keys using the `io.cncf.notary` namespace are reserved for use in the Notary Project signature specification and MUST NOT be used by other specifications. - **`io.cncf.notary.x509chain.thumbprint#S256`**: A REQUIRED annotation whose value contains the list of SHA-256 fingerprints of signing certificate and certificate chain (including root) used for signature generation. The list of fingerprints is present as a JSON array string, corresponding to ordered certificates in [*Certificate Chain* unsigned attribute](#unsigned-attributes) in the signature envelope. The annotation name contains the hash algorithm as a suffix (`#S256`) and can be extended to support other hashing algorithms in future. -### OCI Signature Discovery +### Signature Discovery The client should be able to discover all the signatures belonging to an artifact (such as image manifest) by using [OCI Distribution Referrers API][oci-distribution-referrers]. OCI Distribution Referrers API returns a paginated list of all artifacts belonging to a target artifact (such as container images, SBoMs). The implementation can filter Notary Project signatures by either using OCI Distribution Referrers API or using custom logic on the client. Each Notary Project signature refers to a signature envelope blob. -### OCI Signature Filtering +### Signature Filtering An OCI artifact can have multiple signatures, implementations of the Notary Project signature specification uses annotations of the signature manifest to filter relevant signatures based on the applicable trust policy. The Notary Project signature manifest's `io.cncf.notary.x509chain.thumbprint#S256` annotation key MUST contain the list of SHA-256 fingerprints of certificate and certificate chain used for signing. -## Blob Signatures - -The Notary Project facilitates signing arbitrary blobs using detached signatures. These detached signatures can be transported via any preferred medium and verified on the receiving end. A detached signature refers to a signature that is not embedded within (and therefore does not modify) the original blob, instead it consists of a detached signature envelope with a signature over the unique representation of the blob (i.e. blob's digest). The file extension can either be 'jws' or 'cose', indicating the signature envelope format. - -![Signature storage inside file system](../media/blob-signature-specification.svg) - -### Differences between OCI and blob signatures - -1. Apart from the `payload` field, all other fields of a signature envelope are identical between OCI and blob signatures. -1. OCI signatures have signature manifest files, containing the mediaType of the signature envelope (application/jose+json or application/cose). However, blob signatures lack such manifest file and this mediaType information is instead found in the signature file extension. - ## Signature Algorithm Requirements The implementation MUST support the following set of algorithms: @@ -331,7 +284,7 @@ An `authentic signing time` is a signing time authenticated by a `Signing Author This is an optional feature that provides a "best by use" time for the artifact, as defined by the signer. The Notary Project signature specification allows users to include an optional expiry time when they generate a signature. The expiry time is not set by default and requires explicit configuration by users at the time of signature generation. The artifact is considered expired when the current time is greater than or equal to expiry time, users performing verification can either configure their trust policies to fail the verification or even accept the artifact with expiry date in the past using policy. This is an advanced feature that allows implementing controls for user defined semantics like deprecation for older artifacts, or block older artifacts in a production environment. Users should only include an expiry time in the signed artifact after considering the behavior they expect for consumers of the artifact after it expires. Users can choose to consume an artifact even after the expiry time based on their specific needs. -### OCI Signature Portability +### Signature Portability Portability of signatures is associated with the portability of associated artifacts which are being signed. OCI artifacts are inherently registry agnostic, artifacts can be pulled from and pushed to any OCI compliant registry to which a user has access. @@ -345,13 +298,13 @@ Signatures associated with these artifacts require broad portability. E.g. Images for containerized applications and services used within an organization, or shared with limited authorized parties. Based on user requirements a private artifact can have different levels of portability, the signature’s portability should at least match the the artifact’s portability. -*The Notary Project OCI signature portability* is based on the following +*The Notary Project signature portability* is based on the following #### Signature discovery -The Notary Project OCI signature specification addressed signature discovery by storing signatures in the same registry (location) where an artifact is present. +The Notary Project signature specification addressed signature discovery by storing signatures in the same registry (location) where an artifact is present. This is supported through [OCI Distribution Referrers API][oci-distribution-referrers] which allows reference artifacts such as signatures, SBOMs to be associated with existing artifacts like Images. -The Notary Project OCI signature specification allows multiple signatures to be associated with an artifact, and clients may automatically push signatures for an artifact to a destination registry when a signed artifact moves from one registry to other. +The Notary Project signature specification allows multiple signatures to be associated with an artifact, and clients may automatically push signatures of an artifact to a destination registry when a signed artifact moves from one registry to another. #### Verification requirements @@ -369,9 +322,6 @@ The Notary Project signatures without any critical extended attributes do not im Whereas, the Notary Project signatures that contain critical extended attributes will require additional dependencies for signature validation, either on Notation compliant plugins or equivalent tooling which may not be available in all environments. Similarly, Notation compliant plugin vendors should be aware that usage of extended signed attributes which are marked critical in signature will have implications on portability of the signature. -### Blob Signature Portability -Notary Project blob signatures provide the maximum portability as there are no requirements on storage or transport medium. Users can store and transport their blobs and associated detached signatures as required. - ### Guidelines for implementations of the Notary Project signature specification Implementations of the Notary Project signature specification, can choose to be [Notation plugin protocol](./plugin-extensibility.md#plugin-contract) aware or not. If an implementation chooses to be plugin protocol aware, and it encounters the Verification Plugin and Verification Plugin minimum version attributes during signature verification, it MUST process these attributes. This involves finding the appropriate plugin and the version to use, and executing `verify-signature` plugin command with correct inputs and processing the plugin response, as per the [Verification Plugin interface](./plugin-extensibility.md#verification-extensibility). @@ -382,9 +332,9 @@ Alternatively, an implementation of the Notary Project signature specification c - An implementation MUST fail signature verification if it cannot perform the equivalent verification logic, as skipping the plugin equivalent verification logic will cause incorrect and inconsistent signature verification behavior. - An implementation MAY choose to support a set of known plugin’s verification logic and fail others. -[annotation-rules]: https://github.com/opencontainers/image-spec/blob/v1.0.0/annotations.md#rules -[oci-descriptor]: https://github.com/opencontainers/image-spec/blob/v1.0.0/descriptor.md +[annotation-rules]: https://github.com/opencontainers/image-spec/blob/v1.1.0/annotations.md#rules +[oci-descriptor]: https://github.com/opencontainers/image-spec/blob/v1.1.0/descriptor.md [ietf-rfc3161]: https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.2 -[oci-distribution-referrers]: https://github.com/opencontainers/distribution-spec/blob/v1.0.0/spec.md#listing-referrers -[oci-image-manifest]: https://github.com/opencontainers/image-spec/blob/v1.1.0-rc3/manifest.md -[image-manifest-property-descriptions]: https://github.com/opencontainers/image-spec/blob/v1.1.0-rc3/manifest.md#image-manifest-property-descriptions +[oci-distribution-referrers]: https://github.com/opencontainers/distribution-spec/blob/v1.1.0/spec.md#listing-referrers +[oci-image-manifest]: https://github.com/opencontainers/image-spec/blob/v1.1.0/manifest.md +[image-manifest-property-descriptions]: https://github.com/opencontainers/image-spec/blob/v1.1.0/manifest.md#image-manifest-property-descriptions diff --git a/specs/signing-and-verification-workflow.md b/specs/signing-and-verification-workflow.md index 216a7be..7ac0752 100644 --- a/specs/signing-and-verification-workflow.md +++ b/specs/signing-and-verification-workflow.md @@ -1,8 +1,8 @@ # Signing and Verification Workflow -This document describes workflows for signing and verifying OCI artifacts and arbitrary blobs. +This document describes workflows for signing and verifying OCI artifacts. -## OCI artifact signing workflow +## Signing workflow The user wants to sign an OCI artifact and push the signature to a repository. @@ -27,7 +27,7 @@ The user wants to sign an OCI artifact and push the signature to a repository. The user pushes the OCI artifact to the repository before the signature generation process as the signature reference must exist for the signature push to succeed. -## OCI artifact verification workflow +## Verification workflow The user wants to pull an OCI artifact only if they are signed by a trusted publisher and the signature is valid. @@ -50,7 +50,7 @@ The user wants to pull an OCI artifact only if they are signed by a trusted publ 1. **Filter signature artifact manifest:** 1. Filter out the unsupported signature formats by comparing the signature envelope format type (`[descriptors].descriptor.mediaType`) in the signature manifest, with the supported formats defined in [signature specification](./signature-specification.md#storage). 1. Depending upon the trust-store and trust-policy configuration, further filter out signature manifests. - 1. Using the `scopes` configured in trust policies, get the applicable trust policy. + 1. Using the `registryScopes` configured in trust policies, get the applicable trust policy. 1. Get the list of trusted certificates from the trust stores specified in the applicable trust policy. If the trust policy contains multiple trust stores, create a list of trusted certificates by merging the trusted certificate list of each trust store. 1. Calculate the SHA-256 fingerprint of all the trusted certificates and compare them against the list of SHA-256 certificate fingerprints present in `io.cncf.notary.x509certs.fingerprint.sha256` annotation of artifact manifest. @@ -69,48 +69,4 @@ The user wants to pull an OCI artifact only if they are signed by a trusted publ Otherwise, move to the next signature artifact descriptor(step 3.1). If all signature artifact descriptors have already been processed, fail the signature verification and exit. 1. **Get OCI artifact:** Using the verified digest, download the OCI artifact. - This step is not in the purview of Notary Project. - -## Blob signing workflow - -The user wants to sign an arbitrary blob with a detached signature. - -### Signing Prerequisites - -- User has access to the signing certificate and private key or a remote signing service through a notation plugin. - -### Signing Steps - -1. **Generate signature:** Using notation CLI or any other compliant signing tool, sign the blob. The signing tool should follow the following guideline. - 1. Construct the blob payload as defined in [`signature specification`](./signature-specification.md#payload) - 1. Verify that the signing certificate is valid and satisfies [certificate requirements](./signature-specification.md#certificate-requirements). - 1. Verify that the signing algorithm satisfies [algorithm requirements](./signature-specification.md#signature-algorithm-requirements). - 1. Generate signature. - 1. Generate signature using a signature format specified in [supported signature envelopes](./signature-specification.md#supported-signature-envelopes). Also, as part of this step, the user-defined/supplied custom attributes should be added to the annotations of the signature payload. - 1. If signing scheme is [`notary.x509`](./signing-scheme.md/#notaryx509) and timestamp countersignature is demanded, extract the [primitive signature](./signature-specification.md#signature-envelope) (the digital signature computed on payload and signed attributes) from the signature envelope generated in the previous step. Compute hash of the signature (the hash algorithm SHOULD be deduced from signing certificate's public key) and send it to a [RFC 3161](https://datatracker.ietf.org/doc/html/rfc3161.html) compliant *Timestamp Authority (TSA)* for timestamping. Otherwise, continue to the next step. - 1. Verify that the timestamp signing certificate satisfies [certificate requirements](./signature-specification.md#certificate-requirements). - 1. Verify that the timestamp signing algorithm satisfies [algorithm requirements](./signature-specification.md#signature-algorithm-requirements). - 1. On success, embed the timestamp countersignature into the *Timestamp Signature* unsigned attribute of the signature envelope. If any of the above timestamping step failed, implementations MUST fail the signing process. -1. **Save the signature envelope:** Save the signature envelope generated in the previous step to a file. File extension should be the original blob file name plus `.sig.jws` for JWS signatures and `.sig.cose` for COSE signatures. - -## Arbitrary blob verification workflow - -The user wants to consume an arbitrary blob only if it was signed by a trusted publisher and the signature associated with the blob is valid. - -### Verification Prerequisites - -- User has the blob that they want to consume, along with its detached signature. -- User has configured [trust store and trust policy](./trust-store-trust-policy.md) required for signature verification. - -### Verification Steps - -1. **Should implementations of this specification verify the signature? :** Depending upon [trust-policy](./trust-store-trust-policy.md#blob-trust-policy) configuration, determine whether implementations of this specification need to verify the signature or not. - If signature verification should be skipped for the given blob, skip the below steps. -1. **Verify the detached signature:** - 1. Parse and validate the signature envelope using the detached signature's file extension as the envelope type. - 1. Verify the signature envelope using trust-store and trust-policy as mentioned in [signature evaluation](./trust-store-trust-policy.md#signature-evaluation) section. - 1. If the signature verification fails, exit. -1. Calculate the blob's size and verify that it matches the size present in `targetArtifact.size`. Fail signature verification if there is a mismatch. -1. If provided by the user, verify blob's media type to the one present in `targetArtifact.mediaType`. Fail signature verification if there is a mismatch. -1. Calculate the digest of the blob using the digest algorithm deduced from signing certificate's public key (see [Algorithm Selection](./signature-specification.md#algorithm-selection)) and match it with the digest specified at `targetArtifact.digest`. Fail signature verification if there is a mismatch. -1. If there any user-defined/supplied custom annotations, match them against the ones present in `targetArtifact.annotations`. If they match, signature verification is considered successful. \ No newline at end of file + This step is not in the purview of Notary Project. \ No newline at end of file diff --git a/specs/trust-store-trust-policy.md b/specs/trust-store-trust-policy.md index 829377e..de2a5c7 100644 --- a/specs/trust-store-trust-policy.md +++ b/specs/trust-store-trust-policy.md @@ -5,7 +5,7 @@ Notary Project currently supports X.509 based PKI and identities, and uses a tru This document consists of the following sections: - **[Trust Store](#trust-store)**: Contains a set of trusted identities through which trust is derived for the rest of the system. For X.509 PKI, the trust store typically contains a set of root certificates. -- **[Trust Policy](#trust-policy)**: A policy language which indicates which identities are trusted to produce artifacts. Both trust store and trust policy need to be configured by users/administrators before artifact signature can be evaluated. Notation supports different trust policies for verifying different types of artifacts like signed OCI images and arbitrary blobs, etc. +- **[Trust Policy](#trust-policy)**: A policy language which indicates which identities are trusted to produce artifacts. Both trust store and trust policy need to be configured by users/administrators before artifact signature can be evaluated. - **[Signature Verification](#signature-verification)**: Describes how signatures are evaluated using the policy, to determine if a signed artifact is authentic. This section is meant for implementations of the [Notary Project verification specification](./signing-and-verification-workflow.md). Other types of identities and trust models may be supported in future, which may introduce other constructs/policy elements to support signature evaluation. @@ -60,51 +60,31 @@ Any additional sub directories under a named store and certificates in it are ig ## Trust Policy -Users who consume signed artifacts from OCI registries, or signed arbitrary blobs stored on file system, use trust policies to specify trusted identities that signed the artifacts, and level of signature verification to enforce. Trust policy files are JSON documents. +Users who consume signed artifacts from OCI registries use trust policies to specify trusted identities that signed the artifacts, and level of signature verification to enforce. Trust policy files are JSON documents. > [!NOTE] -> Users are required to setup separate trust policy files for verifying different types of signed artifacts. Notation expects OCI trust policy file to be placed at `{NOTATION_CONFIG}/trustpolicy.oci.json`. For backward compatibility reasons, Notation accepts `{NOTATION_CONFIG}/trustpolicy.json` as OCI trust policy file as well. For arbitrary blobs, Notation expects trust policy file to be placed at `{NOTATION_CONFIG}/trustpolicy.blob.json`. +> Notation expects trust policy file to be placed at `{NOTATION_CONFIG}/trustpolicy.json`. ### Trust Policy Properties -#### OCI Trust Policy - -##### Version 1.0 +#### Version 1.0 - **`version`**(*string*): This REQUIRED property is the version of the trust policy. This MUST be `1.0` at the moment. - **`trustPolicies`**(*string-array of objects map*): This REQUIRED property represents a collection of trust policies. - **`name`**(*string*): This REQUIRED property represents the name of the trust policy. - **`registryScopes`**(*array of strings*): This REQUIRED property determines which trust policy is applicable for the given artifact. The scope field supports filtering based on fully qualified repository URI `${registry-name}/${namespace}/${repository-name}`. - For more information, see [trust policy constraints](#oci-trust-policy-constraints) section. - - **`signatureVerification`**(*object*): This REQUIRED property dictates how signature verification is performed. - An *object* that specifies a predefined verification level, with an option to override the Notary Project trust policy defined verification level if user wants to specify a [custom verification level](#custom-verification-level). - - **`level`**(*string*): A REQUIRED property that specifies the verification level, supported values are `strict`, `permissive`, `audit` and `skip`. Detailed explanation of each level is present [here](#signatureverification-details). - - **`override`**(*map of string-string*): This OPTIONAL map is used to specify a [custom verification level](#custom-verification-level). - - **`verifyTimestamp`**(*string*): An OPTIONAL property that specifies timestamp verification configuration. Supported values are `always` and `afterCertExpiry`. The default value is `always`, which means always verify timestamp countersignature. `afterCertExpiry` means only verify timestamp countersignature if at least one certificate in the signing certificate chain has expired at the time of verification. - - **`trustStores`**(*array of string*): This REQUIRED property specifies a set of one or more named trust stores, each of which contain the trusted roots against which signatures are verified. Each named trust store uses the format `{trust-store-type}:{named-store}`. Currently supported values for `trust-store-type` are `ca`, `signingAuthority` and `tsa`. To enable timestamp verification, type `tsa` MUST be configured. - - **`trustedIdentities`**(*array of strings*): This REQUIRED property specifies a set of identities that the user trusts. For X.509 PKI, it supports list of elements/attributes of the signing certificate's subject. For more information, see [identities constraints](#trusted-identities-constraints) section. A value `*` is supported if user trusts any identity (signing certificate) issued by the CA(s) in `trustStore`. This field only contains trusted identities issued by CA(s) or Signing Authorities. - -#### Blob Trust Policy - -##### Version 1.0 - -- **`version`**(*string*): This REQUIRED property is the version of the trust policy. This MUST be `1.0` at the moment. -- **`trustPolicies`**(*string-array of objects map*): This REQUIRED property represents a collection of trust policies. - - **`name`**(*string*): This REQUIRED property represents the name of the trust policy. This will be used to select the policy to verify a signed blob. + For more information, see [trust policy constraints](#trust-policy-constraints) section. - **`signatureVerification`**(*object*): This REQUIRED property dictates how signature verification is performed. An *object* that specifies a predefined verification level, with an option to override the Notary Project trust policy defined verification level if user wants to specify a [custom verification level](#custom-verification-level). - **`level`**(*string*): A REQUIRED property that specifies the verification level, supported values are `strict`, `permissive`, `audit` and `skip`. Detailed explanation of each level is present [here](#signatureverification-details). - **`override`**(*map of string-string*): This OPTIONAL map is used to specify a [custom verification level](#custom-verification-level). - **`verifyTimestamp`**(*string*): An OPTIONAL property that specifies timestamp verification configuration. Supported values are `always` and `afterCertExpiry`. The default value is `always`, which means always verify timestamp countersignature. `afterCertExpiry` means only verify timestamp countersignature if at least one certificate in the signing certificate chain has expired at the time of verification. - - **`globalPolicy`**(*boolean*): This OPTIONAL property flags the policy as the global trust policy if set to `true`. This policy will be used for verification if the user does not select any policy by its name during verification. - **`trustStores`**(*array of string*): This REQUIRED property specifies a set of one or more named trust stores, each of which contain the trusted roots against which signatures are verified. Each named trust store uses the format `{trust-store-type}:{named-store}`. Currently supported values for `trust-store-type` are `ca`, `signingAuthority` and `tsa`. To enable timestamp verification, type `tsa` MUST be configured. - **`trustedIdentities`**(*array of strings*): This REQUIRED property specifies a set of identities that the user trusts. For X.509 PKI, it supports list of elements/attributes of the signing certificate's subject. For more information, see [identities constraints](#trusted-identities-constraints) section. A value `*` is supported if user trusts any identity (signing certificate) issued by the CA(s) in `trustStore`. This field only contains trusted identities issued by CA(s) or Signing Authorities. ### Trust Policy Examples -#### Trust Policy for OCI artifacts - 1. Trust policy for a simple scenario where ACME Rockets consumes only the OCI artifacts signed by their own CI/CD. Any third party artifacts consumed by ACME Rockets are also signed and vetted by their CI/CD. ```jsonc @@ -212,76 +192,6 @@ Users who consume signed artifacts from OCI registries, or signed arbitrary blob } ``` -#### Trust Policy for Blobs - -1. Trust policy for the scenario where ACME Rockets consumes arbitrary blobs signed by Wabbit Networks and some signed by ACME Rockets. - -```jsonc -{ - "version": "1.0", - "trustPolicies": [ - { - // Policy for set of blobs signed by Wabbit Networks - "name": "wabbit-networks-blobs", - "signatureVerification": { - "level" : "strict" - }, - "trustStores": ["ca:wabbit-networks"], - "trustedIdentities": [ - "x509.subject: C=US, ST=WA, L=Seattle, O=wabbit-networks.io, OU=Security Tools" - ] - }, - { - // Policy that uses custom verification level to relax the strict verification. - // It logs expiry and skips the revocation check. - "name": "use-expired-blobs", - "signatureVerification": { - "level" : "strict", - "override" : { - "expiry" : "log", - "revocation" : "skip" - } - }, - "trustStores": ["ca:acme-rockets"], - "trustedIdentities": ["*"] - }, - { - // Global policy for all arbitrarily blobs - "name": "global-policy-for-all-blobs", - "signatureVerification": { - "level" : "audit" - }, - "globalPolicy": true, - "trustStores": ["ca:acme-rockets", "ca:acme-rockets-ca2"], - "trustedIdentities": [ - "x509.subject: C=US, ST=WA, L=Seattle, O=acme-rockets.io, OU=Finance, CN=SecureBuilder" - ] - } - ] -} -``` - -2. Trust policy for the scenario where ACME Rockets consumes arbitrary blobs signed by Wabbit Networks with timestamp countersignature. - -```jsonc -{ - "version": "1.0", - "trustPolicies": [ - { - "name": "wabbit-networks-blobs", - "signatureVerification": { - "level" : "strict", - "verifyTimestamp": "afterCertExpiry" // Only verify any timestamp countersignature when codesigning certificate chain has expired - }, - "trustStores": ["ca:acme-rockets", "tsa:trusted-tsa"], // The trust store type `tsa` MUST be configured to enable timestamp verification. - "trustedIdentities": [ - "x509.subject: C=US, ST=WA, L=Seattle, O=acme-rockets.io, OU=Finance, CN=SecureBuilder" - ] - } - ] -} -``` - #### Signature Verification details - Signature verification is a multi step process performs the following validations @@ -391,8 +301,6 @@ Timestamp countersignature verification is a multi step process performs the fol #### Trust Policy Constraints -##### OCI Trust Policy Constraints - - Each trust policy MUST contain scope property `registryScopes` and the scope collection MUST contain at least one value. - The scope MUST contain one of the following: - List of one or more fully qualified repository URIs. @@ -402,10 +310,6 @@ Timestamp countersignature verification is a multi step process performs the fol The trust policy with global scope applies to all the artifacts. There can only be one trust policy that uses a global scope. -##### Blob Trust Policy Constraints -- There MUST be only one trust policy with `globalPolicy` set to `true` -- `signatureVerification` MUST not be set to `skip` if the policy is marked as a global policy - #### Selecting a trust policy to verify a signed OCI artifact - The URI of an OCI artifact dictates the trust policy that gets applied to verify the artifact's signature. @@ -419,17 +323,6 @@ Timestamp countersignature verification is a multi step process performs the fol 1. *Global*: If there exists a trust policy with global scope (`*`) then use that policy for signature evaluation. Otherwise, fail the signature verification. -#### Selecting a trust policy to verify a signed blob - -- The signature verifier must select the appropriate trust policy for blob signature verification using policy names. -- For a given policy name selected by the verifier, there MUST be only one trust policy with that exact name. -- For a given policy name selected by the verifier, if there is no matching trust policy with that name, then implementations of the [Notary Project verification specification](./signing-and-verification-workflow.md) MUST consider the blob as untrusted and fail signature verification. -- Selecting a trust policy: - 1. *Exact match*: If there exists a trust policy whose name exactly matches the one provided by the signature verifier then the aforementioned policy MUST be used for signature evaluation. - Otherwise, fail the signature verification. - 1. *Global*: If verifier does not select a policy by its name and if there exists a trust policy marked as a global policy (`globalPolicy:true`) then use that policy for signature evaluation. - Otherwise, fail the signature verification. - ### Trusted Identities Constraints This section defines how to specify `trustedIdentities` for X.509 certificates using its distinguished name. A distinguished name (usually just shortened to "DN") uniquely identifies the requestor/holder of the certificate. @@ -471,8 +364,7 @@ Notary Project allows user to execute custom validations during verification usi ### Steps 1. **Identify applicable trust policy** - 1. For OCI artifacts, refer to `{NOTATION_CONFIG}/trustpolicy.oci.json` or `{NOTATION_CONFIG}/trustpolicy.json` file and use [the artifact URI as the policy selector](#selecting-a-trust-policy-to-verify-a-signed-oci-artifact) and select the policy with matching scope from `registryScopes`. - 1. For Blob artifacts, refer to `{NOTATION_CONFIG}/trustpolicy.blob.json` and use [the policy name provided by the verifier](#selecting-a-trust-policy-to-verify-a-signed-blob) as the policy selector and select a policy. + 1. Refer to `{NOTATION_CONFIG}/trustpolicy.json` file and use [the artifact URI as the policy selector](#selecting-a-trust-policy-to-verify-a-signed-oci-artifact) and select the policy with matching scope from `registryScopes`. 1. If an applicable trust policy cannot be found, fail signature verification. 1. **Proceed based on signature verification level** 1. If `signatureVerification` level is set to `skip` in the trust policy, return success. @@ -483,15 +375,13 @@ Notary Project allows user to execute custom validations during verification usi 1. A signature verification is considered successful when all validation steps are completed without critical failure. 1. **Validate Integrity:** 1. Validate signature envelope - 1. For OCI artifacts, validate that signature envelope can be parsed successfully based on the signature envelope type specified in the `blobs[0].mediaType` attribute of the signature artifact manifest. - 1. For Blob artifacts, validate that signature envelope can be parsed successfully based on the signature envelope type specified in the detached signature file extension. If no file extension is available, parse the envelope type by trying each of the [supported signature envelopes](./signature-specification.md#supported-signature-envelopes). Fail integrity check if unsuccessful. + 1. Validate that signature envelope can be parsed successfully based on the signature envelope type specified in the `blobs[0].mediaType` attribute of the signature artifact manifest. 1. Validate that the content type indicated by the `content type` signed attribute in the signature envelope is supported. - 1. Get the signing certificate from the parsed [signature envelope](https://github.com/notaryproject/notaryproject/blob/7b7d283038/signature-specification.md#signature-envelope). + 1. Get the signing certificate from the parsed [signature envelope](./signature-specification.md#signature-envelope). 1. Determine the signing algorithm(hash+encryption) from the signing certificate and validate that the signing algorithm satisfies [algorithm requirements](./signature-specification.md#signature-algorithm-requirements) 1. Using the public key of the signing certificate and signing algorithm identified in the previous step, validate the integrity of the signature envelope. 1. Verify signature `payload` 1. Verify the signature envelope's `payload` matches the source [`payload`](./signature-specification.md#payload) that is getting verified. Make sure the artifact's digest, media type and size match the ones present in the signature envelope. - 1. Additionally for Blob artifacts, calculate the digest of the blob using the hashing algorithm deduced from signing certificate's public key (see [Algorithm Selection](./signature-specification.md#algorithm-selection)) and make sure the digests match. 1. **Validate Authenticity.** 1. For the applicable trust policy, **validate trust store and identities:** 1. Validate that the signature envelope contains a complete certificate chain that starts from a code signing certificate and terminates with a root certificate. Also, validate that code signing certificate satisfies [certificate requirements](./signature-specification.md#certificate-requirements). diff --git a/threatmodels/notation-threatmodel.md b/threatmodels/notation-threatmodel.md index f51748b..613793e 100644 --- a/threatmodels/notation-threatmodel.md +++ b/threatmodels/notation-threatmodel.md @@ -9,7 +9,7 @@ The following diagram illustrates the architecture and components. ![Notation system overview](../media/notation-system.svg) - **User**: The actor could be a signer or a verifier. A signer interacts with Notation CLI to sign artifacts. A verifier interacts with Notation CLI to verify artifacts against signatures. -- **Artifact Builder**: The actor who is responsible for producing software artifacts using build systems. Notation supports signing and verification of software artifacts including but are not limited to container images, helm charts, Software Bill of Materials (SBOMs). These artifacts can be stored either in remote registries or locally on disk using [OCI image layout](https://github.com/opencontainers/image-spec/blob/v1.0.0/image-layout.md). +- **Artifact Builder**: The actor who is responsible for producing software artifacts using build systems. Notation supports signing and verification of software artifacts including but are not limited to container images, helm charts, Software Bill of Materials (SBOMs). These artifacts can be stored either in remote registries or locally on disk using [OCI image layout](https://github.com/opencontainers/image-spec/blob/v1.1.0/image-layout.md). - **Execution Environment**: The execution environment includes the host and **File System** where notation CLI will be installed and executed. Notation works with a shared responsibility model which means users/organizations are responsible for securing the notation execution environment. Following are the various directories and files used by the Notation: - `config.json` file is used to store various configurations such as credential store information, etc. - `trustpolicy.json` file is used to store trust policy related data. @@ -37,7 +37,7 @@ The following diagram illustrates Notation signing artifacts as OCI image layout ![Notation signs artifacts as OCI image layout in the filesystem](../media/notation-sign-local.svg) -As per the [Notary signature specification](../specs/signature-specification.md), the signature payload is a JSON document which requires the [OCI descriptor](https://github.com/opencontainers/image-spec/blob/v1.0.0/descriptor.md) of the target artifact. For artifacts stored in a registry, the descriptor info can be retrieved from [image manifest](https://github.com/opencontainers/image-spec/blob/v1.1.0-rc2/manifest.md) stored in the registry. For artifacts stored as an [OCI Image layout](https://github.com/opencontainers/image-spec/blob/v1.0.0/image-layout.md), the descriptor info can be retrieved by inspecting the `index.json` file of OCI Image layout. +As per the [Notary signature specification](../specs/signature-specification.md), the signature payload is a JSON document which requires the [OCI descriptor](https://github.com/opencontainers/image-spec/blob/v1.1.0/descriptor.md) of the target artifact. For artifacts stored in a registry, the descriptor info can be retrieved from [image manifest](https://github.com/opencontainers/image-spec/blob/v1.1.0/manifest.md) stored in the registry. For artifacts stored as an [OCI Image layout](https://github.com/opencontainers/image-spec/blob/v1.1.0/image-layout.md), the descriptor info can be retrieved by inspecting the `index.json` file of OCI Image layout. ### Threats and Mitigation