AWSTemplateFormatVersion: 2010-09-09 Transform: AWS::Serverless-2016-10-31 Description: Automated Best Practices for AWS Cloud setups - https://superwerker.cloud (qs-1rhrhoi4t) Metadata: cfn-lint: config: ignore_checks: - E9007 SuperwerkerVersion: 0.13.2 QuickStartDocumentation: EntrypointName: "Parameters for launching Superwerker" Order: "1" AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Features Parameters: - IncludeBudget - IncludeGuardDuty - IncludeSecurityHub - IncludeBackup - IncludeServiceControlPolicies - Label: default: Domain configuration Parameters: - Domain - Subdomain - Label: default: Notifications Parameters: - NotificationsMail - Label: default: AWS Quick Start configuration Parameters: - QSS3BucketName - QSS3KeyPrefix - QSS3BucketRegion ParameterLabels: Domain: default: Domain for automated DNS configuration Subdomain: default: Sub domain for automated DNS configuration NotificationsMail: default: Mail address used for important notification regarding your AWS account (leave empty for no notifications) IncludeBudget: default: Include AWS Budgets alarm IncludeGuardDuty: default: Include Amazon GuardDuty IncludeSecurityHub: default: Include AWS Security Hub IncludeBackup: default: Include Automated Backups IncludeServiceControlPolicies: default: Include service control policies QSS3BucketName: default: Quick Start S3 bucket name QSS3BucketRegion: default: Quick Start S3 bucket Region QSS3KeyPrefix: default: Quick Start S3 key prefix Parameters: Domain: Type: String Description: Domain used for root mail feature Subdomain: Type: String Default: aws Description: Subdomain used for root mail feature NotificationsMail: Type: String Description: Mail address used for notifications Default: "" AllowedPattern: "(^$|^.*@.*\\..*$)" IncludeBudget: AllowedValues: - 'Yes' - 'No' Default: 'Yes' Type: String Description: Enable AWS Budgets alarm for monthly AWS spending IncludeGuardDuty: AllowedValues: - 'Yes' - 'No' Default: 'Yes' Type: String Description: Enable Amazon GuardDuty IncludeSecurityHub: AllowedValues: - 'Yes' - 'No' Default: 'Yes' Type: String Description: Enable AWS Security Hub IncludeBackup: AllowedValues: - 'Yes' - 'No' Default: 'Yes' Type: String Description: Enable automated backups IncludeServiceControlPolicies: AllowedValues: - 'Yes' - 'No' Default: 'Yes' Type: String Description: Enable service control policies in AWS organizations QSS3BucketName: AllowedPattern: '^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$' ConstraintDescription: The Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Default: aws-quickstart Description: Name of the S3 bucket for your copy of the Quick Start assets. Keep the default name unless you are customizing the template. Changing the name updates code references to point to a new Quick Start location. This name can include numbers, lowercase letters, uppercase letters, and hyphens, but do not start or end with a hyphen (-). See https://aws-quickstart.github.io/option1.html. Type: String QSS3BucketRegion: Default: 'us-east-1' Description: 'AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. Keep the default Region unless you are customizing the template. Changing this Region updates code references to point to a new Quick Start location. When using your own bucket, specify the Region. See https://aws-quickstart.github.io/option1.html.' Type: String QSS3KeyPrefix: AllowedPattern: '^([0-9a-zA-Z-.:]+/)*$' ConstraintDescription: The Quick Start S3 key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), colon (:), and forward slashes (/). Default: quickstart-superwerker/ Description: S3 key prefix that is used to simulate a directory for your copy of the Quick Start assets. Keep the default prefix unless you are customizing the template. Changing this prefix updates code references to point to a new Quick Start location. This prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), colon (:), and forward slashes (/). See https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html and https://aws-quickstart.github.io/option1.html. Type: String Conditions: UsingDefaultBucket: !Equals [!Ref QSS3BucketName, 'aws-quickstart'] IncludeNotifications: !Not [!Equals [ !Ref NotificationsMail, '' ]] IncludeBudget: !Equals [ !Ref IncludeBudget, 'Yes' ] IncludeGuardDuty: !Equals [ !Ref IncludeGuardDuty, 'Yes' ] IncludeSecurityHub: !Equals [ !Ref IncludeSecurityHub, 'Yes' ] IncludeBackup: !Equals [ !Ref IncludeBackup, 'Yes' ] IncludeServiceControlPolicies: !Equals [ !Ref IncludeServiceControlPolicies, 'Yes' ] Resources: Budget: Condition: IncludeBudget Type: AWS::CloudFormation::Stack Properties: TemplateURL: Fn::Sub: - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/budget.yaml' - S3Region: !If [UsingDefaultBucket, !Sub '${AWS::Region}', !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] ControlTower: Type: AWS::CloudFormation::Stack Properties: TemplateURL: Fn::Sub: - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/control-tower.yaml' - S3Region: !If [UsingDefaultBucket, !Sub '${AWS::Region}', !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: AuditAWSAccountEmail: !GetAtt GeneratedAuditAWSAccountEmail.email LogArchiveAWSAccountEmail: !GetAtt GeneratedLogArchiveAWSAccountEmail.email GeneratedAuditAWSAccountEmail: Type: AWS::CloudFormation::CustomResource Properties: ServiceToken: !GetAtt GenerateLogAndOrAuditEmailCustomResource.Arn GeneratedLogArchiveAWSAccountEmail: Type: AWS::CloudFormation::CustomResource Properties: ServiceToken: !GetAtt GenerateLogAndOrAuditEmailCustomResource.Arn GenerateLogAndOrAuditEmailCustomResource: Type: AWS::Serverless::Function Properties: Timeout: 200 Handler: index.handler Runtime: python3.7 Policies: - LambdaInvokePolicy: FunctionName: !GetAtt RootMail.Outputs.EmailGeneratorFunction InlineCode: !Sub | import boto3 import cfnresponse import json lambda_client = boto3.client("lambda") CREATE = 'Create' DELETE = 'Delete' UPDATE = 'Update' def exception_handling(function): def catch(event, context): try: function(event, context) except Exception as e: print(e) print(event) cfnresponse.send(event, context, cfnresponse.FAILED, {}) return catch @exception_handling def handler(event, context): RequestType = event["RequestType"] Properties = event["ResourceProperties"] LogicalResourceId = event["LogicalResourceId"] PhysicalResourceId = event.get("PhysicalResourceId") print('RequestType: {}'.format(RequestType)) print('PhysicalResourceId: {}'.format(PhysicalResourceId)) print('LogicalResourceId: {}'.format(LogicalResourceId)) id = PhysicalResourceId data = {} if RequestType == CREATE or RequestType == UPDATE: lambda_response = lambda_client.invoke( FunctionName='${RootMail.Outputs.EmailGeneratorFunction}' ) response_json = json.loads(lambda_response['Payload'].read().decode('utf-8')) data['email'] = response_json['email'] cfnresponse.send(event, context, cfnresponse.SUCCESS, data, id) GuardDuty: Condition: IncludeGuardDuty Type: AWS::CloudFormation::Stack Properties: TemplateURL: Fn::Sub: - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/guardduty.yaml' - S3Region: !If [UsingDefaultBucket, !Sub '${AWS::Region}', !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] LivingDocumentation: Type: AWS::CloudFormation::Stack Properties: TemplateURL: Fn::Sub: - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/living-documentation.yaml' - S3Region: !If [UsingDefaultBucket, !Sub '${AWS::Region}', !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: SuperwerkerDomain: !Sub '${Subdomain}.${Domain}' RootMail: Type: AWS::CloudFormation::Stack Properties: TemplateURL: Fn::Sub: - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/rootmail.yaml' - S3Region: !If [UsingDefaultBucket, !Sub '${AWS::Region}', !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: Domain: !Ref Domain Subdomain: !Ref Subdomain SecurityHub: Condition: IncludeSecurityHub Type: AWS::CloudFormation::Stack Properties: TemplateURL: Fn::Sub: - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/security-hub.yaml' - S3Region: !If [UsingDefaultBucket, !Sub '${AWS::Region}', !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Backup: Condition: IncludeBackup Type: AWS::CloudFormation::Stack DependsOn: ControlTower Properties: TemplateURL: Fn::Sub: - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/backup.yaml' - S3Region: !If [UsingDefaultBucket, !Sub '${AWS::Region}', !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] ServiceControlPolicies: Condition: IncludeServiceControlPolicies Type: AWS::CloudFormation::Stack DependsOn: ControlTower Properties: TemplateURL: Fn::Sub: - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/service-control-policies.yaml' - S3Region: !If [UsingDefaultBucket, !Sub '${AWS::Region}', !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: IncludeSecurityHub: !If - IncludeSecurityHub - true - false IncludeBackup: !If - IncludeBackup - true - false Notifications: Condition: IncludeNotifications Type: AWS::CloudFormation::Stack DependsOn: RootMail Properties: TemplateURL: Fn::Sub: - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/notifications.yaml' - S3Region: !If [UsingDefaultBucket, !Sub '${AWS::Region}', !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: NotificationsMail: !Ref NotificationsMail Outputs: RootMailDelegationTarget: Description: Name servers for the hosted zone delegation Value: !GetAtt RootMail.Outputs.DelegationTarget CloudWatchDashboard: Description: See the CloudWatch superwerker dashboard for post-deployment steps Value: https://console.aws.amazon.com/cloudwatch/home#dashboards:name=superwerker