def key_build(**kwargs): """ Args: kwargs: IamUsers: list of IAM user names to grant admin access to the key IamRoles: list of IAM role names to grant admin access to the key UseCloudtrail: bool() to define whether or not the key shall be used for CloudTrail AccountsIds: list() of account ids representing the accounts using the key for CT OrganizationUnitName: str() of the name of the organization unit to lookup accounts for UseOrganizationUnitAsRoot: bool() - if True, will lookup all accounts within in the OU and in the SubOu to apply it to Returns: key Key() """ iam_users = [] iam_roles = [] if 'IamUsers' in kwargs.keys(): iam_users = kwargs['IamUsers'] if 'IamRoles' in kwargs.keys(): iam_roles = kwargs['IamRoles'] key_policy = { "Version": "2012-10-17", "Id": "Key polocy for cloudtrail", "Statement": [] } key_policy['Statement'].append(iam_access(iam_users, iam_roles)) if 'UseCloudTrail' in kwargs.keys(): if 'AccountsIds' in kwargs.keys(): key_policy['Statement'] += add_cloudtrail_access( kwargs['AccountsIds']) elif 'OrganizationName' in kwargs.keys(): if ('UseOrganizationUnitAsRoot' in kwargs.keys() and kwargs['UseOrganizationUnitAsRoot']): key_policy['Statement'] += add_cloudtrail_ou_access( kwargs['OrganizationName'], use_as_root=True) else: key_policy['Statement'] += add_cloudtrail_ou_access( kwargs['OrganizationName']) else: raise KeyError( 'When using CloudFormation, either AccountsIds or OrganizationName must be set' ) kms_key = Key('KmsKey', Description=Sub('KMS Key in ${AWS::Region}'), Enabled=True, EnableKeyRotation=True, KeyPolicy=key_policy) for key in [ 'Tags', 'Description', 'Enabled', 'EnableKeyRotation', 'KmsKeyPolicy' ]: if key in kwargs.keys(): setattr(kms_key, key, kwargs[key]) if 'Name' in kwargs.keys(): kms_key.title = kwargs['Name'] return kms_key
def define_kms_key(self): """ Method to set the KMS Key """ if not self.properties: props = { "Description": Sub( f"{self.name} created in ${{STACK_NAME}}", STACK_NAME=define_stack_name(), ), "Enabled": True, "EnableKeyRotation": True, "KeyUsage": "ENCRYPT_DECRYPT", "PendingWindowInDays": 7, } else: props = import_record_properties(self.properties, Key) if not keyisset("KeyPolicy", props): props.update({"KeyPolicy": define_default_key_policy()}) props.update({"Metadata": metadata}) LOG.debug(props) self.cfn_resource = Key(self.logical_name, **props)
def generate_key(key_name, res_name, key_def): """ Function to create the KMS Key :param key_name: :param res_name: :param key_def: :return: key :rtype: troposphere.kms.Key """ properties = ( key_def["Properties"] if keyisset("Properties", key_def) else { "Description": Sub(f"{key_name} created in ${{{ROOT_STACK_NAME.title}}}"), "Enabled": True, "EnableKeyRotation": True, "KeyUsage": "ENCRYPT_DECRYPT", "PendingWindowInDays": 7, } ) if not keyisset("KeyPolicy", properties): properties.update({"KeyPolicy": define_default_key_policy()}) properties.update({"Metadata": metadata}) LOG.debug(properties) kms_key = Key(res_name, **properties) return kms_key
} }) # Add the project's kms key to the cfn template project_key = t.add_resource( Key('projectkey', Description='Key used for ML pipeline', Enabled=True, EnableKeyRotation=True, KeyPolicy={ "Version": "2012-10-17", "Id": 'mlkey', "Statement": [{ "Sid": "Enable IAM User Permissions", "Effect": "Allow", "Principal": { "AWS": Join(":", ["arn:aws:iam:", Ref("AWS::AccountId"), "root"]) }, "Action": "kms:*", "Resource": "*" }] })) #Encryption configs for input and output buckets bucket_encryption_config = ServerSideEncryptionByDefault( KMSMasterKeyID=GetAtt('projectkey', "Arn"), SSEAlgorithm='aws:kms')
Key( "MasterKey", Description="Master Key for this Account", Enabled=True, EnableKeyRotation=True, KeyPolicy={ "Version": "2012-10-17", "Statement": [ { "Sid": "Enable IAM User Permissions", "Effect": "Allow", "Principal": { "AWS": { "Fn::Join": [ ":", [ "arn:aws:iam:", Ref("AWS::AccountId"), "root" ] ] } }, "Action": "kms:*", "Resource": "*" }, { # https://docs.aws.amazon.com/awscloudtrail/latest/userguide/create-kms-key-policy-for-cloudtrail-encrypt.html "Sid": "Allow CloudTrail to encrypt logs", "Effect": "Allow", "Principal": { "Service": ["cloudtrail.amazonaws.com"] }, "Action": "kms:GenerateDataKey*", "Resource": "*", "Condition": { "StringLike": { "kms:EncryptionContext:aws:cloudtrail:arn": { "Fn::Join": [ "", [ "arn:aws:cloudtrail:*:", Ref("AWS::AccountId"), ":trail/*" ] ] } } } }, { "Sid": "Allow CloudTrail to describe key", "Effect": "Allow", "Principal": { "Service": ["cloudtrail.amazonaws.com"] }, "Action": "kms:DescribeKey", "Resource": "*" }, { "Sid": "Allow principals in the account to decrypt log files", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": ["kms:Decrypt", "kms:ReEncryptFrom"], "Resource": "*", "Condition": { "StringEquals": { "kms:CallerAccount": Ref("AWS::AccountId") }, "StringLike": { "kms:EncryptionContext:aws:cloudtrail:arn": { "Fn::Join": [ "", [ "arn:aws:cloudtrail:*:", Ref("AWS::AccountId"), ":trail/*" ] ] } } } }, { "Sid": "Allow alias creation during setup", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "kms:CreateAlias", "Resource": "*", "Condition": { "StringEquals": { "kms:ViaService": { "Fn::Join": [ ".", [ "ec2", Ref("AWS::Region"), "amazonaws.com" ] ] }, "kms:CallerAccount": Ref("AWS::AccountId") } } }, { "Sid": "Enable cross account log decryption", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": ["kms:Decrypt", "kms:ReEncryptFrom"], "Resource": "*", "Condition": { "StringEquals": { "kms:CallerAccount": Ref("AWS::AccountId") }, "StringLike": { "kms:EncryptionContext:aws:cloudtrail:arn": { "Fn::Join": [ "", [ "arn:aws:cloudtrail:*:", Ref("AWS::AccountId"), ":trail/*" ] ] } } } } ] }))
), Action=[ Action("kms", "CreateGrant"), Action("kms", "ListGrants"), Action("kms", "RevokeGrant"), ], Resource=["*"], Condition=Condition(Bool({"kms:GrantIsForAWSResource": True})), ), ], ) kms_key = t.add_resource( Key( "KmsKey", Description="Key for encrypting the secrets", KeyPolicy=key_policy, )) t.add_output(Output( "KeyId", Value=Ref(kms_key), Description="KeyId of KMS", )) kms_alias = t.add_resource( Alias( "KeyAlias", AliasName=Join( "", [
def generate_queues_template(QueueNamePrefix, Environment): QueueName = f'{QueueNamePrefix}-{Environment}' DLQQueueName = f'{QueueNamePrefix}DLQ-{Environment}' t = Template(Description='A template for a messaging queue') t.version = '2010-09-09' KMSKey = t.add_resource( Key('KMSKey', Description=f'KMS Key for encrypting {QueueName}', Enabled=True, EnableKeyRotation=True, KeyPolicy=Policy( Version='2012-10-17', Statement=[ Statement(Sid='Enable IAM User Permissions', Effect=Allow, Principal=AWSPrincipal( Sub('arn:aws:iam::${AWS::AccountId}:root')), Action=[KmsAction(All)], Resource=AllResources), Statement(Sid='Allow access for Key Administrators', Effect=Allow, Principal=AWSPrincipal([ Sub(f'{USER}/frank'), Sub(f'{USER}/moonunit') ]), Action=[ KmsAction('Create*'), KmsAction('Describe*'), KmsAction('Enable*'), KmsAction('List*'), KmsAction('Put*'), KmsAction('Update*'), KmsAction('Revoke*'), KmsAction('Disable*'), KmsAction('Get*'), KmsAction('Delete*'), KmsAction('ScheduleKeyDeletion'), KmsAction('CancelKeyDeletion') ], Resource=AllResources) ]))) t.add_resource( Alias('KMSKeyAlias', AliasName=f'alias/{QueueName}', TargetKeyId=Ref(KMSKey))) dlq = t.add_resource( Queue( 'DeadLetterQueue', QueueName=DLQQueueName, MaximumMessageSize=262144, # 256KiB MessageRetentionPeriod=1209600, # 14 days VisibilityTimeout=30)) t.add_resource( Queue( 'PrimaryQueue', QueueName=QueueName, MaximumMessageSize=262144, # 256KiB MessageRetentionPeriod=1209600, # 14 days VisibilityTimeout=30, RedrivePolicy=RedrivePolicy(deadLetterTargetArn=GetAtt( dlq.title, 'Arn'), maxReceiveCount=10), KmsMasterKeyId=Ref(KMSKey), KmsDataKeyReusePeriodSeconds=300)) t.add_output([ Output('QueueArn', Description=f'ARN of {QueueName} Queue', Value=GetAtt('PrimaryQueue', 'Arn'), Export=Export(Name(Sub('${AWS::StackName}:PrimaryQueueArn')))), Output('KmsKeyArn', Description=f'KMS Key ARN for {QueueName} Queue', Value=GetAtt('KMSKey', 'Arn'), Export=Export(Name(Sub('${AWS::StackName}:KmsKeyArn')))) ]) return t
def __init__(self, key_title, key_rotation, key_admins, key_users, template): """ AWS - http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kms-key.html Troposphere - https://github.com/cloudtools/troposphere/blob/master/troposphere/kms.py Create a Customer Master key in KMS for encrpytion and use with credstash :param key_title: String title of the key in AWS, not the alias name, must be alphanumeric :param key_rotation: Boolean to enable or disable key rotation at a cost :param key_admins: single string or list of ARNs of IAM objects for apply key admin policy to :param key_users: single string or list of ARNs of IAM objects for apply key user policy to :param template: The troposphere template to add the Elastic Loadbalancer to. """ # Policy for Admins and users k_key_policy = { "Version": "2012-10-17", "Id": "key-default-1", "Statement": [ { "Sid": "Allow administration of the key", "Effect": "Allow", "Principal": {"AWS": key_admins}, "Action": [ "kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*", "kms:Put*", "kms:Update*", "kms:Revoke*", "kms:Disable*", "kms:Get*", "kms:Delete*", "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion" ], "Resource": "*" }, { "Sid": "Allow use of the key", "Effect": "Allow", "Principal": {"AWS": key_users}, "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt", "kms:GenerateDataKey*", "kms:DescribeKey" ], "Resource": "*" } ] } # Create Key Resource self.k_key = template.add_resource(Key(key_title, Description=Join('', [key_title, ' on Stack: ', Ref('AWS::StackName')]), Enabled=True, EnableKeyRotation=key_rotation, KeyPolicy=k_key_policy)) # Add Output template.add_output(Output( key_title, Value=Join('', [Ref(self.k_key), ' is a managed AWS KMS Key and Key Rotation = ', self.k_key.EnableKeyRotation.upper(), '. Created with Amazonia as part of stack name - ', Ref('AWS::StackName'), ]), Description='Amazonia KMS Key Bucket' ))