diff --git a/libs/java/dynamodb_client_factory/pom.xml b/libs/java/dynamodb_client_factory/pom.xml
index fbbed834cc1..95d21f57368 100644
--- a/libs/java/dynamodb_client_factory/pom.xml
+++ b/libs/java/dynamodb_client_factory/pom.xml
@@ -31,27 +31,9 @@
athenz-dynamodb-client-factory
Generate dynamodb client based on AWS temporary credentials
jar
-
-
-
- com.amazonaws
- aws-java-sdk-bom
- ${aws.version}
- pom
- import
-
-
- software.amazon.awssdk
- bom
- ${aws2.version}
- pom
- import
-
-
-
- 0.9230
+ 0.9417
@@ -60,13 +42,10 @@
athenz-zts-java-client
${project.parent.version}
-
- com.amazonaws
- aws-java-sdk-dynamodb
-
software.amazon.awssdk
dynamodb
+ ${aws2.version}
com.google.guava
diff --git a/libs/java/dynamodb_client_factory/src/main/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientAndCredentials.java b/libs/java/dynamodb_client_factory/src/main/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientAndCredentials.java
index 54068de8e80..79deec74eba 100644
--- a/libs/java/dynamodb_client_factory/src/main/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientAndCredentials.java
+++ b/libs/java/dynamodb_client_factory/src/main/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientAndCredentials.java
@@ -18,30 +18,43 @@
package com.yahoo.athenz.db.dynamodb;
-import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
-import com.yahoo.athenz.zts.AWSCredentialsProviderImpl;
+import com.yahoo.athenz.zts.AWSCredentialsProviderImplV2;
+import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
public class DynamoDBClientAndCredentials {
- private final AmazonDynamoDB amazonDynamoDB;
- private final DynamoDbAsyncClient amazonDynamoAsyncDB;
- private final AWSCredentialsProviderImpl awsCredentialsProvider;
- public DynamoDBClientAndCredentials(AmazonDynamoDB amazonDynamoDB, DynamoDbAsyncClient amazonDynamoAsyncDB, AWSCredentialsProviderImpl awsCredentialsProvider) {
- this.amazonDynamoDB = amazonDynamoDB;
- this.amazonDynamoAsyncDB = amazonDynamoAsyncDB;
+ private final DynamoDbClient dynamoDbClient;
+ private final DynamoDbAsyncClient dynamoDbAsyncClient;
+ private final AWSCredentialsProviderImplV2 awsCredentialsProvider;
+
+ public DynamoDBClientAndCredentials(DynamoDbClient dynamoDbClient, DynamoDbAsyncClient dynamoDbAsyncClient,
+ AWSCredentialsProviderImplV2 awsCredentialsProvider) {
+ this.dynamoDbClient = dynamoDbClient;
+ this.dynamoDbAsyncClient = dynamoDbAsyncClient;
this.awsCredentialsProvider = awsCredentialsProvider;
}
- public AmazonDynamoDB getAmazonDynamoDB() {
- return amazonDynamoDB;
+ public DynamoDbClient getDynamoDbClient() {
+ return dynamoDbClient;
}
- public DynamoDbAsyncClient getAmazonDynamoAsyncDB() {
- return amazonDynamoAsyncDB;
+ public DynamoDbAsyncClient getDynamoDbAsyncClient() {
+ return dynamoDbAsyncClient;
}
- public AWSCredentialsProviderImpl getAwsCredentialsProvider() {
- return awsCredentialsProvider;
+ public void close() {
+ if (dynamoDbClient != null) {
+ dynamoDbClient.close();
+ }
+ if (dynamoDbAsyncClient != null) {
+ dynamoDbAsyncClient.close();
+ }
+ if (awsCredentialsProvider != null) {
+ try {
+ awsCredentialsProvider.close();
+ } catch (Exception ignored) {
+ }
+ }
}
}
diff --git a/libs/java/dynamodb_client_factory/src/main/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientFetcher.java b/libs/java/dynamodb_client_factory/src/main/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientFetcher.java
index 81d9810569d..ff53590caee 100644
--- a/libs/java/dynamodb_client_factory/src/main/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientFetcher.java
+++ b/libs/java/dynamodb_client_factory/src/main/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientFetcher.java
@@ -23,12 +23,14 @@
public interface DynamoDBClientFetcher {
/**
- * Returns a DynamoDBClient and the AWS credential provider used for authentication.
- * The credentialProvider should be closed after DynamoDBClient is no longer needed.
+ * Returns a DynamoDBClient wrapper object that includes both regular
+ * and async clients along with the AWS credentials provider.
+ * The clients should be closed after DynamoDBClient is no
+ * longer needed which would close the associated AWS credential provider.
* (GC might not run for a long period of time)
* @param ztsClientNotificationSender notification sender object
* @param dynamoDBClientSettings contains private key store and client settings
- * @return DynamoDBClientAndCredentials which contains both a DynamoDB client and the credentialProvider used
+ * @return DynamoDBClientAndCredentials which contains both DynamoDB clients and the credentialProvider used
*/
DynamoDBClientAndCredentials getDynamoDBClient(ZTSClientNotificationSender ztsClientNotificationSender,
DynamoDBClientSettings dynamoDBClientSettings);
diff --git a/libs/java/dynamodb_client_factory/src/main/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientFetcherImpl.java b/libs/java/dynamodb_client_factory/src/main/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientFetcherImpl.java
index 41009c7e36b..44593bdb851 100644
--- a/libs/java/dynamodb_client_factory/src/main/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientFetcherImpl.java
+++ b/libs/java/dynamodb_client_factory/src/main/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientFetcherImpl.java
@@ -18,33 +18,27 @@
package com.yahoo.athenz.db.dynamodb;
-import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
-import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
-import com.amazonaws.util.EC2MetadataUtils;
import com.oath.auth.KeyRefresher;
import com.oath.auth.Utils;
-import com.yahoo.athenz.zts.AWSCredentialsProviderImpl;
import com.yahoo.athenz.zts.AWSCredentialsProviderImplV2;
import com.yahoo.athenz.zts.ZTSClientNotificationSender;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain;
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
+import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.utils.StringUtils;
import javax.net.ssl.SSLContext;
public class DynamoDBClientFetcherImpl implements DynamoDBClientFetcher {
private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDBClientFetcherImpl.class);
- private String defaultAwsRegion;
public DynamoDBClientFetcherImpl() {
}
- public DynamoDBClientFetcherImpl(String defaultAwsRegion) {
- this.defaultAwsRegion = defaultAwsRegion;
- }
-
@Override
public DynamoDBClientAndCredentials getDynamoDBClient(ZTSClientNotificationSender ztsClientNotificationSender,
DynamoDBClientSettings dynamoDBClientSettings) {
@@ -58,28 +52,29 @@ public DynamoDBClientAndCredentials getDynamoDBClient(ZTSClientNotificationSende
return getAuthenticatedDynamoDBClient(dynamoDBClientSettings, ztsClientNotificationSender);
} else {
LOGGER.info("DynamoDB client will use existing AWS authentication");
- String region = getAWSRegion(dynamoDBClientSettings.getRegion());
- AmazonDynamoDB client = AmazonDynamoDBClientBuilder
- .standard()
- .withRegion(region)
- .build();
- DynamoDbAsyncClient asyncClient = DynamoDbAsyncClient.builder()
- .region(Region.of(region))
- .build();
+ DynamoDbClient dynamoDbClient = null;
+ DynamoDbAsyncClient dynamoDbAsyncClient = null;
+ if (dynamoDBClientSettings.isAsyncClient()) {
+ dynamoDbAsyncClient = DynamoDbAsyncClient.builder()
+ .region(getAWSRegion(dynamoDBClientSettings.getRegion()))
+ .build();
+ } else {
+ dynamoDbClient = DynamoDbClient.builder()
+ .region(getAWSRegion(dynamoDBClientSettings.getRegion()))
+ .build();
+ }
- return new DynamoDBClientAndCredentials(client, asyncClient, null);
+ return new DynamoDBClientAndCredentials(dynamoDbClient, dynamoDbAsyncClient, null);
}
}
- String getAWSRegion(final String settingRegion) {
- if (StringUtils.isEmpty(settingRegion)) {
- if (defaultAwsRegion == null) {
- defaultAwsRegion = EC2MetadataUtils.getEC2InstanceRegion();
- }
- return defaultAwsRegion;
+ Region getAWSRegion(final String settingRegion) {
+ if (!StringUtils.isEmpty(settingRegion)) {
+ return Region.of(settingRegion);
} else {
- return settingRegion;
+ DefaultAwsRegionProviderChain regionProvider = DefaultAwsRegionProviderChain.builder().build();
+ return regionProvider.getRegion();
}
}
@@ -102,10 +97,10 @@ private DynamoDBClientAndCredentials getAuthenticatedDynamoDBClient(DynamoDBClie
LOGGER.error("Failed to get AWS Temporary credentials", ex);
}
- AWSCredentialsProviderImpl credentialsProvider = null;
- String region = dynamoDBClientSettings.getRegion();
+ AWSCredentialsProviderImplV2 credentialsProvider = null;
+
try {
- credentialsProvider = new AWSCredentialsProviderImpl(
+ credentialsProvider = new AWSCredentialsProviderImplV2(
dynamoDBClientSettings.getZtsURL(),
sslContext,
dynamoDBClientSettings.getDomainName(),
@@ -114,35 +109,24 @@ private DynamoDBClientAndCredentials getAuthenticatedDynamoDBClient(DynamoDBClie
dynamoDBClientSettings.getMinExpiryTime(),
dynamoDBClientSettings.getMaxExpiryTime(),
ztsClientNotificationSender);
-
} catch (Exception ex) {
- LOGGER.error("Failed to generate AmazonDynamoDB client", ex);
+ LOGGER.error("Failed to generate DynamoDbClient client", ex);
}
- AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
- .withCredentials(credentialsProvider)
- .withRegion(region)
- .build();
-
- AWSCredentialsProviderImplV2 credentialsProviderV2 = null;
- try {
- credentialsProviderV2 = new AWSCredentialsProviderImplV2(
- dynamoDBClientSettings.getZtsURL(),
- sslContext,
- dynamoDBClientSettings.getDomainName(),
- dynamoDBClientSettings.getRoleName(),
- dynamoDBClientSettings.getExternalId(),
- dynamoDBClientSettings.getMinExpiryTime(),
- dynamoDBClientSettings.getMaxExpiryTime(),
- ztsClientNotificationSender);
- } catch (Exception ex) {
- LOGGER.error("Failed to generate DynamoDbAsyncClient client", ex);
+ DynamoDbClient dynamoDbClient = null;
+ DynamoDbAsyncClient dynamoDbAsyncClient = null;
+ if (dynamoDBClientSettings.isAsyncClient()) {
+ dynamoDbAsyncClient = DynamoDbAsyncClient.builder()
+ .credentialsProvider(credentialsProvider)
+ .region(getAWSRegion(dynamoDBClientSettings.getRegion()))
+ .build();
+ } else {
+ dynamoDbClient = DynamoDbClient.builder()
+ .credentialsProvider(credentialsProvider)
+ .region(getAWSRegion(dynamoDBClientSettings.getRegion()))
+ .build();
}
- DynamoDbAsyncClient asyncClient = DynamoDbAsyncClient.builder()
- .credentialsProvider(credentialsProviderV2)
- .region(Region.of(region))
- .build();
- return new DynamoDBClientAndCredentials(client, asyncClient, credentialsProvider);
+ return new DynamoDBClientAndCredentials(dynamoDbClient, dynamoDbAsyncClient, credentialsProvider);
}
}
diff --git a/libs/java/dynamodb_client_factory/src/main/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientSettings.java b/libs/java/dynamodb_client_factory/src/main/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientSettings.java
index 3f0268ddb0b..1cf637fa982 100644
--- a/libs/java/dynamodb_client_factory/src/main/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientSettings.java
+++ b/libs/java/dynamodb_client_factory/src/main/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientSettings.java
@@ -34,22 +34,14 @@ public class DynamoDBClientSettings {
private final String externalId;
private final Integer minExpiryTime;
private final Integer maxExpiryTime;
- private final String keygroupName;
-
- public DynamoDBClientSettings(String certPath,
- String domainName,
- String roleName,
- String trustStore,
- String trustStorePassword,
- String ztsURL,
- String region,
- String keyPath,
- String appName,
- PrivateKeyStore keyStore,
- String externalId,
- Integer minExpiryTime,
- Integer maxExpiryTime,
- String keygroupName) {
+ private final String keyGroupName;
+ private final boolean isAsyncClient;
+
+ public DynamoDBClientSettings(String certPath, String domainName, String roleName, String trustStore,
+ String trustStorePassword, String ztsURL, String region, String keyPath, String appName,
+ PrivateKeyStore keyStore, String externalId, Integer minExpiryTime, Integer maxExpiryTime,
+ String keyGroupName, boolean isAsyncClient) {
+
this.certPath = certPath;
this.domainName = domainName;
this.roleName = roleName;
@@ -63,7 +55,8 @@ public DynamoDBClientSettings(String certPath,
this.externalId = externalId;
this.minExpiryTime = minExpiryTime;
this.maxExpiryTime = maxExpiryTime;
- this.keygroupName = keygroupName;
+ this.keyGroupName = keyGroupName;
+ this.isAsyncClient = isAsyncClient;
}
public boolean areCredentialsProvided() {
@@ -123,6 +116,10 @@ public char[] getTrustStorePasswordChars() {
return null;
}
- return keyStore.getSecret(appName, keygroupName, trustStorePassword);
+ return keyStore.getSecret(appName, keyGroupName, trustStorePassword);
+ }
+
+ public boolean isAsyncClient() {
+ return isAsyncClient;
}
}
diff --git a/libs/java/dynamodb_client_factory/src/test/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientAndCredentialsTest.java b/libs/java/dynamodb_client_factory/src/test/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientAndCredentialsTest.java
index f121af18388..a592f2b4793 100644
--- a/libs/java/dynamodb_client_factory/src/test/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientAndCredentialsTest.java
+++ b/libs/java/dynamodb_client_factory/src/test/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientAndCredentialsTest.java
@@ -18,28 +18,61 @@
package com.yahoo.athenz.db.dynamodb;
+import com.yahoo.athenz.zts.AWSCredentialsProviderImplV2;
import org.mockito.Mockito;
import org.testng.annotations.Test;
-import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
-import com.yahoo.athenz.zts.AWSCredentialsProviderImpl;
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
+import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
+
+import java.io.IOException;
import static org.testng.Assert.assertEquals;
public class DynamoDBClientAndCredentialsTest {
@Test
- public void testDynamoDBClientAndCredentials() {
+ public void testDynamoDBClientAndCredentials() throws IOException {
+
+ DynamoDbClient dynamoDbClient = Mockito.mock(DynamoDbClient.class);
+ Mockito.doNothing().when(dynamoDbClient).close();
+ DynamoDbAsyncClient dynamoDbAsyncClient = Mockito.mock(DynamoDbAsyncClient.class);
+ Mockito.doNothing().when(dynamoDbAsyncClient).close();
+ AWSCredentialsProviderImplV2 credentialsProvider = Mockito.mock(AWSCredentialsProviderImplV2.class);
+ Mockito.doNothing().when(credentialsProvider).close();
+ DynamoDBClientAndCredentials dynamoDBClientAndCredentials =
+ new DynamoDBClientAndCredentials(dynamoDbClient, dynamoDbAsyncClient, credentialsProvider);
+ assertEquals(dynamoDbClient, dynamoDBClientAndCredentials.getDynamoDbClient());
+ assertEquals(dynamoDbAsyncClient, dynamoDBClientAndCredentials.getDynamoDbAsyncClient());
+ dynamoDBClientAndCredentials.close();
+ }
- AmazonDynamoDB amazonDynamoDB = Mockito.mock(AmazonDynamoDB.class);
- DynamoDbAsyncClient amazonDynamoAsyncDB = Mockito.mock(DynamoDbAsyncClient.class);
- AWSCredentialsProviderImpl awsCredentialsProvider = Mockito.mock(AWSCredentialsProviderImpl.class);
+ @Test
+ public void testDynamoDBClientAndCredentialsNullProvider() {
- DynamoDBClientAndCredentials dynamoDBClientAndCredentials = new DynamoDBClientAndCredentials(
- amazonDynamoDB, amazonDynamoAsyncDB, awsCredentialsProvider);
+ DynamoDbClient dynamoDbClient = Mockito.mock(DynamoDbClient.class);
+ Mockito.doNothing().when(dynamoDbClient).close();
+ DynamoDbAsyncClient dynamoDbAsyncClient = Mockito.mock(DynamoDbAsyncClient.class);
+ Mockito.doNothing().when(dynamoDbAsyncClient).close();
+ DynamoDBClientAndCredentials dynamoDBClientAndCredentials =
+ new DynamoDBClientAndCredentials(dynamoDbClient, dynamoDbAsyncClient, null);
+ assertEquals(dynamoDbClient, dynamoDBClientAndCredentials.getDynamoDbClient());
+ assertEquals(dynamoDbAsyncClient, dynamoDBClientAndCredentials.getDynamoDbAsyncClient());
+ dynamoDBClientAndCredentials.close();
+ }
+
+ @Test
+ public void testDynamoDBClientAndCredentialsException() throws IOException {
- assertEquals(amazonDynamoDB, dynamoDBClientAndCredentials.getAmazonDynamoDB());
- assertEquals(amazonDynamoAsyncDB, dynamoDBClientAndCredentials.getAmazonDynamoAsyncDB());
- assertEquals(awsCredentialsProvider, dynamoDBClientAndCredentials.getAwsCredentialsProvider());
+ DynamoDbClient dynamoDbClient = Mockito.mock(DynamoDbClient.class);
+ Mockito.doNothing().when(dynamoDbClient).close();
+ DynamoDbAsyncClient dynamoDbAsyncClient = Mockito.mock(DynamoDbAsyncClient.class);
+ Mockito.doNothing().when(dynamoDbAsyncClient).close();
+ AWSCredentialsProviderImplV2 credentialsProvider = Mockito.mock(AWSCredentialsProviderImplV2.class);
+ Mockito.doThrow(new IllegalArgumentException()).when(credentialsProvider).close();
+ DynamoDBClientAndCredentials dynamoDBClientAndCredentials =
+ new DynamoDBClientAndCredentials(dynamoDbClient, dynamoDbAsyncClient, credentialsProvider);
+ assertEquals(dynamoDbClient, dynamoDBClientAndCredentials.getDynamoDbClient());
+ assertEquals(dynamoDbAsyncClient, dynamoDBClientAndCredentials.getDynamoDbAsyncClient());
+ dynamoDBClientAndCredentials.close();
}
}
diff --git a/libs/java/dynamodb_client_factory/src/test/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientFetcherImplTest.java b/libs/java/dynamodb_client_factory/src/test/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientFetcherImplTest.java
index 0b9bc8bf921..c75db45ac38 100644
--- a/libs/java/dynamodb_client_factory/src/test/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientFetcherImplTest.java
+++ b/libs/java/dynamodb_client_factory/src/test/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientFetcherImplTest.java
@@ -18,110 +18,124 @@
package com.yahoo.athenz.db.dynamodb;
-import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.google.common.io.Resources;
import com.yahoo.athenz.auth.PrivateKeyStore;
import com.yahoo.athenz.zts.ZTSClientNotificationSender;
import org.mockito.Mockito;
import org.testng.annotations.Test;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
+import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
import static org.testng.AssertJUnit.assertNotNull;
public class DynamoDBClientFetcherImplTest {
- private static final String ZTS_PROP_DYNAMODB_KEY_PATH = "athenz.zts.dynamodb_key_path";
- private static final String ZTS_PROP_DYNAMODB_CERT_PATH = "athenz.zts.dynamodb_cert_path";
- private static final String ZTS_PROP_DYNAMODB_DOMAIN = "athenz.zts.dynamodb_aws_domain";
- private static final String ZTS_PROP_DYNAMODB_ROLE = "athenz.zts.dynamodb_aws_role";
- private static final String ZTS_PROP_DYNAMODB_TRUSTSTORE = "athenz.zts.dynamodb_trust_store_path";
- private static final String ZTS_PROP_DYNAMODB_TRUSTSTORE_PASSWORD = "athenz.zts.dynamodb_trust_store_password";
- private static final String ZTS_PROP_DYNAMODB_REGION = "athenz.zts.dynamodb_region";
- private static final String ZTS_PROP_DYNAMODB_ZTS_URL = "athenz.zts.dynamodb_zts_url";
- private static final String ZTS_PROP_DYNAMODB_MIN_EXPIRY_TIME = "athenz.zts.dynamodb_min_expiry_time";
- private static final String ZTS_PROP_DYNAMODB_MAX_EXPIRY_TIME = "athenz.zts.dynamodb_max_expiry_time";
-
@Test
- public void testGetClientWitSpecifiedRegion() {
- System.setProperty(ZTS_PROP_DYNAMODB_REGION, "test.region");
- DynamoDBClientFetcher dynamoDBClientFetcher = DynamoDBClientFetcherFactory.getDynamoDBClientFetcher();
- PrivateKeyStore keyStore = Mockito.mock(PrivateKeyStore.class);
- ZTSClientNotificationSender ztsClientNotificationSender = Mockito.mock(ZTSClientNotificationSender.class);
- DynamoDBClientSettings dynamoDBClientSettings = new DynamoDBClientSettings(null, null, null, null, null,
- null, "test.region", null, null, keyStore, null, null, null, null);
- AmazonDynamoDB dynamoDBClient = dynamoDBClientFetcher.getDynamoDBClient(ztsClientNotificationSender,
- dynamoDBClientSettings).getAmazonDynamoDB();
- assertNotNull(dynamoDBClient);
- System.clearProperty(ZTS_PROP_DYNAMODB_REGION);
+ public void testDynamoDBClientFetcherFactory() {
+ DynamoDBClientFetcherFactory dynamoDBClientFetcherFactory = new DynamoDBClientFetcherFactory();
+ assertNotNull(dynamoDBClientFetcherFactory);
+ assertNotNull(DynamoDBClientFetcherFactory.getDynamoDBClientFetcher());
}
@Test
- public void testGetClientWithDefaultRegion() {
- DynamoDBClientFetcher dynamoDBClientFetcher = new DynamoDBClientFetcherImpl("testRegion");
+ public void testGetClientWitSpecifiedRegion() {
+ DynamoDBClientFetcher dynamoDBClientFetcher = DynamoDBClientFetcherFactory.getDynamoDBClientFetcher();
PrivateKeyStore keyStore = Mockito.mock(PrivateKeyStore.class);
ZTSClientNotificationSender ztsClientNotificationSender = Mockito.mock(ZTSClientNotificationSender.class);
DynamoDBClientSettings dynamoDBClientSettings = new DynamoDBClientSettings(null, null, null, null, null,
- null, "testRegion", null, null, keyStore, null, null, null, null);
- AmazonDynamoDB dynamoDBClient = dynamoDBClientFetcher.getDynamoDBClient(ztsClientNotificationSender,
- dynamoDBClientSettings).getAmazonDynamoDB();
- assertNotNull(dynamoDBClient);
+ null, "test.region", null, null, keyStore, null, null, null, null, false);
+ DynamoDbClient dynamoDbClient = dynamoDBClientFetcher.getDynamoDBClient(ztsClientNotificationSender,
+ dynamoDBClientSettings).getDynamoDbClient();
+ assertNotNull(dynamoDbClient);
}
@Test
- public void testGetAuthenticatedClient() {
+ public void testGetAuthenticatedClientWithCreds() {
String certPath = Resources.getResource("gdpr.aws.core.cert.pem").getPath();//public
String keyPath = Resources.getResource("gdpr.aws.core.key.pem").getPath();//private
- System.setProperty(ZTS_PROP_DYNAMODB_KEY_PATH, keyPath);
- System.setProperty(ZTS_PROP_DYNAMODB_CERT_PATH, certPath);
- System.setProperty(ZTS_PROP_DYNAMODB_DOMAIN, "test.domain");
- System.setProperty(ZTS_PROP_DYNAMODB_REGION, "test.region");
- System.setProperty(ZTS_PROP_DYNAMODB_ROLE, "test.role");
- System.setProperty(ZTS_PROP_DYNAMODB_TRUSTSTORE, "test.truststore");
- System.setProperty(ZTS_PROP_DYNAMODB_TRUSTSTORE_PASSWORD, "test.truststore.password");
- System.setProperty(ZTS_PROP_DYNAMODB_ZTS_URL, "https://dev.zts.athenzcompany.com:4443/zts/v1");
-
DynamoDBClientFetcherImpl dynamoDBClientFetcher = new DynamoDBClientFetcherImpl();
PrivateKeyStore keyStore = Mockito.mock(PrivateKeyStore.class);
when(keyStore.getSecret(Mockito.eq(""), Mockito.eq(null), Mockito.eq("test.truststore.password")))
.thenReturn("mockPassword".toCharArray());
ZTSClientNotificationSender ztsClientNotificationSender = Mockito.mock(ZTSClientNotificationSender.class);
+ // first we test the regular client
+
DynamoDBClientSettings dynamoDBClientSettings = new DynamoDBClientSettings(certPath, "test.domain",
"test.role", "test.truststore", "test.truststore.password",
"https://dev.zts.athenzcompany.com:4443/zts/v1", "test.region", keyPath, null,
- keyStore, null, null, null, null);
- AmazonDynamoDB dynamoDBClient = dynamoDBClientFetcher.getDynamoDBClient(ztsClientNotificationSender,
- dynamoDBClientSettings).getAmazonDynamoDB();
- assertNotNull(dynamoDBClient);
-
- System.clearProperty(ZTS_PROP_DYNAMODB_KEY_PATH);
- System.clearProperty(ZTS_PROP_DYNAMODB_CERT_PATH);
- System.clearProperty(ZTS_PROP_DYNAMODB_DOMAIN);
- System.clearProperty(ZTS_PROP_DYNAMODB_REGION);
- System.clearProperty(ZTS_PROP_DYNAMODB_ROLE);
- System.clearProperty(ZTS_PROP_DYNAMODB_TRUSTSTORE);
- System.clearProperty(ZTS_PROP_DYNAMODB_TRUSTSTORE_PASSWORD);
- System.clearProperty(ZTS_PROP_DYNAMODB_ZTS_URL);
+ keyStore, null, null, null, null, false);
+ DynamoDbClient dynamoDbClient = dynamoDBClientFetcher.getDynamoDBClient(ztsClientNotificationSender,
+ dynamoDBClientSettings).getDynamoDbClient();
+ assertNotNull(dynamoDbClient);
+ DynamoDbAsyncClient dynamoDbAsyncClient = dynamoDBClientFetcher.getDynamoDBClient(ztsClientNotificationSender,
+ dynamoDBClientSettings).getDynamoDbAsyncClient();
+ assertNull(dynamoDbAsyncClient);
+
+ // now the async client
+
+ dynamoDBClientSettings = new DynamoDBClientSettings(certPath, "test.domain",
+ "test.role", "test.truststore", "test.truststore.password",
+ "https://dev.zts.athenzcompany.com:4443/zts/v1", "test.region", keyPath, null,
+ keyStore, null, null, null, null, true);
+ dynamoDbClient = dynamoDBClientFetcher.getDynamoDBClient(ztsClientNotificationSender,
+ dynamoDBClientSettings).getDynamoDbClient();
+ assertNull(dynamoDbClient);
+ dynamoDbAsyncClient = dynamoDBClientFetcher.getDynamoDBClient(ztsClientNotificationSender,
+ dynamoDBClientSettings).getDynamoDbAsyncClient();
+ assertNotNull(dynamoDbAsyncClient);
}
@Test
- public void testGetAWSRegion() {
+ public void testGetAuthenticatedClientWithoutCreds() {
DynamoDBClientFetcherImpl dynamoDBClientFetcher = new DynamoDBClientFetcherImpl();
- assertEquals(dynamoDBClientFetcher.getAWSRegion("us-west-2"), "us-west-2");
+ ZTSClientNotificationSender ztsClientNotificationSender = Mockito.mock(ZTSClientNotificationSender.class);
- dynamoDBClientFetcher = new DynamoDBClientFetcherImpl("us-east-1");
- assertEquals(dynamoDBClientFetcher.getAWSRegion("us-west-2"), "us-west-2");
- assertEquals(dynamoDBClientFetcher.getAWSRegion(""), "us-east-1");
- assertEquals(dynamoDBClientFetcher.getAWSRegion(null), "us-east-1");
+ // first we test the regular client
+
+ DynamoDBClientSettings dynamoDBClientSettings = new DynamoDBClientSettings(null, "test.domain",
+ "test.role", null, null, "https://dev.zts.athenzcompany.com:4443/zts/v1", "test.region",
+ null, null, null, null, null, null, null, false);
+ DynamoDbClient dynamoDbClient = dynamoDBClientFetcher.getDynamoDBClient(ztsClientNotificationSender,
+ dynamoDBClientSettings).getDynamoDbClient();
+ assertNotNull(dynamoDbClient);
+ DynamoDbAsyncClient dynamoDbAsyncClient = dynamoDBClientFetcher.getDynamoDBClient(ztsClientNotificationSender,
+ dynamoDBClientSettings).getDynamoDbAsyncClient();
+ assertNull(dynamoDbAsyncClient);
+
+ // now the async client
+
+ dynamoDBClientSettings = new DynamoDBClientSettings(null, "test.domain",
+ "test.role", null, null, "https://dev.zts.athenzcompany.com:4443/zts/v1", "test.region",
+ null, null, null, null, null, null, null, true);
+ dynamoDbClient = dynamoDBClientFetcher.getDynamoDBClient(ztsClientNotificationSender,
+ dynamoDBClientSettings).getDynamoDbClient();
+ assertNull(dynamoDbClient);
+ dynamoDbAsyncClient = dynamoDBClientFetcher.getDynamoDBClient(ztsClientNotificationSender,
+ dynamoDBClientSettings).getDynamoDbAsyncClient();
+ assertNotNull(dynamoDbAsyncClient);
+ }
+
+ @Test
+ public void testGetAWSRegion() {
+
+ DynamoDBClientFetcherImpl dynamoDBClientFetcher = new DynamoDBClientFetcherImpl();
+ assertEquals(dynamoDBClientFetcher.getAWSRegion("us-west-2"), Region.of("us-west-2"));
// if this test is running in aws, then we'll get a valid region
// value. if running on-prem, then we'll get an exception when ec2 meta
// api is called. so we'll get a null value back
dynamoDBClientFetcher = new DynamoDBClientFetcherImpl();
- dynamoDBClientFetcher.getAWSRegion(null);
+ try {
+ dynamoDBClientFetcher.getAWSRegion(null);
+ } catch (Exception ignored) {
+ }
}
}
diff --git a/libs/java/dynamodb_client_factory/src/test/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientSettingsTest.java b/libs/java/dynamodb_client_factory/src/test/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientSettingsTest.java
index 2891f392557..5112d92f5e4 100644
--- a/libs/java/dynamodb_client_factory/src/test/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientSettingsTest.java
+++ b/libs/java/dynamodb_client_factory/src/test/java/com/yahoo/athenz/db/dynamodb/DynamoDBClientSettingsTest.java
@@ -30,21 +30,8 @@ public class DynamoDBClientSettingsTest {
@Test
public void credentialsNotProvided() {
PrivateKeyStore keyStore = Mockito.mock(PrivateKeyStore.class);
- DynamoDBClientSettings dynamoDBClientSettings = new DynamoDBClientSettings(null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- keyStore,
- null,
- null,
- null,
- null);
-
+ DynamoDBClientSettings dynamoDBClientSettings = new DynamoDBClientSettings(null, null, null, null,
+ null, null, null, null, null, keyStore, null, null, null, null, false);
assertFalse(dynamoDBClientSettings.areCredentialsProvided());
}
@@ -64,7 +51,9 @@ public void testCredentialsProvided() {
when(keyStore.getSecret(Mockito.eq("test.appname"), Mockito.eq(null), Mockito.eq("test.truststore.password")))
.thenReturn("decryptedPassword".toCharArray());
- DynamoDBClientSettings dynamoDBClientSettings = new DynamoDBClientSettings(certPath, domain, role, trustStore, trustStorePassword, ztsUrl, region, keyPath, appName, keyStore, null, null, null, null);
+ DynamoDBClientSettings dynamoDBClientSettings = new DynamoDBClientSettings(certPath, domain, role,
+ trustStore, trustStorePassword, ztsUrl, region, keyPath, appName, keyStore, null, null,
+ null, null, false);
assertTrue(dynamoDBClientSettings.areCredentialsProvided());
assertEquals("test.keypath", dynamoDBClientSettings.getKeyPath());
@@ -77,7 +66,8 @@ public void testCredentialsProvided() {
assertEquals("test.ztsurl", dynamoDBClientSettings.getZtsURL());
// Now verify that when keyStore isn't provided, trustStorePassword will be null
- dynamoDBClientSettings = new DynamoDBClientSettings(certPath, domain, role, trustStore, trustStorePassword, ztsUrl, region, keyPath, appName, null, null, null, null, null);
+ dynamoDBClientSettings = new DynamoDBClientSettings(certPath, domain, role, trustStore,
+ trustStorePassword, ztsUrl, region, keyPath, appName, null, null, null, null, null, false);
assertNull(dynamoDBClientSettings.getTrustStorePasswordChars());
}
}
\ No newline at end of file
diff --git a/servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSImpl.java b/servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSImpl.java
index a5f8d114606..9c3dc7ba7ea 100644
--- a/servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSImpl.java
+++ b/servers/zms/src/main/java/com/yahoo/athenz/zms/ZMSImpl.java
@@ -83,7 +83,6 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.security.PrivateKey;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
@@ -1102,9 +1101,7 @@ void loadPrivateKeyStore() {
// when signing policy files
if (privateECKey == null && privateRSAKey == null) {
- StringBuilder privKeyId = new StringBuilder(256);
- PrivateKey pkey = keyStore.getPrivateKey(ZMSConsts.ZMS_SERVICE, serverHostName, privKeyId);
- privateKey = new ServerPrivateKey(pkey, privKeyId.toString());
+ privateKey = keyStore.getPrivateKey(ZMSConsts.ZMS_SERVICE, serverHostName, serverRegion, null);
} else {
privateKey = Objects.requireNonNullElseGet(privateECKey, () -> privateRSAKey);
}
diff --git a/servers/zts/pom.xml b/servers/zts/pom.xml
index 10e94752c03..a1949590bc7 100644
--- a/servers/zts/pom.xml
+++ b/servers/zts/pom.xml
@@ -32,18 +32,6 @@
0.9958
-
-
-
- com.amazonaws
- aws-java-sdk-bom
- ${aws.version}
- pom
- import
-
-
-
-
org.slf4j
@@ -148,20 +136,24 @@
${jersey.version}
- com.amazonaws
- aws-java-sdk-s3
+ software.amazon.awssdk
+ s3
+ ${aws2.version}
- com.amazonaws
- aws-java-sdk-sts
+ software.amazon.awssdk
+ sts
+ ${aws2.version}
- com.amazonaws
- aws-java-sdk-rds
+ software.amazon.awssdk
+ rds
+ ${aws2.version}
- com.amazonaws
- aws-java-sdk-dynamodb
+ software.amazon.awssdk
+ dynamodb
+ ${aws2.version}
org.eclipse.jetty
diff --git a/servers/zts/src/main/java/com/yahoo/athenz/zts/ZTSConsts.java b/servers/zts/src/main/java/com/yahoo/athenz/zts/ZTSConsts.java
index 21a3fd0d0dd..bd1e70bd192 100644
--- a/servers/zts/src/main/java/com/yahoo/athenz/zts/ZTSConsts.java
+++ b/servers/zts/src/main/java/com/yahoo/athenz/zts/ZTSConsts.java
@@ -186,8 +186,8 @@ public final class ZTSConsts {
public static final String ZTS_PROP_AWS_RDS_IAM_ROLE = "athenz.zts.aws_rds_iam_role";
public static final String ZTS_PROP_AWS_RDS_ENGINE = "athenz.zts.aws_rds_engine";
public static final String ZTS_PROP_AWS_RDS_DATABASE = "athenz.zts.aws_rds_database";
- public static final String ZTS_PROP_AWS_RDS_MASTER_INSTANCE = "athenz.zts.aws_rds_master_instance";
- public static final String ZTS_PROP_AWS_RDS_MASTER_PORT = "athenz.zts.aws_rds_master_port";
+ public static final String ZTS_PROP_AWS_RDS_PRIMARY_INSTANCE = "athenz.zts.aws_rds_master_instance";
+ public static final String ZTS_PROP_AWS_RDS_PRIMARY_PORT = "athenz.zts.aws_rds_master_port";
public static final String ZTS_PROP_AWS_RDS_CREDS_REFRESH_TIME = "athenz.zts.aws_rds_creds_refresh_time";
public static final String ZTS_SERVICE = "zts";
diff --git a/servers/zts/src/main/java/com/yahoo/athenz/zts/cert/impl/AWSCertRecordStoreFactory.java b/servers/zts/src/main/java/com/yahoo/athenz/zts/cert/impl/AWSCertRecordStoreFactory.java
index 4cb7d2fabd8..192169d1445 100644
--- a/servers/zts/src/main/java/com/yahoo/athenz/zts/cert/impl/AWSCertRecordStoreFactory.java
+++ b/servers/zts/src/main/java/com/yahoo/athenz/zts/cert/impl/AWSCertRecordStoreFactory.java
@@ -22,18 +22,19 @@
import com.yahoo.athenz.common.server.cert.CertRecordStore;
import com.yahoo.athenz.common.server.cert.CertRecordStoreFactory;
+import com.yahoo.athenz.common.server.util.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.amazonaws.auth.InstanceProfileCredentialsProvider;
-import com.amazonaws.services.rds.auth.GetIamAuthTokenRequest;
-import com.amazonaws.services.rds.auth.RdsIamAuthTokenGenerator;
-import com.amazonaws.util.EC2MetadataUtils;
-
import com.yahoo.athenz.auth.PrivateKeyStore;
import com.yahoo.athenz.common.server.db.DataSourceFactory;
import com.yahoo.athenz.common.server.db.PoolableDataSource;
import com.yahoo.athenz.zts.ZTSConsts;
+import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.rds.RdsClient;
+import software.amazon.awssdk.services.rds.RdsUtilities;
+import software.amazon.awssdk.services.rds.model.GenerateAuthenticationTokenRequest;
public class AWSCertRecordStoreFactory implements CertRecordStoreFactory {
@@ -41,23 +42,21 @@ public class AWSCertRecordStoreFactory implements CertRecordStoreFactory {
private static Properties mysqlConnectionProperties = new Properties();
private static String rdsUser = null;
- private static String rdsIamRole = null;
- private static String rdsMaster = null;
+ private static String rdsPrimary = null;
private int rdsPort = 3306;
@Override
public CertRecordStore create(PrivateKeyStore keyStore) {
rdsUser = System.getProperty(ZTSConsts.ZTS_PROP_AWS_RDS_USER);
- rdsIamRole = System.getProperty(ZTSConsts.ZTS_PROP_AWS_RDS_IAM_ROLE);
- rdsMaster = System.getProperty(ZTSConsts.ZTS_PROP_AWS_RDS_MASTER_INSTANCE);
- rdsPort = Integer.parseInt(System.getProperty(ZTSConsts.ZTS_PROP_AWS_RDS_MASTER_PORT, "3306"));
+ rdsPrimary = System.getProperty(ZTSConsts.ZTS_PROP_AWS_RDS_PRIMARY_INSTANCE);
+ rdsPort = Integer.parseInt(System.getProperty(ZTSConsts.ZTS_PROP_AWS_RDS_PRIMARY_PORT, "3306"));
final String rdsEngine = System.getProperty(ZTSConsts.ZTS_PROP_AWS_RDS_ENGINE, "mysql");
final String rdsDatabase = System.getProperty(ZTSConsts.ZTS_PROP_AWS_RDS_DATABASE, "zts_store");
- final String jdbcStore = String.format("jdbc:%s://%s:%d/%s", rdsEngine, rdsMaster, rdsPort, rdsDatabase);
- String rdsToken = getAuthToken(rdsMaster, rdsPort, rdsUser, rdsIamRole);
+ final String jdbcStore = String.format("jdbc:%s://%s:%d/%s", rdsEngine, rdsPrimary, rdsPort, rdsDatabase);
+ String rdsToken = getAuthToken(rdsPrimary, rdsPort, rdsUser);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Connecting to {} with auth token {}", jdbcStore, rdsToken);
@@ -81,30 +80,28 @@ public CertRecordStore create(PrivateKeyStore keyStore) {
return new JDBCCertRecordStore(dataSource);
}
- String getInstanceRegion() {
- return EC2MetadataUtils.getEC2InstanceRegion();
- }
+ String getAuthToken(String hostname, int port, String rdsUser) {
- RdsIamAuthTokenGenerator getTokenGenerator(InstanceProfileCredentialsProvider awsCredProvider) {
- return RdsIamAuthTokenGenerator.builder()
- .credentials(awsCredProvider)
- .region(getInstanceRegion())
- .build();
- }
+ String authToken = null;
+ try (RdsClient rdsClient = RdsClient.builder().region(Utils.getAwsRegion((Region.US_EAST_1)))
+ .credentialsProvider(ProfileCredentialsProvider.create()).build()) {
- String getAuthToken(String hostname, int port, String rdsUser, String rdsIamRole) {
+ RdsUtilities utilities = rdsClient.utilities();
- InstanceProfileCredentialsProvider awsCredProvider = new InstanceProfileCredentialsProvider(true);
- RdsIamAuthTokenGenerator generator = getTokenGenerator(awsCredProvider);
-
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("Instance {} Port {} User {} Region: {} Role: {}", hostname, port, rdsUser,
- getInstanceRegion(), rdsIamRole);
+ GenerateAuthenticationTokenRequest tokenRequest = GenerateAuthenticationTokenRequest.builder()
+ .credentialsProvider(ProfileCredentialsProvider.create())
+ .username(rdsUser)
+ .port(port)
+ .hostname(hostname)
+ .build();
+
+ authToken = utilities.generateAuthenticationToken(tokenRequest);
+
+ } catch (Exception ex) {
+ LOGGER.error("getAuthToken: unable to generate auth token", ex);
}
-
- return generator.getAuthToken(GetIamAuthTokenRequest.builder()
- .hostname(hostname).port(port).userName(rdsUser)
- .build());
+
+ return authToken;
}
class CredentialsUpdater implements Runnable {
@@ -117,7 +114,7 @@ public void run() {
}
try {
- final String rdsToken = getAuthToken(rdsMaster, rdsPort, rdsUser, rdsIamRole);
+ final String rdsToken = getAuthToken(rdsPrimary, rdsPort, rdsUser);
mysqlConnectionProperties.setProperty(ZTSConsts.DB_PROP_PASSWORD, rdsToken);
} catch (Throwable t) {
diff --git a/servers/zts/src/main/java/com/yahoo/athenz/zts/cert/impl/DynamoDBCertRecordStore.java b/servers/zts/src/main/java/com/yahoo/athenz/zts/cert/impl/DynamoDBCertRecordStore.java
index a8ab053d51b..f7d547e8dd9 100644
--- a/servers/zts/src/main/java/com/yahoo/athenz/zts/cert/impl/DynamoDBCertRecordStore.java
+++ b/servers/zts/src/main/java/com/yahoo/athenz/zts/cert/impl/DynamoDBCertRecordStore.java
@@ -15,18 +15,16 @@
*/
package com.yahoo.athenz.zts.cert.impl;
-import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
-import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.yahoo.athenz.auth.Principal;
import com.yahoo.athenz.common.server.cert.CertRecordStore;
import com.yahoo.athenz.common.server.cert.CertRecordStoreConnection;
import com.yahoo.athenz.common.server.db.RolesProvider;
import com.yahoo.athenz.common.server.notification.NotificationManager;
import com.yahoo.athenz.common.utils.X509CertUtils;
-import com.yahoo.athenz.zts.ResourceException;
import com.yahoo.athenz.zts.notification.ZTSClientNotificationSenderImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import java.security.cert.X509Certificate;
@@ -38,11 +36,12 @@ public class DynamoDBCertRecordStore implements CertRecordStore {
private final String tableName;
private final String currentTimeIndexName;
private final String hostIndexName;
- private final DynamoDB dynamoDB;
+ private final DynamoDbClient dynamoDB;
private final ZTSClientNotificationSenderImpl ztsClientNotificationSender;
- public DynamoDBCertRecordStore(AmazonDynamoDB client, final String tableName, final String currentTimeIndexName, String hostIndexName, ZTSClientNotificationSenderImpl ztsClientNotificationSender) {
- this.dynamoDB = new DynamoDB(client);
+ public DynamoDBCertRecordStore(DynamoDbClient client, final String tableName, final String currentTimeIndexName,
+ String hostIndexName, ZTSClientNotificationSenderImpl ztsClientNotificationSender) {
+ this.dynamoDB = client;
this.tableName = tableName;
this.currentTimeIndexName = currentTimeIndexName;
this.hostIndexName = hostIndexName;
@@ -51,12 +50,7 @@ public DynamoDBCertRecordStore(AmazonDynamoDB client, final String tableName, fi
@Override
public CertRecordStoreConnection getConnection() {
- try {
- return new DynamoDBCertRecordStoreConnection(dynamoDB, tableName, currentTimeIndexName, hostIndexName);
- } catch (Exception ex) {
- LOGGER.error("getConnection: {}", ex.getMessage());
- throw new ResourceException(ResourceException.SERVICE_UNAVAILABLE, ex.getMessage());
- }
+ return new DynamoDBCertRecordStoreConnection(dynamoDB, tableName, currentTimeIndexName, hostIndexName);
}
@Override
@@ -69,12 +63,13 @@ public void clearConnections() {
@Override
public void log(final Principal principal, final String ip, final String provider,
- final String instanceId, final X509Certificate x509Cert) {
+ final String instanceId, final X509Certificate x509Cert) {
X509CertUtils.logCert(CERTLOGGER, principal, ip, provider, instanceId, x509Cert);
}
@Override
- public boolean enableNotifications(NotificationManager notificationManager, RolesProvider rolesProvider, final String serverName) {
+ public boolean enableNotifications(NotificationManager notificationManager, RolesProvider rolesProvider,
+ final String serverName) {
if (ztsClientNotificationSender != null) {
return ztsClientNotificationSender.init(notificationManager, rolesProvider, serverName);
} else {
diff --git a/servers/zts/src/main/java/com/yahoo/athenz/zts/cert/impl/DynamoDBCertRecordStoreConnection.java b/servers/zts/src/main/java/com/yahoo/athenz/zts/cert/impl/DynamoDBCertRecordStoreConnection.java
index eb29a4186a9..3a14d8b8723 100644
--- a/servers/zts/src/main/java/com/yahoo/athenz/zts/cert/impl/DynamoDBCertRecordStoreConnection.java
+++ b/servers/zts/src/main/java/com/yahoo/athenz/zts/cert/impl/DynamoDBCertRecordStoreConnection.java
@@ -19,17 +19,12 @@
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
-import com.amazonaws.services.dynamodbv2.document.*;
-import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
-import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
-import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException;
import com.yahoo.athenz.common.server.cert.CertRecordStoreConnection;
import com.yahoo.athenz.common.server.cert.X509CertRecord;
import com.yahoo.athenz.zts.ZTSConsts;
-
-import com.amazonaws.services.dynamodbv2.document.spec.DeleteItemSpec;
-import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
+import software.amazon.awssdk.services.dynamodb.model.*;
+import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import com.yahoo.athenz.zts.utils.DynamoDBUtils;
import com.yahoo.athenz.zts.utils.RetryDynamoDBCommand;
@@ -61,7 +56,7 @@ public class DynamoDBCertRecordStoreConnection implements CertRecordStoreConnect
private static final String KEY_REGISTER_TIME = "registerTime";
private static final String KEY_SVC_DATA_UPDATE_TIME = "svcDataUpdateTime";
- // the configuration setting is in hours so we'll automatically
+ // the configuration setting is in hours, so we'll automatically
// convert into seconds since that's what dynamoDB needs
// we need to expire records in 30 days
private static final Long EXPIRY_HOURS = Long.parseLong(
@@ -73,22 +68,24 @@ public class DynamoDBCertRecordStoreConnection implements CertRecordStoreConnect
private static long expiryTime = 3660 * EXPIRY_HOURS;
- private Table table;
- private final Index currentTimeIndex;
- private final Index hostNameIndex;
+ private final String tableName;
+ private final String currentTimeIndexName;
+ private final String hostNameIndexName;
+ private final DynamoDbClient dynamoDB;
private final DynamoDBNotificationsHelper dynamoDBNotificationsHelper = new DynamoDBNotificationsHelper();
- private final RetryDynamoDBCommand- getItemRetryDynamoDBCommand = new RetryDynamoDBCommand<>();
- private final RetryDynamoDBCommand updateItemRetryDynamoDBCommand = new RetryDynamoDBCommand<>();
- private final RetryDynamoDBCommand putItemRetryDynamoDBCommand = new RetryDynamoDBCommand<>();
- private final RetryDynamoDBCommand deleteItemRetryDynamoDBCommand = new RetryDynamoDBCommand<>();
- private final RetryDynamoDBCommand> itemCollectionRetryDynamoDBCommand = new RetryDynamoDBCommand<>();
-
-
- public DynamoDBCertRecordStoreConnection(DynamoDB dynamoDB, final String tableName, String currentTimeIndexName, String hostIndexName) {
- this.table = dynamoDB.getTable(tableName);
- this.currentTimeIndex = table.getIndex(currentTimeIndexName);
- this.hostNameIndex = table.getIndex(hostIndexName);
+ private final RetryDynamoDBCommand getItemRetryDynamoDBCommand = new RetryDynamoDBCommand<>();
+ private final RetryDynamoDBCommand updateItemRetryDynamoDBCommand = new RetryDynamoDBCommand<>();
+ private final RetryDynamoDBCommand putItemRetryDynamoDBCommand = new RetryDynamoDBCommand<>();
+ private final RetryDynamoDBCommand deleteItemRetryDynamoDBCommand = new RetryDynamoDBCommand<>();
+ private final RetryDynamoDBCommand itemCollectionRetryDynamoDBCommand = new RetryDynamoDBCommand<>();
+
+ public DynamoDBCertRecordStoreConnection(DynamoDbClient dynamoDB, final String tableName,
+ String currentTimeIndexName, String hostNameIndexName) {
+ this.tableName = tableName;
+ this.dynamoDB = dynamoDB;
+ this.currentTimeIndexName = currentTimeIndexName;
+ this.hostNameIndexName = hostNameIndexName;
}
@Override
@@ -103,9 +100,19 @@ public void close() {
public X509CertRecord getX509CertRecord(String provider, String instanceId, String service) {
final String primaryKey = getPrimaryKey(provider, instanceId, service);
+
+ HashMap keyToGet = new HashMap<>();
+ keyToGet.put(KEY_PRIMARY, AttributeValue.fromS(primaryKey));
+
+ GetItemRequest request = GetItemRequest.builder()
+ .key(keyToGet)
+ .tableName(tableName)
+ .build();
+
try {
- Item item = getItemRetryDynamoDBCommand.run(() -> table.getItem(KEY_PRIMARY, primaryKey));
- if (item == null) {
+ GetItemResponse response = getItemRetryDynamoDBCommand.run(() -> dynamoDB.getItem(request));
+ Map item = response.item();
+ if (item == null || item.isEmpty()) {
LOGGER.error("DynamoDB Get Error for {}: item not found", primaryKey);
return null;
}
@@ -116,29 +123,23 @@ public X509CertRecord getX509CertRecord(String provider, String instanceId, Stri
}
}
- private X509CertRecord itemToX509CertRecord(Item item) {
- boolean clientCert;
- try {
- clientCert = item.getBoolean(KEY_CLIENT_CERT);
- } catch (Exception ex) {
- LOGGER.warn("clientCert for item doesn't exist. Will set it to false. Item: {}", item.toString());
- clientCert = false;
- }
+ private X509CertRecord itemToX509CertRecord(Map item) {
+
X509CertRecord certRecord = new X509CertRecord();
- certRecord.setProvider(item.getString(KEY_PROVIDER));
- certRecord.setInstanceId(item.getString(KEY_INSTANCE_ID));
- certRecord.setService(item.getString(KEY_SERVICE));
- certRecord.setCurrentSerial(item.getString(KEY_CURRENT_SERIAL));
- certRecord.setCurrentIP(item.getString(KEY_CURRENT_IP));
+ certRecord.setProvider(DynamoDBUtils.getString(item, KEY_PROVIDER));
+ certRecord.setInstanceId(DynamoDBUtils.getString(item, KEY_INSTANCE_ID));
+ certRecord.setService(DynamoDBUtils.getString(item, KEY_SERVICE));
+ certRecord.setCurrentSerial(DynamoDBUtils.getString(item, KEY_CURRENT_SERIAL));
+ certRecord.setCurrentIP(DynamoDBUtils.getString(item, KEY_CURRENT_IP));
certRecord.setCurrentTime(DynamoDBUtils.getDateFromItem(item, KEY_CURRENT_TIME));
- certRecord.setPrevSerial(item.getString(KEY_PREV_SERIAL));
- certRecord.setPrevIP(item.getString(KEY_PREV_IP));
+ certRecord.setPrevSerial(DynamoDBUtils.getString(item, KEY_PREV_SERIAL));
+ certRecord.setPrevIP(DynamoDBUtils.getString(item, KEY_PREV_IP));
certRecord.setPrevTime(DynamoDBUtils.getDateFromItem(item, KEY_PREV_TIME));
- certRecord.setClientCert(clientCert);
+ certRecord.setClientCert(DynamoDBUtils.getBoolean(item, KEY_CLIENT_CERT));
certRecord.setLastNotifiedTime(DynamoDBUtils.getDateFromItem(item, KEY_LAST_NOTIFIED_TIME));
- certRecord.setLastNotifiedServer(item.getString(KEY_LAST_NOTIFIED_SERVER));
+ certRecord.setLastNotifiedServer(DynamoDBUtils.getString(item, KEY_LAST_NOTIFIED_SERVER));
certRecord.setExpiryTime(DynamoDBUtils.getDateFromItem(item, KEY_EXPIRY_TIME));
- certRecord.setHostName(item.getString(KEY_HOSTNAME));
+ certRecord.setHostName(DynamoDBUtils.getString(item, KEY_HOSTNAME));
certRecord.setSvcDataUpdateTime(DynamoDBUtils.getDateFromItem(item, KEY_SVC_DATA_UPDATE_TIME));
return certRecord;
}
@@ -156,33 +157,41 @@ public boolean updateX509CertRecord(X509CertRecord certRecord) {
certRecord.setSvcDataUpdateTime(new Date());
}
- String hostName = certRecord.getHostName();
// Prevent inserting null values in hostName as the hostName-Index will not allow it
+
+ String hostName = certRecord.getHostName();
if (StringUtil.isEmpty(hostName)) {
hostName = primaryKey;
}
+ HashMap itemKey = new HashMap<>();
+ itemKey.put(KEY_PRIMARY, AttributeValue.fromS(primaryKey));
+
try {
- UpdateItemSpec updateItemSpec = new UpdateItemSpec()
- .withPrimaryKey(KEY_PRIMARY, primaryKey)
- .withAttributeUpdate(
- new AttributeUpdate(KEY_INSTANCE_ID).put(certRecord.getInstanceId()),
- new AttributeUpdate(KEY_PROVIDER).put(certRecord.getProvider()),
- new AttributeUpdate(KEY_SERVICE).put(certRecord.getService()),
- new AttributeUpdate(KEY_CURRENT_SERIAL).put(certRecord.getCurrentSerial()),
- new AttributeUpdate(KEY_CURRENT_IP).put(certRecord.getCurrentIP()),
- new AttributeUpdate(KEY_CURRENT_TIME).put(DynamoDBUtils.getLongFromDate(certRecord.getCurrentTime())),
- new AttributeUpdate(KEY_CURRENT_DATE).put(DynamoDBUtils.getIso8601FromDate(certRecord.getCurrentTime())),
- new AttributeUpdate(KEY_PREV_SERIAL).put(certRecord.getPrevSerial()),
- new AttributeUpdate(KEY_PREV_IP).put(certRecord.getPrevIP()),
- new AttributeUpdate(KEY_PREV_TIME).put(DynamoDBUtils.getLongFromDate(certRecord.getPrevTime())),
- new AttributeUpdate(KEY_CLIENT_CERT).put(certRecord.getClientCert()),
- new AttributeUpdate(KEY_TTL).put(certRecord.getCurrentTime().getTime() / 1000L + expiryTime),
- new AttributeUpdate(KEY_SVC_DATA_UPDATE_TIME).put(DynamoDBUtils.getLongFromDate(certRecord.getSvcDataUpdateTime())),
- new AttributeUpdate(KEY_EXPIRY_TIME).put(DynamoDBUtils.getLongFromDate(certRecord.getExpiryTime())),
- new AttributeUpdate(KEY_HOSTNAME).put(hostName)
- );
- updateItemRetryDynamoDBCommand.run(() -> table.updateItem(updateItemSpec));
+ HashMap updatedValues = new HashMap<>();
+ DynamoDBUtils.updateItemStringValue(updatedValues, KEY_INSTANCE_ID, certRecord.getInstanceId());
+ DynamoDBUtils.updateItemStringValue(updatedValues, KEY_PROVIDER, certRecord.getProvider());
+ DynamoDBUtils.updateItemStringValue(updatedValues, KEY_SERVICE, certRecord.getService());
+ DynamoDBUtils.updateItemStringValue(updatedValues, KEY_CURRENT_SERIAL, certRecord.getCurrentSerial());
+ DynamoDBUtils.updateItemStringValue(updatedValues, KEY_CURRENT_IP, certRecord.getCurrentIP());
+ DynamoDBUtils.updateItemLongValue(updatedValues, KEY_CURRENT_TIME, certRecord.getCurrentTime());
+ DynamoDBUtils.updateItemStringValue(updatedValues, KEY_CURRENT_DATE, DynamoDBUtils.getIso8601FromDate(certRecord.getCurrentTime()));
+ DynamoDBUtils.updateItemStringValue(updatedValues, KEY_PREV_SERIAL, certRecord.getPrevSerial());
+ DynamoDBUtils.updateItemStringValue(updatedValues, KEY_PREV_IP, certRecord.getPrevIP());
+ DynamoDBUtils.updateItemLongValue(updatedValues, KEY_PREV_TIME, certRecord.getPrevTime());
+ DynamoDBUtils.updateItemBoolValue(updatedValues, KEY_CLIENT_CERT, certRecord.getClientCert());
+ DynamoDBUtils.updateItemLongValue(updatedValues, KEY_TTL, certRecord.getCurrentTime().getTime() / 1000L + expiryTime);
+ DynamoDBUtils.updateItemLongValue(updatedValues, KEY_SVC_DATA_UPDATE_TIME, certRecord.getSvcDataUpdateTime());
+ DynamoDBUtils.updateItemLongValue(updatedValues, KEY_EXPIRY_TIME, certRecord.getExpiryTime());
+ DynamoDBUtils.updateItemStringValue(updatedValues, KEY_HOSTNAME, hostName);
+
+ UpdateItemRequest request = UpdateItemRequest.builder()
+ .tableName(tableName)
+ .key(itemKey)
+ .attributeUpdates(updatedValues)
+ .build();
+
+ updateItemRetryDynamoDBCommand.run(() -> dynamoDB.updateItem(request));
return true;
} catch (Exception ex) {
LOGGER.error("DynamoDB Update Error for {}: {}/{}", primaryKey, ex.getClass(), ex.getMessage());
@@ -195,31 +204,39 @@ public boolean insertX509CertRecord(X509CertRecord certRecord) {
final String primaryKey = getPrimaryKey(certRecord.getProvider(), certRecord.getInstanceId(),
certRecord.getService());
- String hostName = certRecord.getHostName();
+
// Prevent inserting null values in hostName as the hostName-Index will not allow it
+
+ String hostName = certRecord.getHostName();
if (StringUtil.isEmpty(hostName)) {
hostName = primaryKey;
}
try {
- Item item = new Item()
- .withPrimaryKey(KEY_PRIMARY, primaryKey)
- .withString(KEY_INSTANCE_ID, certRecord.getInstanceId())
- .withString(KEY_PROVIDER, certRecord.getProvider())
- .withString(KEY_SERVICE, certRecord.getService())
- .withString(KEY_CURRENT_SERIAL, certRecord.getCurrentSerial())
- .withString(KEY_CURRENT_IP, certRecord.getCurrentIP())
- .with(KEY_CURRENT_TIME, DynamoDBUtils.getLongFromDate(certRecord.getCurrentTime()))
- .withString(KEY_CURRENT_DATE, DynamoDBUtils.getIso8601FromDate(certRecord.getCurrentTime()))
- .withString(KEY_PREV_SERIAL, certRecord.getPrevSerial())
- .withString(KEY_PREV_IP, certRecord.getPrevIP())
- .with(KEY_PREV_TIME, DynamoDBUtils.getLongFromDate(certRecord.getPrevTime()))
- .withBoolean(KEY_CLIENT_CERT, certRecord.getClientCert())
- .withLong(KEY_TTL, certRecord.getCurrentTime().getTime() / 1000L + expiryTime)
- .with(KEY_EXPIRY_TIME, DynamoDBUtils.getLongFromDate(certRecord.getExpiryTime()))
- .with(KEY_SVC_DATA_UPDATE_TIME, DynamoDBUtils.getLongFromDate(certRecord.getSvcDataUpdateTime()))
- .withLong(KEY_REGISTER_TIME, System.currentTimeMillis())
- .with(KEY_HOSTNAME, hostName);
- putItemRetryDynamoDBCommand.run(() -> table.putItem(item));
+ HashMap itemValues = new HashMap<>();
+ itemValues.put(KEY_PRIMARY, AttributeValue.fromS(primaryKey));
+ itemValues.put(KEY_INSTANCE_ID, AttributeValue.fromS(certRecord.getInstanceId()));
+ itemValues.put(KEY_PROVIDER, AttributeValue.fromS(certRecord.getProvider()));
+ itemValues.put(KEY_SERVICE, AttributeValue.fromS(certRecord.getService()));
+ itemValues.put(KEY_CURRENT_SERIAL, AttributeValue.fromS(certRecord.getCurrentSerial()));
+ itemValues.put(KEY_CURRENT_IP, AttributeValue.fromS(certRecord.getCurrentIP()));
+ itemValues.put(KEY_CURRENT_TIME, AttributeValue.fromN(DynamoDBUtils.getNumberFromDate(certRecord.getCurrentTime())));
+ itemValues.put(KEY_CURRENT_DATE, AttributeValue.fromS(DynamoDBUtils.getIso8601FromDate(certRecord.getCurrentTime())));
+ itemValues.put(KEY_PREV_SERIAL, AttributeValue.fromS(certRecord.getPrevSerial()));
+ itemValues.put(KEY_PREV_IP, AttributeValue.fromS(certRecord.getPrevIP()));
+ itemValues.put(KEY_PREV_TIME, AttributeValue.fromN(DynamoDBUtils.getNumberFromDate(certRecord.getPrevTime())));
+ itemValues.put(KEY_CLIENT_CERT, AttributeValue.fromBool(certRecord.getClientCert()));
+ itemValues.put(KEY_TTL, AttributeValue.fromN(Long.toString(certRecord.getCurrentTime().getTime() / 1000L + expiryTime)));
+ itemValues.put(KEY_EXPIRY_TIME, AttributeValue.fromN(DynamoDBUtils.getNumberFromDate(certRecord.getExpiryTime())));
+ itemValues.put(KEY_SVC_DATA_UPDATE_TIME, AttributeValue.fromN(DynamoDBUtils.getNumberFromDate(certRecord.getSvcDataUpdateTime())));
+ itemValues.put(KEY_REGISTER_TIME, AttributeValue.fromN(String.valueOf(System.currentTimeMillis())));
+ itemValues.put(KEY_HOSTNAME, AttributeValue.fromS(hostName));
+
+ PutItemRequest request = PutItemRequest.builder()
+ .tableName(tableName)
+ .item(itemValues)
+ .build();
+
+ putItemRetryDynamoDBCommand.run(() -> dynamoDB.putItem(request));
return true;
} catch (Exception ex) {
LOGGER.error("DynamoDB Insert Error for {}: {}/{}", primaryKey, ex.getClass(), ex.getMessage());
@@ -231,10 +248,17 @@ public boolean insertX509CertRecord(X509CertRecord certRecord) {
public boolean deleteX509CertRecord(String provider, String instanceId, String service) {
final String primaryKey = getPrimaryKey(provider, instanceId, service);
+
+ HashMap keyToGet = new HashMap<>();
+ keyToGet.put(KEY_PRIMARY, AttributeValue.fromS(primaryKey));
+
+ DeleteItemRequest request = DeleteItemRequest.builder()
+ .tableName(tableName)
+ .key(keyToGet)
+ .build();
+
try {
- DeleteItemSpec deleteItemSpec = new DeleteItemSpec()
- .withPrimaryKey(KEY_PRIMARY, primaryKey);
- deleteItemRetryDynamoDBCommand.run(() -> table.deleteItem(deleteItemSpec));
+ deleteItemRetryDynamoDBCommand.run(() -> dynamoDB.deleteItem(request));
return true;
} catch (Exception ex) {
LOGGER.error("DynamoDB Delete Error for {}: {}/{}", primaryKey, ex.getClass(), ex.getMessage());
@@ -246,7 +270,7 @@ public boolean deleteX509CertRecord(String provider, String instanceId, String s
public int deleteExpiredX509CertRecords(int expiryTimeMins) {
// with dynamo db there is no need to manually expunge expired
- // record since we have the TTL option enabled for our table
+ // record since we have the TTL option enabled for our table,
// and we just need to make sure the attribute is updated with
// the epoch time + timeout seconds when it should retire
@@ -254,10 +278,9 @@ public int deleteExpiredX509CertRecords(int expiryTimeMins) {
}
@Override
- public List updateUnrefreshedCertificatesNotificationTimestamp(String lastNotifiedServer,
- long lastNotifiedTime,
- String provider) {
- List
- items = getUnrefreshedCertsRecords(lastNotifiedTime, provider);
+ public List updateUnrefreshedCertificatesNotificationTimestamp(final String lastNotifiedServer,
+ long lastNotifiedTime, final String provider) {
+ List