Lambda中获取有效密钥用于S3转Redshift的问题
问题:Lambda中获取的凭证用于Redshift S3 COPY时报InvalidAccessKeyId错误
问题详情
在Lambda函数中运行Python脚本获取AWS凭证,用于将S3数据复制到Redshift时出现以下错误:
"errorMessage": "S3ServiceException:The AWS Access Key Id you provided does not exist in our records.,Status 403,Error InvalidAccessKeyId"
- 该Lambda角色在其他操作(如直接操作S3、Redshift)中可正常使用;
- 在EC2实例中配置特定用户凭证并通过
boto3.setup_default_session(profile_name='myUserName')指定会话后,脚本可正常运行。
用户提供的脚本:
import boto3 import psycopg2 as sql def lambda_handler(event, context): # retrieve aws credentials client_iamCredentials = boto3.Session() credentials = client_iamCredentials.get_credentials() credentials = credentials.get_frozen_credentials() access_key = credentials.access_key secret_key = credentials.secret_key # psycopg2 connection conn = sql.connect('connection details') cur = conn.cursor() # copy data from s3 to temp_table s3_copy = f"""COPY table_name FROM 's3://bucketname/file.csv' CREDENTIALS 'aws_access_key_id={access_key};aws_secret_access_key={secret_key}' csv DELIMITER AS ',' FILLRECORD emptyasnull blanksasnull IGNOREHEADER 1 NULL 'NaN' ACCEPTINVCHARS;""" cur.execute(s3_copy) conn.commit() cur.close() conn.close()
解决方案
原因分析
Lambda函数获取的是临时安全凭证,这类凭证除了access_key和secret_key外,还包含必填的session_token字段。之前的脚本只传递了前两个字段,导致Redshift无法完成身份验证,从而抛出InvalidAccessKeyId错误。
方案1:传递完整的临时凭证到COPY语句
修改脚本,在COPY语句中加入session_token字段,完整传递Lambda的临时凭证:
import boto3 import psycopg2 as sql def lambda_handler(event, context): # 获取包含session token的完整临时凭证 session = boto3.Session() credentials = session.get_credentials().get_frozen_credentials() access_key = credentials.access_key secret_key = credentials.secret_key session_token = credentials.token # 新增获取会话token # 数据库连接(替换为你的实际连接信息) conn = sql.connect('connection details') cur = conn.cursor() # 更新COPY语句,加入session token s3_copy = f"""COPY table_name FROM 's3://bucketname/file.csv' CREDENTIALS 'aws_access_key_id={access_key};aws_secret_access_key={secret_key};token={session_token}' csv DELIMITER AS ',' FILLRECORD emptyasnull blanksasnull IGNOREHEADER 1 NULL 'NaN' ACCEPTINVCHARS;""" cur.execute(s3_copy) conn.commit() cur.close() conn.close()
方案2:使用IAM角色授权(推荐,更安全)
无需传递任何凭证,通过创建IAM角色让Redshift直接获得S3访问权限,符合AWS安全最佳实践:
创建IAM角色:
- 信任实体选择
Redshift服务; - 添加权限策略,允许访问目标S3桶(例如
s3:GetObject、s3:ListBucket权限)。
- 信任实体选择
关联角色到Redshift:
- 将该IAM角色关联到你的Redshift集群,或者在COPY语句中直接指定角色ARN。
修改COPY语句:
替换原有的CREDENTIALS字段为IAM角色ARN:
import boto3 import psycopg2 as sql def lambda_handler(event, context): # 数据库连接(替换为你的实际连接信息) conn = sql.connect('connection details') cur = conn.cursor() # 使用IAM角色的COPY语句 s3_copy = f"""COPY table_name FROM 's3://bucketname/file.csv' IAM_ROLE 'arn:aws:iam::123456789012:role/RedshiftS3AccessRole' csv DELIMITER AS ',' FILLRECORD emptyasnull blanksasnull IGNOREHEADER 1 NULL 'NaN' ACCEPTINVCHARS;""" cur.execute(s3_copy) conn.commit() cur.close() conn.close()
这种方式下,Lambda仅需要拥有连接Redshift并执行COPY语句的权限,无需处理任何AWS凭证,彻底避免凭证泄露风险。
内容的提问来源于stack exchange,提问作者Elijah Martin
相关产品推荐
相关产品推荐

