【问题标题】:Does Spark allow to use Amazon Assumed Role and STS temporary credentials for DynamoDB?Spark 是否允许为 DynamoDB 使用 Amazon Assumed Role 和 STS 临时凭证?
【发布时间】:2017-11-03 02:31:59
【问题描述】:

我需要使用 Java 从 Spark 的 DynamoDB 表中获取数据。它适用于用户的访问密钥和密钥:

final JobConf jobConf = new JobConf(sc.hadoopConfiguration());
jobConf.set("dynamodb.servicename", "dynamodb");
jobConf.set("dynamodb.input.tableName", tableName);
jobConf.set("mapred.output.format.class", "org.apache.hadoop.dynamodb.write.DynamoDBOutputFormat");
jobConf.set("mapred.input.format.class", "org.apache.hadoop.dynamodb.read.DynamoDBInputFormat");
jobConf.set("dynamodb.awsAccessKeyId",  accessKey);
jobConf.set("dynamodb.awsSecretAccessKey", secretKey);
jobConf.set("dynamodb.endpoint", endpoint);

我需要使用 AWS 代入角色和 STS(至少出于安全原因)来完全使用 spark 从 DynamoDB 获取数据。可能吗?我发现可以使用假定角色通过 spark (https://issues.apache.org/jira/browse/HADOOP-12537, https://hadoop.apache.org/docs/current3/hadoop-aws/tools/hadoop-aws/index.html) 访问 AWS S3,但还没有找到 DynamoDB 的类似想法。

为了接收 STS 临时凭证,我使用以下代码:

AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.defaultClient();
AssumeRoleRequest assumeRequest = new AssumeRoleRequest()
        .withRoleArn(roleArn)  // arn:aws:iam::XXXXXXX:role/assume-role-DynamoDB-ReadOnly
        .withDurationSeconds(3600)
        .withRoleSessionName("assumed-role-session");
AssumeRoleResult assumeResult = stsClient.assumeRole(assumeRequest);
Credentials credentials = assumeResult.getCredentials();

调用 credentials.getAccessKeyId(), credentials.getSecretAccessKey() and credentials.getSessionToken() 返回生成的临时凭据。有了这些凭证,我可以成功地使用 java aws sdk AmazonDynamoDBClient(非火花方法)从 DynamoDB 获取数据。

火花可以吗? spark是否允许使用以下内容: jobConf.set("dynamodb.awsSessionToken”, sessionToken)?

【问题讨论】:

  • 你进步了吗?
  • 不,我使用用户的访问密钥和密钥:jobConf.set("dynamodb.awsAccessKeyId", accessKey); jobConf.set("dynamodb.awsSecretAccessKey", secretKey);

标签: java hadoop apache-spark amazon-dynamodb aws-sdk


【解决方案1】:

查看代码,您可以将 dynamodb.customAWSCredentialsProvider 与 com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider 的实例一起使用,以获得您想要的工作。

https://github.com/awslabs/emr-dynamodb-connector/blob/master/emr-dynamodb-hadoop/src/main/java/org/apache/hadoop/dynamodb/DynamoDBConstants.java#L30

https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/STSAssumeRoleSessionCredentialsProvider.html


编辑:所以这比我最初想象的要难一些。我最终实现了自己的 STSAssumeRoleSessionCredentialsProvider 包装器。

package foo.bar;

import com.amazonaws.auth.AWSSessionCredentials;
import com.amazonaws.auth.AWSSessionCredentialsProvider;
import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider;
import org.apache.hadoop.conf.Configurable;
import org.apache.hadoop.conf.Configuration;

public class HadoopSTSAssumeRoleSessionCredentialsProvider
        implements AWSSessionCredentialsProvider, Configurable {

    private static final String ROLE_ARN_CONF = "assumed.creds.role.arn";
    private static final String SESSION_NAME_CONF = "assumed.creds.session.name";

    private Configuration configuration;
    private STSAssumeRoleSessionCredentialsProvider delegate;

    public AWSSessionCredentials getCredentials() {
        return delegate.getCredentials();
    }

    public void refresh() {
        delegate.refresh();
    }

    public void setConf(Configuration configuration) {
        this.configuration = configuration;
        String roleArn = configuration.get(ROLE_ARN_CONF);
        String sessionName = configuration.get(SESSION_NAME_CONF);

        if (roleArn == null || roleArn.isEmpty() || sessionName == null || sessionName.isEmpty()) {
            throw new IllegalStateException("Please set " + ROLE_ARN_CONF + " and "
                    + SESSION_NAME_CONF + " before use.");
        }
        delegate = new STSAssumeRoleSessionCredentialsProvider.Builder(
                roleArn, sessionName).build();
    }

    public Configuration getConf() {
        return configuration;
    }
}

然后你可以像这样使用它:

val ddbConf: JobConf = new JobConf(sc.hadoopConfiguration)

ddbConf.set("dynamodb.customAWSCredentialsProvider",
    "foo.bar.HadoopSTSAssumeRoleSessionCredentialsProvider")
ddbConf.set("assumed.creds.role.arn", "roleArn")
ddbConf.set("assumed.creds.session.name", "sessionName")

【讨论】:

  • 我尝试了上述解决方案,但我得到 java.lang.RuntimeException: Custom AWSCredentialsProvider not found 错误。有人遇到同样的问题吗?
  • 如果找不到类,那么它可能不在您的类路径中,或者包/类名有问题。我最终构建了一个包含我的自定义凭据提供程序的 superjar。需要注意的一件事是,如果 IAM 角色或类似性质的东西存在问题,异常将保持沉默。对于 Spark 中的这类错误,没有一个很好的日志记录机制。
  • 我也收到了 ClassNotFoundException。我正在使用一个 uber jar,并已验证该类存在于所有工人的 jar 中。还有其他人遇到这种情况吗?
  • 因此我们使用 Java 开发工具包创建/调用 AWS Glue 作业。不确定这将如何在本机 Hadoop 上工作:Map<String, String> arguments = new HashMap<>();arguments.put("--extra-jars", "s3://myBucket/some.jar);new StartJobRunRequest().withArguments(arguments)... 你可能想看看stackoverflow.com/questions/37132559/…spark.executor.extraClassPath 可能是你的票。
猜你喜欢
  • 2022-01-27
  • 2017-06-16
  • 1970-01-01
  • 2020-11-28
  • 1970-01-01
  • 2021-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多