def create_s3_destination()

in security/guardduty/index.py [0:0]


def create_s3_destination(sts_session):
    """
    Create the s3 publishing destination for GuardDuty in the Control Tower
    central logging account.  GuardDuty findings are encrypted using
    the KMS key in the GuardDuty master account.
    :param sts_session: STS sesion of the GuardDuty master account
    :return: properties for the GuardDuty publishing destination
    """
    cloud_trail_client = sts_session.client('cloudtrail')
    cloud_trail_response = cloud_trail_client.describe_trails(
        trailNameList=[
            'aws-controltower-BaselineCloudTrail',
        ]
    )

    logger.debug(cloud_trail_response)

    trail_bucket_name = cloud_trail_response['trailList'][0]['S3BucketName']
    bucket_name = trail_bucket_name.replace('logs', 'guardduty')
    bucket_prefix = cloud_trail_response['trailList'][0]['S3KeyPrefix']
    bucket_region = cloud_trail_response['trailList'][0]['HomeRegion']
    bucket_account = trail_bucket_name.split('-')[3]

    logger.debug(f'trail_bucket_name is {trail_bucket_name}')
    logger.debug(f'bucket_name is {bucket_name}')
    logger.debug(f'bucket_prefix is {bucket_prefix}')
    logger.debug(f'bucket_region is {bucket_region}')
    logger.debug(f'bucket_account is {bucket_account}')

    log_account_session = assume_role(bucket_account, role_to_assume)
    # Create s3 bucket in centralized log account of Control Tower
    s3_client = log_account_session.client('s3')

    # Only these regions are allowed in LocationConstraint
    # see documentation under S3.Client.create_bucket API
    allowed_regions = [
        'af-south-1',
        'ap-east-1',
        'ap-northeast-1',
        'ap-northeast-2',
        'ap-northeast-3',
        'ap-south-1',
        'ap-southeast-1',
        'ap-southeast-2',
        'ca-central-1',
        'cn-north-1',
        'cn-northwest-1',
        'eu-central-1',
        'eu-north-1',
        'eu-south-1',
        'eu-west-1',
        'eu-west-2',
        'eu-west-3',
        'me-south-1',
        'sa-east-1',
        'us-east-2',
        'us-gov-east-1',
        'us-gov-west-1',
        'us-west-1',
        'us-west-2'
    ]

    # KMS key must be in the same region as the s3 bucket,
    # so we create bucket and key together.
    kms_key_arn = ''
    try:
        if bucket_region in allowed_regions:
            kms_key_arn = create_kms_key(sts_session, bucket_region)
            logger.info('Creating Destination S3 Bucket if none exists')
            s3_client.create_bucket(
                Bucket=bucket_name,
                CreateBucketConfiguration={
                    'LocationConstraint': bucket_region
                }
            )
        elif bucket_region.startswith('eu'):
            kms_key_arn = create_kms_key(sts_session, bucket_region)
            logger.info('Creating Destination S3 Bucket if none exists')
            s3_client.create_bucket(
                Bucket=bucket_name,
                CreateBucketConfiguration={
                    'LocationConstraint': 'EU'
                }
            )
        else:
            # Bucket will be created in us-east-1
            kms_key_arn = create_kms_key(sts_session, 'us-east-1')
            logger.info('Creating Destination S3 Bucket if none exists')
            s3_client.create_bucket(Bucket=bucket_name)
    except Exception as e:
        logger.info(f'Bucket {bucket_name} already created.')
        logger.error(f'Skipping creating bucket {bucket_name}', exc_info=True)

    bucket_policy = {
        'Version': '2012-10-17',
        'Statement': [
            {
                'Sid': 'AWSBucketPermissionsCheck',
                'Effect': 'Allow',
                'Principal': {
                    'Service': 'guardduty.amazonaws.com'
                },
                'Action': [
                    's3:GetBucketAcl',
                    's3:ListBucket',
                    's3:GetBucketLocation'
                ],
                'Resource': f'arn:aws:s3:::{bucket_name}'
            },
            {
                'Sid': 'AWSBucketDelivery',
                'Effect': 'Allow',
                'Principal': {
                    'Service': 'guardduty.amazonaws.com'
                },
                'Action': 's3:PutObject',
                'Resource': f'arn:aws:s3:::{bucket_name}/*'
            },
            {
                'Sid': 'Deny unencrypted object uploads. This is optional',
                'Effect': 'Deny',
                'Principal': {
                    'Service': 'guardduty.amazonaws.com'
                },
                'Action': 's3:PutObject',
                'Resource': f'arn:aws:s3:::{bucket_name}/*',
                'Condition': {
                    'StringNotEquals': {
                        's3:x-amz-server-side-encryption': 'aws:kms'
                    }
                }
            },
            {
                'Sid': 'Deny incorrect encryption header. This is optional',
                'Effect': 'Deny',
                'Principal': {
                    'Service': 'guardduty.amazonaws.com'
                },
                'Action': 's3:PutObject',
                'Resource': f'arn:aws:s3:::{bucket_name}/*',
                'Condition': {
                    'StringNotEquals': {
                        's3:x-amz-server-side-encryption-aws-kms-key-id': kms_key_arn
                    }
                }
            },
            {
                'Sid': 'Deny non-HTTPS access',
                'Effect': 'Deny',
                'Principal': '*',
                'Action': 's3:*',
                'Resource': f'arn:aws:s3:::{bucket_name}/*',
                'Condition': {
                    'Bool': {
                        'aws:SecureTransport': 'false'
                    }
                }
            }
        ]
    }

    # Convert the policy from JSON dict to string
    bucket_policy = json.dumps(bucket_policy)

    s3_client.put_bucket_policy(Bucket=bucket_name, Policy=bucket_policy)
    s3_client.put_bucket_encryption(
        Bucket=bucket_name,
        ServerSideEncryptionConfiguration={
            'Rules': [
                {
                    'ApplyServerSideEncryptionByDefault': {
                        'SSEAlgorithm': 'AES256'
                    }
                },
            ]
        }
    )

    destination_properties = {
            'DestinationArn': f'arn:aws:s3:::{bucket_name}',
            'KmsKeyArn': kms_key_arn
    }
    return destination_properties