【问题标题】:How to use java to access dynamodb without access credential on an ec2 instance with IAM role如何在具有 IAM 角色的 ec2 实例上使用 java 访问 dynamodb 而无需访问凭证
【发布时间】:2017-05-21 19:33:32
【问题描述】:

我想使用 Java 访问 Ec2 实例上的 Dynamodb。 此 Ec2 实例已被授予 IAM 角色,我可以使用该角色直接访问 Dynamodb,方法是使用 aws CLI:aws dynamodb list-table。 现在我尝试通过 Java 访问 Dynamodb。 Java 代码应该能够承担角色,但它不起作用。

public static void main(String[] args) throws Exception {

    String ROLE_ARN = "arn:aws:iam::....";

    AWSSecurityTokenServiceClient stsClient = new AWSSecurityTokenServiceClient();

    AssumeRoleRequest assumeRequest = new AssumeRoleRequest()
        .withRoleArn(ROLE_ARN)
        .withDurationSeconds(3600)
        .withRoleSessionName("demo");

    AssumeRoleResult assumeResult = stsClient.assumeRole(assumeRequest);

    BasicSessionCredentials temporaryCredentials = new BasicSessionCredentials(
                assumeResult.getCredentials().getAccessKeyId(),
                assumeResult.getCredentials().getSecretAccessKey(),
                assumeResult.getCredentials().getSessionToken());

    AmazonDynamoDBClient client = new AmazonDynamoDBClient(temporaryCredentials)

    DynamoDB dynamoDB = new DynamoDB(client);

    TableCollection<ListTablesResult> tables = dynamoDB.listTables();
    Iterator<Table> iterator_t = tables.iterator();
    System.out.println("Listing table names");
    while (iterator_t.hasNext()) {
        Table table = iterator_t.next();
        System.out.println(table.getTableName());
    }
}

当我在 ec2 实例上运行代码时,我得到了

Exception in thread "main" com.amazonaws.services.securitytoken.model.AWSSecurityTokenServiceException: Not authorized to perform sts:AssumeRole (Service: AWSSecurityTokenService; Status Code: 403; Error Code: AccessDenied; Request ID: 60313562-d462-11e6-a116-5bf8bb6a59ce)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1586)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1254)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1035)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:747)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:721)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:704)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:672)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:654)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:518)
    at com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient.doInvoke(AWSSecurityTokenServiceClient.java:1188)
    at com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient.invoke(AWSSecurityTokenServiceClient.java:1164)
    at com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient.assumeRole(AWSSecurityTokenServiceClient.java:419)
    at com.spokeo.dynamo_elas.AccessAwsD.main(AccessAwsD.java:stsClient.assumeRole(assumeRequest))

有人知道如何解决这个问题吗? 谢谢。

【问题讨论】:

    标签: java amazon-dynamodb amazon-iam role


    【解决方案1】:

    摸索了半天,终于想出了如下解决方案。

        AWSCredentialsProvider provider = new InstanceProfileCredentialsProvider();
    
        AWSCredentials credential = provider.getCredentials();
    
        AmazonDynamoDBClient client = new AmazonDynamoDBClient(credential);
    
        client.setRegion(Region.getRegion(Regions.US_WEST_2));
    
        DynamoDB dynamoDB = new DynamoDB(client);
    
        TableCollection<ListTablesResult> tables = dynamoDB.listTables();
    

    pom.xml 中的依赖项也需要正确配置以避免冲突,例如, com.amazonaws aws-java-sdk 1.11.72

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.2</version>
        </dependency>
    
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.8.5</version>
        </dependency>
    
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-cbor -->
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-cbor</artifactId>
            <version>2.8.5</version>
        </dependency>
    

    【讨论】:

    • 对于 2019+ 年阅读此答案的人:构造函数 new InstanceProfileCredentialsProvider()deprecated,您应该改用 InstanceProfileCredentialsProvider.getInstance()
    【解决方案2】:

    完成此操作后,我无需专门针对该角色执行任何操作 - 实际上,我不知道我使用的是什么角色。我使用类似的东西:

    AWSCredentialsProviderChain credentialsProvider;
    try {
        credentialsProvider = new DefaultAWSCredentialsProviderChain();
    }
    catch (Exception e) {
        throw new RuntimeException("Error loading credentials", e);
    }
    
    AmazonDynamoDBClient client = new AmazonDynamoDBClient(credentialsProvider);
    

    使用默认提供程序的好处是,如果我在本地使用 ~/.aws/credentials 进行开发,则会使用它。如果我使用 IAM 凭证在 EC2 上,则使用它。

    【讨论】:

    • 感谢您的发帖,stdunbar。
    猜你喜欢
    • 2019-09-13
    • 2018-02-07
    • 2019-08-15
    • 2017-05-27
    • 2015-02-14
    • 2012-08-20
    • 2018-01-07
    • 1970-01-01
    • 2016-04-07
    相关资源
    最近更新 更多