From 684ccb064a9fec6544617fcdce199bd432599a3c Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Mon, 22 Jun 2020 07:42:52 -0700 Subject: [PATCH 01/28] Create keymanagementscenarios.md Signed-off-by: Niaz Khan --- keymanagementscenarios.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 keymanagementscenarios.md diff --git a/keymanagementscenarios.md b/keymanagementscenarios.md new file mode 100644 index 00000000..36317839 --- /dev/null +++ b/keymanagementscenarios.md @@ -0,0 +1,8 @@ +Identify use cases to clarify: +1. Where can keys be stored? What interfaces need to be supported? +2. Any limitations ok key types/sizes supported? +3. How will public keys (root of trust) be distributed? +4. How will key revocation information be distributed? +5a. What is the minimum number of keys needed to succesfully sign a container? +5b. What is the recommended number of keys to sign a container? +6. Any additional requirements for timestamping? From f727c701eb7ec95b2b646b44b3ad6fe915fed5e9 Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Fri, 10 Jul 2020 07:15:57 -0700 Subject: [PATCH 02/28] Update keymanagementscenarios.md Added in initial set of uses cases documented so far in meeting notes. Signed-off-by: Niaz Khan --- keymanagementscenarios.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/keymanagementscenarios.md b/keymanagementscenarios.md index 36317839..7cd6146b 100644 --- a/keymanagementscenarios.md +++ b/keymanagementscenarios.md @@ -1,3 +1,35 @@ +Key management for container signing can be broadly categorized into three general use cases: +- Signing (How are keys made available when Notary v2 signatures are generated?) +- Trust store configuration (How do runtime environments determine which keys to trust?) +- Key setup/revocation (How do key owners create/revoke keys? How do runtime environments get this information?) + +Signing Use Cases: +- Developer runs docker build and notary v2 sign on local machine. Keys are stored in key store or plain text on local machine (Need to identify keystores we want to support. Should we preclude signing with plain text keys to improve security posture?). +- Developer runs docker build and notary v2 sign on local machine. Keys are stored in a USB Token. +- Developer runs docker build and notary v2 sign on local machine. Keys are stored in a network HSM. +- Developer runs docker build and notary v2 sign on local machine. Keys are stored in a Cloud Key Management Service. +- Automated build system runs docker build and notary v2 sign on build machine. +- Automated build system runs docker build on a build machine. Signing is done on a second machine that verifies the container meets developer's release criteria. + +Trust Store Configuration: +- Developer adds/removes their root public keys to the trust store used on a runtime host. The trust store will validate images pulled from any registry. +- Developer adds/removes root public keys for third parties they trust to their trust stores. The trust store will validate images pulled from any registry. +- Enterprises can restrict users to add/remove their root public keys to the trust store used across a fleet of runtime hosts. The trust store will validate images pulled from any registry. +- Enterprises can restrict users to add/remove root public keys for trusted third parties to their trust stores. The trust store will validate images pulled from any registry. +- [TBD] Do we envision a scenario where the trust store will need to define subordinate keys in addition to the root? + +Key setup/revocation use cases: +- Developer sets up a single root key and delegates additional keys from it. +- Developer revokes/rotates chained keys. The revocation/rotation information is automatically available to run time environments. +- Developer revokes root keys. The run time environment administrator needs to update their trust store. +- Run time environments can automatically pull revocation lists for keys in their trust store. +- Air gapped run time environments can periodically pull and cache revocation lists for keys in their trust store. + + +In addition we also need to consider the following for cryptographic security: +- Supported key types +- Supported signing algorithms + Identify use cases to clarify: 1. Where can keys be stored? What interfaces need to be supported? 2. Any limitations ok key types/sizes supported? From aceaa7baff87927aa621bd4037715acb36857a5e Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Fri, 17 Jul 2020 07:28:29 -0700 Subject: [PATCH 03/28] Update keymanagementscenarios.md Signed-off-by: Niaz Khan --- keymanagementscenarios.md | 91 +++++++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 17 deletions(-) diff --git a/keymanagementscenarios.md b/keymanagementscenarios.md index 7cd6146b..6fe57ebc 100644 --- a/keymanagementscenarios.md +++ b/keymanagementscenarios.md @@ -1,30 +1,87 @@ Key management for container signing can be broadly categorized into three general use cases: -- Signing (How are keys made available when Notary v2 signatures are generated?) +- Key Setup/Signing (How are keys set up? How are keys accessed by Notary v2 client when signatures are generated?) - Trust store configuration (How do runtime environments determine which keys to trust?) -- Key setup/revocation (How do key owners create/revoke keys? How do runtime environments get this information?) +- Revocation (How do key owners create/revoke keys? How do runtime environments get this information?) + +Personas: +- Publisher: User who builds containers. +- Deployer: User who deploys containers. Signing Use Cases: -- Developer runs docker build and notary v2 sign on local machine. Keys are stored in key store or plain text on local machine (Need to identify keystores we want to support. Should we preclude signing with plain text keys to improve security posture?). -- Developer runs docker build and notary v2 sign on local machine. Keys are stored in a USB Token. -- Developer runs docker build and notary v2 sign on local machine. Keys are stored in a network HSM. -- Developer runs docker build and notary v2 sign on local machine. Keys are stored in a Cloud Key Management Service. -- Automated build system runs docker build and notary v2 sign on build machine. -- Automated build system runs docker build on a build machine. Signing is done on a second machine that verifies the container meets developer's release criteria. +- Local Key Store + - Publisher creates new root key on local machine. Keys are stored in key store or plain text on local machine (Need to identify keystores we want to support. Should we preclude signing with plain text keys to improve security posture?). + - Publisher uploads root public key to registry (registry can verify user for container uploads). + - Publisher shares root public key (other users can verify containers before running). + - Publisher creates new delegate keys on local machine that chain to root key. + - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with key in memory. +- USB Token Key Store + - Publisher creates new root key on USB token. + - Publisher uploads root public key to registry (registry can verify user for container uploads). + - Publisher shares root public key (other users can verify containers before running). + - Publisher creates new delegate keys on USB token that chain to root key. + - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with key in USB Token. +- Network HSM + - Publisher creates new root key on Network HSM. + - Publisher uploads root public key to registry (registry can verify user for container uploads). + - Publisher shares root public key (other users can verify containers before running). + - Publisher creates new delegate keys on Network HSM that chain to root key. + - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with key in Network HSM. +- Cloud Key Management Service + - Publisher creates new root key on Cloud Key Management Service + - Publisher uploads root public key to registry (registry can verify user for container uploads). + - Publisher shares root public key (other users can verify containers before running). + - Publisher creates new delegate keys on Cloud Key Management Service that chain to root key. + - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with key in Cloud Key Management Service. +- Hybrid + - Publisher creates new root key on USB Token/Network HSM/Cloud Key Management Service + - Publisher uploads root public key to registry (registry can verify user for container uploads). + - Publisher shares root public key (other users can verify containers before running). + - Publisher creates new delegate keys on local machine that chain to root key. + - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with keys on local machine. +- Signing by Build Machines + - Publisher creates new root, uploads root public key to registry, and shares root public key. + - Publisher creates new delegate keys on build machine or on USB Token/Network HSM/Cloud Key Management Service + - Publisher configures build scripts with location of delegate keys. + - Build machine runs docker build and then notary v2 sign with keys in configured location. +- Signing by Dedicated Machines + - Publisher creates new root, uploads root public key to registry, and shares root public key. + - Publisher creates new delegate keys on build machine or on USB Token/Network HSM/Cloud Key Management Service + - Publisher configures signing machine with location of delegate keys. + - Build machine runs docker build and passes objects to be signed to signing host. + - Signing host generates signatures with keys in configured location. Trust Store Configuration: -- Developer adds/removes their root public keys to the trust store used on a runtime host. The trust store will validate images pulled from any registry. -- Developer adds/removes root public keys for third parties they trust to their trust stores. The trust store will validate images pulled from any registry. +- Specify trusted public root keys + - Deployer gets root public key from publisher. + - Deployer adds root public key to runtime configuration. + - Container pulled from any registry is be validated with listed root public keys before execution. +- Specify location of trusted public root keys + - [TODO] - Enterprises can restrict users to add/remove their root public keys to the trust store used across a fleet of runtime hosts. The trust store will validate images pulled from any registry. - Enterprises can restrict users to add/remove root public keys for trusted third parties to their trust stores. The trust store will validate images pulled from any registry. - [TBD] Do we envision a scenario where the trust store will need to define subordinate keys in addition to the root? +- Air gapped environments -Key setup/revocation use cases: -- Developer sets up a single root key and delegates additional keys from it. -- Developer revokes/rotates chained keys. The revocation/rotation information is automatically available to run time environments. -- Developer revokes root keys. The run time environment administrator needs to update their trust store. -- Run time environments can automatically pull revocation lists for keys in their trust store. -- Air gapped run time environments can periodically pull and cache revocation lists for keys in their trust store. - +Key rotation/revocation use cases: +- Root Revocation + - Publisher deletes revoked root public key on registry (registry can stop sharing containers with revoked key). + - Registry stops vending containers signed with old root key. + - Publisher removes revoked root public key from shared list (other users stop trusting artifacts with revoked key). + - Publisher creates new root key. + - Publisher uploads new root public key to registry (registry can verify user for container uploads). + - Publisher updates shared root public key (other users can verify containers with new key before running). + - Publisher creates new delegate keys. +- Delegate Key Revocation + - Publisher lists revoked delegate keys as untrusted. Revocation list is signed by root key. + - Publisher shares revocation list. + - Publisher creates new delegate keys from existing root. +- Root Rotation + - Publisher creates new root key. + - Publisher uploads new root public key to registry (registry can verify user for container uploads). + - Publisher updates shared root public key (other users can verify containers with new key before running). + - Publisher creates new delegate keys. +- Delegate Key Rotation + - Publisher creates new delegate keys from existing root. In addition we also need to consider the following for cryptographic security: - Supported key types From 6e997da786426c76beb638b2f03df87447a7524a Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Sun, 19 Jul 2020 14:54:01 -0700 Subject: [PATCH 04/28] Update keymanagementscenarios.md Signed-off-by: Niaz Khan --- keymanagementscenarios.md | 88 +++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 40 deletions(-) diff --git a/keymanagementscenarios.md b/keymanagementscenarios.md index 6fe57ebc..3581a791 100644 --- a/keymanagementscenarios.md +++ b/keymanagementscenarios.md @@ -4,51 +4,59 @@ Key management for container signing can be broadly categorized into three gener - Revocation (How do key owners create/revoke keys? How do runtime environments get this information?) Personas: -- Publisher: User who builds containers. +- Publisher: User who builds and signs containers. + - Publisher Admin: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Admin users (i.e. security administrator) will be responsible for configuring roots, provide access to use or generate delegate keys, and make decisions for key revocation. + - Publisher Builder [TODO: better wording]: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Builders (i.e. developers, build hosts) will be responsible for building contatiner images. + - Publisher Singer [TODO: better wording]: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Signers (i.e. developers, signing hosts) will be responsible for signing container images. - Deployer: User who deploys containers. -Signing Use Cases: +Signing use cases: - Local Key Store - - Publisher creates new root key on local machine. Keys are stored in key store or plain text on local machine (Need to identify keystores we want to support. Should we preclude signing with plain text keys to improve security posture?). + - Publisher creates new root key on local machine. Keys are stored in key store or plain text on local machine (Need to identify keystores we want to support. We can preclude signing with root keys to improve security posture). - Publisher uploads root public key to registry (registry can verify user for container uploads). - Publisher shares root public key (other users can verify containers before running). - - Publisher creates new delegate keys on local machine that chain to root key. + - Publisher creates new delegate keys on local machine that chain to root key (enabling only delegate keys for signing will help protect the root key). - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with key in memory. - USB Token Key Store - - Publisher creates new root key on USB token. + - Publisher creates new root key on USB token (better security posture as key is not exposed in plain text outside of token). - Publisher uploads root public key to registry (registry can verify user for container uploads). - Publisher shares root public key (other users can verify containers before running). - - Publisher creates new delegate keys on USB token that chain to root key. - - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with key in USB Token. + - Publisher creates new delegate keys on USB token that chain to root key (better security posture as key is not exposed in plain text outside of token). + - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with key in USB Token (using a PKCS 11 interface will prevent keys from being exposed in memory). - Network HSM - - Publisher creates new root key on Network HSM. + - Publisher creates new root key on Network HSM (better security posture as key is not exposed in plain text outside of HSM). - Publisher uploads root public key to registry (registry can verify user for container uploads). - Publisher shares root public key (other users can verify containers before running). - - Publisher creates new delegate keys on Network HSM that chain to root key. + - Publisher creates new delegate keys on Network HSM that chain to root key (better security posture as key is not exposed in plain text outside of HSM). - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with key in Network HSM. -- Cloud Key Management Service - - Publisher creates new root key on Cloud Key Management Service +- Cloud Key Management Service (KMS) + - Publisher creates new root key on Cloud KMS (better security posture as key is not exposed in plain text outside of Cloud KMS). - Publisher uploads root public key to registry (registry can verify user for container uploads). - Publisher shares root public key (other users can verify containers before running). - - Publisher creates new delegate keys on Cloud Key Management Service that chain to root key. - - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with key in Cloud Key Management Service. + - Publisher creates new delegate keys on Cloud KMS that chain to root key (better security posture as key is not exposed in plain text outside of Cloud KMS). + - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with key in Cloud KMS. - Hybrid - - Publisher creates new root key on USB Token/Network HSM/Cloud Key Management Service - - Publisher uploads root public key to registry (registry can verify user for container uploads). - - Publisher shares root public key (other users can verify containers before running). - - Publisher creates new delegate keys on local machine that chain to root key. - - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with keys on local machine. + - Publisher Admin creates new root key on USB Token/Network HSM/Cloud Key Management Service (better security posture as key is never exposed in plain text outside of token). + - Publisher Admin uploads root public key to registry (registry can verify user for container uploads). + - Publisher Admin shares root public key (other users can verify containers before running). + - Publisher Admin provides access to Publisher Signer to create or retrieve delegate keys (admins can focus on delegating access, signers can use a portal or APIs to register keys and sign without having to repeatedly engage the admin). + - Publisher Signer creates new delegate keys on local machine that chain to root key (the root key is not exposed to the signer). + - Publisher Signer runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with keys on local machine. - Signing by Build Machines - - Publisher creates new root, uploads root public key to registry, and shares root public key. - - Publisher creates new delegate keys on build machine or on USB Token/Network HSM/Cloud Key Management Service - - Publisher configures build scripts with location of delegate keys. - - Build machine runs docker build and then notary v2 sign with keys in configured location. + - Publisher Admin creates new root, uploads root public key to registry, and shares root public key (similar justification to earlier scenarios). + - Publisher Admin delegates access for build machine (Publisher Builder and Signer in this context) to create new delegate keys to be used on build machine. The delegate key can be stored on the build machine, USB Token, Network HSM, or Cloud Key Management Service (similar justification to earlier scenarios). + - Publisher Admin configures build scripts with credentials and if needed location of delegate keys. + - Build machine runs docker build and then notary v2 sign with keys from configured location. - Signing by Dedicated Machines - - Publisher creates new root, uploads root public key to registry, and shares root public key. - - Publisher creates new delegate keys on build machine or on USB Token/Network HSM/Cloud Key Management Service - - Publisher configures signing machine with location of delegate keys. - - Build machine runs docker build and passes objects to be signed to signing host. + - Publisher Admin creates new root, uploads root public key to registry, and shares root public key (similar justification to earlier scenarios). + - Publisher Admin delegates access for signing machine (Publisher Signer in this context) to create new delegate keys to be used on build machine. The delegate key can be stored on the build machine, USB Token, Network HSM, or Cloud Key Management Service (similar justification to earlier scenarios). + - Publisher Admin configures signing machine with credentials and if needed location of delegate keys. + - Build machine (Publisher Builder only in this context) runs docker build and passes objects to be signed to signing host (the build machine does not have access to signing keys. This prevents signing keys from being exposed through potential vulnerabilities in build logic). - Signing host generates signatures with keys in configured location. +- Signing in Air Gapped Environments with Shared Root + - Publisher Admin creates new root, uploads root public key to registry, and shares root public key (similar justification to earlier scenarios). + - Publisher Admin creates new subordinate key in air gapped environment on a host, USB Token, Network HSM, or Cloud Key Management Service chaining to root (one time operation enables the root to be used by runtime environments outside of the air gapped environment to validate signatures generated inside the environment). + - Publisher Admin configures credentials for Publisher Signers in air gapped environment to use sub-ordinate key for delegate keys instead of root key (users in air gapped environment do not need to get keys from outside of the environment). Trust Store Configuration: - Specify trusted public root keys @@ -59,29 +67,29 @@ Trust Store Configuration: - [TODO] - Enterprises can restrict users to add/remove their root public keys to the trust store used across a fleet of runtime hosts. The trust store will validate images pulled from any registry. - Enterprises can restrict users to add/remove root public keys for trusted third parties to their trust stores. The trust store will validate images pulled from any registry. -- [TBD] Do we envision a scenario where the trust store will need to define subordinate keys in addition to the root? +- Trust store also includes subordinate keys - Air gapped environments Key rotation/revocation use cases: -- Root Revocation +- Root Revocation (compromised root should not be needed in process to designate itself as revoked, otherwise attacker can use compromised root for a key rotation locking out publisher) - Publisher deletes revoked root public key on registry (registry can stop sharing containers with revoked key). - - Registry stops vending containers signed with old root key. - - Publisher removes revoked root public key from shared list (other users stop trusting artifacts with revoked key). - - Publisher creates new root key. + - [TODO: Discuss if we want this] Registry stops vending containers signed with old root key (will prevent revoked artifacts from being used by developers not checking signature). + - Publisher removes revoked root public key from shared list (other users stop trusting artifacts with revoked key, provides defense in depth as they are not relying on registry). + - Publisher creates new root key following any scenario listed earlier in Signing use cases (starting from scratch as old key can no longer be trusted). - Publisher uploads new root public key to registry (registry can verify user for container uploads). - Publisher updates shared root public key (other users can verify containers with new key before running). - - Publisher creates new delegate keys. -- Delegate Key Revocation - - Publisher lists revoked delegate keys as untrusted. Revocation list is signed by root key. - - Publisher shares revocation list. - - Publisher creates new delegate keys from existing root. -- Root Rotation - - Publisher creates new root key. + - Publisher creates new delegate keys following any scenario listed earlier in Signing use cases. +- Delegate Key Revocation (root can be used here for designating delegate keys as revoked as it has not been compromised) + - Publisher lists revoked delegate keys as untrusted. Revocation list is signed by root key (Design discussion on whether we use CRLs or some other approach to sharing information on revoked keys). + - Publisher shares revocation list (deployer needs to know which keys used prior for generating signatures are no longer trusted). + - Publisher creates new delegate keys from existing root following any scenario listed earlier in Signing use cases. +- Root Rotation (periodic rotation of root will limit blast radius, this process should not revoke existing root as it has not been compromised) + - Publisher creates new root key following any scenario listed earlier in Signing use cases. - Publisher uploads new root public key to registry (registry can verify user for container uploads). - Publisher updates shared root public key (other users can verify containers with new key before running). - - Publisher creates new delegate keys. + - Publisher creates new delegate keys from new root following any scenario listed earlier in Signing use cases. - Delegate Key Rotation - - Publisher creates new delegate keys from existing root. + - Publisher creates new delegate keys from existing root following any scenario listed earlier in Signing use cases. In addition we also need to consider the following for cryptographic security: - Supported key types From 25ea16446ef5e7d56a5cfeb20c8765f0105b4938 Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Mon, 20 Jul 2020 09:47:45 -0700 Subject: [PATCH 05/28] Update keymanagementscenarios.md Co-authored-by: Trishank Karthik Kuppusamy <33133073+trishankatdatadog@users.noreply.github.com> Signed-off-by: Niaz Khan --- keymanagementscenarios.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keymanagementscenarios.md b/keymanagementscenarios.md index 3581a791..a28623f7 100644 --- a/keymanagementscenarios.md +++ b/keymanagementscenarios.md @@ -6,7 +6,7 @@ Key management for container signing can be broadly categorized into three gener Personas: - Publisher: User who builds and signs containers. - Publisher Admin: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Admin users (i.e. security administrator) will be responsible for configuring roots, provide access to use or generate delegate keys, and make decisions for key revocation. - - Publisher Builder [TODO: better wording]: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Builders (i.e. developers, build hosts) will be responsible for building contatiner images. + - Publisher Builder [TODO: better wording]: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Builders (i.e. developers, build hosts) will be responsible for building container images. - Publisher Singer [TODO: better wording]: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Signers (i.e. developers, signing hosts) will be responsible for signing container images. - Deployer: User who deploys containers. From 3ab610e518a0da46d70ce33579a8b4cbced47730 Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Mon, 20 Jul 2020 09:47:53 -0700 Subject: [PATCH 06/28] Update keymanagementscenarios.md Co-authored-by: Trishank Karthik Kuppusamy <33133073+trishankatdatadog@users.noreply.github.com> Signed-off-by: Niaz Khan --- keymanagementscenarios.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keymanagementscenarios.md b/keymanagementscenarios.md index a28623f7..73adb4b4 100644 --- a/keymanagementscenarios.md +++ b/keymanagementscenarios.md @@ -7,7 +7,7 @@ Personas: - Publisher: User who builds and signs containers. - Publisher Admin: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Admin users (i.e. security administrator) will be responsible for configuring roots, provide access to use or generate delegate keys, and make decisions for key revocation. - Publisher Builder [TODO: better wording]: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Builders (i.e. developers, build hosts) will be responsible for building container images. - - Publisher Singer [TODO: better wording]: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Signers (i.e. developers, signing hosts) will be responsible for signing container images. + - Publisher Signer [TODO: better wording]: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Signers (i.e. developers, signing hosts) will be responsible for signing container images. - Deployer: User who deploys containers. Signing use cases: From 053c97f31d3869da358babcbb9a70eb50a84c13c Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Fri, 25 Sep 2020 08:15:29 -0700 Subject: [PATCH 07/28] Architecture Diagrams Diagrams to highlight new components based on preliminary discussions. Signed-off-by: Niaz Khan --- ...v2-keymgmt-architecture-provisionkeys-v1.png | Bin 0 -> 26110 bytes ...mgmt-architecture-provisiontruststore-v1.png | Bin 0 -> 21581 bytes media/nv2-keymgmt-architecture-pull-v1.png | Bin 0 -> 15535 bytes .../nv2-keymgmt-architecture-revokekeys-v1.png | Bin 0 -> 26344 bytes media/nv2-keymgmt-architecture-sign-v1.png | Bin 0 -> 22871 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 media/nv2-keymgmt-architecture-provisionkeys-v1.png create mode 100644 media/nv2-keymgmt-architecture-provisiontruststore-v1.png create mode 100644 media/nv2-keymgmt-architecture-pull-v1.png create mode 100644 media/nv2-keymgmt-architecture-revokekeys-v1.png create mode 100644 media/nv2-keymgmt-architecture-sign-v1.png diff --git a/media/nv2-keymgmt-architecture-provisionkeys-v1.png b/media/nv2-keymgmt-architecture-provisionkeys-v1.png new file mode 100644 index 0000000000000000000000000000000000000000..f9028a81d29cd4a5dad2641a9186853b6bba6b85 GIT binary patch literal 26110 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 literal 0 HcmV?d00001 diff --git a/media/nv2-keymgmt-architecture-provisiontruststore-v1.png b/media/nv2-keymgmt-architecture-provisiontruststore-v1.png new file mode 100644 index 0000000000000000000000000000000000000000..9e9f3231556959b30b7257867176991976e95517 GIT binary patch literal 21581 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 G!~X}pVL?g& literal 0 HcmV?d00001 diff --git a/media/nv2-keymgmt-architecture-revokekeys-v1.png b/media/nv2-keymgmt-architecture-revokekeys-v1.png new file mode 100644 index 0000000000000000000000000000000000000000..78cb78c41ab2b0e554c682ad6cee86c770a8f5f6 GIT binary patch literal 26344 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 D_pHcH literal 0 HcmV?d00001 From 7e7b404bc3ef5b6e45b1cf03e606c3d90e5fb759 Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Fri, 2 Oct 2020 07:25:34 -0700 Subject: [PATCH 08/28] Update keymanagementscenarios.md Added diagrams, new personas, and placeholders for additional definitions. Signed-off-by: Niaz Khan --- keymanagementscenarios.md | 43 +++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/keymanagementscenarios.md b/keymanagementscenarios.md index 73adb4b4..cebb6755 100644 --- a/keymanagementscenarios.md +++ b/keymanagementscenarios.md @@ -6,11 +6,25 @@ Key management for container signing can be broadly categorized into three gener Personas: - Publisher: User who builds and signs containers. - Publisher Admin: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Admin users (i.e. security administrator) will be responsible for configuring roots, provide access to use or generate delegate keys, and make decisions for key revocation. - - Publisher Builder [TODO: better wording]: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Builders (i.e. developers, build hosts) will be responsible for building container images. - - Publisher Signer [TODO: better wording]: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Signers (i.e. developers, signing hosts) will be responsible for signing container images. + - Publisher Builder: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Builders (i.e. developers, build hosts) will be responsible for creating artifacts. + - Publisher Signer: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Signers (i.e. developers, signing hosts) will be responsible for signing artifacts. - Deployer: User who deploys containers. + - Deployer Admin: In some scenarios a deployer will include a group of users (i.e. teams or enterprises). Admin users (i.e. security administrators) will be responsible for configuring deployment policies, including potentially a set of trusted roots or required signatures. + - Deployer Operator: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Operators (i.e. developers, deployment hosts) will be responsible for pulling container images from registries, verifying their signatures, and then running them. +- Repository Owner: In some scenarios a container may be stored in a repository that is managed by the repository owner. The repository may be public or private and could also be air-gapped. + +Additional Definitions: +- Root key: [TODO] +- Signing key: [TODO] Signing use cases: + +Provisioning Keys for Signing: +![Notaryv2 Signing Provisioning](./media/nv2-keymgmt-architecture-provisionkeys-v1.png) +Signing Workflow: +![Notaryv2 Signing Workflow](./media/nv2-keymgmt-architecture-sign-v1.png) + +Detailed Scenarios: - Local Key Store - Publisher creates new root key on local machine. Keys are stored in key store or plain text on local machine (Need to identify keystores we want to support. We can preclude signing with root keys to improve security posture). - Publisher uploads root public key to registry (registry can verify user for container uploads). @@ -22,19 +36,19 @@ Signing use cases: - Publisher uploads root public key to registry (registry can verify user for container uploads). - Publisher shares root public key (other users can verify containers before running). - Publisher creates new delegate keys on USB token that chain to root key (better security posture as key is not exposed in plain text outside of token). - - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with key in USB Token (using a PKCS 11 interface will prevent keys from being exposed in memory). + - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signature by submitting hash to USB Token (using a PKCS 11 interface will prevent keys from being exposed in memory). - Network HSM - Publisher creates new root key on Network HSM (better security posture as key is not exposed in plain text outside of HSM). - Publisher uploads root public key to registry (registry can verify user for container uploads). - Publisher shares root public key (other users can verify containers before running). - Publisher creates new delegate keys on Network HSM that chain to root key (better security posture as key is not exposed in plain text outside of HSM). - - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with key in Network HSM. + - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signature by submitting hash to Network HSM. - Cloud Key Management Service (KMS) - Publisher creates new root key on Cloud KMS (better security posture as key is not exposed in plain text outside of Cloud KMS). - Publisher uploads root public key to registry (registry can verify user for container uploads). - Publisher shares root public key (other users can verify containers before running). - Publisher creates new delegate keys on Cloud KMS that chain to root key (better security posture as key is not exposed in plain text outside of Cloud KMS). - - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with key in Cloud KMS. + - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signature by submitting hash to Cloud KMS. - Hybrid - Publisher Admin creates new root key on USB Token/Network HSM/Cloud Key Management Service (better security posture as key is never exposed in plain text outside of token). - Publisher Admin uploads root public key to registry (registry can verify user for container uploads). @@ -58,19 +72,30 @@ Signing use cases: - Publisher Admin creates new subordinate key in air gapped environment on a host, USB Token, Network HSM, or Cloud Key Management Service chaining to root (one time operation enables the root to be used by runtime environments outside of the air gapped environment to validate signatures generated inside the environment). - Publisher Admin configures credentials for Publisher Signers in air gapped environment to use sub-ordinate key for delegate keys instead of root key (users in air gapped environment do not need to get keys from outside of the environment). -Trust Store Configuration: +Deployment Use Cases: + +Provisioning Truststore for Deployment: +![Notaryv2 Deployment Provisioning](./media/nv2-nv2-keymgmt-architecture-provisiontruststore-v1.png) +Deployment Workflow: +![Notaryv2 Deployment Workflow](./media/nv2-keymgmt-architecture-pull-v1.png) + - Specify trusted public root keys - - Deployer gets root public key from publisher. - - Deployer adds root public key to runtime configuration. + - Deployer Admin gets root public key from publisher. + - Deployer Admin adds root public key to runtime configuration. - Container pulled from any registry is be validated with listed root public keys before execution. - Specify location of trusted public root keys - - [TODO] + - Deployer Admin gets location of key repository from publisher. + - Deployer Admin adds location of key repository to runtime configuration. + - Container pulled from any registry is be validated with listed root public keys before execution. - Enterprises can restrict users to add/remove their root public keys to the trust store used across a fleet of runtime hosts. The trust store will validate images pulled from any registry. - Enterprises can restrict users to add/remove root public keys for trusted third parties to their trust stores. The trust store will validate images pulled from any registry. - Trust store also includes subordinate keys - Air gapped environments Key rotation/revocation use cases: + +![Notaryv2 Revocation Workflow](./media/nv2-keymgmt-architecture-revokekeys-v1.png) + - Root Revocation (compromised root should not be needed in process to designate itself as revoked, otherwise attacker can use compromised root for a key rotation locking out publisher) - Publisher deletes revoked root public key on registry (registry can stop sharing containers with revoked key). - [TODO: Discuss if we want this] Registry stops vending containers signed with old root key (will prevent revoked artifacts from being used by developers not checking signature). From d4ed3cf4c1c19215a0e75f3415357774f7261104 Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Fri, 2 Oct 2020 07:27:17 -0700 Subject: [PATCH 09/28] Update keymanagementscenarios.md Fixed image rendering Signed-off-by: Niaz Khan --- keymanagementscenarios.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/keymanagementscenarios.md b/keymanagementscenarios.md index cebb6755..2ea608f6 100644 --- a/keymanagementscenarios.md +++ b/keymanagementscenarios.md @@ -21,6 +21,7 @@ Signing use cases: Provisioning Keys for Signing: ![Notaryv2 Signing Provisioning](./media/nv2-keymgmt-architecture-provisionkeys-v1.png) + Signing Workflow: ![Notaryv2 Signing Workflow](./media/nv2-keymgmt-architecture-sign-v1.png) @@ -75,10 +76,12 @@ Detailed Scenarios: Deployment Use Cases: Provisioning Truststore for Deployment: -![Notaryv2 Deployment Provisioning](./media/nv2-nv2-keymgmt-architecture-provisiontruststore-v1.png) +![Notaryv2 Deployment Provisioning](./media/nv2-keymgmt-architecture-provisiontruststore-v1.png) + Deployment Workflow: ![Notaryv2 Deployment Workflow](./media/nv2-keymgmt-architecture-pull-v1.png) +Detailed Usecases: - Specify trusted public root keys - Deployer Admin gets root public key from publisher. - Deployer Admin adds root public key to runtime configuration. @@ -94,6 +97,7 @@ Deployment Workflow: Key rotation/revocation use cases: +Key Revocation Workflow: ![Notaryv2 Revocation Workflow](./media/nv2-keymgmt-architecture-revokekeys-v1.png) - Root Revocation (compromised root should not be needed in process to designate itself as revoked, otherwise attacker can use compromised root for a key rotation locking out publisher) From b0f8718f6d37465dc53f3c8440c49add2232de3a Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Fri, 2 Oct 2020 07:28:24 -0700 Subject: [PATCH 10/28] Update keymanagementscenarios.md Fixes for image rendering Signed-off-by: Niaz Khan --- keymanagementscenarios.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/keymanagementscenarios.md b/keymanagementscenarios.md index 2ea608f6..dd8b6de6 100644 --- a/keymanagementscenarios.md +++ b/keymanagementscenarios.md @@ -19,10 +19,12 @@ Additional Definitions: Signing use cases: -Provisioning Keys for Signing: +Provisioning Keys for Signing + ![Notaryv2 Signing Provisioning](./media/nv2-keymgmt-architecture-provisionkeys-v1.png) -Signing Workflow: +Signing Workflow + ![Notaryv2 Signing Workflow](./media/nv2-keymgmt-architecture-sign-v1.png) Detailed Scenarios: @@ -75,10 +77,12 @@ Detailed Scenarios: Deployment Use Cases: -Provisioning Truststore for Deployment: +Provisioning Truststore for Deployment + ![Notaryv2 Deployment Provisioning](./media/nv2-keymgmt-architecture-provisiontruststore-v1.png) -Deployment Workflow: +Deployment Workflow + ![Notaryv2 Deployment Workflow](./media/nv2-keymgmt-architecture-pull-v1.png) Detailed Usecases: @@ -97,7 +101,8 @@ Detailed Usecases: Key rotation/revocation use cases: -Key Revocation Workflow: +Key Revocation Workflow + ![Notaryv2 Revocation Workflow](./media/nv2-keymgmt-architecture-revokekeys-v1.png) - Root Revocation (compromised root should not be needed in process to designate itself as revoked, otherwise attacker can use compromised root for a key rotation locking out publisher) From a5fe2a76d74f84bcb2b1df466b7f6056c5e6be68 Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Mon, 26 Oct 2020 09:00:38 -0700 Subject: [PATCH 11/28] Update keymanagementscenarios.md Signed-off-by: Niaz Khan --- keymanagementscenarios.md | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/keymanagementscenarios.md b/keymanagementscenarios.md index dd8b6de6..bb625e69 100644 --- a/keymanagementscenarios.md +++ b/keymanagementscenarios.md @@ -14,8 +14,14 @@ Personas: - Repository Owner: In some scenarios a container may be stored in a repository that is managed by the repository owner. The repository may be public or private and could also be air-gapped. Additional Definitions: -- Root key: [TODO] -- Signing key: [TODO] +- Root key: A self signed key used for the lowest designation of trust. Root keys can be created by developers, organizations, public/private CAs, and registry operators. The root key should be retrieved from a trusted source that can establish the authenticity of the creator's identity. +- Signing key: A signing key is used to generate artifact signatures. A signing key should be signed with a root key or one of its intermediaries. The certificate chain with a signing key can be used to verify which root it belongs to. While a root key can be used as a signing key, this is not recommended as it creates a large blast radius and increases the risk of compromising a root key. +- Trust Store: The trust store defines the relationship between signing keys and artifacts that are used at validation time to determine whether to trust an artifact with a crytptographically valid signature. The trust store will relate a source (any source, specific registry, specific repository, or specific target) with a certificate (for root key, intermediate, or signing key) or key repository (for automated key distribtuion). It is not recommended to use a signing key as this will cause signature validation to fail if the signing key is rotated. +- Trust Store Certificate: The certificate in the trust store will contain: + - Public Key: Will be matched against CRL and signature artifact. + - Signed CRL URL: Location to retrieve CRL from. + - Signed Identity: Identity of creator of the signed certificate. + - (Optional) Issuer: If the certificate is an intermediate this will describe the issuer of the certificate. Signing use cases: @@ -96,8 +102,17 @@ Detailed Usecases: - Container pulled from any registry is be validated with listed root public keys before execution. - Enterprises can restrict users to add/remove their root public keys to the trust store used across a fleet of runtime hosts. The trust store will validate images pulled from any registry. - Enterprises can restrict users to add/remove root public keys for trusted third parties to their trust stores. The trust store will validate images pulled from any registry. -- Trust store also includes subordinate keys -- Air gapped environments +- Air gapped environments can either specify the + +Key Distribution Workflows: +- Manual Configuration + - Publisher places their root certificate in a public location. This could be a website similar to what public CAs today provide. + - Developer copies certificate from public location and adds it to their trust store. Developer can configure whether they trust this certificate for all their artifacts, individual registries, individual repositories, or individual targets. +- Automated Configuration + - Publisher gets intermediate certificate from a key distriution service i.e public CA or registry operator. + - Developer adds root certificate and location of key respoitory to their trust store. Developer can configure whether they trust certificates for all their artifacts, individual registries, individual repositories, or individual targets. +- Revocation: Note in the event a root certificate is revoked validations will fail, and developers will need to update their root certificate. The publisher will need to pro-actively communicate a rotation out of bands to prevent an outage. + Key rotation/revocation use cases: @@ -126,10 +141,10 @@ Key Revocation Workflow - Publisher creates new delegate keys from existing root following any scenario listed earlier in Signing use cases. In addition we also need to consider the following for cryptographic security: -- Supported key types -- Supported signing algorithms +- Supported key types [TODO: Pull from NIST recommendations] +- Supported signing algorithms [TODO: Pull from NIST recommendations] -Identify use cases to clarify: +Additional questions to clarify as part of implementation (need more research but doesn't impact workflow): 1. Where can keys be stored? What interfaces need to be supported? 2. Any limitations ok key types/sizes supported? 3. How will public keys (root of trust) be distributed? From 388c9eb0bfa9c29cf831cc5340f2cf3d96f0a38d Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Mon, 2 Nov 2020 08:52:14 -0800 Subject: [PATCH 12/28] Update keymanagementscenarios.md Signed-off-by: Niaz Khan --- keymanagementscenarios.md | 52 +++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/keymanagementscenarios.md b/keymanagementscenarios.md index bb625e69..cbb42138 100644 --- a/keymanagementscenarios.md +++ b/keymanagementscenarios.md @@ -1,9 +1,10 @@ +# Overview Key management for container signing can be broadly categorized into three general use cases: - Key Setup/Signing (How are keys set up? How are keys accessed by Notary v2 client when signatures are generated?) - Trust store configuration (How do runtime environments determine which keys to trust?) - Revocation (How do key owners create/revoke keys? How do runtime environments get this information?) -Personas: +## Personas: - Publisher: User who builds and signs containers. - Publisher Admin: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Admin users (i.e. security administrator) will be responsible for configuring roots, provide access to use or generate delegate keys, and make decisions for key revocation. - Publisher Builder: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Builders (i.e. developers, build hosts) will be responsible for creating artifacts. @@ -13,7 +14,7 @@ Personas: - Deployer Operator: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Operators (i.e. developers, deployment hosts) will be responsible for pulling container images from registries, verifying their signatures, and then running them. - Repository Owner: In some scenarios a container may be stored in a repository that is managed by the repository owner. The repository may be public or private and could also be air-gapped. -Additional Definitions: +## Definitions: - Root key: A self signed key used for the lowest designation of trust. Root keys can be created by developers, organizations, public/private CAs, and registry operators. The root key should be retrieved from a trusted source that can establish the authenticity of the creator's identity. - Signing key: A signing key is used to generate artifact signatures. A signing key should be signed with a root key or one of its intermediaries. The certificate chain with a signing key can be used to verify which root it belongs to. While a root key can be used as a signing key, this is not recommended as it creates a large blast radius and increases the risk of compromising a root key. - Trust Store: The trust store defines the relationship between signing keys and artifacts that are used at validation time to determine whether to trust an artifact with a crytptographically valid signature. The trust store will relate a source (any source, specific registry, specific repository, or specific target) with a certificate (for root key, intermediate, or signing key) or key repository (for automated key distribtuion). It is not recommended to use a signing key as this will cause signature validation to fail if the signing key is rotated. @@ -23,17 +24,30 @@ Additional Definitions: - Signed Identity: Identity of creator of the signed certificate. - (Optional) Issuer: If the certificate is an intermediate this will describe the issuer of the certificate. -Signing use cases: +## Requirements +- Signing an artifact SHOULD NOT require the publisher to perform additional actions with a registry or registry operator beyond those required to push an unsigned artifact. +- Validating a signature SHOULD NOT require the deployer to perform additional actions with a registry or registry operator beyond those required to pull an unsigned artifact. +- Moving an artifact from one repository to another SHOULD NOT invalidate the signature on the artifact. +- A rotation of the root key SHOULD NOT require the use of the existing root key. +- Publishers SHOULD be able to sign with keys stored on their local machines, secure tokens, Hardware Security Modules (HSMs), or cloud based Key Management Services. +- Publishers SHOULD be able to generate multiple signatures for a single artifact. +- Publishers MUST have a mechanism to revoke signatures to indicate they are no longer trusted. +- Trust stores SHOULD be configurable by the deployer. +- Deployers MUST be able to configure trusted entities for individual repositories and targets. +- Deployers MUST be able to validate signatures on any version of an artifact including whether they have been revoked by the publisher. +- Signature validation MUST be enforceable in air-gapped environments with minimal updates. -Provisioning Keys for Signing +# Signing use cases: + +## Provisioning Keys for Signing ![Notaryv2 Signing Provisioning](./media/nv2-keymgmt-architecture-provisionkeys-v1.png) -Signing Workflow +## Signing Workflow ![Notaryv2 Signing Workflow](./media/nv2-keymgmt-architecture-sign-v1.png) -Detailed Scenarios: +## Detailed Scenarios: - Local Key Store - Publisher creates new root key on local machine. Keys are stored in key store or plain text on local machine (Need to identify keystores we want to support. We can preclude signing with root keys to improve security posture). - Publisher uploads root public key to registry (registry can verify user for container uploads). @@ -81,17 +95,17 @@ Detailed Scenarios: - Publisher Admin creates new subordinate key in air gapped environment on a host, USB Token, Network HSM, or Cloud Key Management Service chaining to root (one time operation enables the root to be used by runtime environments outside of the air gapped environment to validate signatures generated inside the environment). - Publisher Admin configures credentials for Publisher Signers in air gapped environment to use sub-ordinate key for delegate keys instead of root key (users in air gapped environment do not need to get keys from outside of the environment). -Deployment Use Cases: +# Deployment Use Cases: -Provisioning Truststore for Deployment +## Provisioning Truststore for Deployment ![Notaryv2 Deployment Provisioning](./media/nv2-keymgmt-architecture-provisiontruststore-v1.png) -Deployment Workflow +## Deployment Workflow ![Notaryv2 Deployment Workflow](./media/nv2-keymgmt-architecture-pull-v1.png) -Detailed Usecases: +## Detailed Usecases: - Specify trusted public root keys - Deployer Admin gets root public key from publisher. - Deployer Admin adds root public key to runtime configuration. @@ -102,9 +116,9 @@ Detailed Usecases: - Container pulled from any registry is be validated with listed root public keys before execution. - Enterprises can restrict users to add/remove their root public keys to the trust store used across a fleet of runtime hosts. The trust store will validate images pulled from any registry. - Enterprises can restrict users to add/remove root public keys for trusted third parties to their trust stores. The trust store will validate images pulled from any registry. -- Air gapped environments can either specify the +- Air gapped environments can manually specify the trusted keys in their trust stores. Air-gapped operators will need to either maintain an air-gapped copy of the CRL or re-sign artifacts locally within an air-gapped environment. -Key Distribution Workflows: +# Key Distribution Workflows: - Manual Configuration - Publisher places their root certificate in a public location. This could be a website similar to what public CAs today provide. - Developer copies certificate from public location and adds it to their trust store. Developer can configure whether they trust this certificate for all their artifacts, individual registries, individual repositories, or individual targets. @@ -113,10 +127,9 @@ Key Distribution Workflows: - Developer adds root certificate and location of key respoitory to their trust store. Developer can configure whether they trust certificates for all their artifacts, individual registries, individual repositories, or individual targets. - Revocation: Note in the event a root certificate is revoked validations will fail, and developers will need to update their root certificate. The publisher will need to pro-actively communicate a rotation out of bands to prevent an outage. +# Key rotation/revocation use cases: -Key rotation/revocation use cases: - -Key Revocation Workflow +## Key Revocation Workflow ![Notaryv2 Revocation Workflow](./media/nv2-keymgmt-architecture-revokekeys-v1.png) @@ -140,10 +153,7 @@ Key Revocation Workflow - Delegate Key Rotation - Publisher creates new delegate keys from existing root following any scenario listed earlier in Signing use cases. -In addition we also need to consider the following for cryptographic security: -- Supported key types [TODO: Pull from NIST recommendations] -- Supported signing algorithms [TODO: Pull from NIST recommendations] - +# Follow ups for Implementation Additional questions to clarify as part of implementation (need more research but doesn't impact workflow): 1. Where can keys be stored? What interfaces need to be supported? 2. Any limitations ok key types/sizes supported? @@ -152,3 +162,7 @@ Additional questions to clarify as part of implementation (need more research bu 5a. What is the minimum number of keys needed to succesfully sign a container? 5b. What is the recommended number of keys to sign a container? 6. Any additional requirements for timestamping? + +In addition we also need to consider the following for cryptographic security: +- Supported key types [TODO: Pull from NIST recommendations] +- Supported signing algorithms [TODO: Pull from NIST recommendations] From 7808ca7aa983f23c76d2c5b9c81467c5eabccf2d Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Mon, 2 Nov 2020 08:58:00 -0800 Subject: [PATCH 13/28] Update keymanagementscenarios.md Signed-off-by: Niaz Khan --- keymanagementscenarios.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keymanagementscenarios.md b/keymanagementscenarios.md index cbb42138..2cec9e24 100644 --- a/keymanagementscenarios.md +++ b/keymanagementscenarios.md @@ -25,8 +25,8 @@ Key management for container signing can be broadly categorized into three gener - (Optional) Issuer: If the certificate is an intermediate this will describe the issuer of the certificate. ## Requirements -- Signing an artifact SHOULD NOT require the publisher to perform additional actions with a registry or registry operator beyond those required to push an unsigned artifact. -- Validating a signature SHOULD NOT require the deployer to perform additional actions with a registry or registry operator beyond those required to pull an unsigned artifact. +- Signing an artifact SHOULD NOT require the publisher to perform additional actions with a registry/repository or registry operator beyond those required to push an unsigned artifact. +- Validating a signature SHOULD NOT require the deployer to perform additional actions with a registry/repository or registry operator beyond those required to pull an unsigned artifact. - Moving an artifact from one repository to another SHOULD NOT invalidate the signature on the artifact. - A rotation of the root key SHOULD NOT require the use of the existing root key. - Publishers SHOULD be able to sign with keys stored on their local machines, secure tokens, Hardware Security Modules (HSMs), or cloud based Key Management Services. From 203856d5a29142584c97e0e4478f60cd6fe8c1d4 Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Mon, 8 Feb 2021 08:57:38 -0800 Subject: [PATCH 14/28] Update keymanagementscenarios.md Signed-off-by: Niaz Khan --- keymanagementscenarios.md | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/keymanagementscenarios.md b/keymanagementscenarios.md index 2cec9e24..7d428f6c 100644 --- a/keymanagementscenarios.md +++ b/keymanagementscenarios.md @@ -1,8 +1,8 @@ # Overview Key management for container signing can be broadly categorized into three general use cases: -- Key Setup/Signing (How are keys set up? How are keys accessed by Notary v2 client when signatures are generated?) -- Trust store configuration (How do runtime environments determine which keys to trust?) -- Revocation (How do key owners create/revoke keys? How do runtime environments get this information?) +- Key Setup/Signing (Key managment and integrations with client tooling for generating signatures.) +- Trust store configuration (Configuring which keys to trust for artifacts from a predefined source.) +- Signature Validity (Expiry, Revocation and/or Trusted Update List. Mechanism to update information on the validity of signatures.) ## Personas: - Publisher: User who builds and signs containers. @@ -18,24 +18,36 @@ Key management for container signing can be broadly categorized into three gener - Root key: A self signed key used for the lowest designation of trust. Root keys can be created by developers, organizations, public/private CAs, and registry operators. The root key should be retrieved from a trusted source that can establish the authenticity of the creator's identity. - Signing key: A signing key is used to generate artifact signatures. A signing key should be signed with a root key or one of its intermediaries. The certificate chain with a signing key can be used to verify which root it belongs to. While a root key can be used as a signing key, this is not recommended as it creates a large blast radius and increases the risk of compromising a root key. - Trust Store: The trust store defines the relationship between signing keys and artifacts that are used at validation time to determine whether to trust an artifact with a crytptographically valid signature. The trust store will relate a source (any source, specific registry, specific repository, or specific target) with a certificate (for root key, intermediate, or signing key) or key repository (for automated key distribtuion). It is not recommended to use a signing key as this will cause signature validation to fail if the signing key is rotated. -- Trust Store Certificate: The certificate in the trust store will contain: - - Public Key: Will be matched against CRL and signature artifact. - - Signed CRL URL: Location to retrieve CRL from. - - Signed Identity: Identity of creator of the signed certificate. - - (Optional) Issuer: If the certificate is an intermediate this will describe the issuer of the certificate. +- Trust Store Key Information: The key information configured in the trust store will be cryptographically verifiable and contain: + - Public Key: Will be used to verify signed artifacts. + - Signed Identity: Identity of creator of the signing key. + - (Optional) Issuer: If the key is an intermediate this will describe the owner of the root. + - Mechanism to update validity of signatures generated with the signing key. ## Requirements - Signing an artifact SHOULD NOT require the publisher to perform additional actions with a registry/repository or registry operator beyond those required to push an unsigned artifact. - Validating a signature SHOULD NOT require the deployer to perform additional actions with a registry/repository or registry operator beyond those required to pull an unsigned artifact. - Moving an artifact from one repository to another SHOULD NOT invalidate the signature on the artifact. -- A rotation of the root key SHOULD NOT require the use of the existing root key. - Publishers SHOULD be able to sign with keys stored on their local machines, secure tokens, Hardware Security Modules (HSMs), or cloud based Key Management Services. - Publishers SHOULD be able to generate multiple signatures for a single artifact. - Publishers MUST have a mechanism to revoke signatures to indicate they are no longer trusted. - Trust stores SHOULD be configurable by the deployer. - Deployers MUST be able to configure trusted entities for individual repositories and targets. - Deployers MUST be able to validate signatures on any version of an artifact including whether they have been revoked by the publisher. -- Signature validation MUST be enforceable in air-gapped environments with minimal updates. +- Signature validation MUST be enforceable in air-gapped environments. + +## Requirements for discussion +- Providing a mechanism for rotating a root key: In prior discussions we did not close on whether Notary v2 should provide a mechanism for rotating a root key or not. Tradeoffs are listed below for further discussion. + - Adding a mechanism: + - Allows for the automatic rotation of keys. Can be used to mass update keys if signing algorithms need to be updated. + - Doesn't address the use case of developers losing a root key. + - Provides a bad actor mechanism to insert a new root without deployer acknowledgement. + - Not adding a mechanism: + - Any rotation of root keys will require deployers to acknowledge and make a change. + - Doesn't address the use case of developers losing a root key. + - Prevents a bad actor from inserting a new root without deployer acknowledgement. + +****READ UP TO HERE, SECTIONS BELOW ARE WORK IN PROGRESS**** # Signing use cases: From dc5790eb3b16a0df633086fa5a1568db7282c14e Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Mon, 8 Feb 2021 09:07:40 -0800 Subject: [PATCH 15/28] Update keymanagementscenarios.md Signed-off-by: Niaz Khan --- keymanagementscenarios.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/keymanagementscenarios.md b/keymanagementscenarios.md index 7d428f6c..d9478957 100644 --- a/keymanagementscenarios.md +++ b/keymanagementscenarios.md @@ -40,13 +40,20 @@ Key management for container signing can be broadly categorized into three gener - Providing a mechanism for rotating a root key: In prior discussions we did not close on whether Notary v2 should provide a mechanism for rotating a root key or not. Tradeoffs are listed below for further discussion. - Adding a mechanism: - Allows for the automatic rotation of keys. Can be used to mass update keys if signing algorithms need to be updated. - - Doesn't address the use case of developers losing a root key. + - Doesn't address the use case of publishers losing a root key. - Provides a bad actor mechanism to insert a new root without deployer acknowledgement. - Not adding a mechanism: - Any rotation of root keys will require deployers to acknowledge and make a change. - - Doesn't address the use case of developers losing a root key. + - Doesn't address the use case of publishers losing a root key. - Prevents a bad actor from inserting a new root without deployer acknowledgement. - + - Scenarios to consider: + - Publisher loses key. + - Publisher needs to update key for reasons beside unauthorized access to a key. + - Publisher's root key access is compromised, and they are aware. + - Publisher's root key access is compromised, but they are unaware. + - Publisher's root key is compromised, and they are aware. + - Publisher's root key is compromised, but they are unaware. + ****READ UP TO HERE, SECTIONS BELOW ARE WORK IN PROGRESS**** # Signing use cases: From c1bba8be5d33876388b01129117bc84af112b6f8 Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Wed, 3 Mar 2021 07:23:37 -0800 Subject: [PATCH 16/28] Update keymanagementscenarios.md Signed-off-by: Niaz Khan --- keymanagementscenarios.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/keymanagementscenarios.md b/keymanagementscenarios.md index d9478957..e5c41be5 100644 --- a/keymanagementscenarios.md +++ b/keymanagementscenarios.md @@ -37,18 +37,23 @@ Key management for container signing can be broadly categorized into three gener - Signature validation MUST be enforceable in air-gapped environments. ## Requirements for discussion -- Providing a mechanism for rotating a root key: In prior discussions we did not close on whether Notary v2 should provide a mechanism for rotating a root key or not. Tradeoffs are listed below for further discussion. - - Adding a mechanism: +- Providing a mechanism for configuring/rotating a root key: In prior discussions we did not close on whether Notary v2 should provide a mechanism for rotating a root key or not. Tradeoffs are listed below for further discussion. + - Things to consider for dock: + - Who is handling roots? + - How are roots being distributed? + - What infrastructure requirements for root management + - Adding a mechanism to configure/rotate keys: - Allows for the automatic rotation of keys. Can be used to mass update keys if signing algorithms need to be updated. - Doesn't address the use case of publishers losing a root key. - Provides a bad actor mechanism to insert a new root without deployer acknowledgement. + - Consider whether this mechanism needs to rely on existing root or roots. (Make the distinction for multiple roots) - Not adding a mechanism: - Any rotation of root keys will require deployers to acknowledge and make a change. - Doesn't address the use case of publishers losing a root key. - Prevents a bad actor from inserting a new root without deployer acknowledgement. - Scenarios to consider: - Publisher loses key. - - Publisher needs to update key for reasons beside unauthorized access to a key. + - Publisher needs to update key for reasons beside unauthorized access to a key (includes expiration, new key types). - Publisher's root key access is compromised, and they are aware. - Publisher's root key access is compromised, but they are unaware. - Publisher's root key is compromised, and they are aware. From c9cdf3a27bfffde4a44cf26702171832957d1c34 Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Mon, 8 Mar 2021 07:58:13 -0800 Subject: [PATCH 17/28] Update and rename keymanagementscenarios.md to keymanagementrequirements.md Signed-off-by: Niaz Khan --- keymanagementrequirements.md | 51 ++++++++++ keymanagementscenarios.md | 192 ----------------------------------- 2 files changed, 51 insertions(+), 192 deletions(-) create mode 100644 keymanagementrequirements.md delete mode 100644 keymanagementscenarios.md diff --git a/keymanagementrequirements.md b/keymanagementrequirements.md new file mode 100644 index 00000000..480eb4ee --- /dev/null +++ b/keymanagementrequirements.md @@ -0,0 +1,51 @@ +# Overview +Key management for container signing can be broadly categorized into three general use cases: +- Key Setup/Signing (Key managment and integrations with client tooling for generating signatures.) +- Trust store configuration (Configuring which keys to trust for artifacts from a predefined source.) +- Signature Validity (Expiry, Revocation and/or Trusted Update List. Mechanism to update information on the validity of signatures.) + +## Personas: +- Publisher: User who builds and signs containers. + - Publisher Admin: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Admin users (i.e. security administrator) will be responsible for configuring roots, provide access to use or generate delegate keys, and make decisions for key revocation. + - Publisher Builder: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Builders (i.e. developers, build hosts) will be responsible for creating artifacts. + - Publisher Signer: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Signers (i.e. developers, signing hosts) will be responsible for signing artifacts. +- Deployer: User who deploys containers. + - Deployer Admin: In some scenarios a deployer will include a group of users (i.e. teams or enterprises). Admin users (i.e. security administrators) will be responsible for configuring deployment policies, including potentially a set of trusted roots or required signatures. + - Deployer Operator: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Operators (i.e. developers, deployment hosts) will be responsible for pulling container images from registries, verifying their signatures, and then running them. +- Repository Owner: In some scenarios a container may be stored in a repository that is managed by the repository owner. The repository may be public or private and could also be air-gapped. + +## Definitions: +- Root key: A self signed key used for the lowest designation of trust. Root keys can be created by developers, organizations, public/private CAs, and registry operators. The root key should be retrieved from a trusted source that can establish the authenticity of the creator's identity. +- Signing key: A signing key is used to generate artifact signatures. A signing key should be signed with a root key or one of its intermediaries. The certificate chain with a signing key can be used to verify which root it belongs to. While a root key can be used as a signing key, this is not recommended as it creates a large blast radius and increases the risk of compromising a root key. +- Trust Store: The trust store defines the relationship between signing keys and artifacts that are used at validation time to determine whether to trust an artifact with a crytptographically valid signature. The trust store will relate a source (any source, specific registry, specific repository, or specific target) with a certificate (for root key, intermediate, or signing key) or key repository (for automated key distribtuion). It is not recommended to use a signing key as this will cause signature validation to fail if the signing key is rotated. +- Trust Store Key Information: The key information configured in the trust store will be cryptographically verifiable and contain: + - Public Key: Will be used to verify signed artifacts. + - Signed Identity: Identity of creator of the signing key. + - (Optional) Issuer: If the key is an intermediate this will describe the owner of the root. + - Mechanism to update validity of signatures generated with the signing key. + +## Requirements +- Signing an artifact MUST NOT require the publisher to perform additional actions with a registry/repository or registry operator. Uploading a signature MAY require additional actions. +- Retrieving a signature MUST NOT require the deployer to perform additional actions with a registry/repository or registry operator beyond those required to pull an unsigned artifact. +- Artifact integrity, source, and signature expiry MUST be verifiable from the signature AND NOT require additional calls to the registry/repository. +- Signature allow list/deny list MAY require additional calls that will be defined in a separate document. +- Moving an artifact from one repository to another SHOULD NOT invalidate the signature on the artifact. +- Publishers SHOULD be able to sign with keys stored on their local machines, secure tokens, Hardware Security Modules (HSMs), or cloud based Key Management Services. +- Publishers SHOULD be able to generate multiple signatures for a single artifact. +- Publisher admins MUST have a mechanism to revoke signatures to indicate they are no longer trusted. +- Trust stores MUST be configurable by the deployer admin. +- Deployer admins MUST be able to configure trusted entities for individual repositories and targets. +- Deployers MUST be able to validate signatures on any version of an artifact including whether they have been revoked by the publisher. +- Signature validation MUST be enforceable in air-gapped environments. + +## Requirements that need further discussion +- Signature/Key Expiry +- Root key auto rotation +- Signature allow list/deny list (trusted updates/revocation list) + +## Prototype Stages +1. Signature generation for each of the key storage scenarios. A succesful prototype should enable signing with keys on each of the following: local host, secure tokens, Hardware Security Modules (HSMs), and cloud based Key Management Services. +2. Trust store configuration and signature source validation in runtime environments. A succesful prototype should enable configuring a trust store in a runtime environment. The prototype should validate signatures from a trusted source and reject signatures from a source that is not listed. The prototype will not check for other aspects of signature validity (expiry/revocation). +3. Key rotation. A succesful prototype should meet all requirements from the key rotation document. +4. Signature/Key Expiration. A succesful prototype should meet all requirements from the signature/key expiration document. +5. Signature allowlist/denylist. A succesful prototype should meet all requirements from the signatur allowlist/denylist document. diff --git a/keymanagementscenarios.md b/keymanagementscenarios.md deleted file mode 100644 index e5c41be5..00000000 --- a/keymanagementscenarios.md +++ /dev/null @@ -1,192 +0,0 @@ -# Overview -Key management for container signing can be broadly categorized into three general use cases: -- Key Setup/Signing (Key managment and integrations with client tooling for generating signatures.) -- Trust store configuration (Configuring which keys to trust for artifacts from a predefined source.) -- Signature Validity (Expiry, Revocation and/or Trusted Update List. Mechanism to update information on the validity of signatures.) - -## Personas: -- Publisher: User who builds and signs containers. - - Publisher Admin: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Admin users (i.e. security administrator) will be responsible for configuring roots, provide access to use or generate delegate keys, and make decisions for key revocation. - - Publisher Builder: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Builders (i.e. developers, build hosts) will be responsible for creating artifacts. - - Publisher Signer: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Signers (i.e. developers, signing hosts) will be responsible for signing artifacts. -- Deployer: User who deploys containers. - - Deployer Admin: In some scenarios a deployer will include a group of users (i.e. teams or enterprises). Admin users (i.e. security administrators) will be responsible for configuring deployment policies, including potentially a set of trusted roots or required signatures. - - Deployer Operator: In some scenarios a publisher will include a group of users (i.e. teams or enterprises). Operators (i.e. developers, deployment hosts) will be responsible for pulling container images from registries, verifying their signatures, and then running them. -- Repository Owner: In some scenarios a container may be stored in a repository that is managed by the repository owner. The repository may be public or private and could also be air-gapped. - -## Definitions: -- Root key: A self signed key used for the lowest designation of trust. Root keys can be created by developers, organizations, public/private CAs, and registry operators. The root key should be retrieved from a trusted source that can establish the authenticity of the creator's identity. -- Signing key: A signing key is used to generate artifact signatures. A signing key should be signed with a root key or one of its intermediaries. The certificate chain with a signing key can be used to verify which root it belongs to. While a root key can be used as a signing key, this is not recommended as it creates a large blast radius and increases the risk of compromising a root key. -- Trust Store: The trust store defines the relationship between signing keys and artifacts that are used at validation time to determine whether to trust an artifact with a crytptographically valid signature. The trust store will relate a source (any source, specific registry, specific repository, or specific target) with a certificate (for root key, intermediate, or signing key) or key repository (for automated key distribtuion). It is not recommended to use a signing key as this will cause signature validation to fail if the signing key is rotated. -- Trust Store Key Information: The key information configured in the trust store will be cryptographically verifiable and contain: - - Public Key: Will be used to verify signed artifacts. - - Signed Identity: Identity of creator of the signing key. - - (Optional) Issuer: If the key is an intermediate this will describe the owner of the root. - - Mechanism to update validity of signatures generated with the signing key. - -## Requirements -- Signing an artifact SHOULD NOT require the publisher to perform additional actions with a registry/repository or registry operator beyond those required to push an unsigned artifact. -- Validating a signature SHOULD NOT require the deployer to perform additional actions with a registry/repository or registry operator beyond those required to pull an unsigned artifact. -- Moving an artifact from one repository to another SHOULD NOT invalidate the signature on the artifact. -- Publishers SHOULD be able to sign with keys stored on their local machines, secure tokens, Hardware Security Modules (HSMs), or cloud based Key Management Services. -- Publishers SHOULD be able to generate multiple signatures for a single artifact. -- Publishers MUST have a mechanism to revoke signatures to indicate they are no longer trusted. -- Trust stores SHOULD be configurable by the deployer. -- Deployers MUST be able to configure trusted entities for individual repositories and targets. -- Deployers MUST be able to validate signatures on any version of an artifact including whether they have been revoked by the publisher. -- Signature validation MUST be enforceable in air-gapped environments. - -## Requirements for discussion -- Providing a mechanism for configuring/rotating a root key: In prior discussions we did not close on whether Notary v2 should provide a mechanism for rotating a root key or not. Tradeoffs are listed below for further discussion. - - Things to consider for dock: - - Who is handling roots? - - How are roots being distributed? - - What infrastructure requirements for root management - - Adding a mechanism to configure/rotate keys: - - Allows for the automatic rotation of keys. Can be used to mass update keys if signing algorithms need to be updated. - - Doesn't address the use case of publishers losing a root key. - - Provides a bad actor mechanism to insert a new root without deployer acknowledgement. - - Consider whether this mechanism needs to rely on existing root or roots. (Make the distinction for multiple roots) - - Not adding a mechanism: - - Any rotation of root keys will require deployers to acknowledge and make a change. - - Doesn't address the use case of publishers losing a root key. - - Prevents a bad actor from inserting a new root without deployer acknowledgement. - - Scenarios to consider: - - Publisher loses key. - - Publisher needs to update key for reasons beside unauthorized access to a key (includes expiration, new key types). - - Publisher's root key access is compromised, and they are aware. - - Publisher's root key access is compromised, but they are unaware. - - Publisher's root key is compromised, and they are aware. - - Publisher's root key is compromised, but they are unaware. - -****READ UP TO HERE, SECTIONS BELOW ARE WORK IN PROGRESS**** - -# Signing use cases: - -## Provisioning Keys for Signing - -![Notaryv2 Signing Provisioning](./media/nv2-keymgmt-architecture-provisionkeys-v1.png) - -## Signing Workflow - -![Notaryv2 Signing Workflow](./media/nv2-keymgmt-architecture-sign-v1.png) - -## Detailed Scenarios: -- Local Key Store - - Publisher creates new root key on local machine. Keys are stored in key store or plain text on local machine (Need to identify keystores we want to support. We can preclude signing with root keys to improve security posture). - - Publisher uploads root public key to registry (registry can verify user for container uploads). - - Publisher shares root public key (other users can verify containers before running). - - Publisher creates new delegate keys on local machine that chain to root key (enabling only delegate keys for signing will help protect the root key). - - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with key in memory. -- USB Token Key Store - - Publisher creates new root key on USB token (better security posture as key is not exposed in plain text outside of token). - - Publisher uploads root public key to registry (registry can verify user for container uploads). - - Publisher shares root public key (other users can verify containers before running). - - Publisher creates new delegate keys on USB token that chain to root key (better security posture as key is not exposed in plain text outside of token). - - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signature by submitting hash to USB Token (using a PKCS 11 interface will prevent keys from being exposed in memory). -- Network HSM - - Publisher creates new root key on Network HSM (better security posture as key is not exposed in plain text outside of HSM). - - Publisher uploads root public key to registry (registry can verify user for container uploads). - - Publisher shares root public key (other users can verify containers before running). - - Publisher creates new delegate keys on Network HSM that chain to root key (better security posture as key is not exposed in plain text outside of HSM). - - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signature by submitting hash to Network HSM. -- Cloud Key Management Service (KMS) - - Publisher creates new root key on Cloud KMS (better security posture as key is not exposed in plain text outside of Cloud KMS). - - Publisher uploads root public key to registry (registry can verify user for container uploads). - - Publisher shares root public key (other users can verify containers before running). - - Publisher creates new delegate keys on Cloud KMS that chain to root key (better security posture as key is not exposed in plain text outside of Cloud KMS). - - Publisher runs docker build and notary v2 sign on local machine. Notary v2 client generates signature by submitting hash to Cloud KMS. -- Hybrid - - Publisher Admin creates new root key on USB Token/Network HSM/Cloud Key Management Service (better security posture as key is never exposed in plain text outside of token). - - Publisher Admin uploads root public key to registry (registry can verify user for container uploads). - - Publisher Admin shares root public key (other users can verify containers before running). - - Publisher Admin provides access to Publisher Signer to create or retrieve delegate keys (admins can focus on delegating access, signers can use a portal or APIs to register keys and sign without having to repeatedly engage the admin). - - Publisher Signer creates new delegate keys on local machine that chain to root key (the root key is not exposed to the signer). - - Publisher Signer runs docker build and notary v2 sign on local machine. Notary v2 client generates signatures with keys on local machine. -- Signing by Build Machines - - Publisher Admin creates new root, uploads root public key to registry, and shares root public key (similar justification to earlier scenarios). - - Publisher Admin delegates access for build machine (Publisher Builder and Signer in this context) to create new delegate keys to be used on build machine. The delegate key can be stored on the build machine, USB Token, Network HSM, or Cloud Key Management Service (similar justification to earlier scenarios). - - Publisher Admin configures build scripts with credentials and if needed location of delegate keys. - - Build machine runs docker build and then notary v2 sign with keys from configured location. -- Signing by Dedicated Machines - - Publisher Admin creates new root, uploads root public key to registry, and shares root public key (similar justification to earlier scenarios). - - Publisher Admin delegates access for signing machine (Publisher Signer in this context) to create new delegate keys to be used on build machine. The delegate key can be stored on the build machine, USB Token, Network HSM, or Cloud Key Management Service (similar justification to earlier scenarios). - - Publisher Admin configures signing machine with credentials and if needed location of delegate keys. - - Build machine (Publisher Builder only in this context) runs docker build and passes objects to be signed to signing host (the build machine does not have access to signing keys. This prevents signing keys from being exposed through potential vulnerabilities in build logic). - - Signing host generates signatures with keys in configured location. -- Signing in Air Gapped Environments with Shared Root - - Publisher Admin creates new root, uploads root public key to registry, and shares root public key (similar justification to earlier scenarios). - - Publisher Admin creates new subordinate key in air gapped environment on a host, USB Token, Network HSM, or Cloud Key Management Service chaining to root (one time operation enables the root to be used by runtime environments outside of the air gapped environment to validate signatures generated inside the environment). - - Publisher Admin configures credentials for Publisher Signers in air gapped environment to use sub-ordinate key for delegate keys instead of root key (users in air gapped environment do not need to get keys from outside of the environment). - -# Deployment Use Cases: - -## Provisioning Truststore for Deployment - -![Notaryv2 Deployment Provisioning](./media/nv2-keymgmt-architecture-provisiontruststore-v1.png) - -## Deployment Workflow - -![Notaryv2 Deployment Workflow](./media/nv2-keymgmt-architecture-pull-v1.png) - -## Detailed Usecases: -- Specify trusted public root keys - - Deployer Admin gets root public key from publisher. - - Deployer Admin adds root public key to runtime configuration. - - Container pulled from any registry is be validated with listed root public keys before execution. -- Specify location of trusted public root keys - - Deployer Admin gets location of key repository from publisher. - - Deployer Admin adds location of key repository to runtime configuration. - - Container pulled from any registry is be validated with listed root public keys before execution. -- Enterprises can restrict users to add/remove their root public keys to the trust store used across a fleet of runtime hosts. The trust store will validate images pulled from any registry. -- Enterprises can restrict users to add/remove root public keys for trusted third parties to their trust stores. The trust store will validate images pulled from any registry. -- Air gapped environments can manually specify the trusted keys in their trust stores. Air-gapped operators will need to either maintain an air-gapped copy of the CRL or re-sign artifacts locally within an air-gapped environment. - -# Key Distribution Workflows: -- Manual Configuration - - Publisher places their root certificate in a public location. This could be a website similar to what public CAs today provide. - - Developer copies certificate from public location and adds it to their trust store. Developer can configure whether they trust this certificate for all their artifacts, individual registries, individual repositories, or individual targets. -- Automated Configuration - - Publisher gets intermediate certificate from a key distriution service i.e public CA or registry operator. - - Developer adds root certificate and location of key respoitory to their trust store. Developer can configure whether they trust certificates for all their artifacts, individual registries, individual repositories, or individual targets. -- Revocation: Note in the event a root certificate is revoked validations will fail, and developers will need to update their root certificate. The publisher will need to pro-actively communicate a rotation out of bands to prevent an outage. - -# Key rotation/revocation use cases: - -## Key Revocation Workflow - -![Notaryv2 Revocation Workflow](./media/nv2-keymgmt-architecture-revokekeys-v1.png) - -- Root Revocation (compromised root should not be needed in process to designate itself as revoked, otherwise attacker can use compromised root for a key rotation locking out publisher) - - Publisher deletes revoked root public key on registry (registry can stop sharing containers with revoked key). - - [TODO: Discuss if we want this] Registry stops vending containers signed with old root key (will prevent revoked artifacts from being used by developers not checking signature). - - Publisher removes revoked root public key from shared list (other users stop trusting artifacts with revoked key, provides defense in depth as they are not relying on registry). - - Publisher creates new root key following any scenario listed earlier in Signing use cases (starting from scratch as old key can no longer be trusted). - - Publisher uploads new root public key to registry (registry can verify user for container uploads). - - Publisher updates shared root public key (other users can verify containers with new key before running). - - Publisher creates new delegate keys following any scenario listed earlier in Signing use cases. -- Delegate Key Revocation (root can be used here for designating delegate keys as revoked as it has not been compromised) - - Publisher lists revoked delegate keys as untrusted. Revocation list is signed by root key (Design discussion on whether we use CRLs or some other approach to sharing information on revoked keys). - - Publisher shares revocation list (deployer needs to know which keys used prior for generating signatures are no longer trusted). - - Publisher creates new delegate keys from existing root following any scenario listed earlier in Signing use cases. -- Root Rotation (periodic rotation of root will limit blast radius, this process should not revoke existing root as it has not been compromised) - - Publisher creates new root key following any scenario listed earlier in Signing use cases. - - Publisher uploads new root public key to registry (registry can verify user for container uploads). - - Publisher updates shared root public key (other users can verify containers with new key before running). - - Publisher creates new delegate keys from new root following any scenario listed earlier in Signing use cases. -- Delegate Key Rotation - - Publisher creates new delegate keys from existing root following any scenario listed earlier in Signing use cases. - -# Follow ups for Implementation -Additional questions to clarify as part of implementation (need more research but doesn't impact workflow): -1. Where can keys be stored? What interfaces need to be supported? -2. Any limitations ok key types/sizes supported? -3. How will public keys (root of trust) be distributed? -4. How will key revocation information be distributed? -5a. What is the minimum number of keys needed to succesfully sign a container? -5b. What is the recommended number of keys to sign a container? -6. Any additional requirements for timestamping? - -In addition we also need to consider the following for cryptographic security: -- Supported key types [TODO: Pull from NIST recommendations] -- Supported signing algorithms [TODO: Pull from NIST recommendations] From acd25cf563fdfc820ce9c336f0a714b5ea8e6933 Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Mon, 8 Mar 2021 07:58:53 -0800 Subject: [PATCH 18/28] Update keymanagementrequirements.md Signed-off-by: Niaz Khan --- keymanagementrequirements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keymanagementrequirements.md b/keymanagementrequirements.md index 480eb4ee..a88719e9 100644 --- a/keymanagementrequirements.md +++ b/keymanagementrequirements.md @@ -47,5 +47,5 @@ Key management for container signing can be broadly categorized into three gener 1. Signature generation for each of the key storage scenarios. A succesful prototype should enable signing with keys on each of the following: local host, secure tokens, Hardware Security Modules (HSMs), and cloud based Key Management Services. 2. Trust store configuration and signature source validation in runtime environments. A succesful prototype should enable configuring a trust store in a runtime environment. The prototype should validate signatures from a trusted source and reject signatures from a source that is not listed. The prototype will not check for other aspects of signature validity (expiry/revocation). 3. Key rotation. A succesful prototype should meet all requirements from the key rotation document. -4. Signature/Key Expiration. A succesful prototype should meet all requirements from the signature/key expiration document. +4. Signature/Key Expiration. A succesful prototype should meet all requirements from the signature/key expiry document. 5. Signature allowlist/denylist. A succesful prototype should meet all requirements from the signatur allowlist/denylist document. From 16fc214dce99e8e15bba8d6e31f33fff2431be5f Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Fri, 9 Apr 2021 07:59:26 -0700 Subject: [PATCH 19/28] Update keymanagementrequirements.md Signed-off-by: Niaz Khan --- keymanagementrequirements.md | 93 ++++++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 3 deletions(-) diff --git a/keymanagementrequirements.md b/keymanagementrequirements.md index a88719e9..b26b5c57 100644 --- a/keymanagementrequirements.md +++ b/keymanagementrequirements.md @@ -39,9 +39,96 @@ Key management for container signing can be broadly categorized into three gener - Signature validation MUST be enforceable in air-gapped environments. ## Requirements that need further discussion -- Signature/Key Expiry -- Root key auto rotation -- Signature allow list/deny list (trusted updates/revocation list) +### Signing Key Expiry +In public key cryptography, a pair of private key a.k.a. signing key and public key a.k.a. verification key is generated, and later the public key is certified by a . The cerificate expiry time does not imply the expiry time of the key pair since the public key can be certified by a CA for multiple times. Moreover, a new key pair is always generated before generating a new certificate in the real world. Therefore, we can consider the key expiry is equivilant to certificate expiry. + +### External Timestamp Server +Time Stamping Authorities (TSAs) defined by RFC3161 provide signed timestamp for a signature in order to prove that the signature was generated during the validity period of a certificate. + +#### Scenarios +With TSA, signature can be considered valid even if the signing cerificate is expired. This technique is widely used by Authenticode with SignTool, NuGet, Adobe Acrobat, and many other industrial products. + +In the world of artifacts, including container images, scenarios are +- Developers sign their artifacts or images with certificates. The certificates MAY have a configurable expiry time. +- Developers publish their artifacts or images and at a later date stop maintaining them. Content consumers SHOULD be able to verify signatures until they expire and use the artifacts or images +- Attackers with compromised keys try to sign artifacts or images with timestamps before the key compromise event. + +#### Pros and Cons + +There are many public TSA servers available on the Internet. The advantages of public timestamp servers are obvious: + Public + Free + +However, those public TSAs also come with disadvantages: + Require Internet access for signing + It is not really a disadvantage since public TSAs are online services. Devices in the air-gapped environment SHALL access the Internet for timestamp signing services. + Out of the control of the signer + External dependency + Availability is not assured. No SLA on signing. + Not all TSAs are available in all regions. + Some regions may have high latency. + The certificates of TSAs MAY be revoked at any time without notices. + The removal of trust of VeriSign broke .NET 5+ NuGet. Thus Microsoft has to disable the package verification with a new release to unblock customers. + +Implications of not using a signed timestamp for a signature + In the absense of additional timestamp signature, the signature is only considered valid till key expiry. This may limit the use of short lived keys. + In case of key compromise it’s not possible to revoke signatures from a point in time where the time of compromise is known, as an attacker can create signatures with any signature time (by changing local time) + +### Signature Expiry + +Signatures can expire if + + The certificate of the signing key or the timestamp key (whichever is longer) expires + The signed content indicates a expiry time + +In this section, the #2 scenario is focused. +Scenarios + +The main scenario for using a configurable signature expiry is for the publisher to indicate how long they plan to maintain the signature on the artifact for. For example if a publisher signs an artifact with an expiry for 6 months, they are indicating that if within 6 months they identfy a reason that deployers should no longer trust the artifact they will rescind the signature. + +An added benefit is to defend against freeze attack. Since the signature expires in a short time although the signing key can live longer, the verifiers have to obtain the latest signature to verify, which implies that the verifies have access to the latest content. + + Freeze Attack Similar to a replay attack, a freeze attack works by providing metadata that is not current. However, in a freeze attack, the attacker freezes the information a client sees at the current point in time to prevent the client from seeing updates, rather than providing the client older versions than the client has already seen. As with replay attacks, the attacker’s goal is ultimately to compromise a client who has vulnerable versions of packages installed. A freeze attack may be used to prevent updates in addition to having an installed package be out of date. + +### Transparent Root key auto rotation +Root keys form the basis of hierarchical trust systems, where intermediate and leaf keys chain back to a root key, and leaf keys are used to generate signatures. Consumers of signed artifacts associate a baseline level of trust with signatures that chain to roots they trust. In the scenario that a root key is no longer trusted, all signed artifacts chaining back to the root are no longer trusted. The conditions which render the root keys to be no longer trusted, are disclosed to the customer through some other channel (CVE, internal security audit, etc.). Safe rotation of keys require a overlap period where both new and old root keys are trusted. This is always not possible, such as when a root key is compromised. + +#### Scenarios +1. A public root associated with a key a Publisher uses to sign artifacts is compromised. The access to root key is compromised, rather than the root key itself being stolen, allowing an attacker to create new intermediate and leaf trusted keys. +2. An internal root used by an organization is due to expire. A new root is created and rotated before the existing root expires. +3. An internal root used by an organization is not stored securely and the private key is lost. A new root is created to continue operations. +4. A cryptographic algorithm is deprecated, or a compliance standard requires a customer to upgrade their key strength. The customer wants to safely rotate a root key without rendering existing signatures invalid and disrupting operations. + +### Rescinding Signature Validity +Artifact Publishers need mechanisms to indicate that a signature they generated is still trustworthy. + +#### Scenarios +- A Publisher vends a new version of an artifact, and wants to indicate the new version as trusted in addition to older versions already published. + +#### Discussion Areas +- Code signing is a mechanism for Publishers to explicitly indicate trust which is implicitly trusted by Consumer given some conditions are satisfied (based on trust policy, signature being valid and unrevoked) + - An explicit allowlist is not required + - A denylist is required in addition to indicate which artifacts are no longer trusted + +- Signature Allowlist explicitly specifies the list of trusted artifacts. + - Pros + - Anything not in the list is implicitly untrusted, no separate revocation mechanism is required + - If signed allowlist are used, the artifacts themselves may not need to be signed. + - Cons + - The allowlist needs to be updated for every version of artifact being published + - May need to maintain a large allowlist which may be an overhead to distribute +- Signature Denylist + - For Consumers, denylist allows explicitly indicating that an artifact or dependency is untrusted + - For Publishers, this allows communicating to Consumers that specific versions of artifact are untrusted. + +- Centralized/local public/private lists + - The list can be local to repository, requiring update to the list in each repository, and requires keeping track of all repositories where the artifact needs to be published/revoked. + - The list can be centralized + - Centralized deny list (e.g. CRL maintaned by public CAs) can be used. The endpoint infomation is included in the signature, and signature verification step checks against this list. + - Customers can define network topology with restricted network access, where these endpoints may not be accesible for hosts where signature verification occurs. + - These endpoints may not be available in air-gapped environments. + - Public lists (e.g. transparency logs) may not be suitable for enterprise customers who don’t want their artifact updates to be disclosed publicly. + ## Prototype Stages 1. Signature generation for each of the key storage scenarios. A succesful prototype should enable signing with keys on each of the following: local host, secure tokens, Hardware Security Modules (HSMs), and cloud based Key Management Services. From 6c7c202b2aac145e89d78e06944967b773da56ac Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Fri, 9 Apr 2021 08:13:30 -0700 Subject: [PATCH 20/28] Update keymanagementrequirements.md Signed-off-by: Niaz Khan --- keymanagementrequirements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keymanagementrequirements.md b/keymanagementrequirements.md index b26b5c57..70c933ad 100644 --- a/keymanagementrequirements.md +++ b/keymanagementrequirements.md @@ -40,7 +40,7 @@ Key management for container signing can be broadly categorized into three gener ## Requirements that need further discussion ### Signing Key Expiry -In public key cryptography, a pair of private key a.k.a. signing key and public key a.k.a. verification key is generated, and later the public key is certified by a . The cerificate expiry time does not imply the expiry time of the key pair since the public key can be certified by a CA for multiple times. Moreover, a new key pair is always generated before generating a new certificate in the real world. Therefore, we can consider the key expiry is equivilant to certificate expiry. +In public key cryptography, a pair of private key a.k.a. signing key and public key a.k.a. verification key is generated, and later the public key is certified by a higher key in the hierarchy. The certification of the signing key has a validity period to designate how long it is valid for. This section will discuss tradeoff and recommendations for expiry times and signing key rotation. ### External Timestamp Server Time Stamping Authorities (TSAs) defined by RFC3161 provide signed timestamp for a signature in order to prove that the signature was generated during the validity period of a certificate. From 4cd1eb36e17177ea518e20c15acc20242a98c17d Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Fri, 16 Apr 2021 07:39:27 -0700 Subject: [PATCH 21/28] Update keymanagementrequirements.md Co-authored-by: Brandon Mitchell Signed-off-by: Niaz Khan --- keymanagementrequirements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keymanagementrequirements.md b/keymanagementrequirements.md index 70c933ad..577c0098 100644 --- a/keymanagementrequirements.md +++ b/keymanagementrequirements.md @@ -29,7 +29,7 @@ Key management for container signing can be broadly categorized into three gener - Retrieving a signature MUST NOT require the deployer to perform additional actions with a registry/repository or registry operator beyond those required to pull an unsigned artifact. - Artifact integrity, source, and signature expiry MUST be verifiable from the signature AND NOT require additional calls to the registry/repository. - Signature allow list/deny list MAY require additional calls that will be defined in a separate document. -- Moving an artifact from one repository to another SHOULD NOT invalidate the signature on the artifact. +- Copying an artifact from one repository to another SHOULD NOT invalidate the signature on the artifact. - Publishers SHOULD be able to sign with keys stored on their local machines, secure tokens, Hardware Security Modules (HSMs), or cloud based Key Management Services. - Publishers SHOULD be able to generate multiple signatures for a single artifact. - Publisher admins MUST have a mechanism to revoke signatures to indicate they are no longer trusted. From 269140c23b51b03939134c078b00a52db76c1517 Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Fri, 16 Apr 2021 07:40:43 -0700 Subject: [PATCH 22/28] Update keymanagementrequirements.md Co-authored-by: Brandon Mitchell Signed-off-by: Niaz Khan --- keymanagementrequirements.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keymanagementrequirements.md b/keymanagementrequirements.md index 577c0098..232720df 100644 --- a/keymanagementrequirements.md +++ b/keymanagementrequirements.md @@ -78,8 +78,8 @@ Implications of not using a signed timestamp for a signature Signatures can expire if - The certificate of the signing key or the timestamp key (whichever is longer) expires - The signed content indicates a expiry time +1. The certificate of the signing key expires +2. The signed content indicates a expiry time In this section, the #2 scenario is focused. Scenarios From 6157b487ae78479f30b59a7b42b41c1be70851ca Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Fri, 16 Apr 2021 07:58:13 -0700 Subject: [PATCH 23/28] Update keymanagementrequirements.md Signed-off-by: Niaz Khan --- keymanagementrequirements.md | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/keymanagementrequirements.md b/keymanagementrequirements.md index 232720df..488f096b 100644 --- a/keymanagementrequirements.md +++ b/keymanagementrequirements.md @@ -22,7 +22,7 @@ Key management for container signing can be broadly categorized into three gener - Public Key: Will be used to verify signed artifacts. - Signed Identity: Identity of creator of the signing key. - (Optional) Issuer: If the key is an intermediate this will describe the owner of the root. - - Mechanism to update validity of signatures generated with the signing key. + - (Optional) Mechanism to check whether signatures generated with the signing key have been rescinded. ## Requirements - Signing an artifact MUST NOT require the publisher to perform additional actions with a registry/repository or registry operator. Uploading a signature MAY require additional actions. @@ -90,14 +90,38 @@ An added benefit is to defend against freeze attack. Since the signature expires Freeze Attack Similar to a replay attack, a freeze attack works by providing metadata that is not current. However, in a freeze attack, the attacker freezes the information a client sees at the current point in time to prevent the client from seeing updates, rather than providing the client older versions than the client has already seen. As with replay attacks, the attacker’s goal is ultimately to compromise a client who has vulnerable versions of packages installed. A freeze attack may be used to prevent updates in addition to having an installed package be out of date. -### Transparent Root key auto rotation +### Trust Policy Management and Trust Store Updates + +Deployers who consume signed artifacts from a registry require that only artifacts from trusted parties are deployed and executed. The trusted parties are specified in some form of a trust policy against which the signed artifacts are validated. The trust policy can include a trust store with trusted root and leaf keys/certificates which represent the Publisher identities the Deployer trusts. This section covers where the trust policies should be stored, and how they are distributed/updated. + Root keys form the basis of hierarchical trust systems, where intermediate and leaf keys chain back to a root key, and leaf keys are used to generate signatures. Consumers of signed artifacts associate a baseline level of trust with signatures that chain to roots they trust. In the scenario that a root key is no longer trusted, all signed artifacts chaining back to the root are no longer trusted. The conditions which render the root keys to be no longer trusted, are disclosed to the customer through some other channel (CVE, internal security audit, etc.). Safe rotation of keys require a overlap period where both new and old root keys are trusted. This is always not possible, such as when a root key is compromised. #### Scenarios -1. A public root associated with a key a Publisher uses to sign artifacts is compromised. The access to root key is compromised, rather than the root key itself being stolen, allowing an attacker to create new intermediate and leaf trusted keys. -2. An internal root used by an organization is due to expire. A new root is created and rotated before the existing root expires. -3. An internal root used by an organization is not stored securely and the private key is lost. A new root is created to continue operations. -4. A cryptographic algorithm is deprecated, or a compliance standard requires a customer to upgrade their key strength. The customer wants to safely rotate a root key without rendering existing signatures invalid and disrupting operations. +1. A Deployer consumes artifacts from a third party Publisher and wants to configure the trusted publishers in a policy. The Deployer is not the same user/organization as Publisher and wants to independently define the trusted publishers. +2. A Publisher’s repository may contain a mix of artifacts, published by different teams using different keys. The Deployer wants to trust only artifacts signed by specific keys. + - E.g. A group may include the MySQL image from docker hub, and the MySQL Helm chart from another group in the same registry/repo. These are signed by different entities, and valid to be placed in the same repository. + +#### Scenarios for Trust Store Updates +1. A Deployer updates their dependencies and no longer consumes artifacts from particular Publisher +2. A public root associated with a signing key a Publisher uses to sign artifacts is compromised. +3. An root key used by a Publisher is close to expiry. A new key is created and rotated before the existing root expires. +4. An root key used by a Publisher is not stored securely and the private key is lost. A new key pair is created to continue operations. +5. A cryptographic algorithm is deprecated, or a compliance standard requires a Publisher to upgrade their key strength. + +#### Approaches +1. Storage and distribution of trust policies from registry +Pros +- Trust policies need not be stored in another location +- Allows in band/automated distribution and update of trust policies to consumers. +Cons +- Automated update of trust policies can be disruptive to Deployers that consume artifacts. Deployers should be able to control when trust policies are updated. +- Only allows Publishers to define the trust policy. It works well when Publisher and Deployer are the same user/organization. + - This model does not allow Deployers to independently define trust policies. Furthermore, it may be required that Deployer Admins define trusted publishers, and Deployer Operators only specify/configure which artifacts (from repositories) are deployed. + +#### Recommendation +- Trust policies SHOULD NOT be stored in the registry. Multiple Deployers can consume artifacts from the same repository, and may need to define trust policies independently. +- Trust policies SHOULD be configured, distributed/updated out of band from artifact updates from registry. + ### Rescinding Signature Validity Artifact Publishers need mechanisms to indicate that a signature they generated is still trustworthy. From 4fcb03dbece26697e56388eab705823f62511a43 Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Thu, 22 Apr 2021 16:59:11 -0700 Subject: [PATCH 24/28] Update keymanagementrequirements.md Signed-off-by: Niaz Khan --- keymanagementrequirements.md | 179 ++++++++++++++--------------------- 1 file changed, 73 insertions(+), 106 deletions(-) diff --git a/keymanagementrequirements.md b/keymanagementrequirements.md index 488f096b..321ec08c 100644 --- a/keymanagementrequirements.md +++ b/keymanagementrequirements.md @@ -1,7 +1,7 @@ # Overview Key management for container signing can be broadly categorized into three general use cases: - Key Setup/Signing (Key managment and integrations with client tooling for generating signatures.) -- Trust store configuration (Configuring which keys to trust for artifacts from a predefined source.) +- Deployment configurations (Configuring trust policies and which keys to trust for artifacts.) - Signature Validity (Expiry, Revocation and/or Trusted Update List. Mechanism to update information on the validity of signatures.) ## Personas: @@ -17,7 +17,78 @@ Key management for container signing can be broadly categorized into three gener ## Definitions: - Root key: A self signed key used for the lowest designation of trust. Root keys can be created by developers, organizations, public/private CAs, and registry operators. The root key should be retrieved from a trusted source that can establish the authenticity of the creator's identity. - Signing key: A signing key is used to generate artifact signatures. A signing key should be signed with a root key or one of its intermediaries. The certificate chain with a signing key can be used to verify which root it belongs to. While a root key can be used as a signing key, this is not recommended as it creates a large blast radius and increases the risk of compromising a root key. -- Trust Store: The trust store defines the relationship between signing keys and artifacts that are used at validation time to determine whether to trust an artifact with a crytptographically valid signature. The trust store will relate a source (any source, specific registry, specific repository, or specific target) with a certificate (for root key, intermediate, or signing key) or key repository (for automated key distribtuion). It is not recommended to use a signing key as this will cause signature validation to fail if the signing key is rotated. +- Trust Policy: The trust policy defines whether to enable signature validation and which checks need to be run. An example trust policy: + { + trustPolicy: { + signatureCheck: true, + optionalChecks: { + signatureExpiry: true, + signatureRescinded: false + }, + trustStore: "truststore.json" + } + } +- Trust Store: The trust store defines the relationship between signing keys and artifacts that are used at validation time to determine whether to trust an artifact with a crytptographically valid signature. The trust store will relate a scope (any source, specific registry, specific repository, or specific target) with a certificate (for root key, intermediate, or signing key) or key repository (for automated key distribtuion). It is not recommended to use a signing key as this will cause signature validation to fail if the signing key is rotated. An example trustStore where the first root is trusted for artifacts from any registry and the second root is only trusted for artifacts from "registry.wabbit-networks.io" : + { + trustedRoots: [ + { + root: "-----BEGIN CERTIFICATE----- + MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF + ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 + b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL + MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv + b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj + ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM + 9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw + IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 + VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L + 93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm + jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC + AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA + A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI + U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs + N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv + o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU + 5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy + rqXRfboQnoZsG4q5WTP468SQvvG5 + -----END CERTIFICATE-----" + }, + { + root: "-----BEGIN CERTIFICATE----- + MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF + ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 + b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL + MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv + b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK + gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ + W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg + 1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K + 8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r + 2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me + z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR + 8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj + mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz + 7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 + +XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI + 0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB + Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm + UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 + LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY + +gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS + k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl + 7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm + btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl + urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ + fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 + n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE + 76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H + 9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT + 4PsJYGw= + -----END CERTIFICATE-----", + scope: "registry.wabbit-networks.io" + } + ] + } - Trust Store Key Information: The key information configured in the trust store will be cryptographically verifiable and contain: - Public Key: Will be used to verify signed artifacts. - Signed Identity: Identity of creator of the signing key. @@ -40,118 +111,14 @@ Key management for container signing can be broadly categorized into three gener ## Requirements that need further discussion ### Signing Key Expiry -In public key cryptography, a pair of private key a.k.a. signing key and public key a.k.a. verification key is generated, and later the public key is certified by a higher key in the hierarchy. The certification of the signing key has a validity period to designate how long it is valid for. This section will discuss tradeoff and recommendations for expiry times and signing key rotation. ### External Timestamp Server -Time Stamping Authorities (TSAs) defined by RFC3161 provide signed timestamp for a signature in order to prove that the signature was generated during the validity period of a certificate. - -#### Scenarios -With TSA, signature can be considered valid even if the signing cerificate is expired. This technique is widely used by Authenticode with SignTool, NuGet, Adobe Acrobat, and many other industrial products. - -In the world of artifacts, including container images, scenarios are -- Developers sign their artifacts or images with certificates. The certificates MAY have a configurable expiry time. -- Developers publish their artifacts or images and at a later date stop maintaining them. Content consumers SHOULD be able to verify signatures until they expire and use the artifacts or images -- Attackers with compromised keys try to sign artifacts or images with timestamps before the key compromise event. - -#### Pros and Cons - -There are many public TSA servers available on the Internet. The advantages of public timestamp servers are obvious: - Public - Free - -However, those public TSAs also come with disadvantages: - Require Internet access for signing - It is not really a disadvantage since public TSAs are online services. Devices in the air-gapped environment SHALL access the Internet for timestamp signing services. - Out of the control of the signer - External dependency - Availability is not assured. No SLA on signing. - Not all TSAs are available in all regions. - Some regions may have high latency. - The certificates of TSAs MAY be revoked at any time without notices. - The removal of trust of VeriSign broke .NET 5+ NuGet. Thus Microsoft has to disable the package verification with a new release to unblock customers. - -Implications of not using a signed timestamp for a signature - In the absense of additional timestamp signature, the signature is only considered valid till key expiry. This may limit the use of short lived keys. - In case of key compromise it’s not possible to revoke signatures from a point in time where the time of compromise is known, as an attacker can create signatures with any signature time (by changing local time) ### Signature Expiry -Signatures can expire if - -1. The certificate of the signing key expires -2. The signed content indicates a expiry time - -In this section, the #2 scenario is focused. -Scenarios - -The main scenario for using a configurable signature expiry is for the publisher to indicate how long they plan to maintain the signature on the artifact for. For example if a publisher signs an artifact with an expiry for 6 months, they are indicating that if within 6 months they identfy a reason that deployers should no longer trust the artifact they will rescind the signature. - -An added benefit is to defend against freeze attack. Since the signature expires in a short time although the signing key can live longer, the verifiers have to obtain the latest signature to verify, which implies that the verifies have access to the latest content. - - Freeze Attack Similar to a replay attack, a freeze attack works by providing metadata that is not current. However, in a freeze attack, the attacker freezes the information a client sees at the current point in time to prevent the client from seeing updates, rather than providing the client older versions than the client has already seen. As with replay attacks, the attacker’s goal is ultimately to compromise a client who has vulnerable versions of packages installed. A freeze attack may be used to prevent updates in addition to having an installed package be out of date. - ### Trust Policy Management and Trust Store Updates -Deployers who consume signed artifacts from a registry require that only artifacts from trusted parties are deployed and executed. The trusted parties are specified in some form of a trust policy against which the signed artifacts are validated. The trust policy can include a trust store with trusted root and leaf keys/certificates which represent the Publisher identities the Deployer trusts. This section covers where the trust policies should be stored, and how they are distributed/updated. - -Root keys form the basis of hierarchical trust systems, where intermediate and leaf keys chain back to a root key, and leaf keys are used to generate signatures. Consumers of signed artifacts associate a baseline level of trust with signatures that chain to roots they trust. In the scenario that a root key is no longer trusted, all signed artifacts chaining back to the root are no longer trusted. The conditions which render the root keys to be no longer trusted, are disclosed to the customer through some other channel (CVE, internal security audit, etc.). Safe rotation of keys require a overlap period where both new and old root keys are trusted. This is always not possible, such as when a root key is compromised. - -#### Scenarios -1. A Deployer consumes artifacts from a third party Publisher and wants to configure the trusted publishers in a policy. The Deployer is not the same user/organization as Publisher and wants to independently define the trusted publishers. -2. A Publisher’s repository may contain a mix of artifacts, published by different teams using different keys. The Deployer wants to trust only artifacts signed by specific keys. - - E.g. A group may include the MySQL image from docker hub, and the MySQL Helm chart from another group in the same registry/repo. These are signed by different entities, and valid to be placed in the same repository. - -#### Scenarios for Trust Store Updates -1. A Deployer updates their dependencies and no longer consumes artifacts from particular Publisher -2. A public root associated with a signing key a Publisher uses to sign artifacts is compromised. -3. An root key used by a Publisher is close to expiry. A new key is created and rotated before the existing root expires. -4. An root key used by a Publisher is not stored securely and the private key is lost. A new key pair is created to continue operations. -5. A cryptographic algorithm is deprecated, or a compliance standard requires a Publisher to upgrade their key strength. - -#### Approaches -1. Storage and distribution of trust policies from registry -Pros -- Trust policies need not be stored in another location -- Allows in band/automated distribution and update of trust policies to consumers. -Cons -- Automated update of trust policies can be disruptive to Deployers that consume artifacts. Deployers should be able to control when trust policies are updated. -- Only allows Publishers to define the trust policy. It works well when Publisher and Deployer are the same user/organization. - - This model does not allow Deployers to independently define trust policies. Furthermore, it may be required that Deployer Admins define trusted publishers, and Deployer Operators only specify/configure which artifacts (from repositories) are deployed. - -#### Recommendation -- Trust policies SHOULD NOT be stored in the registry. Multiple Deployers can consume artifacts from the same repository, and may need to define trust policies independently. -- Trust policies SHOULD be configured, distributed/updated out of band from artifact updates from registry. - - ### Rescinding Signature Validity -Artifact Publishers need mechanisms to indicate that a signature they generated is still trustworthy. - -#### Scenarios -- A Publisher vends a new version of an artifact, and wants to indicate the new version as trusted in addition to older versions already published. - -#### Discussion Areas -- Code signing is a mechanism for Publishers to explicitly indicate trust which is implicitly trusted by Consumer given some conditions are satisfied (based on trust policy, signature being valid and unrevoked) - - An explicit allowlist is not required - - A denylist is required in addition to indicate which artifacts are no longer trusted - -- Signature Allowlist explicitly specifies the list of trusted artifacts. - - Pros - - Anything not in the list is implicitly untrusted, no separate revocation mechanism is required - - If signed allowlist are used, the artifacts themselves may not need to be signed. - - Cons - - The allowlist needs to be updated for every version of artifact being published - - May need to maintain a large allowlist which may be an overhead to distribute -- Signature Denylist - - For Consumers, denylist allows explicitly indicating that an artifact or dependency is untrusted - - For Publishers, this allows communicating to Consumers that specific versions of artifact are untrusted. - -- Centralized/local public/private lists - - The list can be local to repository, requiring update to the list in each repository, and requires keeping track of all repositories where the artifact needs to be published/revoked. - - The list can be centralized - - Centralized deny list (e.g. CRL maintaned by public CAs) can be used. The endpoint infomation is included in the signature, and signature verification step checks against this list. - - Customers can define network topology with restricted network access, where these endpoints may not be accesible for hosts where signature verification occurs. - - These endpoints may not be available in air-gapped environments. - - Public lists (e.g. transparency logs) may not be suitable for enterprise customers who don’t want their artifact updates to be disclosed publicly. ## Prototype Stages From 928d70b69ad7a52002109cddf4b5006f810ef191 Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Thu, 22 Apr 2021 17:07:59 -0700 Subject: [PATCH 25/28] Update keymanagementrequirements.md Signed-off-by: Niaz Khan --- keymanagementrequirements.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/keymanagementrequirements.md b/keymanagementrequirements.md index 321ec08c..6e1abbd0 100644 --- a/keymanagementrequirements.md +++ b/keymanagementrequirements.md @@ -18,6 +18,7 @@ Key management for container signing can be broadly categorized into three gener - Root key: A self signed key used for the lowest designation of trust. Root keys can be created by developers, organizations, public/private CAs, and registry operators. The root key should be retrieved from a trusted source that can establish the authenticity of the creator's identity. - Signing key: A signing key is used to generate artifact signatures. A signing key should be signed with a root key or one of its intermediaries. The certificate chain with a signing key can be used to verify which root it belongs to. While a root key can be used as a signing key, this is not recommended as it creates a large blast radius and increases the risk of compromising a root key. - Trust Policy: The trust policy defines whether to enable signature validation and which checks need to be run. An example trust policy: +``` { trustPolicy: { signatureCheck: true, @@ -28,7 +29,9 @@ Key management for container signing can be broadly categorized into three gener trustStore: "truststore.json" } } +``` - Trust Store: The trust store defines the relationship between signing keys and artifacts that are used at validation time to determine whether to trust an artifact with a crytptographically valid signature. The trust store will relate a scope (any source, specific registry, specific repository, or specific target) with a certificate (for root key, intermediate, or signing key) or key repository (for automated key distribtuion). It is not recommended to use a signing key as this will cause signature validation to fail if the signing key is rotated. An example trustStore where the first root is trusted for artifacts from any registry and the second root is only trusted for artifacts from "registry.wabbit-networks.io" : +``` { trustedRoots: [ { @@ -89,6 +92,7 @@ Key management for container signing can be broadly categorized into three gener } ] } +``` - Trust Store Key Information: The key information configured in the trust store will be cryptographically verifiable and contain: - Public Key: Will be used to verify signed artifacts. - Signed Identity: Identity of creator of the signing key. From 7d00034fa024a5842df8005b548825aa4715d342 Mon Sep 17 00:00:00 2001 From: NiazFK <67277579+NiazFK@users.noreply.github.com> Date: Fri, 23 Apr 2021 07:58:50 -0700 Subject: [PATCH 26/28] Update keymanagementrequirements.md Signed-off-by: Niaz Khan --- keymanagementrequirements.md | 45 +++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/keymanagementrequirements.md b/keymanagementrequirements.md index 6e1abbd0..908614c3 100644 --- a/keymanagementrequirements.md +++ b/keymanagementrequirements.md @@ -20,22 +20,32 @@ Key management for container signing can be broadly categorized into three gener - Trust Policy: The trust policy defines whether to enable signature validation and which checks need to be run. An example trust policy: ``` { - trustPolicy: { - signatureCheck: true, - optionalChecks: { - signatureExpiry: true, - signatureRescinded: false + "trustPolicy": { + "signatureCheck": true, + "optionalChecks": { + "signatureExpiry": true, + "signatureRescinded": false }, - trustStore: "truststore.json" + "trustStore": [ + "truststore.json", + { + "trustedRoots": [ + { + "root": "test.crt" + } + ] + } + ], + "trustedArtifacts": [] } } ``` - Trust Store: The trust store defines the relationship between signing keys and artifacts that are used at validation time to determine whether to trust an artifact with a crytptographically valid signature. The trust store will relate a scope (any source, specific registry, specific repository, or specific target) with a certificate (for root key, intermediate, or signing key) or key repository (for automated key distribtuion). It is not recommended to use a signing key as this will cause signature validation to fail if the signing key is rotated. An example trustStore where the first root is trusted for artifacts from any registry and the second root is only trusted for artifacts from "registry.wabbit-networks.io" : ``` { - trustedRoots: [ + "trustedRoots": [ { - root: "-----BEGIN CERTIFICATE----- + "root": "-----BEGIN CERTIFICATE----- MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL @@ -57,7 +67,7 @@ Key management for container signing can be broadly categorized into three gener -----END CERTIFICATE-----" }, { - root: "-----BEGIN CERTIFICATE----- + "root": "-----BEGIN CERTIFICATE----- MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL @@ -88,7 +98,7 @@ Key management for container signing can be broadly categorized into three gener 9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT 4PsJYGw= -----END CERTIFICATE-----", - scope: "registry.wabbit-networks.io" + "scope": "registry.wabbit-networks.io" } ] } @@ -114,15 +124,12 @@ Key management for container signing can be broadly categorized into three gener - Signature validation MUST be enforceable in air-gapped environments. ## Requirements that need further discussion -### Signing Key Expiry - -### External Timestamp Server - -### Signature Expiry - -### Trust Policy Management and Trust Store Updates - -### Rescinding Signature Validity +### Signing Key Expiry - https://hackmd.io/n82ZTBv3TK2Y4rujlnW3ng +### External Timestamp Server - https://hackmd.io/WvoBFNg2TR-ooTe14a6pfw +### Signature Expiry - https://hackmd.io/pT4IicsQRlGhR9szlrIUWQ +### Trust Policy Management and Trust Store Updates - Trust Policy Management and Trust Store Updates +### Rescinding Signature Validity - https://hackmd.io/TnX8l31CQnGPRujZ_gLGJA +### Multiple Signatures ## Prototype Stages From 7a6e9d510833267b1912c12353eff81958263229 Mon Sep 17 00:00:00 2001 From: Niaz Khan <67277579+NiazFK@users.noreply.github.com> Date: Fri, 30 Apr 2021 05:31:41 -0700 Subject: [PATCH 27/28] Moving links to issues Removed links for additional requirements docs. Signed-off-by: Niaz Khan --- keymanagementrequirements.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/keymanagementrequirements.md b/keymanagementrequirements.md index 908614c3..680f402f 100644 --- a/keymanagementrequirements.md +++ b/keymanagementrequirements.md @@ -123,15 +123,6 @@ Key management for container signing can be broadly categorized into three gener - Deployers MUST be able to validate signatures on any version of an artifact including whether they have been revoked by the publisher. - Signature validation MUST be enforceable in air-gapped environments. -## Requirements that need further discussion -### Signing Key Expiry - https://hackmd.io/n82ZTBv3TK2Y4rujlnW3ng -### External Timestamp Server - https://hackmd.io/WvoBFNg2TR-ooTe14a6pfw -### Signature Expiry - https://hackmd.io/pT4IicsQRlGhR9szlrIUWQ -### Trust Policy Management and Trust Store Updates - Trust Policy Management and Trust Store Updates -### Rescinding Signature Validity - https://hackmd.io/TnX8l31CQnGPRujZ_gLGJA -### Multiple Signatures - - ## Prototype Stages 1. Signature generation for each of the key storage scenarios. A succesful prototype should enable signing with keys on each of the following: local host, secure tokens, Hardware Security Modules (HSMs), and cloud based Key Management Services. 2. Trust store configuration and signature source validation in runtime environments. A succesful prototype should enable configuring a trust store in a runtime environment. The prototype should validate signatures from a trusted source and reject signatures from a source that is not listed. The prototype will not check for other aspects of signature validity (expiry/revocation). From 2c04195a784876bce94e649d3393028b7e50b97a Mon Sep 17 00:00:00 2001 From: Niaz Khan Date: Wed, 30 Jun 2021 18:19:51 -0700 Subject: [PATCH 28/28] Updated with proper JSON. Signed-off-by: Niaz Khan --- keymanagementrequirements.md | 108 +++++++++-------------------------- 1 file changed, 28 insertions(+), 80 deletions(-) diff --git a/keymanagementrequirements.md b/keymanagementrequirements.md index 680f402f..50c07812 100644 --- a/keymanagementrequirements.md +++ b/keymanagementrequirements.md @@ -19,89 +19,37 @@ Key management for container signing can be broadly categorized into three gener - Signing key: A signing key is used to generate artifact signatures. A signing key should be signed with a root key or one of its intermediaries. The certificate chain with a signing key can be used to verify which root it belongs to. While a root key can be used as a signing key, this is not recommended as it creates a large blast radius and increases the risk of compromising a root key. - Trust Policy: The trust policy defines whether to enable signature validation and which checks need to be run. An example trust policy: ``` - { - "trustPolicy": { - "signatureCheck": true, - "optionalChecks": { - "signatureExpiry": true, - "signatureRescinded": false - }, - "trustStore": [ - "truststore.json", - { - "trustedRoots": [ - { - "root": "test.crt" - } - ] - } - ], - "trustedArtifacts": [] - } - } + { + "trustPolicy": { + "signatureCheck": true, + "optionalChecks": { + "signatureExpiry": true, + "signatureRescinded": false + }, + "trustStore": [ + "truststore.json", + { + "trustedRoots": [{ + "root": "test.crt" + }] + } + ], + "trustedArtifacts": [] + } + } ``` - Trust Store: The trust store defines the relationship between signing keys and artifacts that are used at validation time to determine whether to trust an artifact with a crytptographically valid signature. The trust store will relate a scope (any source, specific registry, specific repository, or specific target) with a certificate (for root key, intermediate, or signing key) or key repository (for automated key distribtuion). It is not recommended to use a signing key as this will cause signature validation to fail if the signing key is rotated. An example trustStore where the first root is trusted for artifacts from any registry and the second root is only trusted for artifacts from "registry.wabbit-networks.io" : ``` - { - "trustedRoots": [ - { - "root": "-----BEGIN CERTIFICATE----- - MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF - ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 - b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL - MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv - b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj - ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM - 9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw - IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 - VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L - 93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm - jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC - AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA - A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI - U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs - N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv - o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU - 5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy - rqXRfboQnoZsG4q5WTP468SQvvG5 - -----END CERTIFICATE-----" - }, - { - "root": "-----BEGIN CERTIFICATE----- - MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF - ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 - b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL - MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv - b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK - gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ - W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg - 1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K - 8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r - 2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me - z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR - 8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj - mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz - 7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 - +XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI - 0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB - Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm - UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 - LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY - +gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS - k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl - 7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm - btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl - urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ - fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 - n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE - 76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H - 9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT - 4PsJYGw= - -----END CERTIFICATE-----", - "scope": "registry.wabbit-networks.io" - } - ] - } + { + "trustedRoots": [{ + "root": "-----BEGIN CERTIFICATE-----examplecertificate-----END CERTIFICATE-----" + }, + { + "root": "-----BEGIN CERTIFICATE-----examplecertificate-----END CERTIFICATE-----", + "scope": "registry.wabbit-networks.io" + } + ] + } ``` - Trust Store Key Information: The key information configured in the trust store will be cryptographically verifiable and contain: - Public Key: Will be used to verify signed artifacts.