diff --git a/containers/jetty/pom.xml b/containers/jetty/pom.xml
index f33233bc7a4..57097d146a4 100644
--- a/containers/jetty/pom.xml
+++ b/containers/jetty/pom.xml
@@ -155,11 +155,6 @@
bcpkix-jdk18on
${bouncycastle.version}
-
- org.bouncycastle
- bcprov-ext-jdk18on
- 1.78
-
jakarta.ws.rs
jakarta.ws.rs-api
diff --git a/libs/java/auth_core/pom.xml b/libs/java/auth_core/pom.xml
index be16fc39c74..47cf0b3df00 100644
--- a/libs/java/auth_core/pom.xml
+++ b/libs/java/auth_core/pom.xml
@@ -30,6 +30,18 @@
0.9007
+
+
+
+ software.amazon.awssdk
+ bom
+ ${aws2.version}
+ pom
+ import
+
+
+
+
org.slf4j
@@ -79,6 +91,10 @@
jjwt-api
${jjwt.version}
+
+ software.amazon.awssdk
+ ssm
+
io.jsonwebtoken
jjwt-impl
diff --git a/libs/java/auth_core/src/main/java/com/yahoo/athenz/auth/impl/AWSParameterStorePrivateKeyStore.java b/libs/java/auth_core/src/main/java/com/yahoo/athenz/auth/impl/AWSParameterStorePrivateKeyStore.java
new file mode 100644
index 00000000000..b04ebdbd2c7
--- /dev/null
+++ b/libs/java/auth_core/src/main/java/com/yahoo/athenz/auth/impl/AWSParameterStorePrivateKeyStore.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright The Athenz Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.yahoo.athenz.auth.impl;
+
+import com.yahoo.athenz.auth.PrivateKeyStore;
+import com.yahoo.athenz.auth.ServerPrivateKey;
+import com.yahoo.athenz.auth.util.Crypto;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import software.amazon.awssdk.services.ssm.SsmClient;
+
+import java.lang.invoke.MethodHandles;
+import java.security.PrivateKey;
+
+public class AWSParameterStorePrivateKeyStore implements PrivateKeyStore {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ private static final String ZMS_SERVICE = "zms";
+ private static final String ZTS_SERVICE = "zts";
+ private static final String MSD_SERVICE = "msd";
+
+ private static final String ATHENZ_PROP_ZMS_KEY_NAME = "athenz.aws.zms.key_name";
+ private static final String ATHENZ_PROP_ZMS_KEY_ID_NAME = "athenz.aws.zms.key_id_name";
+ private static final String ATHENZ_PROP_ZTS_KEY_NAME = "athenz.aws.zts.key_name";
+ private static final String ATHENZ_PROP_ZTS_KEY_ID_NAME = "athenz.aws.zts.key_id_name";
+ private static final String ATHENZ_PROP_MSD_KEY_NAME = "athenz.aws.msd.key_name";
+ private static final String ATHENZ_PROP_MSD_KEY_ID_NAME = "athenz.aws.msd.key_id_name";
+
+ private static final String ATHENZ_DEFAULT_KEY_NAME = "service_private_key";
+ private static final String ATHENZ_DEFAULT_KEY_ID_NAME = "service_private_key_id";
+
+ private final SsmClient ssmClient;
+
+ AWSParameterStorePrivateKeyStore(SsmClient ssmClient) {
+ this.ssmClient = ssmClient;
+ }
+
+ @Override
+ public char[] getSecret(String appName, String keyName) {
+ return getSsmParameter(keyName).toCharArray();
+ }
+
+ @Override
+ public ServerPrivateKey getPrivateKey(String service, String serverHostName, String serverRegion, String algorithm) {
+ if (serverRegion == null || serverRegion.isEmpty()) {
+ LOG.error("server region not specified");
+ return null;
+ }
+ String keyName;
+ String keyIdName;
+ final String objectSuffix = "." + algorithm.toLowerCase();
+ if (ZMS_SERVICE.equals(service)) {
+ keyName = System.getProperty(ATHENZ_PROP_ZMS_KEY_NAME, ATHENZ_DEFAULT_KEY_NAME) + objectSuffix;
+ keyIdName = System.getProperty(ATHENZ_PROP_ZMS_KEY_ID_NAME, ATHENZ_DEFAULT_KEY_ID_NAME) + objectSuffix;
+ } else if (ZTS_SERVICE.equals(service)) {
+ keyName = System.getProperty(ATHENZ_PROP_ZTS_KEY_NAME, ATHENZ_DEFAULT_KEY_NAME) + objectSuffix;
+ keyIdName = System.getProperty(ATHENZ_PROP_ZTS_KEY_ID_NAME, ATHENZ_DEFAULT_KEY_ID_NAME) + objectSuffix;
+ } else if (MSD_SERVICE.equals(service)) {
+ keyName = System.getProperty(ATHENZ_PROP_MSD_KEY_NAME, ATHENZ_DEFAULT_KEY_NAME) + objectSuffix;
+ keyIdName = System.getProperty(ATHENZ_PROP_MSD_KEY_ID_NAME, ATHENZ_DEFAULT_KEY_ID_NAME) + objectSuffix;
+ } else {
+ LOG.error("Unknown service specified: {}", service);
+ return null;
+ }
+
+ PrivateKey pkey = null;
+ try {
+ pkey = Crypto.loadPrivateKey(getSsmParameter(keyName));
+ } catch (Exception ex) {
+ LOG.error("unable to load private key", ex);
+ }
+ return pkey == null ? null : new ServerPrivateKey(pkey, getSsmParameter(keyIdName));
+ }
+
+ private String getSsmParameter(final String keyName) {
+ return ssmClient.getParameter(r -> r.name(keyName).withDecryption(true)).parameter().value();
+ }
+
+}
diff --git a/libs/java/auth_core/src/main/java/com/yahoo/athenz/auth/impl/AWSParameterStorePrivateKeyStoreFactory.java b/libs/java/auth_core/src/main/java/com/yahoo/athenz/auth/impl/AWSParameterStorePrivateKeyStoreFactory.java
new file mode 100644
index 00000000000..74a5228aec7
--- /dev/null
+++ b/libs/java/auth_core/src/main/java/com/yahoo/athenz/auth/impl/AWSParameterStorePrivateKeyStoreFactory.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright The Athenz Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.yahoo.athenz.auth.impl;
+
+import com.yahoo.athenz.auth.PrivateKeyStore;
+import com.yahoo.athenz.auth.PrivateKeyStoreFactory;
+import software.amazon.awssdk.services.ssm.SsmClient;
+
+public class AWSParameterStorePrivateKeyStoreFactory implements PrivateKeyStoreFactory {
+
+ @Override
+ public PrivateKeyStore create() {
+ return new AWSParameterStorePrivateKeyStore(SsmClient.create());
+ }
+}
diff --git a/libs/java/auth_core/src/test/java/com/yahoo/athenz/auth/impl/AWSParameterStorePrivateKeyStoreFactoryTest.java b/libs/java/auth_core/src/test/java/com/yahoo/athenz/auth/impl/AWSParameterStorePrivateKeyStoreFactoryTest.java
new file mode 100644
index 00000000000..50763be4d5c
--- /dev/null
+++ b/libs/java/auth_core/src/test/java/com/yahoo/athenz/auth/impl/AWSParameterStorePrivateKeyStoreFactoryTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright The Athenz Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.yahoo.athenz.auth.impl;
+
+import com.yahoo.athenz.auth.PrivateKeyStore;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+
+public class AWSParameterStorePrivateKeyStoreFactoryTest {
+
+ @Test
+ public void createAWSParameterStorePrivateKeyStore() {
+ System.setProperty("aws.region", "us-west-2");
+ PrivateKeyStore privateKeyStore = new AWSParameterStorePrivateKeyStoreFactory().create();
+ assertTrue(privateKeyStore instanceof AWSParameterStorePrivateKeyStore);
+ System.clearProperty("aws.region");
+ }
+}
\ No newline at end of file
diff --git a/libs/java/auth_core/src/test/java/com/yahoo/athenz/auth/impl/AWSParameterStorePrivateKeyStoreTest.java b/libs/java/auth_core/src/test/java/com/yahoo/athenz/auth/impl/AWSParameterStorePrivateKeyStoreTest.java
new file mode 100644
index 00000000000..16a451b6066
--- /dev/null
+++ b/libs/java/auth_core/src/test/java/com/yahoo/athenz/auth/impl/AWSParameterStorePrivateKeyStoreTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright The Athenz Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.yahoo.athenz.auth.impl;
+import com.yahoo.athenz.auth.PrivateKeyStore;
+import org.mockito.Mockito;
+import org.testng.annotations.Test;
+import software.amazon.awssdk.services.ssm.SsmClient;
+import software.amazon.awssdk.services.ssm.model.GetParameterResponse;
+import software.amazon.awssdk.services.ssm.model.Parameter;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.function.Consumer;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.*;
+
+public class AWSParameterStorePrivateKeyStoreTest {
+
+ private AWSParameterStorePrivateKeyStoreFactory getFactory(final SsmClient ssmClient) {
+ return new AWSParameterStorePrivateKeyStoreFactory() {
+ @Override
+ public PrivateKeyStore create() {
+ return new AWSParameterStorePrivateKeyStore(ssmClient);
+ }
+ };
+ }
+
+ @Test
+ public void testGetSecret() {
+ SsmClient ssmClient = Mockito.mock(SsmClient.class);
+ when(ssmClient.getParameter(any(Consumer.class)))
+ .thenReturn(GetParameterResponse.builder().parameter(Parameter.builder().value("secret").build()).build());
+ AWSParameterStorePrivateKeyStore store = (AWSParameterStorePrivateKeyStore)getFactory(ssmClient).create();
+ assertEquals(store.getSecret("app1", "key1"), "secret".toCharArray());
+ }
+
+ @Test
+ public void testGetPrivateKey() throws IOException {
+ SsmClient ssmClient = Mockito.mock(SsmClient.class);
+ Path path = Paths.get("src/test/resources/unit_test_ec_private.key");
+ try (FileInputStream fis = new FileInputStream(path.toFile())) {
+ String secret = new String(fis.readAllBytes());
+ when(ssmClient.getParameter(any(Consumer.class)))
+ .thenReturn(GetParameterResponse.builder().parameter(Parameter.builder().value(secret).build()).build());
+ AWSParameterStorePrivateKeyStore store = (AWSParameterStorePrivateKeyStore)getFactory(ssmClient).create();
+ assertNotNull(store.getPrivateKey("zms", "host1", "region1", "EC"));
+ }
+ }
+
+ @Test
+ public void testGetPrivateKeyInvalidInputs() {
+ SsmClient ssmClient = Mockito.mock(SsmClient.class);
+ AWSParameterStorePrivateKeyStore store = (AWSParameterStorePrivateKeyStore)getFactory(ssmClient).create();
+ assertNull(store.getPrivateKey("unknown", "host1", "region1", "EC"));
+ assertNull(store.getPrivateKey("zms", "host1", "region1", "unknown"));
+ assertNull(store.getPrivateKey("zms", "host1", null, "RSA"));
+ }
+}
\ No newline at end of file
diff --git a/libs/java/server_common/pom.xml b/libs/java/server_common/pom.xml
index fbdbfe094fc..0a59a931a15 100644
--- a/libs/java/server_common/pom.xml
+++ b/libs/java/server_common/pom.xml
@@ -168,11 +168,6 @@
bcutil-jdk18on
${bouncycastle.version}
-
- org.bouncycastle
- bcprov-ext-jdk18on
- 1.78
-
com.fasterxml.jackson.core
jackson-databind