Skip to content

Commit 5651e71

Browse files
Add Resource Providers for AWS Secrets Manager (#179)
* Add resource providers for AWS * add documentation for AWS Secrets Manager resource providers (username, password, tcps wallet, seps wallet, tnsnames) * Add fieldName parameter for Resources * Add AwsSecretsManagerResourceParameterNames * Update Tests and Readme * Clarify fieldName parameter usage across AWS resource providers
1 parent 2e4f2ca commit 5651e71

26 files changed

+2228
-30
lines changed

ojdbc-provider-aws/README.md

Lines changed: 398 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
################################################################################
2+
# Copyright (c) 2024 Oracle and/or its affiliates.
3+
#
4+
# The Universal Permissive License (UPL), Version 1.0
5+
#
6+
# Subject to the condition set forth below, permission is hereby granted to any
7+
# person obtaining a copy of this software, associated documentation and/or data
8+
# (collectively the "Software"), free of charge and under any and all copyright
9+
# rights in the Software, and any and all patent rights owned or freely
10+
# licensable by each licensor hereunder covering either (i) the unmodified
11+
# Software as contributed to or provided by such licensor, or (ii) the Larger
12+
# Works (as defined below), to deal in both
13+
#
14+
# (a) the Software, and
15+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
# one is included with the Software (each a "Larger Work" to which the Software
17+
# is contributed by such licensors),
18+
#
19+
# without restriction, including without limitation the rights to copy, create
20+
# derivative works of, display, perform, and distribute the Software and make,
21+
# use, sell, offer for sale, import, export, have made, and have sold the
22+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
# either these or other terms.
24+
#
25+
# This license is subject to the following condition:
26+
# The above copyright notice and either this complete permission notice or at
27+
# a minimum a reference to the UPL must be included in all copies or
28+
# substantial portions of the Software.
29+
#
30+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36+
# SOFTWARE.
37+
################################################################################
38+
39+
# An example of a connection properties file that configures Oracle JDBC to
40+
# obtain a TLS wallet and SEPS credentials from AWS Secrets Manager.
41+
#
42+
# This file can be located by Oracle JDBC using the "oracle.jdbc.config.file"
43+
# connection property. For details, see:
44+
# https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE
45+
46+
# Configures the AWS Secrets Manager TCPS Wallet Provider.
47+
# The wallet secret name, wallet password, and file type are configured via
48+
# "TLS_WALLET_SECRET_NAME", "TLS_FILE_PASSWORD", and "TLS_FILE_TYPE" environment variables or JVM system properties.
49+
oracle.jdbc.provider.tlsConfiguration=ojdbc-provider-aws-secretsmanager-tls
50+
oracle.jdbc.provider.tlsConfiguration.secretName=${TLS_WALLET_SECRET_NAME}
51+
oracle.jdbc.provider.tlsConfiguration.walletPassword=${TLS_FILE_PASSWORD}
52+
oracle.jdbc.provider.tlsConfiguration.type=${TLS_FILE_TYPE}
53+
oracle.jdbc.provider.tlsConfiguration.awsRegion=${AWS_REGION}
54+
55+
# Configures the AWS Secrets Manager SEPS Wallet Provider for both username and password.
56+
# The SEPS wallet secret name, wallet password, and index are configured via
57+
# "SEPS_WALLET_SECRET_NAME", "SEPS_WALLET_PASSWORD", and "SEPS_CONNECTION_STRING_INDEX".
58+
oracle.jdbc.provider.username=ojdbc-provider-aws-secretsmanager-seps
59+
oracle.jdbc.provider.username.secretName=${SEPS_WALLET_SECRET_NAME}
60+
oracle.jdbc.provider.username.walletPassword=${SEPS_WALLET_PASSWORD}
61+
oracle.jdbc.provider.username.connectionStringIndex=${SEPS_CONNECTION_STRING_INDEX}
62+
oracle.jdbc.provider.username.awsRegion=${AWS_REGION}
63+
64+
oracle.jdbc.provider.password=ojdbc-provider-aws-secretsmanager-seps
65+
oracle.jdbc.provider.password.secretName=${SEPS_WALLET_SECRET_NAME}
66+
oracle.jdbc.provider.password.walletPassword=${SEPS_WALLET_PASSWORD}
67+
oracle.jdbc.provider.password.connectionStringIndex=${SEPS_CONNECTION_STRING_INDEX}
68+
oracle.jdbc.provider.password.authenticationMethod=aws-default
69+
oracle.jdbc.provider.password.awsRegion=${AWS_REGION}
70+
71+
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
################################################################################
2+
# Copyright (c) 2025 Oracle and/or its affiliates.
3+
#
4+
# The Universal Permissive License (UPL), Version 1.0
5+
#
6+
# Subject to the condition set forth below, permission is hereby granted to any
7+
# person obtaining a copy of this software, associated documentation and/or data
8+
# (collectively the "Software"), free of charge and under any and all copyright
9+
# rights in the Software, and any and all patent rights owned or freely
10+
# licensable by each licensor hereunder covering either (i) the unmodified
11+
# Software as contributed to or provided by such licensor, or (ii) the Larger
12+
# Works (as defined below), to deal in both
13+
#
14+
# (a) the Software, and
15+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
# one is included with the Software (each a "Larger Work" to which the Software
17+
# is contributed by such licensors),
18+
#
19+
# without restriction, including without limitation the rights to copy, create
20+
# derivative works of, display, perform, and distribute the Software and make,
21+
# use, sell, offer for sale, import, export, have made, and have sold the
22+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
# either these or other terms.
24+
#
25+
# This license is subject to the following condition:
26+
# The above copyright notice and either this complete permission notice or at
27+
# a minimum a reference to the UPL must be included in all copies or
28+
# substantial portions of the Software.
29+
#
30+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36+
# SOFTWARE.
37+
################################################################################
38+
39+
# An example of a connection properties file that configures Oracle JDBC to
40+
# login using a username and password managed by AWS Secrets manager Service.
41+
#
42+
# This file can be located by Oracle JDBC using the "oracle.jdbc.config.file"
43+
# connection property. For details, see:
44+
# https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE
45+
46+
# Configures the AWS Secrets Manager Username Provider.
47+
# The secret name is configured as an environment variable or JVM system property
48+
# named "USERNAME_SECRET_NAME". The AWS region is configured via "AWS_REGION".
49+
oracle.jdbc.provider.username=ojdbc-provider-aws-secretsmanager-username
50+
oracle.jdbc.provider.username.secretName=${USERNAME_SECRET_NAME}
51+
oracle.jdbc.provider.username.awsRegion=${AWS_REGION}
52+
53+
# Configures the AWS Secrets Manager Password Provider.
54+
# The secret name is configured as an environment variable or JVM system property
55+
# named "PASSWORD_SECRET_NAME". The AWS region is configured via "AWS_REGION".
56+
oracle.jdbc.provider.password=ojdbc-provider-aws-secretsmanager-password
57+
oracle.jdbc.provider.password.secretName=${PASSWORD_SECRET_NAME}
58+
oracle.jdbc.provider.password.awsRegion=${AWS_REGION}
59+
60+
# Configures the AWS Secrets Manager Connection String Provider.
61+
# The secret name and alias are configured as environment variables or JVM system properties
62+
# named "TNSNAMES_SECRET_NAME" and "TNS_ALIAS", respectively. The AWS region is configured via "AWS_REGION".
63+
oracle.jdbc.provider.connectionString=ojdbc-provider-aws-secretsmanager-tnsnames
64+
oracle.jdbc.provider.connectionString.secretName=${TNSNAMES_SECRET_NAME}
65+
oracle.jdbc.provider.connectionString.tnsAlias=${TNS_ALIAS}
66+
oracle.jdbc.provider.connectionString.awsRegion=${AWS_REGION}
67+
68+

ojdbc-provider-aws/example-test.properties

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,30 @@ AWS_S3_URL=jdbc:oracle:thin:@config-awss3://...
8686

8787
# The URL to test with the AWS Secrets Manager Configuration Provider
8888
AWS_SECRETS_MANAGER_URL=jdbc:oracle:thin:@config-awssecretsmanager://...
89+
90+
# The name of an AWS Secrets Manager secret
91+
AWS_USERNAME_SECRET_NAME=example-name
92+
93+
# The name of an AWS Secrets Manager secret for TCPS (TLS) wallet
94+
AWS_TLS_WALLET_SECRET_NAME=aws-tcps-wallet-secret
95+
96+
# The type of the file stored in AWS Secrets Manager (SSO, PKCS12, PEM)
97+
AWS_TLS_FILE_TYPE=PKCS12
98+
99+
# Optional password for the TLS file stored in AWS Secrets Manager
100+
AWS_TLS_FILE_PASSWORD=******
101+
102+
# The name of an AWS Secrets Manager secret for SEPS wallet
103+
AWS_SEPS_WALLET_SECRET_NAME=aws-seps-wallet-secret
104+
105+
# Optional password for the SEPS wallet stored in AWS Secrets Manager
106+
AWS_SEPS_WALLET_PASSWORD=*****
107+
108+
# Optional index to select specific credentials from the SEPS wallet
109+
AWS_SEPS_CONNECTION_STRING_INDEX=1
110+
111+
# The name of the AWS Secrets Manager secret containing the tnsnames.ora file
112+
AWS_TNSNAMES_SECRET_NAME=aws-tnsnames-secret
113+
114+
# The alias in the tnsnames.ora file to use for the connection string
115+
AWS_TNS_NAMES_ALIAS=your_tns_alias

ojdbc-provider-aws/src/main/java/oracle/jdbc/provider/aws/configuration/AwsJsonSecretsManagerProvider.java

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,11 @@
3737
*/
3838
package oracle.jdbc.provider.aws.configuration;
3939

40+
import oracle.jdbc.provider.aws.secrets.AwsSecretExtractor;
4041
import oracle.jdbc.provider.aws.secrets.SecretsManagerFactory;
4142
import oracle.jdbc.provider.parameter.ParameterSet;
4243
import oracle.jdbc.spi.OracleConfigurationSecretProvider;
43-
import oracle.sql.json.OracleJsonException;
44-
import oracle.sql.json.OracleJsonFactory;
45-
import oracle.sql.json.OracleJsonObject;
4644

47-
import java.io.ByteArrayInputStream;
4845
import java.nio.charset.StandardCharsets;
4946
import java.util.Base64;
5047
import java.util.Map;
@@ -55,8 +52,6 @@
5552
public class AwsJsonSecretsManagerProvider
5653
implements OracleConfigurationSecretProvider {
5754

58-
private static final OracleJsonFactory JSON_FACTORY = new OracleJsonFactory();
59-
6055
/**
6156
* {@inheritDoc}
6257
* <p>
@@ -98,28 +93,8 @@ public char[] getSecret(Map<String, String> map) {
9893
.request(parameterSet)
9994
.getContent();
10095

101-
String extractedSecret;
102-
103-
try {
104-
OracleJsonObject jsonObject = JSON_FACTORY.createJsonTextValue(
105-
new ByteArrayInputStream(secretString.getBytes(StandardCharsets.UTF_8)))
106-
.asJsonObject();
107-
108-
if (fieldName != null) {
109-
if (!jsonObject.containsKey(fieldName)) {
110-
throw new IllegalStateException("Field '" + fieldName + "' not found in secret JSON.");
111-
}
112-
extractedSecret = jsonObject.get(fieldName).asJsonString().getString();
113-
} else if (jsonObject.size() == 1) {
114-
extractedSecret = jsonObject.values().iterator().next().asJsonString().getString();
115-
} else {
116-
throw new IllegalStateException(
117-
"FIELD_NAME is required when multiple keys exist in the secret JSON");
118-
}
119-
120-
} catch (OracleJsonException e) {
121-
extractedSecret = secretString;
122-
}
96+
String extractedSecret = AwsSecretExtractor.extractSecret(secretString,
97+
fieldName);
12398

12499
return Base64.getEncoder()
125100
.encodeToString(extractedSecret.getBytes(StandardCharsets.UTF_8))
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
** Copyright (c) 2025 Oracle and/or its affiliates.
3+
**
4+
** The Universal Permissive License (UPL), Version 1.0
5+
**
6+
** Subject to the condition set forth below, permission is hereby granted to any
7+
** person obtaining a copy of this software, associated documentation and/or data
8+
** (collectively the "Software"), free of charge and under any and all copyright
9+
** rights in the Software, and any and all patent rights owned or freely
10+
** licensable by each licensor hereunder covering either (i) the unmodified
11+
** Software as contributed to or provided by such licensor, or (ii) the Larger
12+
** Works (as defined below), to deal in both
13+
**
14+
** (a) the Software, and
15+
** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
** one is included with the Software (each a "Larger Work" to which the Software
17+
** is contributed by such licensors),
18+
**
19+
** without restriction, including without limitation the rights to copy, create
20+
** derivative works of, display, perform, and distribute the Software and make,
21+
** use, sell, offer for sale, import, export, have made, and have sold the
22+
** Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
** either these or other terms.
24+
**
25+
** This license is subject to the following condition:
26+
** The above copyright notice and either this complete permission notice or at
27+
** a minimum a reference to the UPL must be included in all copies or
28+
** substantial portions of the Software.
29+
**
30+
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35+
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36+
** SOFTWARE.
37+
*/
38+
39+
package oracle.jdbc.provider.aws.resource;
40+
41+
import oracle.jdbc.provider.aws.authentication.AwsAuthenticationMethod;
42+
import oracle.jdbc.provider.aws.authentication.AwsCredentialsFactory;
43+
import oracle.jdbc.provider.resource.AbstractResourceProvider;
44+
import oracle.jdbc.provider.resource.ResourceParameter;
45+
46+
import java.util.stream.Stream;
47+
48+
import static oracle.jdbc.provider.aws.authentication.AwsAuthenticationMethod.DEFAULT;
49+
import static oracle.jdbc.provider.aws.authentication.AwsCredentialsFactory.AUTHENTICATION_METHOD;
50+
import static oracle.jdbc.provider.aws.configuration.AwsConfigurationParameters.REGION;
51+
import static oracle.jdbc.provider.aws.resource.AwsSecretsManagerResourceParameterNames.AWS_REGION;
52+
53+
/**
54+
* Super class of all {@code OracleResourceProvider} implementations
55+
* that request a resource from AWS. This super class defines parameters for
56+
* authentication with AWS.
57+
*/
58+
public abstract class AwsResourceProvider extends AbstractResourceProvider {
59+
60+
private static final ResourceParameter[] PARAMETERS = {
61+
new ResourceParameter("authenticationMethod", AUTHENTICATION_METHOD,
62+
"aws-default",
63+
AwsResourceProvider::parseAuthenticationMethod),
64+
new ResourceParameter(AWS_REGION, REGION)
65+
};
66+
67+
/**
68+
* Constructs a provider identified by the name:
69+
* <pre>{@code
70+
* ojdbc-provider-aws-{resourceType}
71+
* }</pre>
72+
* @param resourceType The resource type identifier used in the provider name.
73+
* @param parameters Additional parameters specific to the subclass provider.
74+
*/
75+
protected AwsResourceProvider(String resourceType, ResourceParameter... parameters) {
76+
super("aws", resourceType,
77+
Stream.concat(Stream.of(PARAMETERS), Stream.of(parameters))
78+
.toArray(ResourceParameter[]::new));
79+
}
80+
81+
/**
82+
* Parses the "authenticationMethod" parameter as an
83+
* {@link AwsAuthenticationMethod} recognized by {@link AwsCredentialsFactory}.
84+
*
85+
* @param authenticationMethod The value to parse.
86+
* @return An {@link AwsAuthenticationMethod} enum.
87+
* @throws IllegalArgumentException if the value is unrecognized.
88+
*/
89+
private static AwsAuthenticationMethod parseAuthenticationMethod(String authenticationMethod) {
90+
switch (authenticationMethod) {
91+
case "aws-default": return DEFAULT;
92+
default:
93+
throw new IllegalArgumentException("Unrecognized authentication method: " + authenticationMethod);
94+
}
95+
}
96+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
** Copyright (c) 2025 Oracle and/or its affiliates.
3+
**
4+
** The Universal Permissive License (UPL), Version 1.0
5+
**
6+
** Subject to the condition set forth below, permission is hereby granted to any
7+
** person obtaining a copy of this software, associated documentation and/or data
8+
** (collectively the "Software"), free of charge and under any and all copyright
9+
** rights in the Software, and any and all patent rights owned or freely
10+
** licensable by each licensor hereunder covering either (i) the unmodified
11+
** Software as contributed to or provided by such licensor, or (ii) the Larger
12+
** Works (as defined below), to deal in both
13+
**
14+
** (a) the Software, and
15+
** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
** one is included with the Software (each a "Larger Work" to which the Software
17+
** is contributed by such licensors),
18+
**
19+
** without restriction, including without limitation the rights to copy, create
20+
** derivative works of, display, perform, and distribute the Software and make,
21+
** use, sell, offer for sale, import, export, have made, and have sold the
22+
** Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
** either these or other terms.
24+
**
25+
** This license is subject to the following condition:
26+
** The above copyright notice and either this complete permission notice or at
27+
** a minimum a reference to the UPL must be included in all copies or
28+
** substantial portions of the Software.
29+
**
30+
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35+
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36+
** SOFTWARE.
37+
*/
38+
39+
package oracle.jdbc.provider.aws.resource;
40+
41+
/**
42+
* Centralized parameter name constants used by AWS Secrets Manager resource providers.
43+
*/
44+
public final class AwsSecretsManagerResourceParameterNames {
45+
46+
private AwsSecretsManagerResourceParameterNames() {}
47+
48+
/** The AWS region where the secret is located (e.g., eu-north-1). */
49+
public static final String AWS_REGION = "awsRegion";
50+
51+
/** The name of the secret stored in AWS Secrets Manager. */
52+
public static final String SECRET_NAME = "secretName";
53+
54+
/** Optional field name to extract from a JSON secret. */
55+
public static final String FIELD_NAME = "fieldName";
56+
57+
/** The alias used to retrieve a connection string from tnsnames.ora. */
58+
public static final String TNS_ALIAS = "tnsAlias";
59+
60+
/** Optional password used to decrypt the wallet (for PKCS12 or encrypted PEM). */
61+
public static final String WALLET_PASSWORD = "walletPassword";
62+
63+
/** The wallet format: SSO, PKCS12, or PEM. */
64+
public static final String TYPE = "type";
65+
66+
/** Index of the credential set in the wallet */
67+
public static final String CONNECTION_STRING_INDEX = "connectionStringIndex";
68+
}

0 commit comments

Comments
 (0)