简体   繁体   English

使用 Workload Identity 从 aws fargete 到 gcp bigquery 的连接错误

[英]connection error from aws fargete to gcp bigquery by using Workload Identity

I used Workload Identity from AWS EC2 to GCP Bigquery by using assigned role on EC2, and it worked fine.我通过在 EC2 上使用分配的角色,使用从 AWS EC2 到 GCP Bigquery 的 Workload Identity,它运行良好。

However when I use Workload Identity from AWS Fargete to GCP Bigquery by using fargate task role, it does not work.但是,当我通过使用 Fargate 任务角色从 AWS Fargete 到 GCP Bigquery 使用 Workload Identity 时,它不起作用。

How should I set up the Workload Identity on this case?在这种情况下,我应该如何设置工作负载身份?

I used the libraries below.我使用了下面的库。

implementation(platform("com.google.cloud:libraries-bom:20.9.0"))
implementation("com.google.cloud:google-cloud-bigquery")

Stacktrace has messages below Stacktrace 有以下消息

com.google.cloud.bigquery.BigQueryException: Failed to retrieve AWS IAM role.
    at com.google.cloud.bigquery.spi.v2.HttpBigQueryRpc.translate(HttpBigQueryRpc.java:115) ~[google-cloud-bigquery-1.137.1.jar!/:1.137.1]
…
    at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]
Caused by: java.io.IOException: Failed to retrieve AWS IAM role.
    at com.google.auth.oauth2.AwsCredentials.retrieveResource(AwsCredentials.java:217) ~[google-auth-library-oauth2-http-0.26.0.jar!/:na]
…
    at com.google.cloud.bigquery.spi.v2.HttpBigQueryRpc.getDataset(HttpBigQueryRpc.java:126) ~[google-cloud-bigquery-1.137.1.jar!/:1.137.1]
    ... 113 common frames omitted
Caused by: java.net.ConnectException: Invalid argument (connect failed)
    at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:na]
    at com.google.auth.oauth2.AwsCredentials.retrieveResource(AwsCredentials.java:214) ~[google-auth-library-oauth2-http-0.26.0.jar!/:na]
    ... 132 common frames omitted

I had the same issue but for Python code, anyway I think it should be the same.我有同样的问题,但对于 Python 代码,无论如何我认为它应该是相同的。 You're getting this as getting the AWS IAM role at AWS Fargate is different from AWS EC2, where EC2 you can get them from instance metadata, as shown here:您得到这个是因为在 AWS Fargate 中获取 AWS IAM 角色与 AWS EC2 不同,您可以在 EC2 中从实例元数据中获取它们,如下所示:

curl http://169.254.169.254/latest/meta-data/iam/security-credentials/s3access

While in AWS Faragte:在 AWS Faragte 中:

curl 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI

So to get around that, the following need to be done:因此,为了解决这个问题,需要完成以下工作:

  1. Change GCP Workload Identity Federation Credential file content [wif_cred_file] as the following:将 GCP 工作负载身份联合凭据文件内容 [wif_cred_file] 更改为以下内容:
    wif_cred_file["credential_source"]["url"]=f"http://169.254.170.2{AWS_CONTAINER_CREDENTIALS_RELATIVE_URI}"
  1. In the "python3.8/site-packages/google/auth/ aws.py " file in the library [Try to find the similar file in Java], I've updated this code as the following:在库中的“python3.8/site-packages/google/auth/ aws.py ”文件[尝试在Java中查找类似文件]中,我已将此代码更新如下:
  2. Comment this line: # role_name = self._get_metadata_role_name(request)评论这一行: # role_name = self._get_metadata_role_name(request)
  3. Remove role_name from _get_metadata_security_credentials function args.role_name function 参数中删除_get_metadata_security_credentials名称。

Or if you like, you may change step 1 at the aws.py file, both ways should be fine.或者,如果您愿意,可以更改aws.py文件中的第 1 步,两种方式都可以。

And that should be it.应该就是这样。

I faced a similar issue with Google Cloud Storage (GCS).我在使用 Google Cloud Storage (GCS) 时遇到了类似的问题。

As Peter mentioned, retrieving the credentials on an AWS Farage task is not the same as if the code is running on an EC2 instance, therefore Google SDK fails to compose the correct AWS credentials for exchange with Google Workload Identity Federation.正如 Peter 所提到的,检索 AWS Farage 任务的凭证与在 EC2 实例上运行代码不同,因此 Google SDK 无法编写正确的 AWS 凭证以与 Google Workload Identity Federation 进行交换。

I came up with a workaround that saved the trouble of editing core files in "../google/auth/aws.py" by doing 2 things:我想出了一个解决方法,通过做两件事来省去在“../google/auth/aws.py”中编辑核心文件的麻烦:

  1. Get session credentials with boto3使用 boto3 获取 session 凭据
import boto3

task_credentials = boto3.Session().get_credentials().get_frozen_credentials()
  1. Set the relevant environment variables设置相关环境变量
from google.auth.aws import environment_vars

os.environ[environment_vars.AWS_ACCESS_KEY_ID] = task_credentials.access_key
os.environ[environment_vars.AWS_SECRET_ACCESS_KEY] = task_credentials.secret_key
os.environ[environment_vars.AWS_SESSION_TOKEN] = task_credentials.token

Explanation:解释:
I am using Python3.9 with boto3 and google-cloud==2.4.0, however it should work for other versions of google SDK if the following code is in the function "_get_security_credentials" under the class "Credentials" in "google.auth.aws" package: I am using Python3.9 with boto3 and google-cloud==2.4.0, however it should work for other versions of google SDK if the following code is in the function "_get_security_credentials" under the class "Credentials" in "google.auth .aws" package:

        # Check environment variables for permanent credentials first.
        # https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html
        env_aws_access_key_id = os.environ.get(environment_vars.AWS_ACCESS_KEY_ID)
        env_aws_secret_access_key = os.environ.get(
            environment_vars.AWS_SECRET_ACCESS_KEY
        )
        # This is normally not available for permanent credentials.
        env_aws_session_token = os.environ.get(environment_vars.AWS_SESSION_TOKEN)
        if env_aws_access_key_id and env_aws_secret_access_key:
            return {
                "access_key_id": env_aws_access_key_id,
                "secret_access_key": env_aws_secret_access_key,
                "security_token": env_aws_session_token,
            }

Caveat:警告:
When running code inside an ECS task the credentials that are being used are temporary (ECS assumes the task's role), therefore you can't generate temporary credentials via AWS STS as it is usually recommended.在 ECS 任务中运行代码时,正在使用的凭证是临时的(ECS 承担任务的角色),因此您不能像通常建议的那样通过 AWS STS 生成临时凭证。
Why is it a problem?为什么会出现问题? Well since a task is running with temporary credentials it is subjected to expire & refresh.好吧,由于任务是使用临时凭据运行的,因此它会受到过期和刷新的影响。 In order to solve that you can set up a background function that will do the operation again every 5 minutes or so (Haven't faced a problem where the temporary credentials expired).为了解决这个问题,您可以设置一个后台 function 每隔 5 分钟左右再次执行一次操作(没有遇到临时凭证过期的问题)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM