From 42937a70c7fc65d1170881523b7957046f63b9db Mon Sep 17 00:00:00 2001 From: Mouhsin Elmajdouby Date: Fri, 25 Apr 2025 14:22:58 +0100 Subject: [PATCH 1/4] add centralized configuration support for AWS Parameter Store --- ojdbc-provider-aws/example-test.properties | 3 + ojdbc-provider-aws/pom.xml | 4 + .../AwsJsonParameterStoreProvider.java | 97 ++++++++++++++ ...wsParameterStoreConfigurationProvider.java | 119 ++++++++++++++++++ .../parameterstore/ParameterStoreFactory.java | 108 ++++++++++++++++ ...racle.jdbc.spi.OracleConfigurationProvider | 3 +- ...jdbc.spi.OracleConfigurationSecretProvider | 3 +- ...rameterStoreConfigurationProviderTest.java | 78 ++++++++++++ .../aws/configuration/AwsTestProperty.java | 3 +- 9 files changed, 415 insertions(+), 3 deletions(-) create mode 100644 ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsJsonParameterStoreProvider.java create mode 100644 ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsParameterStoreConfigurationProvider.java create mode 100644 ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/parameterstore/ParameterStoreFactory.java create mode 100644 ojdbc-provider-aws/src/test/java/oracle/provider/aws/configuration/AwsParameterStoreConfigurationProviderTest.java diff --git a/ojdbc-provider-aws/example-test.properties b/ojdbc-provider-aws/example-test.properties index d3ef0175..c940a6c8 100644 --- a/ojdbc-provider-aws/example-test.properties +++ b/ojdbc-provider-aws/example-test.properties @@ -86,3 +86,6 @@ AWS_S3_URL=jdbc:oracle:thin:@config-awss3://... # The URL to test with the AWS Secrets Manager Configuration Provider AWS_SECRETS_MANAGER_URL=jdbc:oracle:thin:@config-awssecretsmanager://... + +# The URL to test with the AWS Parameter Store Configuration Provider +AWS_PARAMETER_STORE_URL=jdbc:oracle:thin:@config-awsparameterstore://... \ No newline at end of file diff --git a/ojdbc-provider-aws/pom.xml b/ojdbc-provider-aws/pom.xml index 99c648a6..f4475d56 100644 --- a/ojdbc-provider-aws/pom.xml +++ b/ojdbc-provider-aws/pom.xml @@ -66,6 +66,10 @@ software.amazon.awssdk secretsmanager + + software.amazon.awssdk + ssm + com.oracle.database.jdbc diff --git a/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsJsonParameterStoreProvider.java b/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsJsonParameterStoreProvider.java new file mode 100644 index 00000000..671033c5 --- /dev/null +++ b/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsJsonParameterStoreProvider.java @@ -0,0 +1,97 @@ +/* + ** Copyright (c) 2025 Oracle and/or its affiliates. + ** + ** The Universal Permissive License (UPL), Version 1.0 + ** + ** Subject to the condition set forth below, permission is hereby granted to any + ** person obtaining a copy of this software, associated documentation and/or data + ** (collectively the "Software"), free of charge and under any and all copyright + ** rights in the Software, and any and all patent rights owned or freely + ** licensable by each licensor hereunder covering either (i) the unmodified + ** Software as contributed to or provided by such licensor, or (ii) the Larger + ** Works (as defined below), to deal in both + ** + ** (a) the Software, and + ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + ** one is included with the Software (each a "Larger Work" to which the Software + ** is contributed by such licensors), + ** + ** without restriction, including without limitation the rights to copy, create + ** derivative works of, display, perform, and distribute the Software and make, + ** use, sell, offer for sale, import, export, have made, and have sold the + ** Software and the Larger Work(s), and to sublicense the foregoing rights on + ** either these or other terms. + ** + ** This license is subject to the following condition: + ** The above copyright notice and either this complete permission notice or at + ** a minimum a reference to the UPL must be included in all copies or + ** substantial portions of the Software. + ** + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + ** SOFTWARE. + */ + +package oracle.jdbc.provider.aws.configuration; + +import oracle.jdbc.provider.aws.parameterstore.ParameterStoreFactory; +import oracle.jdbc.provider.parameter.ParameterSet; +import oracle.jdbc.spi.OracleConfigurationSecretProvider; + +import java.util.Base64; +import java.util.Map; + +import static oracle.jdbc.provider.aws.configuration.AwsParameterStoreConfigurationProvider.PARAMETER_SET_PARSER; + +public class AwsJsonParameterStoreProvider + implements OracleConfigurationSecretProvider { + + /** + * {@inheritDoc} + *

