AWS Lambda Cross account Keys & Roles use for S3 transfer

Oct 01 2020

Eu tenho um caso de uso para usar o AWS Lambda para copiar arquivos / objetos de um intervalo S3 para outro. Nesse caso de uso, o depósito Source S3 está em uma conta AWS separada (digamos, Conta 1), em que o provedor nos forneceu apenas AccessKey e SecretAccess Key. Nosso Lambda é executado na Conta 2 e o intervalo de destino pode estar na Conta 2 ou em alguma outra conta 3, que pode ser acessada usando a função IAM. A configuração é assim devido a vários parceiros compartilhando arquivos de dados

Normalmente, eu costumava usar o seguinte comando boto3 para copiar o conteúdo entre dois baldes quando tudo está na mesma conta, mas quero saber como isso pode ser modificado para o novo caso de uso

copy_source_object = {'Bucket': source_bucket_name, 'Key': source_file_key}
s3_client.copy_object(CopySource=copy_source_object, Bucket=destination_bucket_name, Key=destination_file_key)

Como o código acima pode ser modificado para se adequar ao meu caso de uso de conexão baseada em chave de acesso para o intervalo de origem e funções para o intervalo de destino (que também pode ser função entre contas)? Por favor, deixe-me saber se algum esclarecimento for necessário

Respostas

JohnRotenstein Oct 01 2020 at 18:00

Sua situação parece ser:

Conta-1:

  • Bucket do Amazon S3 contendo arquivos que você deseja copiar
  • Você tem uma chave de acesso + chave secreta da conta-1 que pode ler esses objetos

Conta-2:

  • Função do AWS Lambda que possui uma função IAM que pode gravar em um intervalo de destino

Ao usar o CopyObject()comando, as credenciais usadas devem ter permissão de leitura no intervalo de origem e permissão de gravação no intervalo de destino . Normalmente, existem duas maneiras de fazer isso:

  1. Use as credenciais da Conta-1 para 'enviar' o arquivo para a Conta-2. Isso requer uma política de intervalo no intervalo de destino que permite PutObjectas credenciais da conta-1. Além disso, você deve definir o ACL= bucket-owner-full-controlcontrole de transferência para a Conta-2. (Isso parece semelhante à sua situação.) OU
  2. Use as credenciais da Conta-2 para 'puxar' o arquivo da Conta-1. Isso requer uma política de intervalo no intervalo de origem que permite GetObjectas credenciais da conta-2.

Se você não pode solicitar uma mudança na política de intervalo no intervalo de origem que permite que a conta-2 leia o conteúdo, ** você precisará de uma política de intervalo no intervalo de destino que permite acesso de gravação pelas credenciais da conta -1`.

Isso se torna mais complexo pelo fato de que você está potencialmente copiando o objeto para um intervalo em "alguma outra conta". Não há uma resposta fácil se você está começando a usar 3 contas no processo.

Resumindo: se possível, peça a eles uma mudança na política de intervalo do intervalo de origem para que sua função Lambda possa ler os arquivos sem precisar alterar as credenciais. Ele pode então copiar objetos para qualquer intervalo que a função IAM da função possa acessar.

1 Exelian Oct 01 2020 at 01:25

Existem várias opções aqui. O mais fácil é fornecer credenciais para boto3 ( documentos ). Eu sugeriria recuperar as chaves do armazenamento de parâmetros SSM ou do gerenciador de segredos para que não sejam armazenadas em código fixo.


Edit: Eu percebo o problema agora, você não pode usar o mesmo sessionpara os dois baldes, faz sentido. A coisa exata que você deseja não é possível (ou seja, usar copy_object). O truque é usar 2 sessões separadas para não misturar as credenciais. Você precisaria get_objectpartir da primeira conta e put_objectdos segundos objetos. Você deve ser capaz de simplesmente colocar o resp['Body']from the get na solicitação put, mas não testei isso.


import boto3
acc1_session = boto3.session.Session(
    aws_access_key_id=ACCESS_KEY_acc1,
    aws_secret_access_key=SECRET_KEY_acc1
)
acc2_session = boto3.session.Session(
    aws_access_key_id=ACCESS_KEY_acc2,
    aws_secret_access_key=SECRET_KEY_acc2
)
acc1_client = acc1_session.client('s3')
acc2_client = acc2_session.client('s3')

copy_source_object = {'Bucket': source_bucket_name, 'Key': source_file_key}
resp = acc1_client.get_object(Bucket=source_bucket_name, Key=source_file_key)
acc2_client.put_object(Bucket=destination_bucket_name, Key=destination_file_key, Body=resp['Body'])