如何在具有 IAM 角色的 ec2 实例上使用 java 在没有访问凭证的情况下访问 dynamodb

How to use java to access dynamodb without access credential on an ec2 instance with IAM role

我想使用 Java 访问 Ec2 实例上的 Dynamodb。 这个 Ec2 实例已经被 g运行 赋予了一个 IAM 角色,我可以通过它使用 aws CLI 直接访问 Dynamodb: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.access0(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))

有人知道怎么解决这个问题吗? 谢谢

完成此操作后,我就再也不必专门针对该角色做任何事情了——事实上,我不知道我在使用什么角色。我使用类似的东西:

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 上,则会使用它。

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

    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>