From 52d49a4a0b96468ef16279d47c6a28c5d5b52c68 Mon Sep 17 00:00:00 2001 From: Simon Kok Date: Fri, 23 Sep 2022 11:05:25 +0200 Subject: [PATCH] Fix repository creation permission in pipeline management **Why?** When a CodeCommit repository was supposed to be created, it would fail with the following error message: > An error occurred (AccessDenied) when calling the AssumeRole operation: > User: arn:aws:sts::111111111111:assumed-role/adf-global-base-deploymen-CreateRepositoryLambdaRo-GP8W3IRDCGY2/ADFPipelineCreateRepositoryFunction > is not authorized to perform: sts:AssumeRole on resource: > arn:aws:iam::111111111111:role/adf-automation-role > Traceback (most recent call last): > File "/var/task/create_repository.py", line 48, in lambda_handler > repo = Repo( > File "/opt/python/repo.py", line 36, in __init__ > self.session = sts.assume_cross_account_role( > File "/opt/python/sts.py", line 24, in assume_cross_account_role > sts_response = self.client.assume_role( > File "/var/runtime/botocore/client.py", line 391, in _api_call > return self._make_api_call(operation_name, kwargs) > File "/var/runtime/botocore/client.py", line 719, in _make_api_call > raise error_class(parsed_response, operation_name) **What?** Updated the crate repository role and create/update rule roles to include a role name. Updated the `adf-automation-role` assume role permissions to allow these two roles to assume into it. --- .../adf-bootstrap/deployment/global.yml | 2 ++ .../pipeline_management/create_repository.py | 14 +++++++---- .../deployment/pipeline_management.yml | 8 +++++++ .../adf-bootstrap/global.yml | 2 ++ .../adf-build/shared/python/repo.py | 24 ++++++++++++++----- 5 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/global.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/global.yml index 8e77ad6dd..0212a98a2 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/global.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/global.yml @@ -617,6 +617,8 @@ Resources: Principal: AWS: - !GetAtt PipelineProvisionerCodeBuildRole.Arn + - !GetAtt PipelineManagementApplication.Outputs.CreateRepositoryLambdaRoleArn + - !GetAtt PipelineManagementApplication.Outputs.CreateOrUpdateRuleLambdaRoleArn Action: - sts:AssumeRole Path: / diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/pipeline_management/create_repository.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/pipeline_management/create_repository.py index fcfcfa376..a8015d656 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/pipeline_management/create_repository.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/lambda_codebase/pipeline_management/create_repository.py @@ -23,8 +23,8 @@ def lambda_handler(pipeline, _): """Main Lambda Entry point""" parameter_store = ParameterStore(DEPLOYMENT_ACCOUNT_REGION, boto3) auto_create_repositories = parameter_store.fetch_parameter( - "auto_create_repositories" - ) + "auto_create_repositories" + ) LOGGER.info(auto_create_repositories) if auto_create_repositories == "enabled": code_account_id = ( @@ -46,11 +46,17 @@ def lambda_handler(pipeline, _): and not has_custom_repo ): repo = Repo( - code_account_id, pipeline.get("name"), pipeline.get("description") + code_account_id, + pipeline.get("name"), + pipeline.get("description"), ) repo.create_update() METRICS.put_metric_data( - {"MetricName": "CreateOrUpdate", "Value": 1, "Unit": "Count"} + { + "MetricName": "CreateOrUpdate", + "Value": 1, + "Unit": "Count", + } ) return pipeline diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/pipeline_management.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/pipeline_management.yml index fd127b9b6..5d64e7a90 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/pipeline_management.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/pipeline_management.yml @@ -150,6 +150,7 @@ Resources: Type: "AWS::IAM::Role" Properties: Path: "/adf-automation/" + RoleName: "adf-pipeline-create-update-rule" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: @@ -164,6 +165,7 @@ Resources: Type: "AWS::IAM::Role" Properties: Path: "/adf-automation/" + RoleName: "adf-pipeline-create-repository" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: @@ -1006,3 +1008,9 @@ Resources: Outputs: Bucket: Value: !Ref ADFPipelineBucket + + CreateOrUpdateRuleLambdaRoleArn: + Value: !GetAtt CreateOrUpdateRuleLambdaRole.Arn + + CreateRepositoryLambdaRoleArn: + Value: !GetAtt CreateRepositoryLambdaRole.Arn diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/global.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/global.yml index dbb7596b4..35a48cb75 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/global.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/global.yml @@ -234,6 +234,8 @@ Resources: Principal: AWS: - !Sub arn:${AWS::Partition}:iam::${DeploymentAccountId}:role/adf-pipeline-provisioner-codebuild-role + - !Sub arn:${AWS::Partition}:iam::${DeploymentAccountId}:role/adf-automation/adf-pipeline-create-update-rule + - !Sub arn:${AWS::Partition}:iam::${DeploymentAccountId}:role/adf-automation/adf-pipeline-create-repository Action: - sts:AssumeRole Path: / diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/repo.py b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/repo.py index a7bed7e2d..e7ad2a577 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/repo.py +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/python/repo.py @@ -40,13 +40,19 @@ def __init__(self, account_id, name, description=''): def repo_exists(self): try: - codecommit = self.session.client('codecommit', DEPLOYMENT_ACCOUNT_REGION) + codecommit = self.session.client( + 'codecommit', + DEPLOYMENT_ACCOUNT_REGION, + ) repository = codecommit.get_repository(repositoryName=self.name) if repository['repositoryMetadata']['Arn']: return True - except Exception: # pylint: disable=broad-except - LOGGER.debug('Attempted to find the repo %s but it failed.', self.name) - return False # Return False if the Repo Doesnt Exist + except Exception: # pylint: disable=broad-except + LOGGER.debug( + 'Attempted to find the repo %s but it failed.', + self.name, + ) + return False # Return False if the repository does not exist def define_repo_parameters(self): return [{ @@ -78,8 +84,14 @@ def create_update(self): _repo_exists = self.repo_exists() _stack_exists = cloudformation.get_stack_status() if _repo_exists and not _stack_exists: - # return when the repository exists without a stack (previously made) + # No need to create or update the CloudFormation stack to + # deploy the repository if the repo exists already and it was not + # created with the ADF CodeCommit Repository stack. return - LOGGER.info(f"Ensuring State for CodeCommit Repository Stack {self.name} on Account {self.account_id}") + LOGGER.info( + "Ensuring State for CodeCommit Repository Stack %s on Account %s", + self.name, + self.account_id, + ) cloudformation.create_stack()