+ * Returns the value of the parameter retrieved from AWS Systems Manager + * Parameter Store. + *

+ *

+ * The {@code jsonObject} is expected to be in the following form: + *

+ * + *
{@code
+   *   "password": {
+   *       "type": "awsparameterstore",
+   *       "value": "/my-app/database-password"
+   *   }
+   * }
+ * + *

+ * The provider retrieves the parameter specified by the {@code value} field + * from AWS Parameter Store, then encodes it as a Base64 string. + * The encoded value is returned as a {@code char[]} for use with Oracle JDBC's + * centralized configuration. + *

+ * + * @param map Map object containing key-value pairs parsed from the JSON configuration. + * @return Base64-encoded {@code char[]} representing the retrieved secret value. + */ + @Override + public char[] getSecret(Map map) { + ParameterSet parameterSet = PARAMETER_SET_PARSER.parseNamedValues(map); + + String parameterValue = ParameterStoreFactory.getInstance() + .request(parameterSet) + .getContent(); + + return Base64.getEncoder() + .encodeToString(parameterValue.getBytes()) + .toCharArray(); + } + + @Override + public String getSecretType() { + return "awsparameterstore"; + } +} \ No newline at end of file diff --git a/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsParameterStoreConfigurationProvider.java b/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsParameterStoreConfigurationProvider.java new file mode 100644 index 00000000..1dde8350 --- /dev/null +++ b/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsParameterStoreConfigurationProvider.java @@ -0,0 +1,119 @@ +/* + ** Copyright (c) 2025 Oracle and/or its affiliates. + ** + ** The Universal Permissive License (UPL), Version 1.0 + ** + ** Subject to the condition set forth below, permission is hereby granted to any + ** person obtaining a copy of this software, associated documentation and/or data + ** (collectively the "Software"), free of charge and under any and all copyright + ** rights in the Software, and any and all patent rights owned or freely + ** licensable by each licensor hereunder covering either (i) the unmodified + ** Software as contributed to or provided by such licensor, or (ii) the Larger + ** Works (as defined below), to deal in both + ** + ** (a) the Software, and + ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + ** one is included with the Software (each a "Larger Work" to which the Software + ** is contributed by such licensors), + ** + ** without restriction, including without limitation the rights to copy, create + ** derivative works of, display, perform, and distribute the Software and make, + ** use, sell, offer for sale, import, export, have made, and have sold the + ** Software and the Larger Work(s), and to sublicense the foregoing rights on + ** either these or other terms. + ** + ** This license is subject to the following condition: + ** The above copyright notice and either this complete permission notice or at + ** a minimum a reference to the UPL must be included in all copies or + ** substantial portions of the Software. + ** + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + ** SOFTWARE. + */ + +package oracle.jdbc.provider.aws.configuration; + +import oracle.jdbc.driver.configuration.OracleConfigurationParsableProvider; +import oracle.jdbc.provider.aws.parameterstore.ParameterStoreFactory; +import oracle.jdbc.provider.parameter.Parameter; +import oracle.jdbc.provider.parameter.ParameterSet; +import oracle.jdbc.provider.parameter.ParameterSetParser; +import oracle.jdbc.util.OracleConfigurationCache; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import static oracle.jdbc.provider.aws.configuration.AwsConfigurationParameters.KEY; +import static oracle.jdbc.provider.aws.configuration.AwsConfigurationParameters.REGION; + +/** + * A provider for JSON payload which contains configuration from AWS Systems + * Manager Parameter Store. + * See {@link #getInputStream(String)} for the spec of the JSON payload. + **/ +public class AwsParameterStoreConfigurationProvider + extends OracleConfigurationParsableProvider { + + static final ParameterSetParser PARAMETER_SET_PARSER = + AwsConfigurationParameters.configureBuilder( + ParameterSetParser.builder() + .addParameter("value", ParameterStoreFactory.PARAMETER_NAME) + .addParameter("key", KEY) + .addParameter("type", Parameter.create()) + .addParameter("AWS_REGION", REGION) + ).build(); + + /** + * {@inheritDoc} + *

+ * Returns the JSON payload stored in AWS Systems Manager Parameter Store. + *

+ * + * @param parameterName name of the secret + * @return JSON payload + */ + @Override + public InputStream getInputStream(String parameterName) { + // The JSON “value” field holds the Parameter Store name + final String VALUE = "value"; + Map opts = new HashMap<>(options); + opts.put(VALUE, parameterName); + + ParameterSet params = PARAMETER_SET_PARSER.parseNamedValues(opts); + String json = ParameterStoreFactory.getInstance() + .request(params) + .getContent(); + + return new ByteArrayInputStream(json.getBytes()); + } + + @Override + public String getType() { + return "awsparameterstore"; + } + + /** + * {@inheritDoc} + * @return cache of this provider which is used to store configuration + */ + @Override + public OracleConfigurationCache getCache() { + return CACHE; + } + + /** + * {@inheritDoc} + * @return the parser type + */ + @Override + public String getParserType(String location) { + return "json"; + } +} \ No newline at end of file diff --git a/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/parameterstore/ParameterStoreFactory.java b/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/parameterstore/ParameterStoreFactory.java new file mode 100644 index 00000000..6a96ac57 --- /dev/null +++ b/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/parameterstore/ParameterStoreFactory.java @@ -0,0 +1,108 @@ +/* + ** Copyright (c) 2025 Oracle and/or its affiliates. + ** + ** The Universal Permissive License (UPL), Version 1.0 + ** + ** Subject to the condition set forth below, permission is hereby granted to any + ** person obtaining a copy of this software, associated documentation and/or data + ** (collectively the "Software"), free of charge and under any and all copyright + ** rights in the Software, and any and all patent rights owned or freely + ** licensable by each licensor hereunder covering either (i) the unmodified + ** Software as contributed to or provided by such licensor, or (ii) the Larger + ** Works (as defined below), to deal in both + ** + ** (a) the Software, and + ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + ** one is included with the Software (each a "Larger Work" to which the Software + ** is contributed by such licensors), + ** + ** without restriction, including without limitation the rights to copy, create + ** derivative works of, display, perform, and distribute the Software and make, + ** use, sell, offer for sale, import, export, have made, and have sold the + ** Software and the Larger Work(s), and to sublicense the foregoing rights on + ** either these or other terms. + ** + ** This license is subject to the following condition: + ** The above copyright notice and either this complete permission notice or at + ** a minimum a reference to the UPL must be included in all copies or + ** substantial portions of the Software. + ** + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + ** SOFTWARE. + */ + +package oracle.jdbc.provider.aws.parameterstore; + +import oracle.jdbc.provider.aws.AwsResourceFactory; +import oracle.jdbc.provider.cache.CachedResourceFactory; +import oracle.jdbc.provider.factory.Resource; +import oracle.jdbc.provider.factory.ResourceFactory; +import oracle.jdbc.provider.parameter.Parameter; +import oracle.jdbc.provider.parameter.ParameterSet; +import software.amazon.awssdk.auth.credentials.AwsCredentials; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.ssm.SsmClient; +import software.amazon.awssdk.services.ssm.SsmClientBuilder; +import software.amazon.awssdk.services.ssm.model.GetParameterRequest; +import software.amazon.awssdk.services.ssm.model.GetParameterResponse; + +import static oracle.jdbc.provider.aws.configuration.AwsConfigurationParameters.REGION; +import static oracle.jdbc.provider.parameter.Parameter.CommonAttribute.REQUIRED; + +public final class ParameterStoreFactory + extends AwsResourceFactory { + + /** + * The name of the parameter to retrieve from AWS Systems Manager Parameter Store. + * This is a required parameter. + */ + public static final Parameter PARAMETER_NAME = + Parameter.create(REQUIRED); + + /** + * The single instance of {@code CachedResourceFactory} for requesting + * parameter values from AWS Systems Manager Parameter Store. + */ + private static final ResourceFactory INSTANCE = + CachedResourceFactory.create(new ParameterStoreFactory()); + + private ParameterStoreFactory() { } + + /** + * Returns a singleton instance of {@code ParameterStoreFactory}. + * + * @return the singleton factory instance + */ + public static ResourceFactory getInstance() { + return INSTANCE; + } + + @Override + public Resource request(AwsCredentials awsCredentials, ParameterSet parameterSet) { + String name = parameterSet.getRequired(PARAMETER_NAME); + String region = parameterSet.getOptional(REGION); + + SsmClientBuilder builder = SsmClient + .builder() + .credentialsProvider(() -> awsCredentials); + + if (region != null) { + builder.region(Region.of(region)); + } + + try (SsmClient client = builder.build()) { + GetParameterRequest req = GetParameterRequest.builder() + .name(name) + .withDecryption(true) + .build(); + GetParameterResponse resp = client.getParameter(req); + String value = resp.parameter().value(); + return Resource.createPermanentResource(value, true); + } + } +} \ No newline at end of file diff --git a/ojdbc-provider-aws/src/main/resources/META-INF/services/oracle.jdbc.spi.OracleConfigurationProvider b/ojdbc-provider-aws/src/main/resources/META-INF/services/oracle.jdbc.spi.OracleConfigurationProvider index d09ec836..d431ae41 100644 --- a/ojdbc-provider-aws/src/main/resources/META-INF/services/oracle.jdbc.spi.OracleConfigurationProvider +++ b/ojdbc-provider-aws/src/main/resources/META-INF/services/oracle.jdbc.spi.OracleConfigurationProvider @@ -1,2 +1,3 @@ oracle.jdbc.provider.aws.configuration.AwsS3ConfigurationProvider -oracle.jdbc.provider.aws.configuration.AwsSecretsManagerConfigurationProvider \ No newline at end of file +oracle.jdbc.provider.aws.configuration.AwsSecretsManagerConfigurationProvider +oracle.jdbc.provider.aws.configuration.AwsParameterStoreConfigurationProvider \ No newline at end of file diff --git a/ojdbc-provider-aws/src/main/resources/META-INF/services/oracle.jdbc.spi.OracleConfigurationSecretProvider b/ojdbc-provider-aws/src/main/resources/META-INF/services/oracle.jdbc.spi.OracleConfigurationSecretProvider index 9741b03f..2561ee64 100644 --- a/ojdbc-provider-aws/src/main/resources/META-INF/services/oracle.jdbc.spi.OracleConfigurationSecretProvider +++ b/ojdbc-provider-aws/src/main/resources/META-INF/services/oracle.jdbc.spi.OracleConfigurationSecretProvider @@ -1 +1,2 @@ -oracle.jdbc.provider.aws.configuration.AwsJsonSecretsManagerProvider \ No newline at end of file +oracle.jdbc.provider.aws.configuration.AwsJsonSecretsManagerProvider +oracle.jdbc.provider.aws.configuration.AwsJsonParameterStoreProvider \ No newline at end of file diff --git a/ojdbc-provider-aws/src/test/java/oracle/provider/aws/configuration/AwsParameterStoreConfigurationProviderTest.java b/ojdbc-provider-aws/src/test/java/oracle/provider/aws/configuration/AwsParameterStoreConfigurationProviderTest.java new file mode 100644 index 00000000..92651d62 --- /dev/null +++ b/ojdbc-provider-aws/src/test/java/oracle/provider/aws/configuration/AwsParameterStoreConfigurationProviderTest.java @@ -0,0 +1,78 @@ +/* + ** Copyright (c) 2025 Oracle and/or its affiliates. + ** + ** The Universal Permissive License (UPL), Version 1.0 + ** + ** Subject to the condition set forth below, permission is hereby granted to any + ** person obtaining a copy of this software, associated documentation and/or data + ** (collectively the "Software"), free of charge and under any and all copyright + ** rights in the Software, and any and all patent rights owned or freely + ** licensable by each licensor hereunder covering either (i) the unmodified + ** Software as contributed to or provided by such licensor, or (ii) the Larger + ** Works (as defined below), to deal in both + ** + ** (a) the Software, and + ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + ** one is included with the Software (each a "Larger Work" to which the Software + ** is contributed by such licensors), + ** + ** without restriction, including without limitation the rights to copy, create + ** derivative works of, display, perform, and distribute the Software and make, + ** use, sell, offer for sale, import, export, have made, and have sold the + ** Software and the Larger Work(s), and to sublicense the foregoing rights on + ** either these or other terms. + ** + ** This license is subject to the following condition: + ** The above copyright notice and either this complete permission notice or at + ** a minimum a reference to the UPL must be included in all copies or + ** substantial portions of the Software. + ** + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + ** SOFTWARE. + */ +package oracle.provider.aws.configuration; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.spi.OracleConfigurationProvider; +import org.junit.jupiter.api.Test; + +import java.sql.SQLException; +import java.util.Properties; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class AwsParameterStoreConfigurationProviderTest { + + static { + OracleConfigurationProvider.allowedProviders.add("awsparameterstore"); + } + + private static final OracleConfigurationProvider PROVIDER = + OracleConfigurationProvider.find("awsparameterstore"); + + /** + * Verifies if AWS Parameter Store Configuration Provider works with default authentication + * @throws SQLException + */ + @Test + public void testDefaultAuthentication() throws SQLException { + final String prefix = "jdbc:oracle:thin:@config-awsparameterstore://"; + + String url = TestProperties.getOrAbort( + AwsTestProperty.AWS_PARAMETER_STORE_URL); + assertTrue(url.startsWith(prefix), + "AWS_PARAMETER_STORE_URL should start with " + prefix); + + Properties properties = PROVIDER + .getConnectionProperties(url.substring(prefix.length())); + + assertTrue(properties.containsKey("URL"), "Contains property URL"); + assertTrue(properties.containsKey("user"), "Contains property user"); + assertTrue(properties.containsKey("password"), "Contains property password"); + } +} diff --git a/ojdbc-provider-aws/src/test/java/oracle/provider/aws/configuration/AwsTestProperty.java b/ojdbc-provider-aws/src/test/java/oracle/provider/aws/configuration/AwsTestProperty.java index 214437ca..ced3aa5e 100644 --- a/ojdbc-provider-aws/src/test/java/oracle/provider/aws/configuration/AwsTestProperty.java +++ b/ojdbc-provider-aws/src/test/java/oracle/provider/aws/configuration/AwsTestProperty.java @@ -39,5 +39,6 @@ public enum AwsTestProperty { AWS_S3_URL, - AWS_SECRETS_MANAGER_URL + AWS_SECRETS_MANAGER_URL, + AWS_PARAMETER_STORE_URL } From c6a96a03eb2b07539a50500c483948b5cba8d4d6 Mon Sep 17 00:00:00 2001 From: Mouhsin Elmajdouby Date: Fri, 25 Apr 2025 16:23:22 +0100 Subject: [PATCH 2/4] Update Readme file with AWS Parameter Store configuration provider --- ojdbc-provider-aws/README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/ojdbc-provider-aws/README.md b/ojdbc-provider-aws/README.md index 72495d37..8538ed55 100644 --- a/ojdbc-provider-aws/README.md +++ b/ojdbc-provider-aws/README.md @@ -12,6 +12,9 @@ Provider
AWS Secrets Manager Configuration Provider
Provides connection properties managed by the Secrets Manager service
+
AWS Parameter Store Configuration +Provider
+
Provides connection properties managed by the Systems Manager Parameter Store
Common Parameters for Centralized Config Providers
Common parameters supported by the config providers
Caching configuration
@@ -97,7 +100,7 @@ The sample code below executes as expected with the previous configuration. ### Password JSON Object -For the JSON type of provider (AWS S3, AWS Secrets Manager, HTTP/HTTPS, File) the password is an object itself with the following spec: +For the JSON type of provider (AWS S3, AWS Secrets Manager, AWS Parameter Store, HTTP/HTTPS, File) the password is an object itself with the following spec: - type - Mandatory @@ -106,6 +109,7 @@ For the JSON type of provider (AWS S3, AWS Secrets Manager, HTTP/HTTPS, File) th - azurevault - base64 - awssecretsmanager + - awsparameterstore - value - Mandatory - Possible values @@ -113,6 +117,7 @@ For the JSON type of provider (AWS S3, AWS Secrets Manager, HTTP/HTTPS, File) th - Azure Key Vault URI (if azurevault) - Base64 Encoded password (if base64) - AWS Secret name (if awssecretsmanager) + - AWS Parameter name (if awsparameterstore) - authentication - Optional - Possible Values @@ -128,6 +133,16 @@ jdbc:oracle:thin:@config-awssecretsmanager://{secret-name} The JSON Payload retrieved by AWS Secrets Manager Provider follows the same format in [AWS S3 Configuration Provider](#json-payload-format). +## AWS Parameter Store Config Provider +Apart from AWS S3 and Secrets Manager, users can also store JSON payload in AWS Systems Manager Parameter Store. +To use it, specify the name of the parameter: + +
+jdbc:oracle:thin:@config-awsparameterstore://{parameter-name}
+
+ +The JSON payload stored in the parameter should follow the same format as described in [AWS S3 Configuration Provider](#json-payload-format). + ## Common Parameters for Centralized Config Providers AWS S3 Configuration Provider and AWS Secrets Manager Configuration Provider share the same sets of parameters for authentication configuration. From eac2c0255a005af01d0430664adbe3a304421aa8 Mon Sep 17 00:00:00 2001 From: Mouhsin Elmajdouby Date: Mon, 28 Apr 2025 16:29:30 +0100 Subject: [PATCH 3/4] Add AWS Parameter Store sample and fix indentation --- .../AwsJsonParameterStoreProvider.java | 10 +-- ...wsParameterStoreConfigurationProvider.java | 20 ++--- .../parameterstore/ParameterStoreFactory.java | 16 ++-- ...AwsParameterStoreConfigurationExample.java | 84 +++++++++++++++++++ 4 files changed, 107 insertions(+), 23 deletions(-) create mode 100644 ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/aws/configuration/AwsParameterStoreConfigurationExample.java diff --git a/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsJsonParameterStoreProvider.java b/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsJsonParameterStoreProvider.java index 671033c5..96ed1a39 100644 --- a/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsJsonParameterStoreProvider.java +++ b/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsJsonParameterStoreProvider.java @@ -48,7 +48,7 @@ import static oracle.jdbc.provider.aws.configuration.AwsParameterStoreConfigurationProvider.PARAMETER_SET_PARSER; public class AwsJsonParameterStoreProvider - implements OracleConfigurationSecretProvider { + implements OracleConfigurationSecretProvider { /** * {@inheritDoc} @@ -82,12 +82,12 @@ public char[] getSecret(Map map) { ParameterSet parameterSet = PARAMETER_SET_PARSER.parseNamedValues(map); String parameterValue = ParameterStoreFactory.getInstance() - .request(parameterSet) - .getContent(); + .request(parameterSet) + .getContent(); return Base64.getEncoder() - .encodeToString(parameterValue.getBytes()) - .toCharArray(); + .encodeToString(parameterValue.getBytes()) + .toCharArray(); } @Override diff --git a/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsParameterStoreConfigurationProvider.java b/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsParameterStoreConfigurationProvider.java index 1dde8350..133158f8 100644 --- a/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsParameterStoreConfigurationProvider.java +++ b/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsParameterStoreConfigurationProvider.java @@ -59,16 +59,16 @@ * See {@link #getInputStream(String)} for the spec of the JSON payload. **/ public class AwsParameterStoreConfigurationProvider - extends OracleConfigurationParsableProvider { + extends OracleConfigurationParsableProvider { static final ParameterSetParser PARAMETER_SET_PARSER = - AwsConfigurationParameters.configureBuilder( - ParameterSetParser.builder() - .addParameter("value", ParameterStoreFactory.PARAMETER_NAME) - .addParameter("key", KEY) - .addParameter("type", Parameter.create()) - .addParameter("AWS_REGION", REGION) - ).build(); + AwsConfigurationParameters.configureBuilder( + ParameterSetParser.builder() + .addParameter("value", ParameterStoreFactory.PARAMETER_NAME) + .addParameter("key", KEY) + .addParameter("type", Parameter.create()) + .addParameter("AWS_REGION", REGION) + ).build(); /** * {@inheritDoc} @@ -88,8 +88,8 @@ public InputStream getInputStream(String parameterName) { ParameterSet params = PARAMETER_SET_PARSER.parseNamedValues(opts); String json = ParameterStoreFactory.getInstance() - .request(params) - .getContent(); + .request(params) + .getContent(); return new ByteArrayInputStream(json.getBytes()); } diff --git a/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/parameterstore/ParameterStoreFactory.java b/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/parameterstore/ParameterStoreFactory.java index 6a96ac57..e4b6fdb9 100644 --- a/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/parameterstore/ParameterStoreFactory.java +++ b/ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/parameterstore/ParameterStoreFactory.java @@ -55,21 +55,21 @@ import static oracle.jdbc.provider.parameter.Parameter.CommonAttribute.REQUIRED; public final class ParameterStoreFactory - extends AwsResourceFactory { + extends AwsResourceFactory { /** * The name of the parameter to retrieve from AWS Systems Manager Parameter Store. * This is a required parameter. */ public static final Parameter PARAMETER_NAME = - Parameter.create(REQUIRED); + Parameter.create(REQUIRED); /** * The single instance of {@code CachedResourceFactory} for requesting * parameter values from AWS Systems Manager Parameter Store. */ private static final ResourceFactory INSTANCE = - CachedResourceFactory.create(new ParameterStoreFactory()); + CachedResourceFactory.create(new ParameterStoreFactory()); private ParameterStoreFactory() { } @@ -88,8 +88,8 @@ public Resource request(AwsCredentials awsCredentials, ParameterSet para String region = parameterSet.getOptional(REGION); SsmClientBuilder builder = SsmClient - .builder() - .credentialsProvider(() -> awsCredentials); + .builder() + .credentialsProvider(() -> awsCredentials); if (region != null) { builder.region(Region.of(region)); @@ -97,9 +97,9 @@ public Resource request(AwsCredentials awsCredentials, ParameterSet para try (SsmClient client = builder.build()) { GetParameterRequest req = GetParameterRequest.builder() - .name(name) - .withDecryption(true) - .build(); + .name(name) + .withDecryption(true) + .build(); GetParameterResponse resp = client.getParameter(req); String value = resp.parameter().value(); return Resource.createPermanentResource(value, true); diff --git a/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/aws/configuration/AwsParameterStoreConfigurationExample.java b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/aws/configuration/AwsParameterStoreConfigurationExample.java new file mode 100644 index 00000000..d0564aab --- /dev/null +++ b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/aws/configuration/AwsParameterStoreConfigurationExample.java @@ -0,0 +1,84 @@ +/* + ** Copyright (c) 2025 Oracle and/or its affiliates. + ** + ** The Universal Permissive License (UPL), Version 1.0 + ** + ** Subject to the condition set forth below, permission is hereby granted to any + ** person obtaining a copy of this software, associated documentation and/or data + ** (collectively the "Software"), free of charge and under any and all copyright + ** rights in the Software, and any and all patent rights owned or freely + ** licensable by each licensor hereunder covering either (i) the unmodified + ** Software as contributed to or provided by such licensor, or (ii) the Larger + ** Works (as defined below), to deal in both + ** + ** (a) the Software, and + ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + ** one is included with the Software (each a "Larger Work" to which the Software + ** is contributed by such licensors), + ** + ** without restriction, including without limitation the rights to copy, create + ** derivative works of, display, perform, and distribute the Software and make, + ** use, sell, offer for sale, import, export, have made, and have sold the + ** Software and the Larger Work(s), and to sublicense the foregoing rights on + ** either these or other terms. + ** + ** This license is subject to the following condition: + ** The above copyright notice and either this complete permission notice or at + ** a minimum a reference to the UPL must be included in all copies or + ** substantial portions of the Software. + ** + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + ** SOFTWARE. + */ +package oracle.jdbc.provider.aws.configuration; + +import oracle.jdbc.datasource.impl.OracleDataSource; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * A standalone example that configures Oracle JDBC to be provided with the + * connection properties retrieved from AWS Systems Manager Parameter Store. + */ +public class AwsParameterStoreConfigurationExample { + private static String url; + + /** + *

+ * A simple example to retrieve connection properties from AWS Parameter Store. + *

+ * For the default authentication, the only required local configuration is + * to have a valid AWS Config in ~/.aws/config and ~/.aws/credentials. + *

+ * @param args the command line arguments + * @throws SQLException if an error occurs during the database calls + */ + public static void main(String[] args) throws SQLException { + + // Sample default URL if non present + if (args.length == 0) { + url = "jdbc:oracle:thin:@config-awsparameterstore://parameter_name"; + } else { + url = args[0]; + } + + // No changes required, configuration provider is loaded at runtime + OracleDataSource ds = new OracleDataSource(); + ds.setURL(url); + + // Standard JDBC code + Connection cn = ds.getConnection(); + Statement st = cn.createStatement(); + ResultSet rs = st.executeQuery("SELECT 'Hello, db' FROM sys.dual"); + if (rs.next()) + System.out.println(rs.getString(1)); + } +} From 7880853ed02d074862504e9c779bcfc069369e2b Mon Sep 17 00:00:00 2001 From: Mouhsin Elmajdouby Date: Fri, 18 Jul 2025 16:39:40 +0100 Subject: [PATCH 4/4] Fix import after syncing with main branch --- .../AwsParameterStoreConfigurationProviderTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ojdbc-provider-aws/src/test/java/oracle/provider/aws/configuration/AwsParameterStoreConfigurationProviderTest.java b/ojdbc-provider-aws/src/test/java/oracle/provider/aws/configuration/AwsParameterStoreConfigurationProviderTest.java index 92651d62..e0347306 100644 --- a/ojdbc-provider-aws/src/test/java/oracle/provider/aws/configuration/AwsParameterStoreConfigurationProviderTest.java +++ b/ojdbc-provider-aws/src/test/java/oracle/provider/aws/configuration/AwsParameterStoreConfigurationProviderTest.java @@ -39,6 +39,7 @@ import oracle.jdbc.provider.TestProperties; import oracle.jdbc.spi.OracleConfigurationProvider; +import oracle.provider.aws.AwsTestProperty; import org.junit.jupiter.api.Test; import java.sql.SQLException;