Package: aws-cdk.aws-kms
AWS Key Management Service Construct Library---AWS CDK v1 has reached End-of-Support on 2023-06-01.
This package is no longer being updated, and users should migrate to AWS CDK v2.For more information on how to migrate, see theMigrating to AWS CDK v2guide.Define a KMS key:kms.Key(self,"MyKey",enable_key_rotation=True)Define a KMS key with waiting period:Specifies the number of days in the waiting period before AWS KMS deletes a CMK that has been removed from a CloudFormation stack.key=kms.Key(self,"MyKey",pending_window=Duration.days(10))Add a couple of aliases:key=kms.Key(self,"MyKey")key.add_alias("alias/foo")key.add_alias("alias/bar")Define a key with specific key spec and key usage:ValidkeySpecvalues depends onkeyUsagevalue.key=kms.Key(self,"MyKey",key_spec=kms.KeySpec.ECC_SECG_P256K1,# Default to SYMMETRIC_DEFAULTkey_usage=kms.KeyUsage.SIGN_VERIFY)Sharing keys between stacksTo use a KMS key in a different stack in the same CDK application,
pass the construct to the other stack:## Stack that defines the key#classKeyStack(cdk.Stack):def__init__(self,scope,id,*,description=None,env=None,stackName=None,tags=None,synthesizer=None,terminationProtection=None,analyticsReporting=None):super().__init__(scope,id,description=description,env=env,stackName=stackName,tags=tags,synthesizer=synthesizer,terminationProtection=terminationProtection,analyticsReporting=analyticsReporting)self.key=kms.Key(self,"MyKey",removal_policy=cdk.RemovalPolicy.DESTROY)## Stack that uses the key#classUseStack(cdk.Stack):def__init__(self,scope,id,*,key,description=None,env=None,stackName=None,tags=None,synthesizer=None,terminationProtection=None,analyticsReporting=None):super().__init__(scope,id,key=key,description=description,env=env,stackName=stackName,tags=tags,synthesizer=synthesizer,terminationProtection=terminationProtection,analyticsReporting=analyticsReporting)# Use the IKey object here.kms.Alias(self,"Alias",alias_name="alias/foo",target_key=key)key_stack=KeyStack(app,"KeyStack")UseStack(app,"UseStack",key=key_stack.key)Importing existing keysImport key by ARNTo use a KMS key that is not defined in this CDK app, but is created through other means, useKey.fromKeyArn(parent, name, ref):my_key_imported=kms.Key.from_key_arn(self,"MyImportedKey","arn:aws:...")# you can do stuff with this imported key.my_key_imported.add_alias("alias/foo")Note that a call to.addToResourcePolicy(statement)onmyKeyImportedwill not have
an affect on the key's policy because it is not owned by your stack. The call
will be a no-op.Import key by aliasIf a Key has an associated Alias, the Alias can be imported by name and used in place
of the Key as a reference. A common scenario for this is in referencing AWS managed keys.importaws_cdk.aws_cloudtrailascloudtrailmy_key_alias=kms.Alias.from_alias_name(self,"myKey","alias/aws/s3")trail=cloudtrail.Trail(self,"myCloudTrail",send_to_cloud_watch_logs=True,kms_key=my_key_alias)Note that calls toaddToResourcePolicyandgrant*methods onmyKeyAliaswill be
no-ops, andaddAliasandaliasTargetKeywill fail, as the imported alias does not
have a reference to the underlying KMS Key.Lookup key by aliasIf you can't use a KMS key imported by alias (e.g. because you need access to the key id), you can lookup the key withKey.fromLookup().In general, the preferred method would be to useAlias.fromAliasName()which returns anIAliasobject which extendsIKey. However, some services need to have access to the underlying key id. In this case,Key.fromLookup()allows to lookup the key id.The result of theKey.fromLookup()operation will be written to a file
calledcdk.context.json. You must commit this file to source control so
that the lookup values are available in non-privileged environments such
as CI build steps, and to ensure your template builds are repeatable.Here's howKey.fromLookup()can be used:my_key_lookup=kms.Key.from_lookup(self,"MyKeyLookup",alias_name="alias/KeyAlias")role=iam.Role(self,"MyRole",assumed_by=iam.ServicePrincipal("lambda.amazonaws.com"))my_key_lookup.grant_encrypt_decrypt(role)Note that a call to.addToResourcePolicy(statement)onmyKeyLookupwill not have
an affect on the key's policy because it is not owned by your stack. The call
will be a no-op.Key PoliciesControlling access and usage of KMS Keys requires the use of key policies (resource-based policies attached to the key);
this is in contrast to most other AWS resources where access can be entirely controlled with IAM policies,
and optionally complemented with resource policies. For more in-depth understanding of KMS key access and policies, seehttps://docs.aws.amazon.com/kms/latest/developerguide/control-access-overview.htmlhttps://docs.aws.amazon.com/kms/latest/developerguide/key-policies.htmlKMS keys can be created to trust IAM policies. This is the default behavior for both the KMS APIs and in
the console. This behavior is enabled by the '@aws-cdk/aws-kms:defaultKeyPolicies' feature flag,
which is set for all new projects; for existing projects, this same behavior can be enabled by
passing thetrustAccountIdentitiesproperty astruewhen creating the key:kms.Key(self,"MyKey",trust_account_identities=True)With either the@aws-cdk/aws-kms:defaultKeyPoliciesfeature flag set,
or thetrustAccountIdentitiesprop set, the Key will be given the following default key policy:{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::111122223333:root"},"Action":"kms:*","Resource":"*"}This policy grants full access to the key to the root account user.
This enables the root account user -- via IAM policies -- to grant access to other IAM principals.
With the above default policy, future permissions can be added to either the key policy or IAM principal policy.key=kms.Key(self,"MyKey")user=iam.User(self,"MyUser")key.grant_encrypt(user)Adopting the default KMS key policy (and so trusting account identities)
solves many issues around cyclic dependencies between stacks.
Without this default key policy, future permissions must be added to both the key policy and IAM principal policy,
which can cause cyclic dependencies if the permissions cross stack boundaries.
(For example, an encrypted bucket in one stack, and Lambda function that accesses it in another.)Appending to or replacing the default key policyThe default key policy can be amended or replaced entirely, depending on your use case and requirements.
A common addition to the key policy would be to add other key admins that are allowed to administer the key
(e.g., change permissions, revoke, delete). Additional key admins can be specified at key creation or after
via thegrantAdminmethod.my_trusted_admin_role=iam.Role.from_role_arn(self,"TrustedRole","arn:aws:iam:....")key=kms.Key(self,"MyKey",admins=[my_trusted_admin_role])second_key=kms.Key(self,"MyKey2")second_key.grant_admin(my_trusted_admin_role)Alternatively, a custom key policy can be specified, which will replace the default key policy.Note: In applications without the '@aws-cdk/aws-kms:defaultKeyPolicies' feature flag set
and withtrustedAccountIdentitiesset to false (the default), specifying a policy at key creationappendsthe
provided policy to the default key policy, rather thanreplacingthe default policy.my_trusted_admin_role=iam.Role.from_role_arn(self,"TrustedRole","arn:aws:iam:....")# Creates a limited admin policy and assigns to the account root.my_custom_policy=iam.PolicyDocument(statements=[iam.PolicyStatement(actions=["kms:Create*","kms:Describe*","kms:Enable*","kms:List*","kms:Put*"],principals=[iam.AccountRootPrincipal()],resources=["*"])])key=kms.Key(self,"MyKey",policy=my_custom_policy)Warning:Replacing the default key policy with one that only grants access to a specific user or role
runs the risk of the key becoming unmanageable if that user or role is deleted.
It is highly recommended that the key policy grants access to the account root, rather than specific principals.
Seehttps://docs.aws.amazon.com/kms/latest/developerguide/key-policies.htmlfor more information.