# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 AWSTemplateFormatVersion: "2010-09-09" Description: | Initialiser template used to bring up the install ServiceCatalog-Puppet {"version": "latest", "framework": "servicecatalog-puppet", "role": "initialiser"} Parameters: EnabledRegions: Type: String Default: eu-west-1 AllowedValues: - eu-west-1 Description: Single AWS Regions for which your Puppet should operate in ShouldCollectCloudformationEvents: Type: String AllowedValues: - True - False Default: False ShouldForwardEventsToEventbridge: Type: String AllowedValues: - True - False Default: False ShouldForwardFailuresToOpscenter: Type: String AllowedValues: - True - False Default: False OrgIAMRoleArn: Type: String Default: None CodeBuildProjectName: Type: String Description: Name of the CodeBuild Project to use for Build Default: servicecatalog-product-puppet-initialiser Conditions: NotUsingOrgs: !Equals [!Ref OrgIAMRoleArn, "None" ] UsingOrgs: !Not [Condition: NotUsingOrgs] Resources: InitialiserRole: Type: AWS::IAM::Role Properties: RoleName: PuppetInitialiser Path: /servicecatalog-product-puppet/ AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: - "codebuild.amazonaws.com" Action: - "sts:AssumeRole" ManagedPolicyArns: - arn:aws:iam::aws:policy/AdministratorAccess InitialiserProject: Type: AWS::CodeBuild::Project Condition: NotUsingOrgs Properties: Name: servicecatalog-product-puppet-initialiser Description: "Initialiser for the framework" ServiceRole: !GetAtt InitialiserRole.Arn Artifacts: Type: NO_ARTIFACTS Environment: Type: linuxContainer ComputeType: BUILD_GENERAL1_SMALL Image: aws/codebuild/python:3.7.1 EnvironmentVariables: - Name: ENABLED_REGIONS Type: PLAINTEXT Value: !Join [ ',', !Split [ ', ', !Ref EnabledRegions]] - Name: SHOULD_COLLECT_CLOUDFORMATION_EVENTS Type: PLAINTEXT Value: !Ref ShouldCollectCloudformationEvents - Name: SHOULD_FORWARD_EVENTS_TO_EVENTBRIDGE Type: PLAINTEXT Value: !Ref ShouldForwardEventsToEventbridge - Name: SHOULD_FORWARD_FAILURES_TO_OPSCENTER Type: PLAINTEXT Value: !Ref ShouldForwardFailuresToOpscenter - Name: PUPPET_ACCOUNT_ID Type: PLAINTEXT Value: !Ref AWS::AccountId Source: Type: NO_SOURCE BuildSpec: | version: 0.2 phases: install: commands: - pip install aws-service-catalog-puppet --upgrade - servicecatalog-puppet --info set-regions ${ENABLED_REGIONS} - servicecatalog-puppet set-config-value should_collect_cloudformation_events ${SHOULD_COLLECT_CLOUDFORMATION_EVENTS} - servicecatalog-puppet set-config-value should_forward_events_to_eventbridge ${SHOULD_FORWARD_EVENTS_TO_EVENTBRIDGE} - servicecatalog-puppet set-config-value should_forward_failures_to_opscenter ${SHOULD_FORWARD_FAILURES_TO_OPSCENTER} - servicecatalog-puppet bootstrap-spoke ${PUPPET_ACCOUNT_ID} build: commands: - servicecatalog-puppet --info bootstrap TimeoutInMinutes: 60 InitialiserProjectForOrgs: Type: AWS::CodeBuild::Project Condition: UsingOrgs Properties: Name: servicecatalog-product-puppet-initialiser-for-orgs Description: "Initialiser for the framework" ServiceRole: !GetAtt InitialiserRole.Arn Artifacts: Type: NO_ARTIFACTS Environment: Type: linuxContainer ComputeType: BUILD_GENERAL1_SMALL Image: aws/codebuild/python:3.7.1 EnvironmentVariables: - Name: ENABLED_REGIONS Type: PLAINTEXT Value: !Join [ ',', !Split [ ', ', !Ref EnabledRegions]] - Name: SHOULD_COLLECT_CLOUDFORMATION_EVENTS Type: PLAINTEXT Value: !Ref ShouldCollectCloudformationEvents - Name: SHOULD_FORWARD_EVENTS_TO_EVENTBRIDGE Type: PLAINTEXT Value: !Ref ShouldForwardEventsToEventbridge - Name: SHOULD_FORWARD_FAILURES_TO_OPSCENTER Type: PLAINTEXT Value: !Ref ShouldForwardFailuresToOpscenter - Name: PUPPET_ACCOUNT_ID Type: PLAINTEXT Value: !Ref AWS::AccountId - Name: ORG_IAM_ROLE_ARN Type: PLAINTEXT Value: !Ref OrgIAMRoleArn Source: Type: NO_SOURCE BuildSpec: | version: 0.2 phases: install: commands: - pip install aws-service-catalog-puppet --upgrade - servicecatalog-puppet --info set-regions ${ENABLED_REGIONS} - servicecatalog-puppet set-config-value should_collect_cloudformation_events ${SHOULD_COLLECT_CLOUDFORMATION_EVENTS} - servicecatalog-puppet set-config-value should_forward_events_to_eventbridge ${SHOULD_FORWARD_EVENTS_TO_EVENTBRIDGE} - servicecatalog-puppet set-config-value should_forward_failures_to_opscenter ${SHOULD_FORWARD_FAILURES_TO_OPSCENTER} - servicecatalog-puppet set-org-iam-role-arn ${ORG_IAM_ROLE_ARN} - servicecatalog-puppet bootstrap-spoke ${PUPPET_ACCOUNT_ID} build: commands: - servicecatalog-puppet --info bootstrap TimeoutInMinutes: 60 StartInstallPuppetRole: Type: AWS::IAM::Role Properties: Path: /servicefactory-puppet/ ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AWSCodeBuildDeveloperAccess AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: - "lambda.amazonaws.com" Action: - "sts:AssumeRole" StartInstallPuppetCustomresource: Type: AWS::Lambda::Function Properties: Role: !GetAtt StartInstallPuppetRole.Arn Handler: "index.handler" Description: Lambda for starting CodeBuild Job Runtime: python3.7 Timeout: 5 Code: ZipFile: | import boto3 import json import logging from urllib.request import Request, urlopen logger = logging.getLogger() logger.setLevel(logging.INFO) def handler(event, context): request_type = event['RequestType'] codebuild_projectname = event.get('ResourceProperties').get('ProjectName') try: logger.info(request_type) if request_type == 'Create': codebuild_client = boto3.client('codebuild') logger.info("Starting CodeBuild Job: {}".format(codebuild_projectname)) codebuild_response = codebuild_client.start_build( projectName = codebuild_projectname ) send_response(event, context, "SUCCESS", {"Message": "Updated"}) elif request_type == 'Update': send_response(event, context, "SUCCESS", {"Message": "Updated"}) elif request_type == 'Delete': send_response(event, context, "SUCCESS", {"Message": "Deleted"}) else: send_response(event, context, "FAILED", {"Message": "Unexpected"}) except Exception as ex: logger.error(ex) send_response(event, context,"FAILED", {"Message": "Exception"}) def send_response(e, c, rs, rd): r = json.dumps({ "Status": rs, "Reason": "CloudWatch Log Stream: " + c.log_stream_name, "PhysicalResourceId": c.log_stream_name, "StackId": e['StackId'], "RequestId": e['RequestId'], "LogicalResourceId": e['LogicalResourceId'], "Data": rd }) d = str.encode(r) h = { 'content-type': '', 'content-length': str(len(d)) } req = Request(e['ResponseURL'], data=d, method='PUT', headers=h) r = urlopen(req) logger.info("Status message: {} {}".format(r.msg, r.getcode())) StartInstallPuppet: Type: Custom::CustomResource DependsOn: InitialiserProject Properties: ServiceToken: !GetAtt StartInstallPuppetCustomresource.Arn ProjectName: !Ref CodeBuildProjectName Outputs: ServiceCatalogPuppetRepoConsoleURL: Value: !Sub "https://${AWS::Region}.console.aws.amazon.com/codesuite/codecommit/repositories/ServiceCatalogPuppet/browse" ServiceCatalogPuppetRepoCloneURLSSH: Value: !Sub "ssh://git-codecommit.${AWS::Region}.amazonaws.com/v1/repos/ServiceCatalogPuppet" ServiceCatalogPuppetRepoCloneURLHTTPS: Value: !Sub "https://git-codecommit.${AWS::Region}.amazonaws.com/v1/repos/ServiceCatalogPuppet"