You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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安全最佳实践:

  1. 创建IAM角色:

    • 信任实体选择Redshift服务;
    • 添加权限策略,允许访问目标S3桶(例如s3:GetObject、s3:ListBucket权限)。
  2. 关联角色到Redshift:

    • 将该IAM角色关联到你的Redshift集群,或者在COPY语句中直接指定角色ARN。
  3. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 20:15:38