【问题标题】:Transfer data from a S3 bucket to a GCP bucket using temporary credentials使用临时凭证将数据从 S3 存储桶传输到 GCP 存储桶
【发布时间】:2019-12-19 00:21:37
【问题描述】:

我想从NIMH Data Archive 下载一个公共数据集。在他们的网站上创建帐户并接受他们的数据使用协议后,我可以下载一个 CSV 文件,其中包含我感兴趣的数据集中所有文件的路径。每个路径的格式为 s3://NDAR_Central_1/...

1 在我的个人电脑上下载

NDA Github repository 中,nda-tools Python 库公开了一些有用的 Python 代码,可以将这些文件下载到我自己的计算机上。假设我要下载以下文件:

s3://NDAR_Central_1/submission_13364/00m/0.C.2/9007827/20041006/10263603.tar.gz

给定我的用户名 (USRNAME) 和密码 (PASSWD)(我用来在 NIMH 数据存档上创建帐户的那些),下面的代码允许我将此文件下载到我个人的 TARGET_PATH电脑:

from NDATools.clientscripts.downloadcmd import configure
from NDATools.Download import Download

config = configure(username=USRNAME, password=PASSWD)
s3Download = Download(TARGET_PATH, config)

target_fnames = ['s3://NDAR_Central_1/submission_13364/00m/0.C.2/9007827/20041006/10263603.tar.gz']

s3Download.get_links('paths', target_fnames, filters=None)
s3Download.get_tokens()
s3Download.start_workers(False, None, 1)

在后台,s3Downloadget_tokens 方法将使用USRNAMEPASSWD 生成临时访问密钥、密钥和安全令牌。然后,start_workers 方法将使用 boto3 和 s3 传输 Python 库到download 选定的文件。

一切正常!

2 下载到 GCP 存储桶

现在,假设我在 GCP 上创建了一个项目,并想直接将该文件下载到 GCP 存储桶中。

理想情况下,我想做这样的事情:

gsutil cp s3://NDAR_Central_1/submission_13364/00m/0.C.2/9007827/20041006/10263603.tar.gz gs://my-bucket

为此,我在 Cloud Shell 中执行以下 Python 代码(通过运行 python3):

from NDATools.TokenGenerator import NDATokenGenerator
data_api_url = 'https://nda.nih.gov/DataManager/dataManager'
generator = NDATokenGenerator(data_api_url)
token = generator.generate_token(USRNAME, PASSWD)

这给了我访问密钥、秘密密钥和会话令牌。事实上,在下面,

  • ACCESS_KEY指的是token.access_key的值,
  • SECRET_KEY指的是token.secret_key的值,
  • SECURITY_TOKEN 指的是token.session 的值。

然后,我将这些凭据设置为 Cloud Shell 中的环境变量:

export AWS_ACCESS_KEY_ID = [copy-paste ACCESS_KEY here]
export AWS_SECRET_ACCESS_KEY = [copy-paste SECRET_KEY here]
export AWS_SECURITY_TOKEN = [copy-paste SECURITY_TOKEN here]

最后,我还在家里设置了.boto 配置文件。它看起来像这样:

[Credentials]
aws_access_key_id = $AWS_ACCESS_KEY_ID
aws_secret_access_key = $AWS_SECRET_ACCESS_KEY
aws_session_token = $AWS_SECURITY_TOKEN
[s3]
calling_format = boto.s3.connection.OrdinaryCallingFormat
use-sigv4=True
host=s3.us-east-1.amazonaws.com

当我运行以下命令时:

gsutil cp s3://NDAR_Central_1/submission_13364/00m/0.C.2/9007827/20041006/10263603.tar.gz gs://my-bucket

我最终得到:

AccessDeniedException: 403 AccessDenied

完整的追溯如下:

Non-MD5 etag ("a21a0b2eba27a0a32a26a6b30f3cb060-6") present for key <Key: NDAR_Central_1,submission_13364/00m/0.C.2/9007827/20041006/10263603.tar.gz>, data integrity checks are not possible.
Copying s3://NDAR_Central_1/submission_13364/00m/0.C.2/9007827/20041006/10263603.tar.gz [Content-Type=application/x-gzip]...
Exception in thread Thread-2:iB]
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/google/google-cloud-sdk/platform/gsutil/gslib/daisy_chain_wrapper.py", line 213, in PerformDownload
    decryption_tuple=self.decryption_tuple)
  File "/google/google-cloud-sdk/platform/gsutil/gslib/cloud_api_delegator.py", line 353, in GetObjectMedia
    decryption_tuple=decryption_tuple)
  File "/google/google-cloud-sdk/platform/gsutil/gslib/boto_translation.py", line 590, in GetObjectMedia
    generation=generation)
  File "/google/google-cloud-sdk/platform/gsutil/gslib/boto_translation.py", line 1723, in _TranslateExceptionAndRaise
    raise translated_exception  # pylint: disable=raising-bad-type
AccessDeniedException: AccessDeniedException: 403 AccessDenied
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>A93DBEA60B68E04D</RequestId><HostId>Z5XqPBmUdq05btXgZ2Tt7HQMzodgal6XxTD6OLQ2sGjbP20AyZ+fVFjbNfOF5+Bdy6RuXGSOzVs=</HostId></Error>

