如何为 EMR 实例中的 spark-redshift 正确提供凭据?

How to properly provide credentials for spark-redshift in EMR instances?

我们尝试使用 spark-redshift 项目,遵循提供凭据的第三条建议。即:

IAM instance profiles: If you are running on EC2 and authenticate to S3 using IAM and instance profiles, then you must must configure the temporary_aws_access_key_id, temporary_aws_secret_access_key, and temporary_aws_session_token configuration properties to point to temporary keys created via the AWS Security Token Service. These temporary keys will then be passed to Redshift via LOAD and UNLOAD commands.

我们的 Spark 应用程序 运行 来自 EMR 集群。为此,我们尝试从该节点调用 getSessionToken 的内部实例中获取临时凭证,如下所示:

val stsClient = new AWSSecurityTokenServiceClient(new InstanceProfileCredentialsProvider())        
val getSessionTokenRequest = new GetSessionTokenRequest()
val sessionTokenResult =  stsClient.getSessionToken(getSessionTokenRequest);
val sessionCredentials = sessionTokenResult.getCredentials()

但这会抛出 403 Access Denied,即使具有 sts:getSessionToken 的策略应用于 EMR 实例的角色。

然后我们尝试了以下两种方案。首先,使用 AssumeRole 策略:

val p = new STSAssumeRoleSessionCredentialsProvider("arn:aws:iam::123456798123:role/My_EMR_Role", "session_name")
val credentials: AWSSessionCredentials = p.getCredentials
val token = credentials.getSessionToken

其次,从 InstanceProfileCredentialsProvider:

转换结果
val provider = new InstanceProfileCredentialsProvider()
val credentials: AWSSessionCredentials = provider.getCredentials.asInstanceOf[AWSSessionCredentials]
val token = credentials.getSessionToken

它们都有效,但预期的实现方式是哪种?强制转换结果或添加 AssumeRole 政策有什么严重错误吗?

谢谢!

GetSessionToken API 旨在由 IAM 用户调用,如他们的文档中所述:

Returns a set of temporary credentials for an AWS account or IAM user.

在您的第一个示例中,您正在使用您的 EMR 实例角色调用 API,这是一个 IAM 角色(解释了一些差异 here)。在这种特定情况下,EMR 实例角色凭证是 EMR 代表您的实例获取的会话凭证。

你的错误的具体措辞是什么?如果是Cannot call GetSessionToken with session credentials,那就证实了以上所有内容。

当您将实例角色转换为会话令牌时,它会起作用,因为如上所述,事实证明,假定角色的凭据 会话凭据,因此它会起作用.

显式调用 AssumeRole 没有错。这正是 EMR 服务在幕后所做的。将您的结果转换为会话凭据也没有错,因为它们几乎可以保证是您用例的会话凭据。