--- AWSTemplateFormatVersion: 2010-09-09 Description: EKSWSV1 Parameters: EksClusterName: Type: String Description: The name of the EKS cluster created Default: eksworkshop-eksctl MinLength: 1 MaxLength: 100 ConstraintDescription: You must enter the EKS cluster name # TODO: Update this to final repo name GitSourceRepo: Type: String Description: GitHub source repository - must contain a Dockerfile and buildspec.yml in the base Default: eks-workshop-sample-api-service-go MinLength: 1 MaxLength: 100 ConstraintDescription: You must enter a GitHub repository name GitBranch: Type: String Default: master Description: GitHub git repository branch - change triggers a new build MinLength: 1 MaxLength: 100 ConstraintDescription: You must enter a GitHub repository branch name GitHubToken: Type: String NoEcho: true Description: GitHub API token - see https://github.com/blog/1509-personal-api-tokens MinLength: 3 MaxLength: 100 ConstraintDescription: You must enter a GitHub personal access token GitHubUser: Type: String Description: GitHub username or organization MinLength: 3 MaxLength: 100 ConstraintDescription: You must enter a GitHub username or organization CodeBuildDockerImage: Type: String Default: aws/codebuild/docker:17.09.0 Description: Default AWS CodeBuild Docker optimized image MinLength: 3 MaxLength: 100 ConstraintDescription: You must enter a CodeBuild Docker image KubectlRoleName: Type: String Default: EksWorkshopCodeBuildKubectlRole Description: IAM role used by kubectl to interact with EKS cluster MinLength: 3 MaxLength: 100 ConstraintDescription: You must enter a kubectl IAM role Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: GitHub Parameters: - GitHubUser - GitHubToken - GitSourceRepo - GitBranch - Label: default: CodeBuild Parameters: - CodeBuildDockerImage - Label: default: IAM Parameters: - KubectlRoleName - Label: default: EKS Parameters: - EksClusterName ParameterLabels: GitHubUser: default: Username GitHubToken: default: Access token GitSourceRepo: default: Repository GitBranch: default: Branch CodeBuildDockerImage: default: Docker image KubectlRoleName: default: kubectl IAM role EksClusterName: default: EKS cluster name Resources: EcrDockerRepository: Type: AWS::ECR::Repository DeletionPolicy: Retain CodePipelineArtifactBucket: Type: AWS::S3::Bucket DeletionPolicy: Retain CustomResourceLambda: Type: AWS::Lambda::Function Properties: Code: ZipFile: | import json import boto3 from botocore.vendored import requests def handler(event, context): response = { 'Status': 'SUCCESS', "Reason": "See the details in CloudWatch Log Stream: " + context.log_stream_name, 'PhysicalResourceId': context.log_stream_name, 'StackId': event['StackId'], 'RequestId': event['RequestId'], 'LogicalResourceId': event['LogicalResourceId'], 'Data': {"Message": "Resource creation successful!"}, } client = boto3.client('iam') try: if event['RequestType'] == 'Create': kubectl_role_name = event['ResourceProperties']['KubectlRoleName'] build_role_arn = event['ResourceProperties']['CodeBuildServiceRoleArn'] assume = client.get_role(RoleName = kubectl_role_name) assume_doc = assume['Role']['AssumeRolePolicyDocument'] roles = [ { 'Effect': 'Allow', 'Principal': { 'AWS': build_role_arn }, 'Action': 'sts:AssumeRole' } ] for statement in assume_doc['Statement']: if 'AWS' in statement['Principal']: if statement['Principal']['AWS'].startswith('arn:aws:iam:'): roles.append(statement) assume_doc['Statement'] = roles update_response = client.update_assume_role_policy(RoleName = kubectl_role_name, PolicyDocument = json.dumps(assume_doc)) except Exception as e: print(e) response['Status'] = 'FAILED' response["Reason"] = e response['Data'] = {"Message": "Resource creation failed"} response_body = json.dumps(response) headers = {'content-type': '', "content-length": len(response_body) } put_response = requests.put(event['ResponseURL'], headers=headers, data=response_body) return response Handler: index.handler Role: !GetAtt CustomResourceLambdaExecutionRole.Arn Runtime: python2.7 Timeout: 300 CustomResourceLambdaExecutionRole: Type: AWS::IAM::Role Properties: ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/service-role/AWSLambdaENIManagementAccess Path: / AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: sts:AssumeRole Principal: Service: - lambda.amazonaws.com Policies: - PolicyName: codepipeline-access PolicyDocument: Version: 2012-10-17 Statement: - Resource: !Sub arn:aws:iam::${AWS::AccountId}:role/${KubectlRoleName} Effect: Allow Action: - iam:GetRole - iam:UpdateAssumeRolePolicy KubectlAssumeRoleCustomResource: Type: Custom::CustomResource Properties: ServiceToken: !GetAtt CustomResourceLambda.Arn KubectlRoleName: !Ref KubectlRoleName CodeBuildServiceRoleArn: !GetAtt CodeBuildServiceRole.Arn DependsOn: - CustomResourceLambda - CodeBuildServiceRole CodePipelineServiceRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: codepipeline.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: codepipeline-access PolicyDocument: Version: 2012-10-17 Statement: - Resource: "*" Effect: Allow Action: - codebuild:StartBuild - codebuild:BatchGetBuilds - codecommit:GetBranch - codecommit:GetCommit - codecommit:UploadArchive - codecommit:GetUploadArchiveStatus - codecommit:CancelUploadArchive - iam:PassRole - Resource: !Sub arn:aws:s3:::${CodePipelineArtifactBucket}/* Effect: Allow Action: - s3:PutObject - s3:GetObject - s3:GetObjectVersion - s3:GetBucketVersioning DependsOn: CodePipelineArtifactBucket CodeBuildServiceRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: codebuild.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: root PolicyDocument: Version: 2012-10-17 Statement: - Resource: !Sub arn:aws:iam::${AWS::AccountId}:role/${KubectlRoleName} Effect: Allow Action: - sts:AssumeRole - Resource: '*' Effect: Allow Action: - eks:Describe* - Resource: '*' Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - Resource: '*' Effect: Allow Action: - ecr:GetAuthorizationToken - Resource: '*' Effect: Allow Action: - ec2:CreateNetworkInterface - ec2:DescribeDhcpOptions - ec2:DescribeNetworkInterfaces - ec2:DeleteNetworkInterface - ec2:DescribeSubnets - ec2:DescribeSecurityGroups - ec2:DescribeVpcs - ec2:CreateNetworkInterfacePermission - Resource: !Sub arn:aws:s3:::${CodePipelineArtifactBucket}/* Effect: Allow Action: - s3:GetObject - s3:PutObject - s3:GetObjectVersion - Resource: !Sub arn:aws:ecr:${AWS::Region}:${AWS::AccountId}:repository/${EcrDockerRepository} Effect: Allow Action: - ecr:GetDownloadUrlForLayer - ecr:BatchGetImage - ecr:BatchCheckLayerAvailability - ecr:PutImage - ecr:InitiateLayerUpload - ecr:UploadLayerPart - ecr:CompleteLayerUpload CodeBuildProject: Type: AWS::CodeBuild::Project Properties: Artifacts: Type: CODEPIPELINE Source: Type: CODEPIPELINE Environment: ComputeType: BUILD_GENERAL1_SMALL Type: LINUX_CONTAINER Image: !Ref CodeBuildDockerImage EnvironmentVariables: - Name: REPOSITORY_URI Value: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${EcrDockerRepository} - Name: REPOSITORY_NAME Value: !Ref GitSourceRepo - Name: REPOSITORY_BRANCH Value: !Ref GitBranch - Name: EKS_CLUSTER_NAME Value: !Ref EksClusterName - Name: EKS_KUBECTL_ROLE_ARN Value: !Sub arn:aws:iam::${AWS::AccountId}:role/${KubectlRoleName} Name: !Ref AWS::StackName ServiceRole: !GetAtt CodeBuildServiceRole.Arn DependsOn: KubectlAssumeRoleCustomResource CodePipelineGitHub: Type: AWS::CodePipeline::Pipeline Properties: RoleArn: !GetAtt CodePipelineServiceRole.Arn ArtifactStore: Type: S3 Location: !Ref CodePipelineArtifactBucket Stages: - Name: Source Actions: - Name: App ActionTypeId: Category: Source Owner: ThirdParty Version: 1 Provider: GitHub Configuration: Owner: !Ref GitHubUser Repo: !Ref GitSourceRepo Branch: !Ref GitBranch OAuthToken: !Ref GitHubToken OutputArtifacts: - Name: App RunOrder: 1 - Name: Build Actions: - Name: Build ActionTypeId: Category: Build Owner: AWS Version: 1 Provider: CodeBuild Configuration: ProjectName: !Ref CodeBuildProject InputArtifacts: - Name: App OutputArtifacts: - Name: BuildOutput RunOrder: 1 DependsOn: CodeBuildProject