Me gustaría escribir un archivo en S3 desde mi función lambda escrita en Python. Pero estoy luchando para pasar mi ID y clave S3.
Lo siguiente funciona en mi máquina local después de configurar mis variables de entorno local de Python AWS_SHARED_CREDENTIALS_FILE y AWS_CONFIG_FILE para señalar los archivos locales que creé con AWS CLI.
session = boto3.session.Session(region_name='us-east-2') s3 = session.client('s3', config=boto3.session.Config(signature_version='s3v4'))Y lo siguiente funciona en Lambda donde codifico a mano mi ID y clave (usando *** aquí):
AWS_ACCESS_KEY_ID = '***' AWS_SECRET_ACCESS_KEY = '***' session = boto3.session.Session(region_name='us-east-2') s3 = session.client('s3', config=boto3.session.Config(signature_version='s3v4'), aws_access_key_id=AWS_ACCESS_KEY_ID, aws_secret_access_key=AWS_SECRET_ACCESS_KEY)Pero entiendo que esto es inseguro después de leer las mejores prácticas de Amazon. Así que intento:
AWS_ACCESS_KEY_ID = os.environ['AWS_ACCESS_KEY_ID'] AWS_SECRET_ACCESS_KEY = os.environ['AWS_SECRET_ACCESS_KEY'] session = boto3.session.Session(region_name='us-east-2') s3 = session.client('s3', config=boto3.session.Config(signature_version='s3v4'), aws_access_key_id=AWS_ACCESS_KEY_ID, aws_secret_access_key=AWS_SECRET_ACCESS_KEY)Pero aparece un error: "El ID de la clave de acceso de AWS que proporcionó no existe en nuestros registros". También traté de definir estas variables en la consola de Lambda, pero luego aparece: "Lambda no pudo configurar sus variables de entorno porque las variables de entorno que proporcionó contienen claves reservadas".
Estoy un poco sorprendido de tener que pasar una identificación o clave, ya que creo que mi cuenta para crear la función Lambda también tiene permiso para escribir en la cuenta S3 (la clave y el código secreto que entrego son de IAM para esta misma cuenta) . Tuve la misma sensación al leer la siguiente publicación: la función AWS Lambda escribe en S3
Nunca necesita usar claves de acceso de AWS cuando está usando un recurso de AWS dentro de otro. Simplemente permita que la función Lambda acceda al depósito S3 y a cualquier acción que desee realizar (p. ej., PutObject). Si se asegura de que la función de Lambda reciba el rol con la política para permitir ese tipo de acceso, el SDK le quitará toda la autenticación.
Si necesita usar claves secretas en Lambda, por ejemplo, de sistemas de terceros o una base de datos de AWS RDS (que no sea Aurora), puede consultar AWS KMS. Esto funciona muy bien junto con Lambda. Pero nuevamente: el uso de S3 en Lambda debe manejarse con la función/política correcta en IAM.
El hecho de que tu cuenta tenga permisos para "escribir" en la cuenta S3 no significa que puedas hacerlo. AWS tiene un servicio llamado IAM que manejará los permisos que tu lambda (entre muchos otros servicios) tiene para realizar acciones contra otros recursos de AWS.
Lo más probable es que le falte la función/política de IAM relevante asociada a su lambda para escribir en el depósito de S3.
Como se indica en el modelo de permisos de AWS Lambda , debe crear y asociar un rol de IAM al crear el lambda. Puede hacerlo desde la consola o usando CloudFormation .
Una vez que tenga los permisos relevantes para su lambda, no necesita lidiar con claves o autenticación.
Por cierto, tenía curiosidad por ver si AWS tardaba menos en autenticarme si pasaba explícitamente ACCESS_KEY y SECRET_ACCESS_KEY al acceder a AWS DynamoDB desde AWS Lambda en lugar de dejar que Lambda encontrara mis credenciales automáticamente a través de variables de entorno. Aquí está la entrada de registro de AWS Cloudwatch, por ejemplo:
[INFO] 2018-12-23T15:34:56.174Z 4c399add-06c8-11e9-8970-3b3cbb83cd9c Credenciales encontradas en variables de entorno.
Hice esto porque cuando cambié de usar AWS RDS con MySQL a DynamoDB, me llevó casi 1000 ms más completar algunas lecturas y actualizaciones de tablas simples. Como referencia, mis llamadas a AWS RDS MySQL pasaron las credenciales explícitamente, por ejemplo:
conn = pymysql.connect(host=db_host, port=db_port, user=db_user, \ passwd=db_pass, db=db_name, connect_timeout=5)entonces, pensé que este podría ser el problema porque cuando me conectaba a DynamoDB estaba usando:
db = boto3.resource('dynamodb') table = db.Table(dynamo_db_table)Decidí probar lo siguiente para ver si mi tiempo de autenticación disminuyó:
session = boto3.Session( aws_access_key_id=AWS_ACCESS_KEY_ID, aws_secret_access_key=AWS_SECRET_ACCESS_KEY ) db = session.resource('dynamodb') table = db.Table(dynamo_db_table)El resultado final fue que proporcionar explícitamente mis claves de acceso terminó ahorrando menos de 100 ms en promedio, así que volví a dejar que el entorno de ejecución de Lambda determinara dinámicamente mi credencial de acceso. Todavía estoy trabajando para entender por qué MySQL es mucho más rápido para mi caso de uso de consulta y actualización de {key:value} de tabla simple.