From f7a4fdc4268b38079dde83253d6d75e0dd7808f9 Mon Sep 17 00:00:00 2001 From: Yi Zha Date: Thu, 22 Dec 2022 21:32:37 +0800 Subject: [PATCH 1/2] doc: fix spec links, artifact and oras related info Signed-off-by: Yi Zha --- specs/plugin-extensibility.md | 44 +++++++++++----------- specs/signature-envelope-jws.md | 2 +- specs/signature-specification.md | 4 +- specs/signing-and-verification-workflow.md | 12 +++--- 4 files changed, 30 insertions(+), 32 deletions(-) diff --git a/specs/plugin-extensibility.md b/specs/plugin-extensibility.md index 95991225..422b1f54 100644 --- a/specs/plugin-extensibility.md +++ b/specs/plugin-extensibility.md @@ -1,6 +1,6 @@ # Notation Extensibility for Signing and Verification -Keys and associated certificates used for signing artifacts using Notary could be available to users through varied solutions that provide secure key generation, storage and cryptographic operations. Some are well established with standards like [PIV](https://csrc.nist.gov/projects/piv/piv-standards-and-supporting-documentation) and [PKCS #11](https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/os/pkcs11-base-v3.0-os.html) implemented by hardware tokens, smart cards. More recent options which use varied authentication and API protocols are remote key management services and signing services by third party vendors and cloud service providers. Notation will support a few built-in integrations with standard providers, and will provide plugin interfaces for users, and vendors to implement their own integrations with the solutions they use. This allows a plugin publisher to implement, test, release and patch their solutions independent of Notation’s development and release cycle. This document provides specification for the plugin model, and interfaces to implement. This specification aims to work both for [existing](../signature-specification.md) and future signature formats adopted by Notary. +Keys and associated certificates used for signing artifacts using Notary could be available to users through varied solutions that provide secure key generation, storage and cryptographic operations. Some are well established with standards like [PIV](https://csrc.nist.gov/projects/piv/piv-standards-and-supporting-documentation) and [PKCS #11](https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/os/pkcs11-base-v3.0-os.html) implemented by hardware tokens, smart cards. More recent options which use varied authentication and API protocols are remote key management services and signing services by third party vendors and cloud service providers. Notation will support a few built-in integrations with standard providers, and will provide plugin interfaces for users, and vendors to implement their own integrations with the solutions they use. This allows a plugin publisher to implement, test, release and patch their solutions independent of Notation’s development and release cycle. This document provides specification for the plugin model, and interfaces to implement. This specification aims to work both for [existing](./signature-specification.md) and future signature formats adopted by Notary. ## Terminology @@ -92,11 +92,11 @@ Plugins may require additional configuration to work correctly, that could be se For the previous example, plugin config can be set using command line arguments as part of registering a key with the `notation key add` command. E.g. -* `notation key add --name "mysigningkey" --id "keyid" --plugin "com.example.nv2plugin" --pluginConfig key1=value1,"key 2"="value 2"` +* `notation key add "mysigningkey" --id "keyid" --plugin "com.example.nv2plugin" --plugin-config key1=value1 --plugin-config "key 2"="value 2"` Plugin config can be also set/overriden during signing with the `notation sign` command. Following example overrides value for `key 2` already set in `config.json` by previous command. -* `notation sign $IMAGE --key "mysigningkey" --pluginConfig "key 2"=newValue2` +* `notation sign $IMAGE --key "mysigningkey" --plugin-config "key 2"=newValue2` ### Plugin contract @@ -200,18 +200,18 @@ This interface targets plugins that integrate with providers of basic cryptograp 5. Execute the plugin with `get-plugin-metadata` command 1. If plugin supports capability `SIGNATURE_GENERATOR.RAW` 1. Execute the plugin with `describe-key` command, set `request.keyId` and the optional `request.pluginConfig` to corresponding values associated with signing key `keyName` in `config.json`. - 2. Generate the payload to be signed for [JWS](../signature-specification.md#supported-signature-envelopes) envelope format. - 1. Create the JWS protected headers collection and set `alg` to value corresponding to `describe-key.response.keySpec` as per [signature algorithm selection](../signature-specification.md#algorithm-selection). - 2. Create the Notary v2 Payload (JWS Payload) as defined [here](../signature-specification.md#payload). + 2. Generate the payload to be signed for [JWS](./signature-specification.md#supported-signature-envelopes) envelope format. + 1. Create the JWS protected headers collection and set `alg` to value corresponding to `describe-key.response.keySpec` as per [signature algorithm selection](./signature-specification.md#algorithm-selection). + 2. Create the Notary v2 Payload (JWS Payload) as defined [here](./signature-specification.md#payload). 3. The *payload to sign* is then created as - `ASCII(BASE64URL(UTF8(ProtectedHeaders)) ‘.’ BASE64URL(JWSPayload))` 3. Execute the plugin with `generate-signature` command. 1. Set `request.keyId` and the optional `request.pluginConfig` to corresponding values associated with signing key `keyName` in `config.json`. 2. Set `request.payload` as base64 encoded *payload to sign* (the JWS *payload to sign* is double encoded, this is a shortcoming of using plugin contract with JSON encoding). - 3. Set `keySpec` to value returned by `describe-key` command in `response.keySpec`, and `hashAlgorithm` to hash algorithm corresponding to the key spec, as per [signature algorithm selection](../signature-specification.md#algorithm-selection). The algorithm specified in `hashAlgorithm` MUST be used by the plugin to hash the payload (`request.payload`) as part of signature generation. + 3. Set `keySpec` to value returned by `describe-key` command in `response.keySpec`, and `hashAlgorithm` to hash algorithm corresponding to the key spec, as per [signature algorithm selection](./signature-specification.md#algorithm-selection). The algorithm specified in `hashAlgorithm` MUST be used by the plugin to hash the payload (`request.payload`) as part of signature generation. 4. Validate the generated signature, return an error if any of the checks fails. - 1. Check if `response.signingAlgorithm` is one of [supported signing algorithms](../signature-specification.md#algorithm-selection). + 1. Check if `response.signingAlgorithm` is one of [supported signing algorithms](./signature-specification.md#algorithm-selection). 2. Check that the plugin did not modify `request.payload` before generating the signature, and the signature is valid for the given payload. Verify the hash of the `request.payload` against `response.signature`, using the public key of signing certificate (leaf certificate) in `response.certificateChain` along with the `response.signingAlgorithm`. This step does not include certificate chain validation (certificate chain leads to a trusted root configured in Notation's Trust Store), or revocation check. - 3. Check that the `response.certificateChain` conforms to [Certificate Requirements](../signature-specification.md#certificate-requirements). + 3. Check that the `response.certificateChain` conforms to [Certificate Requirements](./signature-specification.md#certificate-requirements). 5. Assemble the JWS Signature envelope using `response.signature`, `response.signingAlgorithm` and `response.certificateChain`. Notation may also generate and include timestamp signature in this step. 6. Generate a signature manifest for the given signature envelope. 2. Else if, plugin supports capability `SIGNATURE_GENERATOR.ENVELOPE` *(covered in next section)* @@ -250,7 +250,7 @@ This command is used to get metadata for a given key. } ``` -*keySpec* : One of following [supported key types](../signature-specification.md#algorithm-selection) - `RSA-2048`, `RSA-3072`, `RSA-4096`, `EC-256`, `EC-384`, `EC-521`. +*keySpec* : One of following [supported key types](./signature-specification.md#algorithm-selection) - `RSA-2048`, `RSA-3072`, `RSA-4096`, `EC-256`, `EC-384`, `EC-521`. NOTE: This command can also be used as part of `notation key describe {key-name}` which will include the following output @@ -293,7 +293,7 @@ This command is used to generate the raw signature for a given payload. *pluginConfig* : Optional field for plugin configuration. For details, see [Plugin Configuration section](#plugin-configuration). -*keySpec* : Required field that has one of following [supported key types](../signature-specification.md#algorithm-selection) - `RSA-2048`, `RSA-3072`, `RSA-4096`, `EC-256`, `EC-384`, `EC-521`. Specifies the key type and size for the key. +*keySpec* : Required field that has one of following [supported key types](./signature-specification.md#algorithm-selection) - `RSA-2048`, `RSA-3072`, `RSA-4096`, `EC-256`, `EC-384`, `EC-521`. Specifies the key type and size for the key. *hashAlgorithm* : Required field that specifies Hash algorithm corresponding to the signature algorithm determined by `keySpec` for the key. @@ -313,7 +313,7 @@ All response attributes are required. } ``` -*signingAlgorithm* : One of following [supported signing algorithms](../signature-specification.md#algorithm-selection), Notation uses this validate the signature, and to set the appropriate attribute in signature envelope (e.g. JWS `alg`). Supported values are +*signingAlgorithm* : One of following [supported signing algorithms](./signature-specification.md#algorithm-selection), Notation uses this validate the signature, and to set the appropriate attribute in signature envelope (e.g. JWS `alg`). Supported values are * `RSASSA-PSS-SHA-256`: RSASSA-PSS with SHA-256 * `RSASSA-PSS-SHA-384`: RSASSA-PSS with SHA-384 @@ -345,12 +345,12 @@ This interface targets plugins that in addition to signature generation want to 1. Determine if the registered key uses a plugin 1. Execute the plugin with `get-plugin-metadata` command 1. If plugin supports capability `SIGNATURE_GENERATOR.ENVELOPE` - 1. Execute the plugin with `generate-envelope` command. Set `request.keyId` and the optional `request.pluginConfig` to corresponding values associated with signing key `keyName` in `config.json`. Set `request.payload` to base64 encoded [Notary v2 Payload](../signature-specification.md#payload), `request.payloadType` to `application/vnd.cncf.notary.payload.v1+json` and `request.signatureEnvelopeType` to a pre-defined type (`application/jose+json` for JWS). + 1. Execute the plugin with `generate-envelope` command. Set `request.keyId` and the optional `request.pluginConfig` to corresponding values associated with signing key `keyName` in `config.json`. Set `request.payload` to base64 encoded [Notary v2 Payload](./signature-specification.md#payload), `request.payloadType` to `application/vnd.cncf.notary.payload.v1+json` and `request.signatureEnvelopeType` to a pre-defined type (`application/jose+json` for JWS). 2. `response.signatureEnvelope` contains the base64 encoded signature envelope, value of `response.signatureEnvelopeType` MUST match `request.signatureEnvelopeType`. 3. Validate the generated signature, return an error if of the checks fails. 1. Check if `response.signatureEnvelopeType` is a supported envelope type and `response.signatureEnvelope`'s format matches `response.signatureEnvelopeType`. - 2. Check if the signing algorithm in the signature envelope is one of [supported signing algorithms](../signature-specification.md#algorithm-selection). - 3. Check that the [`targetArtifact` descriptor](../signature-specification.md#payload) in JWSPayload in `response.signatureEnvelope` matches `request.payload`. Plugins MAY append additional annotations but MUST NOT replace/override existing descriptor attributes and annotations. + 2. Check if the signing algorithm in the signature envelope is one of [supported signing algorithms](./signature-specification.md#algorithm-selection). + 3. Check that the [`targetArtifact` descriptor](./signature-specification.md#payload) in JWSPayload in `response.signatureEnvelope` matches `request.payload`. Plugins MAY append additional annotations but MUST NOT replace/override existing descriptor attributes and annotations. 4. Check that `response.signatureEnvelope` can be verified using the public key and signing algorithm specified in the signing certificate, which is embedded as part of certificate chain in `response.signatureEnvelope` . This step does not include certificate chain validation (certificate chain leads to a trusted root configure in Notation), or revocation check. 5. Check that the certificate chain in `response.signatureEnvelope` confirm to [Certificate Requirements]. 4. Generate a signature manifest for the given signature envelope, and append `response.annotations` to manifest annotations. @@ -395,7 +395,7 @@ All request attributes are required. *expiryDurationInSeconds* : Optional field which contains signature expiry duration(in seconds) as integer number. *signatureEnvelopeType* - defines the type of signature envelope expected from the plugin. As Notation clients need to be updated in order to parse and verify new signature formats, the default signature format can only be changed with new major version releases of Notation. Users however can opt into using an updated signature envelope format supported by Notation, by passing an optional parameter. -e.g. `notation sign $IMAGE --key {key-name} --envelope-type {some-new-type}` +e.g. `notation sign $IMAGE --key {key-name} --signature-format {some-new-type}` *Response* All response attributes are required. @@ -429,13 +429,13 @@ All response attributes are required. ### Requirements * The interface MUST NOT be tied to a specific signature envelope format. -* The interface MUST NOT allow a plugin to customize the complete [signature verification workflow](../trust-store-trust-policy-specification.md#signature-verification). Certain steps like identifying the applicable trust policy for the artifact, signature envelope schema validation, integrity checks, certificate chain validation against trust store will be performed by Notation, and cannot be customized by a plugin. +* The interface MUST NOT allow a plugin to customize the complete [signature verification workflow](./trust-store-trust-policy.md#signature-verification). Certain steps like identifying the applicable trust policy for the artifact, signature envelope schema validation, integrity checks, certificate chain validation against trust store will be performed by Notation, and cannot be customized by a plugin. * The interface MUST allow plugins to customize verification logic for specific supported steps * Trusted Identity validation * Revocation check validation * The interface MAY be extended in future to support additional steps which can be customized through a plugin. * The interface MUST be agnostic of sequencing of steps in signature verification workflow as implemented in Notation or other implementations. -* The interface MUST allow processing of [extended attributes](../signature-specification.md#extended-attributes) that are not part of Notary v2 [standard attributes](../signature-specification.md#standard-attributes). +* The interface MUST allow processing of [extended attributes](./signature-specification.md#extended-attributes) that are not part of Notary v2 [standard attributes](./signature-specification.md#standard-attributes). ### Guidelines for Verification plugin publishers @@ -459,11 +459,11 @@ This allows Notary v2 implementations to perform the same logic themselves, if t 3. Fail signature verification if these validations fail 3. Validate if plugin capabilities contains any `SIGNATURE_VERIFIER` capabilities 1. Fail signature verification if a matching plugin with `SIGNATURE_VERIFIER` capability cannot be found. Include *Verification Plugin Name* attribute as a hint in error response. -2. Complete steps *Identify applicable trust policy* and *Proceed based on signature verification level* from [signature verification workflow](../trust-store-trust-policy-specification.md#steps). -3. Complete steps *Validate Integrity, Validate Expiry* and *Validate Trust Store* from [signature verification workflow](../trust-store-trust-policy-specification.md#steps). +2. Complete steps *Identify applicable trust policy* and *Proceed based on signature verification level* from [signature verification workflow](./trust-store-trust-policy.md#steps). +3. Complete steps *Validate Integrity, Validate Expiry* and *Validate Trust Store* from [signature verification workflow](./trust-store-trust-policy.md#steps). 4. Based on the signature verification level, each validation may be enforced, logged or skipped. 5. Populate `verify-signature` request. NOTE: The processing order of remaining known attributes does not matter as long as they are processed before the end of signature verification workflow. - 1. Set `request.signature.criticalAttributes` to the set of [standard Notary v2 attributes](../signature-specification.md#standard-attributes) that are marked critical, from the signature envelope. + 1. Set `request.signature.criticalAttributes` to the set of [standard Notary v2 attributes](./signature-specification.md#standard-attributes) that are marked critical, from the signature envelope. 2. Set `request.signature.criticalAttributes.extendedAttributes` to extended attributes that Notation does not recognize. Notation only supports JSON primitive types for critical extended attributes. If a signature producer required complex types, it MUST set the value to a primitive type by encoding it (e.g. Base64), and MUST be decoded by the plugin which processed the attribute. 3. Set `request.signature.unprocessedAttributes` to set of critical attribute names that are marked critical, but unknown to Notation, and therefore cannot be processed by Notation. 4. Set `request.signature.certificateChain` to ordered array of certificates from signing envelope. @@ -475,7 +475,7 @@ This allows Notary v2 implementations to perform the same logic themselves, if t 1. If `verificationResult.success` is true, proceed to next element. 2. Else if `verificationResult.success` is `false`, check if the failure should be enforced or logged based on value of `signatureVerification` level in Trust Policy. Proceed to next element if failure is logged, else fail signature verification with `verificationResult.reason`. 3. Validate values in `response.processedAttributes` match the set of values in `request.signature.unprocessedAttributes`. If they don't, fail signature verification, as the plugin did not process a critical attribute that is unknown to the caller. -7. Perform any remaining steps in [signature verification workflow](../trust-store-trust-policy-specification.md#signature-verification) which are not covered by plugin's verification capabilities. These steps MUST process any remaining critical attributes. Fail signature verification if any critical attributes are unprocessed at the end of this step. +7. Perform any remaining steps in [signature verification workflow](./trust-store-trust-policy.md#signature-verification) which are not covered by plugin's verification capabilities. These steps MUST process any remaining critical attributes. Fail signature verification if any critical attributes are unprocessed at the end of this step. #### *verify-signature* command diff --git a/specs/signature-envelope-jws.md b/specs/signature-envelope-jws.md index d55895b9..183ed4b2 100644 --- a/specs/signature-envelope-jws.md +++ b/specs/signature-envelope-jws.md @@ -10,7 +10,7 @@ Signature Manifest Example ```jsonc { - "mediaType": "application/vnd.cncf.oras.artifact.manifest.v1+json", + "mediaType": "application/vnd.oci.artifact.manifest.v1+json", "artifactType": "application/vnd.cncf.notary.signature", "blobs": [ { diff --git a/specs/signature-specification.md b/specs/signature-specification.md index 88b18ba6..0234fa2d 100644 --- a/specs/signature-specification.md +++ b/specs/signature-specification.md @@ -244,7 +244,7 @@ The client implementation can use the aforementioned `mediaType` to parse the si **A:** The Signature envelope MUST have a versioning mechanism to support multiple payload formats. -- For [JWS JSON serialization](./signature-envelope-jwt.md) signature envelope, versioning is achieved by the `cty` field in ProtectedHeaders. +- For [JWS JSON serialization](./signature-envelope-jws.md) signature envelope, versioning is achieved by the `cty` field in ProtectedHeaders. - For [COSE_Sign1_Tagged](./signature-envelope-cose.md) signature envelope, versioning is achieved by the `content type` (label: `3`) field in ProtectedHeaders. ## Appendix @@ -297,7 +297,7 @@ Similarly, Notary v2 compliant plugin vendors should be aware that usage of exte ### Guidelines for Notary v2 Implementors -Implementations of Notary v2, can choose to be [Notation plugin protocol](./specs/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](../specs/../notaryproject-specs/specs/plugin-extensibility.md#verification-extensibility). +Implementations of Notary v2, 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). Alternatively, an implementation of Notary v2 can choose not to implement plugin protocol. diff --git a/specs/signing-and-verification-workflow.md b/specs/signing-and-verification-workflow.md index 6da84433..85c0009a 100644 --- a/specs/signing-and-verification-workflow.md +++ b/specs/signing-and-verification-workflow.md @@ -26,7 +26,6 @@ The user wants to sign an OCI artifact and push the signature to a repository. 1. **Push signature artifact manifest:** Push Notary v2 signature artifact manifest to the 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. -See: [ORAS Artifact Push Validation](https://github.com/oras-project/artifacts-spec/blob/main/artifact-manifest.md#push-validation) for more info. ## Verification workflow @@ -38,15 +37,14 @@ The user wants to pull an OCI artifact only if they are signed by a trusted publ If the fully qualified artifact reference contains a tag then the user needs to resolve this tag to a digest. E.g. If a fully qualified reference is `wabbit-networks.io/software:latest` where `latest` is a tag pointing to an artifact. The user must resolve the `latest` tag to a digest and construct a new artifact reference using the resolved digest `wabbit-networks.io/software@sha256:${digest}`. -- User has configured [trust store and trust policy](./trust-store-trust-policy-specification.md) required for signature verification. +- User has configured [trust store and trust policy](./trust-store-trust-policy.md) required for signature verification. ### Verification Steps -1. **Should Notary v2 verify the signature? :** Depending upon [trust-policy](./trust-store-trust-policy-specification.md#trust-policy) configuration, determine whether Notary v2 needs to verify the signature or not. +1. **Should Notary v2 verify the signature? :** Depending upon [trust-policy](./trust-store-trust-policy.md#trust-policy) configuration, determine whether Notary v2 needs to verify the signature or not. If signature verification should be skipped for the given artifact, skip the below steps and directly jump to step 4. -1. **Get signature artifact descriptors:** Using the ORAS [Manifest Referrers API](https://github.com/oras-project/artifacts-spec/blob/main/manifest-referrers-api.md) download the Notary v2 signature artifact descriptors. - The `artifactType` parameter is set to Notary v2 signature's artifact type `application/vnd.cncf.notary.v2.signature`. - Note that all ORAS implementations may not support filtering using `artifactType`. +1. **Get signature artifact descriptors:** Using the [OCI Distribution Referrers API](https://github.com/opencontainers/distribution-spec/blob/main/spec.md#listing-referrers) download the Notary v2 signature artifact descriptors. + The `artifactType` parameter is set to Notary v2 signature's artifact type `application/vnd.cncf.notary.signature`. 1. For each signature artifact descriptor, perform the following steps: 1. **Get signature artifact manifest:** Download the Notary v2 signature's artifact manifest for the given artifact descriptor. 1. **Filter signature artifact manifest:** @@ -63,7 +61,7 @@ The user wants to pull an OCI artifact only if they are signed by a trusted publ If all signature artifact descriptors have already been processed, fail the signature verification and exit. 1. **Get and verify signatures:** On the filtered Notary v2 signature artifact manifest, perform the following steps: 1. Download the signature envelope. - 1. Verify the signature envelope using trust-store and trust-policy as mentioned in [signature evaluation](./trust-store-trust-policy-specification.md#signature-evaluation) section. + 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, skip the below steps and 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. If signature verification succeeds, compare the digest derived from the given OCI artifact reference with the signed digest present in the signature envelope's payload. From 7d84d8db6034b1e0c150380abe3f9c63838fffe3 Mon Sep 17 00:00:00 2001 From: Yi Zha Date: Thu, 22 Dec 2022 21:47:43 +0800 Subject: [PATCH 2/2] doc: update per comments Signed-off-by: Yi Zha --- specs/signing-and-verification-workflow.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/signing-and-verification-workflow.md b/specs/signing-and-verification-workflow.md index 85c0009a..0ac1bbb4 100644 --- a/specs/signing-and-verification-workflow.md +++ b/specs/signing-and-verification-workflow.md @@ -44,7 +44,7 @@ The user wants to pull an OCI artifact only if they are signed by a trusted publ 1. **Should Notary v2 verify the signature? :** Depending upon [trust-policy](./trust-store-trust-policy.md#trust-policy) configuration, determine whether Notary v2 needs to verify the signature or not. If signature verification should be skipped for the given artifact, skip the below steps and directly jump to step 4. 1. **Get signature artifact descriptors:** Using the [OCI Distribution Referrers API](https://github.com/opencontainers/distribution-spec/blob/main/spec.md#listing-referrers) download the Notary v2 signature artifact descriptors. - The `artifactType` parameter is set to Notary v2 signature's artifact type `application/vnd.cncf.notary.signature`. + The `artifactType` parameter is set to Notary v2 signature's artifact type `application/vnd.cncf.notary.signature`. 1. For each signature artifact descriptor, perform the following steps: 1. **Get signature artifact manifest:** Download the Notary v2 signature's artifact manifest for the given artifact descriptor. 1. **Filter signature artifact manifest:**