我很困惑,我不知道这是怎么回事。
我正在使用 DuckDB 查询 s3 存储桶中的 parquet 文件。
import pandas as pd
import duckdb
query = """
INSTALL httpfs;
LOAD httpfs;
SET s3_region='us-west-2';
SET s3_access_key_id='key';
SET s3_secret_access_key='secret';
SELECT
FROM read_parquet('s3://bucket/folder/file.parquet')
cursor = duckdb.connect()
cursor.execute(query).df()
我有一个具有管理员访问权限的 IAM 用户。我可以使用编程访问键查询此镶木地板文件。我还想在应用程序中使用一个角色,我还授予了管理员访问权限只是为了测试目的。
当我担任该角色并创建临时凭据并将其输入上面的代码时
export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s" \
$(aws sts assume-role \
--role-arn arn:aws:iam::<account-id>:role/<role-name> \
--role-session-name test-session \
--query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" \
--output text))
我收到错误
duckdb.Error:无效错误:无法连接到 URL “s3://bucket/folder/file.parquet”:403(禁止)
但是,当我使用 IAM 用户时,我能够访问这个 s3 对象并查询数据。我是否遗漏了角色和 IAM 用户之间的区别?
如果有帮助,我想做的是为 lambda 函数创建一个角色,然后访问环境变量
AWS_ACCESS_KEY_ID
,以及上面代码中使用 AWS_SECRET_ACCESS_KEY
的 os.getenviron()
。我相信,如果我可以通过写入临时凭证来使该角色正常工作,那么当我在 lambda 函数中使用 os.getenv()
时,它应该可以工作。
我有一个非常类似的问题,在通过
s3_session_token
设置 SET s3_session_token='sessiontoken';
后它起作用了。另外,请注意,S3 不是全局服务,这意味着您需要确保设置正确的s3_region
。
代码将更改为
import pandas as pd
import duckdb
query = """
INSTALL httpfs;
LOAD httpfs;
SET s3_region='us-west-2';
SET s3_access_key_id='key';
SET s3_secret_access_key='secret';
SET s3_session_token='session-token';
SELECT
FROM read_parquet('s3://bucket/folder/file.parquet')
cursor = duckdb.connect()
cursor.execute(query).df()
如果其他答案对您没有帮助,您可能想尝试设置另一个S3_region。
我收到相同的错误消息
Error: Invalid Error: IO Error: Unable to connect to URL "s3://elsa-data-lake/transformed/20230228_041047_00038_yihfd_00629123-f824-4a31-ba70-e341d4028a3b.parquet": 400 (Bad Request)
,但潜在问题不同。我设置了错误的S3区域,认为S3是全球服务。我使用 SET s3_region='us-east-1'
因为这是我们设置 SSO 服务的地方,但我需要指定文件在 S3 上存储的区域。所以如果我使用 SET s3_region='eu-west-1
一切正常!
这是 S3 控制台的屏幕截图,显示我的文件存储在“EU(爱尔兰)eu-west-1”中。
我在尝试在 Sagemaker 实例上使用 DuckDB 并通过基于 IAM 角色的 S3 访问时看到了这篇文章。 DuckDB 文档、互联网搜索和 ChatGPT 没有指定如何使用 IAM 角色从 S3 读取文件。
在尝试了 SET 选项的各种组合并失败后,它使用 Secrets 以及将 Provider 作为 Credential_Chain 并将链设置为实例来工作。这是有效的代码片段 -
import duckdb
# Connect to DuckDB
con = duckdb.connect()
# Install and load HTTPFS extension
con.execute("INSTALL httpfs;")
con.execute("LOAD httpfs;")
con.execute("""CREATE SECRET secret1(
TYPE S3,
PROVIDER CREDENTIAL_CHAIN,
CHAIN 'instance',
REGION 'us-east-1',
ENDPOINT 's3.us-east-1.amazonaws.com'
)
""")
# Try querying the file
result = con.execute("""
SELECT *
FROM read_parquet('s3://some-bucket/some-folder/data.parquet')
LIMIT 10
""").fetchall()
print(result)
希望这可以帮助尝试解决同样问题的人。