AccessDeniedException: 403 AccessDenied
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>A93DBEA60B68E04D</RequestId><HostId>Z5XqPBmUdq05btXgZ2Tt7HQMzodgal6XxTD6OLQ2sGjbP20AyZ+fVFjbNfOF5+Bdy6RuXGSOzVs=</HostId></Error>

我希望能够直接将此文件从 S3 存储桶下载到我的 GCP 存储桶(无需创建虚拟机、设置 Python 并运行上面的代码 [可行])。为什么临时生成的凭据在我的计算机上有效,但在 GCP Cloud Shell 中无效?

调试命令的完整日志

gsutil -DD cp s3://NDAR_Central_1/submission_13364/00m/0.C.2/9007827/20041006/10263603.tar.gz gs://my-bucket

可以找到here

【问题讨论】:

  • 您的 .boto 文件凭证不包括 aws_security_token。这是故意的吗?
  • @jarmod 谢谢,我在帖子里忘记了。它已经在我的.boto 文件中。
  • 文档有点混乱,我不使用 .boto 配置文件。是aws_security_token 还是aws_session_token
  • @jarmod 我认为这并不重要,因为凭据是在环境变量中设置的。顺便说一句,我帖子末尾的日志是:DEBUG 1217 15:20:11.074951 provider.py] Using access key found in environment variable. DEBUG 1217 15:20:11.075263 provider.py] Using secret key found in environment variable. DEBUG 1217 15:20:11.075522 provider.py] Using security token found in environment variable. 因此,.boto 文件似乎无法在此处设置 S3 凭据。

标签: python amazon-s3 google-cloud-platform


【解决方案1】:

您尝试实现的过程称为"Transfer Job"

要将文件从 Amazon S3 存储桶传输到 Cloud Storage 存储桶:

A.点击左上角的汉堡菜单

B.转到存储 > 传输

C.点击创建转移

  1. 在选择源下,选择 Amazon S3 存储桶。

  2. 在 Amazon S3 存储桶文本框中,指定源 Amazon S3 存储桶名称。 存储桶名称是显示在 AWS 管理控制台中的名称。

  3. 在相应的文本框中,输入关联的访问密钥 ID 和密钥 使用 Amazon S3 存储桶。

  4. 要指定源中的文件子集,请单击下方的指定文件过滤器 桶字段。您可以根据文件名前缀包含或排除文件 文件年龄。

  5. 在选择目标下,选择一个接收器存储桶或创建一个新存储桶。

    • 要选择现有存储桶,请输入存储桶的名称(不带前缀 gs://),或单击浏览并浏览到它。
    • 要将文件传输到新存储桶,请单击浏览,然后单击新存储桶 图标。
  6. 根据需要启用覆盖/删除选项。

    默认情况下,您的传输作业仅在源版本为 与水槽版本不同。没有其他对象被覆盖或删除。 在传输选项下启用其他覆盖/删除选项。

  7. 在配置传输下,将您的传输作业安排为立即运行(一次)或运行 每天在您指定的当地时间。

  8. 点击创建。

在设置传输作业之前,请确保您已为您的帐户分配了必要的角色以及here 所述的所需权限。

还要考虑到存储传输服务目前可用于某些 Amazon S3 区域,在 设置传输作业的 AMAZON S3 选项卡下进行了描述

传输作业也可以以编程方式完成。更多信息here

如果这有帮助,请告诉我。

编辑

Transfer Service 或 gsutil 命令目前都不支持“临时安全凭证”,即使它们受 AWS 支持。一种解决方法是更改​​ gsutil 命令的源代码。

我还代表您提交了Feature Request,建议您为它加注星标以获取程序的更新。

【讨论】:

  • 感谢您的回答。我应该说我已经尝试过了。当我按照您上面列出的步骤进行操作时,传输作业失败并显示 Failed to obtain the location of the source S3 bucket. Additional details: The AWS Access Key Id you provided does not exist in our records. 似乎是访问密钥(而不是角色/权限)的问题。
  • 搜索该错误时我发现了this article,这可能会有所帮助。我还在亚马逊论坛中找到了这个Topic。最后,看看这些:Post 1Post 2。我从上面了解到,问题与您使用的临时凭据有关。
  • 感谢您提供这些链接。我还认为这个问题一定与我的凭据是临时这一事实有关。尽管如此,正如我的帖子所暗示的,它们在我的个人电脑上工作。因此,我假设有一种方法可以让它们在 GCP 上也能正常工作(无需创建 VM 来运行 Python 代码)。另外,根据我从帖子末尾的日志中了解到的情况,我的凭据(在环境变量中设置)允许我连接到主机 (s3.us-east-1.amazonaws.com),对吗?
  • 我为谷歌云平台支持工作。请检查我的答案上的编辑。希望这有帮助。
猜你喜欢
  • 1970-01-01
  • 2018-11-04
  • 2020-11-09
  • 2018-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-23
相关资源
最近更新 更多