Add AWS credentials profile name parameter

Some Gerrit setups shares the AWS dynamodb tables between AWS Regions,
for example multi-site setup in multiple regions. For security
reason access to the other regions should be limited to necessary
services. Add configuration param which allows to specify AWS
credentials profile to be used only by the aws-dynamodb-refdb
plugin when connecting to the dynamoDb. This profile allows us to
setup credentials or IAM Role with access to the dynamoDb setup on
the other region.

Bug: Issue 16877
Change-Id: Ifc60162f747bc3fdf810f23e67ef8c6a04d957c7
diff --git a/src/main/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/AmazonDynamoDBProvider.java b/src/main/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/AmazonDynamoDBProvider.java
index 76ec8c0..eb13649 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/AmazonDynamoDBProvider.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/AmazonDynamoDBProvider.java
@@ -14,7 +14,9 @@
 
 package com.googlesource.gerrit.plugins.validation.dfsrefdb.dynamodb;
 
+import com.amazonaws.auth.AWSCredentialsProvider;
 import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
+import com.amazonaws.auth.profile.ProfileCredentialsProvider;
 import com.amazonaws.client.builder.AwsClientBuilder;
 import com.amazonaws.regions.DefaultAwsRegionProviderChain;
 import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
@@ -48,6 +50,13 @@
             endpoint ->
                 builder.withEndpointConfiguration(
                     new AwsClientBuilder.EndpointConfiguration(endpoint.toASCIIString(), region)));
-    return builder.withCredentials(new DefaultAWSCredentialsProviderChain()).build();
+    return builder.withCredentials(getCredentialsProvider()).build();
+  }
+
+  private AWSCredentialsProvider getCredentialsProvider() {
+    return configuration
+        .getAwsConfigurationProfileName()
+        .<AWSCredentialsProvider>map(ProfileCredentialsProvider::new)
+        .orElse(new DefaultAWSCredentialsProviderChain());
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/Configuration.java b/src/main/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/Configuration.java
index 791e1c7..01e2f4f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/Configuration.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/Configuration.java
@@ -34,6 +34,7 @@
   private final Optional<URI> endpoint;
   private final String refsDbTableName;
   private final String locksTableName;
+  private final Optional<String> awsConfigurationProfileName;
 
   @Inject
   Configuration(PluginConfigFactory configFactory, @PluginName String pluginName) {
@@ -44,12 +45,14 @@
     // TODO: add prefix
     this.refsDbTableName = pluginConfig.getString("refsDbTableName", DEFAULT_REFS_DB_TABLE_NAME);
     this.locksTableName = pluginConfig.getString("locksTableName", DEFAULT_LOCKS_TABLE_NAME);
+    this.awsConfigurationProfileName = Optional.ofNullable(pluginConfig.getString("profileName"));
     logger.atInfo().log(
-        "dynamodb-refdb configuration: refsDbTableName: %s|locksTableName:%s%s%s",
+        "dynamodb-refdb configuration: refsDbTableName: %s|locksTableName:%s%s%s%s",
         refsDbTableName,
         locksTableName,
         region.map(r -> String.format("|region: %s", r.id())).orElse(""),
-        endpoint.map(e -> String.format("|endpoint: %s", e.toASCIIString())).orElse(""));
+        endpoint.map(e -> String.format("|endpoint: %s", e.toASCIIString())).orElse(""),
+        awsConfigurationProfileName.map(p -> String.format("|profile: %s", p)).orElse(""));
   }
 
   Optional<Region> getRegion() {
@@ -73,4 +76,8 @@
   String getLocksTableName() {
     return locksTableName;
   }
+
+  Optional<String> getAwsConfigurationProfileName() {
+    return awsConfigurationProfileName;
+  }
 }
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index ca94b64..0d871cc 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -10,6 +10,7 @@
     endpoint = http://localhost:4566
     locksTableName = lockTable
     refsDbTableName = refsDb
+    profileName = aws-dynamodb-refdb
 ```
 
 `plugin.aws-dynamodb-refdb.region`
@@ -33,4 +34,11 @@
 :   Optional. The name of the dynamoDB table used to store git refs and their
 associated sha1.
 
+`plugin.aws-dynamodb-refdb.profileName`
+:   Optional. The name of the aws configuration and credentials profile used to
+connect to the DynamoDb. See [Configuration and credential file settings](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html)
+Default: When not specified credentials are provided via the Default Credentials
+Provider Chain, as explained [here](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html)
+
+
 
diff --git a/src/test/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/ConfigurationTest.java b/src/test/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/ConfigurationTest.java
index 5195c01..6b961d7 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/ConfigurationTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/validation/dfsrefdb/dynamodb/ConfigurationTest.java
@@ -101,6 +101,26 @@
   }
 
   @Test
+  public void shouldReadEmptyAwsConfigurationProfileNameByDefault() {
+    when(pluginConfigFactoryMock.getFromGerritConfig(PLUGIN_NAME))
+        .thenReturn(pluginConfig.asPluginConfig());
+
+    Configuration configuration = new Configuration(pluginConfigFactoryMock, PLUGIN_NAME);
+    assertThat(configuration.getAwsConfigurationProfileName().isPresent()).isFalse();
+  }
+
+  @Test
+  public void shouldReadConfiguredAwsConfigurationProfileName() {
+    String profileName = "aws-dynamodb-refdb";
+    pluginConfig.setString("profileName", profileName);
+    when(pluginConfigFactoryMock.getFromGerritConfig(PLUGIN_NAME))
+        .thenReturn(pluginConfig.asPluginConfig());
+
+    Configuration configuration = new Configuration(pluginConfigFactoryMock, PLUGIN_NAME);
+    assertThat(configuration.getAwsConfigurationProfileName().get()).isEqualTo(profileName);
+  }
+
+  @Test
   public void shouldReadEmptyRegionByDefault() {
     when(pluginConfigFactoryMock.getFromGerritConfig(PLUGIN_NAME))
         .thenReturn(pluginConfig.asPluginConfig());