AWSTemplateFormatVersion: "2010-09-09" Description: Build MLOps Pipeline Parameters: UniqueID: Type: String Default: yourinitials Description: Enter your initials in lower case as a unique identifier for components created (atleast 3 characters) AllowedPattern: "^([a-z]|(d(?!d{0,2}.d{1,3}.d{1,3}.d{1,3})))([a-zd]|(.(?!(.|-)))|(-(?!.))){1,61}[a-zd.]$" LambdaFunctionsBucket: Type: String Default: mlops-bia-lambda-functions Description: S3 Bucket containing your Lambda Functions (Should match the bucket created by the PrepPipeline stack DataScienceAccountID: Type: String Description: AWS Account ID of the data science account StageAccountID: Type: String Description: AWS Account ID of the staging account. Resources: CodePipelineArtifactBucket: Type: AWS::S3::Bucket Properties: AccessControl: BucketOwnerFullControl VersioningConfiguration: Status: Enabled BucketName: Fn::Join: - "" - - "mlops-bia-codepipeline-artifacts-" - !Ref UniqueID - "-" - !Select - 0 - !Split - "-" - !Select - 2 - !Split - "/" - !Ref "AWS::StackId" S3DataModelBucket: Type: AWS::S3::Bucket Properties: AccessControl: BucketOwnerFullControl VersioningConfiguration: Status: Enabled BucketName: Fn::Join: - "" - - "mlops-bia-data-model-" - !Ref "AWS::AccountId" CodePipeline: Type: AWS::CodePipeline::Pipeline Properties: RoleArn: !GetAtt [CodePipelineRole, Arn] ArtifactStore: Location: Ref: CodePipelineArtifactBucket Type: S3 Stages: - Name: Source Actions: - Name: Data ActionTypeId: Category: Source Owner: AWS Version: 1 Provider: S3 OutputArtifacts: - Name: SourceArtifact Configuration: S3Bucket: !Ref S3DataModelBucket S3ObjectKey: "models/model.tar.gz" RunOrder: 1 - Name: DeployModel-Tools Actions: - Name: DeployToToolsEnv ActionTypeId: Category: Invoke Owner: AWS Version: 1 Provider: Lambda OutputArtifacts: - Name: HostingInfo InputArtifacts: - Name: SourceArtifact Configuration: FunctionName: Fn::Join: - "" - - "MLOps-BIA-DeployModel-" - !Ref UniqueID UserParameters: '{ "InitialInstanceCount": 1, "InitialVariantWeight": 1, "InstanceType": "ml.t2.medium", "EndpointConfigName": "Tools" , "TrainingImage": "825641698319.dkr.ecr.us-east-2.amazonaws.com/xgboost:1"}' RunOrder: 1 - Name: GetDeployStatus ActionTypeId: Category: Invoke Owner: AWS Version: 1 Provider: Lambda OutputArtifacts: - Name: CompletedDevDeploy InputArtifacts: - Name: HostingInfo Configuration: FunctionName: Fn::Join: - "" - - "MLOps-BIA-GetStatus-" - !Ref UniqueID UserParameters: '{ "stage": "Deployment", "endpointConfigSuffix": "Tools"}' RunOrder: 2 - Name: SmokeTest ActionTypeId: Category: Invoke Owner: AWS Version: 1 Provider: Lambda OutputArtifacts: - Name: SmokeTestOut InputArtifacts: - Name: HostingInfo Configuration: FunctionName: Fn::Join: - "" - - "MLOps-BIA-EvaluateModel-" - !Ref UniqueID UserParameters: ' { "env": "Dev", "endpointConfigSuffix": "Tools" } ' RunOrder: 3 - Name: DeployModel-Stage Actions: - Name: DeployToStageEnv ActionTypeId: Category: Invoke Owner: AWS Version: 1 Provider: Lambda OutputArtifacts: - Name: StageHostingInfo InputArtifacts: - Name: SourceArtifact Configuration: FunctionName: Fn::Join: - "" - - "MLOps-BIA-DeployModel-" - !Ref UniqueID UserParameters: '{ "InitialInstanceCount": 1, "InitialVariantWeight": 1, "InstanceType": "ml.t2.medium", "EndpointConfigName": "Stage", "TrainingImage": "825641698319.dkr.ecr.us-east-2.amazonaws.com/xgboost:1"}' RunOrder: 1 - Name: GetStageDeployStatus ActionTypeId: Category: Invoke Owner: AWS Version: 1 Provider: Lambda OutputArtifacts: - Name: CompletedStageDeploy InputArtifacts: - Name: StageHostingInfo Configuration: FunctionName: Fn::Join: - "" - - "MLOps-BIA-GetStatus-" - !Ref UniqueID UserParameters: '{ "stage": "Deployment", "endpointConfigSuffix": "Stage"}' RunOrder: 2 - Name: FullTest ActionTypeId: Category: Invoke Owner: AWS Version: 1 Provider: Lambda OutputArtifacts: - Name: FullTestOut InputArtifacts: - Name: StageHostingInfo Configuration: FunctionName: Fn::Join: - "" - - "MLOps-BIA-EvaluateModel-" - !Ref UniqueID UserParameters: '{ "env": "Test", "endpointConfigSuffix": "Stage"} ' RunOrder: 3 CodePipelineRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: Effect: Allow Principal: Service: codepipeline.amazonaws.com Action: sts:AssumeRole Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/AdministratorAccess RoleName: Fn::Join: - "" - - "MLOps-BIA-CodePipeline-ServiceRole-" - !Ref UniqueID DeployLambdaFunction: Type: "AWS::Lambda::Function" Properties: Handler: "MLOps-BIA-DeployModel.lambda_handler" Role: !GetAtt [LambdaExecutionRole, Arn] Environment: Variables: SageMakerExecutionRole: !GetAtt [SageMakerRole, Arn] SageMakerExecutionRoleStage: Fn::Join: - "" - - 'arn:aws:iam::' - !Ref StageAccountID - ':role/SageMakerExecutionRole-' - !Ref StageAccountID StageAccountS3Bucket: Fn::Join: - "-" - - "mlops-bia-data-model" - !Ref StageAccountID StageAccountAccessRole: Fn::Join: - "" - - 'arn:aws:iam::' - !Ref StageAccountID - ':role/AllowAccessToToolsAccountRole-' - !Ref StageAccountID SSEKMSKeyIdIn: !Ref KMSMasterKeyID TrainingImage: "825641698319.dkr.ecr.us-east-2.amazonaws.com/xgboost:1" FunctionName: Fn::Join: - "" - - "MLOps-BIA-DeployModel-" - !Ref UniqueID Code: S3Bucket: Fn::Join: - "-" - - !Ref LambdaFunctionsBucket - !Ref "AWS::AccountId" S3Key: "MLOps-BIA-DeployModel.py.zip" Runtime: "python3.6" Timeout: 900 GetStatusLambdaFunction: Type: "AWS::Lambda::Function" Properties: Handler: "MLOps-BIA-GetStatus.lambda_handler" Role: !GetAtt [LambdaExecutionRole, Arn] Environment: Variables: SSEKMSKeyIdIn: !Ref KMSMasterKeyID StageAccountAccessRole: Fn::Join: - "" - - 'arn:aws:iam::' - !Ref StageAccountID - ':role/AllowAccessToToolsAccountRole-' - !Ref StageAccountID FunctionName: Fn::Join: - "" - - "MLOps-BIA-GetStatus-" - !Ref UniqueID Code: #S3Bucket: !Ref LambdaFunctionsBucket S3Bucket: Fn::Join: - "-" - - !Ref LambdaFunctionsBucket - !Ref "AWS::AccountId" S3Key: "MLOps-BIA-GetStatus.py.zip" Runtime: "python3.6" Timeout: 900 EvaluateModelLambdaFunction: Type: "AWS::Lambda::Function" Properties: Handler: "MLOps-BIA-EvaluateModel.lambda_handler" Role: !GetAtt [LambdaExecutionRole, Arn] Environment: Variables: SSEKMSKeyIdIn: !Ref KMSMasterKeyID S3DataModelBucket: !Ref S3DataModelBucket StageAccountAccessRole: Fn::Join: - "" - - 'arn:aws:iam::' - !Ref StageAccountID - ':role/AllowAccessToToolsAccountRole-' - !Ref StageAccountID FunctionName: Fn::Join: - "" - - "MLOps-BIA-EvaluateModel-" - !Ref UniqueID Code: #S3Bucket: !Ref LambdaFunctionsBucket S3Bucket: Fn::Join: - "-" - - !Ref LambdaFunctionsBucket - !Ref "AWS::AccountId" S3Key: "MLOps-BIA-EvaluateModel.py.zip" Runtime: "python3.6" Timeout: 900 LambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonSageMakerFullAccess - arn:aws:iam::aws:policy/AmazonS3FullAccess - arn:aws:iam::aws:policy/CloudWatchFullAccess - arn:aws:iam::aws:policy/AWSCodePipelineFullAccess - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyName: crossaccountaccess PolicyDocument: Version: 2012-10-17 Statement: - "Effect": "Allow" "Action": "sts:AssumeRole" "Resource": Fn::Join: - "" - - 'arn:aws:iam::' - !Ref StageAccountID - ':role/AllowAccessToToolsAccountRole-' - !Ref StageAccountID - "Effect": "Allow" "Action": "iam:PassRole" "Resource": Fn::Join: - "" - - 'arn:aws:iam::' - !Ref StageAccountID - ':role/SageMakerExecutionRole-' - !Ref StageAccountID - "Effect": "Allow" "Action": "sts:AssumeRole" "Resource": Fn::Join: - "" - - 'arn:aws:iam::' - !Ref StageAccountID - ':role/SageMakerExecutionRole-' - !Ref StageAccountID RoleName: Fn::Join: - "" - - "MLOps-BIA-Lambda-ServiceRole-" - !Ref UniqueID SageMakerRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: Effect: Allow Principal: Service: sagemaker.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonSageMakerFullAccess - arn:aws:iam::aws:policy/AmazonS3FullAccess - arn:aws:iam::aws:policy/CloudWatchFullAccess - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess RoleName: Fn::Join: - "" - - "MLOps-BIA-SageMaker-ServiceRole-" - !Ref UniqueID KMSMasterKeyID: Type: AWS::KMS::Key Properties: Description: "An example CMK" KeyPolicy: Version: "2012-10-17" Id: "key-default-1" Statement: - Sid: "Enable IAM User Permissions" Effect: "Allow" Principal: AWS: Fn::Join: - "" - - "arn:aws:iam::" - !Ref AWS::AccountId - ":root" Action: "kms:*" Resource: "*" AllowAccessToDataScienceAccountRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: Effect: Allow Principal: AWS: !Ref DataScienceAccountID Action: sts:AssumeRole Policies: - PolicyName: crossaccountaccess PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: s3:PutObject Resource: Fn::Join: - "" - - !GetAtt S3DataModelBucket.Arn - "/" - "*" RoleName: Fn::Join: - "-" - - "AllowAccessToDataScienceAccountRole" - !Ref "AWS::AccountId" Outputs: S3DataModelBucket: Description: The ID of the S3 Bucket for model training and test data Value: !Ref S3DataModelBucket CodePipeline: Description: Pipeline created inside the CodePipeline service-role Value: !Ref CodePipeline