diff --git a/cicd/cloudformation/release.yaml b/cicd/cloudformation/release.yaml index 750b0c9..135c990 100644 --- a/cicd/cloudformation/release.yaml +++ b/cicd/cloudformation/release.yaml @@ -79,11 +79,11 @@ Metadata: NonDelegatedAccount: default: "What is the account id of the Test Orgs, Non-delegated admin account?" ManagementBucket: - default: "my-bucket" + default: "Artifact Bucket within the Management account" DelegatedBucket: - default: "my-bucket" + default: "Artifact Bucket within the Delegated Admin account" NonDelegatedBucket: - default: "my-bucket" + default: "Artifact Bucket within the Non-delegated Admin account" SecretsConfig: default: "TestConfig from the output of secrets.yaml" diff --git a/cicd/cloudformation/testing.yaml b/cicd/cloudformation/testing.yaml index 170054f..c5527bf 100644 --- a/cicd/cloudformation/testing.yaml +++ b/cicd/cloudformation/testing.yaml @@ -20,6 +20,14 @@ Parameters: - Management - Delegated - NonDelegated + DelegatedAccount: + Description: The test account type + Default: "622987834645" + Type: String + DelegatedBucket: + Description: The S3 bucket arn from the testing stack in the the delegated account + Type: String + Metadata: AWS::CloudFormation::Interface: @@ -32,12 +40,21 @@ Metadata: default: Testing Account Parameters: - TestAccount + - Label: + default: Delegated Account + Parameters: + - DelegatedAccount + - DelegatedBucket ParameterLabels: ProductionAccount: default: "ProductionAccount" TestAccount: default: "Account Type" + DelegatedAccount: + default: "Only required for Management Account" + DelegatedBucket: + default: "bucket in the Delegated Account" Conditions: DeployManagement: !Equals [ !Ref TestAccount, Management] @@ -280,7 +297,7 @@ Resources: PollForSourceChanges: false - Name: Deploy Actions: - - Name: Deploy + - Name: DeploySecrets ActionTypeId: Category: Deploy Owner: AWS @@ -291,41 +308,27 @@ Resources: Capabilities: CAPABILITY_IAM,CAPABILITY_AUTO_EXPAND,CAPABILITY_NAMED_IAM StackName: TestCrossAccountSecrets RoleArn: !GetAtt [CloudFormationDeployerRole, Arn] - TemplateConfiguration: 'Tests::deploy/cross_account_secrets.json' - TemplatePath: !Sub 'Tests::deploy/cross_account_secrets.yml' + TemplateConfiguration: 'Tests::deploy/crossaccountsecrets.json' + TemplatePath: !Sub 'Tests::deploy/crossaccountsecrets.yml' + OutputFileName: crossaccountapp.json InputArtifacts: - Name: Tests + OutputArtifact: + - Name: Secrets RunOrder: 1 - - CodePipelineCleanUpCrossAccountSecrets: - Type: AWS::CodePipeline::Pipeline - Condition: DeployManagement - Properties: - Name: SSOSync-CleanUp_CrossAccount_Secrets - RoleArn: !Sub ${CodePipelineRole.Arn} - ArtifactStore: - Type: S3 - Location: !Ref ArtifactBucket - EncryptionKey: - Type: KMS - Id: !GetAtt ArtifactBucketKey.Arn - Stages: - - Name: Source - Actions: - - Name: Tests - Namespace: Test + - Name: DeployAppInDelegated ActionTypeId: - Category: Source + Category: Build Owner: AWS Version: 1 - Provider: S3 - OutputArtifacts: - - Name: Tests - RunOrder: '1' + Provider: CodeBuild + RunOrder: 2 Configuration: - S3Bucket: !Ref StagingBucket - S3ObjectKey: crossaccount_secrets.zip - PollForSourceChanges: false + ProjectName: !Ref CodeBuildTestingAppStack + PrimarySource: Tests + InputArtifacts: + - Name: Tests + - Name: Secrets - Name: CleanUp Actions: - Name: RemoveStack @@ -401,7 +404,7 @@ Resources: Configuration: FunctionName: SSOSyncFunction OutputArtifacts: - - Name: ExecuteSingleStack + - Name: ExecuteCrossAccountApp InputArtifacts: - Name: Tests - Name: CleanUp @@ -449,7 +452,7 @@ Resources: S3Bucket: !Ref StagingBucket S3ObjectKey: singlestack.zip PollForSourceChanges: false - - Name: Deploy + - Name: NamedFunction Actions: - Name: Deploy ActionTypeId: @@ -463,25 +466,41 @@ Resources: StackName: TestSingleStack RoleArn: !GetAtt [CloudFormationDeployerRole, Arn] TemplateConfiguration: 'Tests::deploy/singlestack.json' - TemplatePath: !Sub 'Tests::deploy/singlestack.yml' + TemplatePath: !Sub 'Tests::deploy/namedfunction.yml' InputArtifacts: - Name: Tests RunOrder: 1 - - Name: Execute - Actions: - Name: Run-Test ActionTypeId: Category: Invoke Owner: AWS Version: 1 Provider: Lambda - RunOrder: 3 + RunOrder: 2 Configuration: FunctionName: SSOSyncFunction OutputArtifacts: - Name: ExecuteSingleStack InputArtifacts: - Name: Tests + - Name: UnNamedFunction + Actions: + - Name: Deploy + ActionTypeId: + Category: Deploy + Owner: AWS + Version: '1' + Provider: CloudFormation + Configuration: + ActionMode: CREATE_UPDATE + Capabilities: CAPABILITY_IAM,CAPABILITY_AUTO_EXPAND,CAPABILITY_NAMED_IAM + StackName: TestSingleStack + RoleArn: !GetAtt [CloudFormationDeployerRole, Arn] + TemplateConfiguration: 'Tests::deploy/singlestack.json' + TemplatePath: !Sub 'Tests::deploy/unnamedfunction.yml' + InputArtifacts: + - Name: Tests + RunOrder: 1 - Name: CleanUp Actions: - Name: RemoveStack @@ -542,8 +561,11 @@ Resources: RoleArn: !GetAtt [CloudFormationDeployerRole, Arn] TemplateConfiguration: 'Tests::deploy/secretsonly.json' TemplatePath: !Sub 'Tests::deploy/secretsonly.yml' + OutputFileName: apponly.json InputArtifacts: - Name: Tests + OutputArtifacts: + - Name: Secrets RunOrder: 1 - Name: DeployApp ActionTypeId: @@ -556,10 +578,11 @@ Resources: Capabilities: CAPABILITY_IAM,CAPABILITY_AUTO_EXPAND,CAPABILITY_NAMED_IAM StackName: TestAppOnly RoleArn: !GetAtt [CloudFormationDeployerRole, Arn] - TemplateConfiguration: 'Tests::deploy/secretsonly.json' - TemplatePath: !Sub 'Tests::deploy/secretsonly.yml' + TemplateConfiguration: 'Tests::deploy/apponly.json' + TemplatePath: !Sub 'Tests::deploy/apponly.yml' InputArtifacts: - Name: Tests + - Name: Secrets RunOrder: 2 - Name: Execute Actions: @@ -667,6 +690,44 @@ Resources: LogGroupName: !Ref CodePipelineLogGroup LogStreamName: SSOSync-Smoke-Lambda + CodeBuildTestingAppStack: + Type: AWS::CodeBuild::Project + Properties: + Name: SSOSync-Testing-AppStack + Description: "Deploy and execute an app stack deployment of ssosync into the Delegated account" + ServiceRole: !Ref CodeBuildTestRole + Source: + Type: CODEPIPELINE + BuildSpec: "tests/deploy_patterns/crossaccount/appstack/buildspec.yml" + Environment: + ComputeType: BUILD_GENERAL1_SMALL + Image: aws/codebuild/standard:7.0 + Type: LINUX_CONTAINER + EnvironmentVariables: + - Name: ARTIFACT_S3_BUCKET + Value: !Sub ${ArtifactBucket} + - Name: AppArn + Value: !Sub "arn:aws:serverlessrepo:${AWS::Region}:${AWS::AccountId}:applications/SSOSync-Staging" + - Name: TARGETS3BUCKET + Value: !Sub ${DelegatedBucket} + - Name: StagingRole + Value: !Sub "arn:aws:iam::${DelegatedAccount}:role/SSOSync-ProdAccount-${AWS::Region}" + - Name: pipeline + Value: "SSSOSync-CrossAccountApp" + Artifacts: + Name: SSOSync + Type: CODEPIPELINE + LogsConfig: + CloudWatchLogs: + GroupName: !Ref CodePipelineLogGroup + StreamName: !Ref CodeBuildTestingLogs + Status: ENABLED + + CodeBuildTestingLogs: + Type: AWS::Logs::LogStream + Properties: + LogGroupName: !Ref CodePipelineLogGroup + LogStreamName: SSOSync-Testing CodePipelineRole: Type: AWS::IAM::Role diff --git a/cicd/deploy_patterns/singlestack/buildspec.yml b/cicd/deploy_patterns/singlestack/buildspec.yml index 98deec3..ffa852a 100644 --- a/cicd/deploy_patterns/singlestack/buildspec.yml +++ b/cicd/deploy_patterns/singlestack/buildspec.yml @@ -24,7 +24,8 @@ phases: # Copy in the stack and params templates - mkdir deploy - - cp cicd/deploy_patterns/singlestack/stack.yml ./deploy/singlestack.yml + - cp cicd/deploy_patterns/singlestack/namedfunction.yml ./deploy/namedfunction.yml + - cp cicd/deploy_patterns/singlestack/unnamedfunction.yml ./deploy/unnamedfunction.yml # Update params with the values for this run for a developer account - | @@ -45,7 +46,7 @@ phases: - export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s" $(aws sts assume-role --role-arn "${StagingRole}" --role-session-name "CodePipelineRole" --query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" --output text)) # upload the zipfile to the S3 Bucket - - aws s3 cp ./singlestack.zip s3://${TARGETS3BUCKET}/ + - aws s3 cp ./singlestack.zip s3://${TARGETS3BUCKET}/ # Start the test pipeline in the staging account - export ExecutionId=$(aws codepipeline start-pipeline-execution --name $pipeline --output text) diff --git a/cicd/deploy_patterns/singlestack/stack.yml b/cicd/deploy_patterns/singlestack/namedfunction.yaml similarity index 100% rename from cicd/deploy_patterns/singlestack/stack.yml rename to cicd/deploy_patterns/singlestack/namedfunction.yaml diff --git a/cicd/deploy_patterns/singlestack/unnamedfunction.yaml b/cicd/deploy_patterns/singlestack/unnamedfunction.yaml new file mode 100644 index 0000000..57f2205 --- /dev/null +++ b/cicd/deploy_patterns/singlestack/unnamedfunction.yaml @@ -0,0 +1,88 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: 'AWS::Serverless-2016-10-31' + +Description: + This CloudFormation template will deploy an instance of the SSOSync-Staging + candidate releases (via privately shared app in the AWS Serverless Application + Repository (SAR) within the Staging Account. + +Parameters: + AppArn: + Description: The candidate release in the SAR + Default: 'arn:aws:serverlessrepo:::applications/' + Type: String + AppVersion: + Description: The version of this build in SAR + Default: 'v1.0.0-rc.10' + Type: String + GoogleAdminEmailArn: + Type: String + GoogleCredentialsArn: + Type: String + SCIMEndpointUrlArn: + Type: String + SCIMAccessTokenArn: + Type: String + RegionArn: + Type: String + IdentityStoreIdArn: + Type: String + GroupMatch: + Description: The search string to match Groups in Google Workspace + Default: 'name:AWS*' + Type: String + +Resources: + SARApp: + Type: AWS::Serverless::Application + Properties: + Location: + ApplicationId: !Ref AppArn + SemanticVersion: !Ref AppVersion + Parameters: + GoogleAdminEmail: !Join + - '' + - - '{{resolve:secretsmanager:' + - !Ref GoogleAdminEmailArn + - '}}' + GoogleCredentials: !Join + - '' + - - '{{resolve:secretsmanager:' + - !Ref GoogleCredentialsArn + - '}}' + SCIMEndpointUrl: !Join + - '' + - - '{{resolve:secretsmanager:' + - !Ref SCIMEndpointUrlArn + - '}}' + SCIMEndpointAccessToken: !Join + - '' + - - '{{resolve:secretsmanager:' + - !Ref SCIMAccessTokenArn + - '}}' + Region: !Join + - '' + - - '{{resolve:secretsmanager:' + - !Ref RegionArn + - '}}' + IdentityStoreID: !Join + - '' + - - '{{resolve:secretsmanager:' + - !Ref IdentityStoreIdArn + - '}}' + SyncMethod: groups + GoogleGroupMatch: !Ref GroupMatch + LogLevel: warn + LogFormat: json + +Outputs: + FunctionArn: + Condition: OutputFunction + Description: "The Arn of the deployed lambda function" + Value: + Fn::GetAtt: + - SARApp + - Outputs.FunctionArn + Export: + Name: FunctionARN +