diff --git a/changes/2024-TBD_key-store-admin/background.md b/changes/2024-TBD_key-store-admin/background.md new file mode 100644 index 00000000..93396d38 --- /dev/null +++ b/changes/2024-TBD_key-store-admin/background.md @@ -0,0 +1,224 @@ +[//]: # "Copyright Amazon.com Inc. or its affiliates. All Rights Reserved." +[//]: # "SPDX-License-Identifier: CC-BY-SA-4.0" + +# Key Store Administration Client & Configuration + +# Definitions + +## Conventions used in this document + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", +"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be +interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119). + +# Background + +The parameters needed to fetch Branch Keys for usage (encrypt, decrypt) +are distinct from the parameters needed to administrate them +(create, version/rotate, any future operations). + +The permissions needed for the persistence medium, +which is DynamoDB by default, +and to Key Management Service, +which currently can only be AWS KMS, +are also different between usage and administration activities. + +As such, it makes sense to create a +new Branch Key Store Administration Client, +that cannot facilitate usage, +only administrative operations. + +## Alternatives to a new Client/Local Service? + +### Refactor Key Store + +Rather than creating a new Client/Local Service, +Crypto Tools could refactor the existing +Key Store Client to behave in the manner described below. + +This would be a breaking change, +and is therefore not recommended. + +### Static Methods on the MPL + +A non-breaking change is to add the behaviors +described below to the Material Provider's Local Service/Client, +rather than creating a new Client. + +The advantage of such an approach is less software +maintained and documented by Crypto Tools. + +However, +this approach forces the Material Provider's Client +to directly reference DynamoDB. +In the long run, +Crypto Tools MAY want allow MPL Consumers to optionally +depend on the AWS SDK, +as the original AWS Encryption SDK afforded that. +Adding a direct reference to DynamoDB +to the Material Provider's Client +complicates such an ambition. + +# Name of the Client? + +It is best that we bike shed on this early. + +The proposed name for this client is +`the Key Store Admin Client` +though we may often refer to it as +just the `Key Store Admin`. + +# Proposed Construction + +The Key Store Admin requires the following arguments: + +- Storage Reference +- Logical Key Store Name + +See [Key Store Persistence Changes](changes/2024-6-17_key-store-persistance/background.md) for details +on Storage Reference. + +# Common Parameters and their defaults + +## `KMS Identifier` + +`KMS Identifier` is a KMS ARN which identifies the KMS Key +that will be used for the operation. +This ARN MUST NOT be an Alias. +This ARN MUST be a valid +[AWS KMS Key ARN](./aws-kms/aws-kms-key-arn.md#a-valid-aws-kms-arn). +This ARN MAY be a Multi-Region Key (MRK) or Single Region Key. + +## Key Management + +`Key Management` is a union, +such that additional options may be added at a later date. + +Members of `Key Management` are elements that +authorize the use of Branch Key Cryptographic Materials +by decrypting them in a manner that +authenticates all attributes of the Branch Key. + +They are also used to create Branch Key Encrypted Cryptographic Materials, +and when doing so MUST cryptographically bind all attributes of the Branch Key +to the cipher-text. + +Currently, there is only one `Key Management` option. + +`Key Management` is never used directly by the Key Store Admin. + +However, it was introduced into the Key Store +as part of the [Key Store Persistence Changes](changes/2024-6-17_key-store-persistance/background.md). +It is, at least at this time, +not visible to any MPL Consumer facing operations. + +### `AwsKms` + +`AwsKms` is the only `Key Management` option currently +supported by the Key Store or Key Store Admin. + +This option is provided by default, +if no other `Key Management` is provided. + +`AwsKms` represents AWS Key Management Service (KMS). + +The structure has two optional fields: + +- `grantTokenList`, a list of strings +- `kmsClient`, a reference to an AWS SDK KMS client + +If no `grantTokenList` is provided, +it defaults to an empty list. + +If no `kmsClient` is provided, +the default KMS client is constructed via the AWS SDK. + +## Key Management Strategy + +`Key Management Strategy` is a union, +such that additional options may be added at a later date. + +`Key Management Strategy` determines which Operations +of a `Key Management` are used by the Client. + +For example, +an MPL Consumer MAY want to avoid calling `kms:ReEncrypt`, +and would rather use `kms:Decrypt` followed by `kms:Encrypt` +to re-wrap a new DECRYPT_ONLY Branch Key as a ACTIVE Branch Key. + +At this time, +there are only two +`Key Management Strategy`s. + +### AWS KMS ReEncrypt (default) + +`AwsKmsReEncrypt` dictates the Key Store Operation use +AWS KMS' ReEncrypt Operation to +[authenticate a Key Store Item](../../framework/branch-key-store.md#authenticating-a-keystore-item) +or re-wrap Branch Keys +during [Wrapped Branch Key Creation](../../framework/branch-key-store.md#wrapped-branch-key-creation). + +`AwsKmsReEncrypt` is a structure that holds a `AwsKms`, +which MAY contain the KMS Client +or Grant Tokens the Key Store, +if they are set, +will use when calling KMS. + +`AwsKmsReEncrypt` is the default option if +`Key Management Strategy` is marked as optional +and the parameter is unfilled. + +### AWS KMS Decrypt Encrypt + +`AwsKmsDecryptEncrypt` dictates the Key Store Operation to use +AWS KMS' Decrypt Operation followed by AWS KMS Encrypt Operation +to re-wrap Branch Keys +during [Wrapped Branch Key Creation](../../framework/branch-key-store.md#wrapped-branch-key-creation). + +`AwsKmsDecryptEncrypt` is a structure that holds two `AwsKms`, +one designated for Decrypt, +one designated for Encrypt. + +This allows MPL Consumers to configure different +credentials or request headers for the KMS Operations. + +# Modified Operations from the original [Branch Key Store Specification](../../framework/branch-key-store.md#operations) + +## CreateKey + +The CreateKey caller MUST provide: + +- A `KMS Identifier` + +The CreateKey caller MAY provide: + +- A Branch Key ID +- Encryption Context +- A Key Management Strategy + +The behavior is mostly identical. + +However, +during the [Wrapped Branch Key Creation](../../framework/branch-key-store.md#wrapped-branch-key-creation), +the Key Management Strategy MUST be respected. + +## Version Key + +The VersionKey caller MUST provide: + +- A `KMS Identifier` +- A `branch-key-id` + +The VersionKey caller MAY provide: + +- A Key Management Strategy + +The behavior is mostly identical. + +However, +during the [Wrapped Branch Key Creation](../../framework/branch-key-store.md#wrapped-branch-key-creation), +the Key Management Strategy MUST be respected. + + + + diff --git a/changes/2024-TBD_key-store-admin/proposed.smithy b/changes/2024-TBD_key-store-admin/proposed.smithy new file mode 100644 index 00000000..92c7ce53 --- /dev/null +++ b/changes/2024-TBD_key-store-admin/proposed.smithy @@ -0,0 +1,171 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +namespace aws.cryptography.keyStoreAdmin + +// The top level namespace for this project. +// Contains an entry-point for helper methods, +// and common structures used throughout this project. + +use aws.polymorph#localService + +use com.amazonaws.dynamodb#DynamoDB_20120810 +use com.amazonaws.kms#TrentService + +use aws.cryptography.keyStore#EncryptionContext + +@localService( + sdkId: "KeyStoreAdmin", + config: KeyStoreAdminConfig, + dependencies: [ + DynamoDB_20120810, + TrentService + ] +) +service KeyStoreAdmin { + version: "2023-04-01", + operations: [ + CreateKey + VersionKey + ], + errors: [ + KeyStoreAdminException + aws.cryptography.keyStore#VersionRaceException + ] +} + +structure KeyStoreAdminConfig { + @required + @documentation( + "The logical name for this Key Store, + which is cryptographically bound to the keys it holds. + This appears in the Encryption Context of KMS requests as `tablename`. + + There SHOULD be a one to one mapping between the Storage's physical name, + i.e: DynamoDB Table Names, + and the Logical KeyStore Name. + This value can be set to the DynamoDB table name itself + (Storage's physical name), + but does not need to. + + Controlling this value independently enables restoring from DDB table backups + even when the table name after restoration is not exactly the same.") + logicalKeyStoreName: String, + + @required + @documentation("The storage configuration for this Key Store.") + storage: aws.cryptography.keyStore#Storage +} + +// KMS Arn validation MUST occur in Dafny +union KMSIdentifier { + @documentation( + "Key Store is restricted to only this KMS Key ARN. + If a different KMS Key ARN is encountered + when creating, versioning, or getting a Branch Key or Beacon Key, + KMS is never called and an exception is thrown. + While a Multi-Region Key (MKR) may be provided, + the whole ARN, including the Region, + is persisted in Branch Keys and + MUST strictly equal this value to be considered valid.") + kmsKeyArn: String, + + @documentation( + "If an MRK ARN is provided, + and the persisted Branch Key holds an MRK ARN, + then those two ARNs may differ in region, + although they must be otherwise equal. + If either ARN is not an MRK ARN, then + kmsMRKeyArn behaves exactly as kmsKeyArn.") + kmsMRKeyArn: String, +} + +structure AwsKmsDecryptEncrypt { + @documentation("The KMS Client (and Grant Tokens) used to Decrypt Branch Key Store Items.") + decrypt: aws.cryptography.keyStore#AwsKms + @documentation( + "The KMS Client (and Grant Tokens) used to Encrypt Branch Key Store Items + and to Generate new Cryptographic Material.") + encrypt: aws.cryptography.keyStore#AwsKms +} + +@documentation( + "This configures which Key Management Operations will be used + AND the Key Management Clients (and Grant Tokens) used to invoke those Operations.") +union KeyManagementStrategy { + @documentation( + "Key Store Items are authenicated and re-wrapped via KMS ReEncrypt, + executed with the provided Grant Tokens and KMS Client. + This is one request to Key Management, as compared to two. + But only one set of credentials can be used.") + AwsKmsReEncrypt: aws.cryptography.keyStore#AwsKms + @documentation( + "Key Store Items are authenicated and re-wrapped via a Decrypt and then Encrypt request. + This is two separate requests to Key Management, as compared to one. + But the Decrypt requests will use the Decrypt KMS Client (and Grant Tokens), + while the Encrypt requests will use the Encrypt KMS Client (and Grant Tokens). + This option affords for different credentials to be utilized, + based on the operation. + When Generating new material, + KMS GenerateDataKeyWithoutPlaintext will be executed against + the Encrypt option.") + AwsKmsDecryptEncrypt: AwsKmsDecryptEncrypt +} + +@documentation( +"Create a new Branch Key in the Key Store. +Additionally create a Beacon Key that is tied to this Branch Key.") +operation CreateKey { + input: CreateKeyInput, + output: CreateKeyOutput +} + +structure CreateKeyInput { + @documentation("The identifier for the created Branch Key.") + branchKeyIdentifier: String, + + @documentation( + "Custom encryption context for the Branch Key. + Required if branchKeyIdentifier is set.") + encryptionContext: aws.cryptography.keyStore#EncryptionContext + + @required + @documentation( + "Multi-Region or Single Region AWS KMS Key + used to protect the Branch Key, but not aliases!") + kmsArn: KMSIdentifier + + strategy: KeyManagementStrategy +} + +structure CreateKeyOutput { + @required + @documentation("A identifier for the created Branch Key.") + branchKeyIdentifier: String +} + +@documentation( + "Create a new ACTIVE version of an existing Branch Key, + along with a complementing Version (DECRYT_ONLY) in the Key Store. + This generates a fresh AES-256 key which all future encrypts will use + for the Key Derivation Function, + until VersionKey is executed again.") +operation VersionKey { + input: VersionKeyInput, + output: VersionKeyOutput, + errors: [aws.cryptography.keyStore#VersionRaceException] +} + +structure VersionKeyInput { + @required + @documentation("The identifier for the Branch Key to be versioned.") + branchKeyIdentifier: String + + @required + @documentation("Multi-Region or Single Region AWS KMS Key used to protect the Branch Key, but not aliases!") + kmsArn: KMSIdentifier + + strategy: KeyManagementStrategy +} + +structure VersionKeyOutput { +} diff --git a/framework/branch-key-store-admin.md b/framework/branch-key-store-admin.md new file mode 100644 index 00000000..983add0c --- /dev/null +++ b/framework/branch-key-store-admin.md @@ -0,0 +1,263 @@ +[//]: # "Copyright Amazon.com Inc. or its affiliates. All Rights Reserved." +[//]: # "SPDX-License-Identifier: CC-BY-SA-4.0" + +# Key Store Admin + +The Key Store Administrative Client, +or just "Key Store Admin". + +## Version + +1.0.0 + +### Changelog + +- 1.0.0 + - Initial record + +## Implementations + +| Language | Confirmed Compatible with Spec Version | Minimum Version Confirmed | Implementation | +| -------- | -------------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Dafny | 1.0.0 | TBD | [AwsCryptographyKeyStoreOperations.dfy](https://github.com/aws/aws-cryptographic-material-providers-library/blob/main/AwsCryptographicMaterialProviders/dafny/AwsCryptographyKeyStoreAdmin/src/AwsCryptographyKeyStoreAdminOperations.dfy) | +| Java | 1.0.0 | TBD | TBD | +| .NET | 1.0.0 | TBD | TBD | + +## Overview + +See [Key Store Overview](../branch-key-store.md#overview) +for the general purpose of the Key Store. + +The Key Store Administrative Client, +or just Key Store Admin, +consolidates the operations that can create +or modify Branch Keys. + +## Definitions + +See [Key Store Overview](../branch-key-store.md#definitions). + +### `KMS Identifier` + +`KMS Identifier` is a Union. + +The members of `KMS Identifier` are a KMS ARN which identifies the KMS Key +that will be used for the operation. +This ARN MUST NOT be an Alias. +This ARN MUST be a valid +[AWS KMS Key ARN](./aws-kms/aws-kms-key-arn.md#a-valid-aws-kms-arn). +This ARN MAY be a Multi-Region Key (MRK) or Single Region Key. + +There are two members for this Union. + +- KMS Single Region Key ARN (`kmsKeyArn`): [See `KMS Key ARN` in the Key Store Client](../branch-key-store.md#aws-kms-configuration). +- KMS Multi Region Key ARN (`kmsMRKeyArn`): [See `KMS MRKey ARN` in the Key Store Client](../branch-key-store.md#aws-kms-configuration). + +### Key Management Strategy + +`Key Management Strategy` is a union, +such that additional options maybe added at a later date. + +`Key Management Strategy` determines which Operations +of a `Key Management` are used by the Client. + +For example, +an MPL Consumer MAY want to avoid calling `kms:ReEncrypt`, +and would rather use `kms:Decrypt` followed by `kms:Encrypt` +to re-wrap a new DECRYPT_ONLY Branch Key as a ACTIVE Branch Key. + +At this time, +there are two +`Key Management Strategy`s. + +#### AWS KMS ReEncrypt (default) + +`AwsKmsReEncrypt` dictates the Key Store Operation use +AWS KMS' ReEncrypt Operation to +[authenticate a Key Store Item](../branch-key-store.md#authenticating-a-keystore-item) +or re-wrap Branch Keys +during [Wrapped Branch Key Creation](../branch-key-store.md#wrapped-branch-key-creation). + +`AwsKmsReEncrypt` is a structure that holds a [`AwsKms`](../branch-key-store.md#awskms), +which MAY contain the KMS Client +or Grant Tokens the Key Store, +if they are set, +will use when calling KMS. + +`AwsKmsReEncrypt` is the default option if +`Key Management Strategy` is marked as optional +and the parameter is unfilled. + +### AWS KMS Decrypt Encrypt + +`AwsKmsDecryptEncrypt` dictates the Key Store Operation to use +AWS KMS' Decrypt Operation followed by AWS KMS Encrypt Operation +to re-wrap Branch Keys +during [Wrapped Branch Key Creation](../branch-key-store.md#wrapped-branch-key-creation). + +`AwsKmsDecryptEncrypt` is a structure that holds two [`AwsKms`](../branch-key-store.md#awskms), +one designated for Decrypt, +one designated for Encrypt. + +This allows MPL Consumers to configure different +credentials or request headers for the KMS Operations. + +### Conventions used in this document + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" +in this document are to be interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119). + +## Initialization + +The Key Store Admin requires the following arguments: + +- [Storage](../branch-key-store.md#storage) +- [Logical Key Store Name](../branch-key-store.md##logical-keystore-name) + +### User Agent + +Whenever possible, +the Key Store Admin SHOULD +append a user agent string to AWS Service requests with +the value of `aws-kms-hierarchy`. + +## Operations + +The Key Store Admin MUST support the following operations: + +- [CreateKey](#createkey) +- [VersionKey](#versionkey) + +### CreateKey + +The CreateKey caller MUST provide: + +- A [`KMS Identifier`](#kms-identifier) + +The CreateKey caller MAY provide: + +- An optional Branch Key ID +- An optional Encryption Context +- An optional [Key Management Strategy](#key-management-strategy) + +The Operation behaves identically to the [Key Store Client's CreateKey](../branch-key-store.md#createkey), +with the following caveats: + +#### KMS Configuration + +Where ever the Key Store Client's CreateKey method refers to the Key Store Client's KMS Configuration, +use the equivalent [`KMS Identifier`](#kms-identifier) expression. + +#### [Branch Key and Beacon Key Creation](../branch-key-store.md#branch-key-and-beacon-key-creation) + +If the [Key Management Strategy](#key-management-strategy) is `AwsKmsDecryptEncrypt`, +the AWS KMS Encrypt configuration MUST be used to generate the Beacon Key. + +Otherwise, +the `AwsKmsReEncrypt` configuration MUST be treated as if it were the Key Store Client's. + +#### Wrapped Branch Key Creation + +Given a `branchKeyId`, `version` and `timestamp` + +The operation MUST call [AWS KMS API GenerateDataKeyWithoutPlaintext](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKeyWithoutPlaintext.html). + +##### Generate DECRYPT_ONLY + +If the [Key Management Strategy](#key-management-strategy) is `AwsKmsDecryptEncrypt`, +the AWS KMS Encrypt client MUST be used to make the call +AND +the AWS KMS Encrypt Grant Tokens MUST be added to the request. + +Otherwise, the [Key Management Strategy](#key-management-strategy) is `AwsKmsReEncrypt`, +AWS KMS ReEncrypt MUST be used to make the call. +AND +the AWS KMS ReEncrypt Grant Tokens MUST be added to the request. + +The operation MUST call AWS KMS GenerateDataKeyWithoutPlaintext with a request constructed as follows: + +- `KeyId` MUST be [KMS Identifier](#kms-identifier) +- `NumberOfBytes` MUST be 32. +- `EncryptionContext` MUST be the [DECRYPT_ONLY encryption context for branch keys](../branch-key-store.md##decrypt_only-encryption-context). +- `GrantTokens` MUST respect the [Key Management Strategy](#key-management-strategy), as detailed above. + +If the call to AWS KMS GenerateDataKeyWithoutPlaintext succeeds, +the operation MUST use the GenerateDataKeyWithoutPlaintext result `CiphertextBlob` +as the wrapped DECRYPT_ONLY Branch Key. + +##### Generate ACTIVE if `AwsKmsDecryptEncrypt` + +If the [Key Management Strategy](#key-management-strategy) is `AwsKmsDecryptEncrypt`, +the Key Store Admin MUST call [AWS KMS Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html) +via the AWS KMS Decrypt client. + +The operation MUST call AWS KMS Decrypt with a request constructed as follows: + +- `CiphertextBlob` MUST be the wrapped DECRYPT_ONLY Branch Key. +- `EncryptionContext` MUST be the [DECRYPT_ONLY encryption context for branch keys](../branch-key-store.md#decrypt_only-encryption-context) +- `GrantTokens` MUST be the AWS KMS Decrypt Grant Tokens +- `KeyId` MUST be [KMS Identifier](#kms-identifier) + +If the call to KMS Decrypt fails, +the Key Store Admin MUST fail the Operation, +with as much as detail as possible. + +Otherwise, +the Key Store Admin MUST call KMS Encrypt via the AWS KMS Encrypt client. + +The Encrypt request MUST be constructed as follows: + +- `EncryptionContext` MUST be the [ACTIVE encryption context for branch keys](../branch-key-store.md#active-encryption-context) +- `GrantTokens` MUST be the AWS KMS Encrypt Grant Tokens +- `KeyId` MUST be [KMS Identifier](#kms-identifier) +- `Plaintext` MUST be the `Plaintext` element of the Decrypt Response + +If the KMS Encrypt request succeeds, +the operation MUST use the Encrypt response' `CiphertextBlob` +as the wrapped ACTIVE Branch Key. + +##### Generate ACTIVE else-if `AwsKmsReEncrypt` + +The operation MUST call [AWS KMS API ReEncrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_ReEncrypt.html) +with a request constructed as follows: + +- `SourceEncryptionContext` MUST be the [DECRYPT_ONLY encryption context for branch keys](../branch-key-store.md#decrypt_only-encryption-context). +- `SourceKeyId` MUST be [KMS Identifier](#kms-identifier) +- `CiphertextBlob` MUST be the wrapped DECRYPT_ONLY Branch Key. +- `GrantTokens` be the AWS KMS ReEncrypt Grant Tokens +- `DestinationKeyId` MUST be [KMS Identifier](#kms-identifier) +- `DestinationEncryptionContext` MUST be the [ACTIVE encryption context for branch keys](../branch-key-store.md#active-encryption-context). + +If the call to AWS KMS ReEncrypt succeeds, +the operation MUST use the ReEncrypt result `CiphertextBlob` +as the wrapped ACTIVE Branch Key. + +### VersionKey + +The VersionKey caller MUST provide: + +- A [`KMS Identifier`](#kms-identifier) +- A `branch-key-id` + +The VersionKey caller MAY provide: + +- An optional [Key Management Strategy](#key-management-strategy) + +The Operation behaves identically to the [Key Store Client's VersionKey](../branch-key-store.md#versionkey), +with the following caveats: + +#### KMS Configuration + +Where ever the Key Store Client's CreateKey method refers to the Key Store Client's KMS Configuration, +use the equivalent [`KMS Identifier`](#kms-identifier) expression. + +#### Wrapped Branch Key Creation + +The wrapped Branch Keys, +DECRYPT_ONLY and ACTIVE, +MUST be created according to [Key Store Admin Wrapped Branch Key Creation](#wrapped-branch-key-creation). + + + + +