Cross-conta da AWS CodePipeline não pode acessar CloudFormation implantar artefatos

votos
0

Eu tenho um gasoduto em várias contas em execução em um CI conta a implantação de recursos via CloudFormation em outro DEV conta . Depois de implantar I salvar as saídas de artefato como um arquivo JSON e quer acessá-lo em outra ação gasoduto através CodeBuild. CodeBuild falha na DOWNLOAD_SOURCE fase com a seguinte messsage:

CLIENT_ERROR: AccessDenied: Acesso código de status negado: 403, pedido id: 123456789, id host: xxxxx / aaaa / zzzz / xxxx = por fonte primária e versão de código arn: AWS: s3 ::: meu balde / my-gasoduto / DeployArti / XcUNqOP

O problema é provável que o CloudFormation, quando executado em uma conta diferente, criptografar os artefatos com uma chave diferente do que o próprio pipeline.

É possível dar a CloudFormation uma chave KMS explícitas para criptografar os artefatos com, ou qualquer outra forma como acessar esses artefatos de volta na calha?

Tudo funciona quando executado a partir de uma única conta.

Aqui está o meu trecho de código (implantado na conta CI):

  MyCodeBuild:
    Type: AWS::CodeBuild::Project
    Properties:
      Artifacts:
        Type: CODEPIPELINE
      Environment: ...
      Name: !Sub my-codebuild
      ServiceRole: !Ref CodeBuildRole
      EncryptionKey: !GetAtt KMSKey.Arn
      Source:
        Type: CODEPIPELINE
        BuildSpec: ...

  CrossAccountCodePipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      Name: my-pipeline
      RoleArn: !GetAtt CodePipelineRole.Arn
      Stages:
      - Name: Source
        ...
      - Name: StagingDev
        Actions:
        - Name: create-stack-in-DEV-account
          InputArtifacts:
          - Name: SourceArtifact
          OutputArtifacts:
          - Name: DeployArtifact
          ActionTypeId:
            Category: Deploy
            Owner: AWS
            Version: 1
            Provider: CloudFormation
          Configuration:
            StackName: my-dev-stack
            ChangeSetName: !Sub my-changeset
            ActionMode: CREATE_UPDATE
            Capabilities: CAPABILITY_NAMED_IAM
            # this is the artifact I want to access from the next action 
            # within this CI account pipeline
            OutputFileName: my-DEV-output.json   
            TemplatePath: !Sub SourceArtifact::stack/my-stack.yml
            RoleArn: !Sub arn:aws:iam::${DevAccountId}:role/dev-cloudformation-role
          RoleArn: !Sub arn:aws:iam::${DevAccountId}:role/dev-cross-account-role
          RunOrder: 1
        - Name: process-DEV-outputs
          InputArtifacts:
          - Name: DeployArtifact
          ActionTypeId:
            Category: Build
            Owner: AWS
            Version: 1
            Provider: CodeBuild
          Configuration:
            ProjectName: !Ref MyCodeBuild
          RunOrder: 2
      ArtifactStore:
        Type: S3
        Location: !Ref S3ArtifactBucket
        EncryptionKey:
          Id: !GetAtt KMSKey.Arn
          Type: KMS
Publicado 19/12/2018 em 14:21
fonte usuário
Em outras línguas...                            


3 respostas

votos
2

CloudFormation gera artefato de saída, fecha-lo e, em seguida, carrega o arquivo no S3. Não adicionar ACL, que concede acesso ao proprietário balde. Então, você começa a 403 quando você tenta usar a saída CloudFormation artefato ainda mais para baixo o pipeline.

solução é ter mais uma ação em seu pipeline imediatamente após a ação CloudFormation para ex: A função Lambda que podem assumir o papel de conta de destino e atualizar o objeto acl ex: bucket-owner-full-controle.

Respondeu 20/12/2018 em 00:34
fonte usuário

votos
0

A resposta de mockora está correto. Aqui está um exemplo de função Lambda em Python que corrige o problema, que pode ser configurada como uma ação Invoke imediatamente após sua implantação conta CloudFormation cruz.

Neste exemplo, você configurar a ação de invocação de configuração Lambda parâmetros do usuário como o ARN do papel que você quer a função Lambda para assumir em conta remota para fixar o objeto ACL S3. Obviamente sua função Lambda terá sts:AssumeRolepermissões para esse papel, eo papel conta remota terá s3:PutObjectAclpermissões sobre o artefato (s) balde pipeline.

import os
import logging, datetime, json
import boto3
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch_all

# X-Ray
patch_all()

# Configure logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(os.environ.get('LOG_LEVEL','INFO'))
def format_json(data):
  return json.dumps(data, default=lambda d: d.isoformat() if isinstance(d, datetime.datetime) else str(d))

# Boto3 Client
client = boto3.client
codepipeline = client('codepipeline')
sts = client('sts')

# S3 Object ACLs Handler
def s3_acl_handler(event, context):
  log.info(f'Received event: {format_json(event)}')
  # Get Job
  jobId = event['CodePipeline.job']['id']
  jobData = event['CodePipeline.job']['data']
  # Ensure we return a success or failure result
  try:
    # Assume IAM role from user parameters
    credentials = sts.assume_role(
      RoleArn=jobData['actionConfiguration']['configuration']['UserParameters'],
      RoleSessionName='codepipeline',
      DurationSeconds=900
    )['Credentials']
    # Create S3 client from assumed role credentials
    s3 = client('s3',
      aws_access_key_id=credentials['AccessKeyId'],
      aws_secret_access_key=credentials['SecretAccessKey'],
      aws_session_token=credentials['SessionToken']
    )
    # Set S3 object ACL for each input artifact
    for inputArtifact in jobData['inputArtifacts']:
      s3.put_object_acl(
        ACL='bucket-owner-full-control',
        Bucket=inputArtifact['location']['s3Location']['bucketName'],
        Key=inputArtifact['location']['s3Location']['objectKey']
      )
    codepipeline.put_job_success_result(jobId=jobId)
  except Exception as e:
    logging.exception('An exception occurred')
    codepipeline.put_job_failure_result(
      jobId=jobId,
      failureDetails={'type': 'JobFailed','message': getattr(e, 'message', repr(e))}
    )
Respondeu 17/06/2019 em 11:31
fonte usuário

votos
-1

CloudFormation deve usar a chave de criptografia KMS fornecido na definição loja artefato do seu pipeline: https://docs.aws.amazon.com/codepipeline/latest/APIReference/API_ArtifactStore.html#CodePipeline-Type-ArtifactStore-encryptionKey

Portanto, desde que você dê a ele uma chave personalizada lá e permitir que a outra conta para usar essa chave também deve funcionar.

Este é principalmente coberta neste doc: https://docs.aws.amazon.com/codepipeline/latest/userguide/pipelines-create-cross-account.html

Respondeu 15/01/2019 em 00:24
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more