generated from oracle/template-repo
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
190a9c0
commit d088b34
Showing
12 changed files
with
569 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<name>Oracle JDBC Hashicorp Providers</name> | ||
|
||
<artifactId>ojdbc-provider-hashicorp</artifactId> | ||
<packaging>jar</packaging> | ||
|
||
<parent> | ||
<groupId>com.oracle.database.jdbc</groupId> | ||
<artifactId>ojdbc-extensions</artifactId> | ||
<version>${extensions-version}</version> | ||
</parent> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.oracle.database.jdbc</groupId> | ||
<artifactId>ojdbc-provider-common</artifactId> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>com.oracle.database.jdbc</groupId> | ||
<artifactId>ojdbc-provider-common</artifactId> | ||
<classifier>tests</classifier> | ||
<type>test-jar</type> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.junit.jupiter</groupId> | ||
<artifactId>junit-jupiter-api</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.junit.jupiter</groupId> | ||
<artifactId>junit-jupiter-engine</artifactId> | ||
</dependency> | ||
</dependencies> | ||
|
||
</project> |
36 changes: 36 additions & 0 deletions
36
...der-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/HashiVaultResourceFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package oracle.jdbc.provider.hashicorp; | ||
|
||
import oracle.jdbc.provider.factory.Resource; | ||
import oracle.jdbc.provider.factory.ResourceFactory; | ||
import oracle.jdbc.provider.hashicorp.authentication.HashiCredentials; | ||
import oracle.jdbc.provider.hashicorp.authentication.HashicorpCredentialsFactory; | ||
import oracle.jdbc.provider.parameter.ParameterSet; | ||
|
||
/** | ||
* Common super class for ResourceFactory implementations that request | ||
* a resource from Vault using HashiCredentials (Vault token). | ||
*/ | ||
public abstract class HashiVaultResourceFactory<T> implements ResourceFactory<T> { | ||
|
||
@Override | ||
public final Resource<T> request(ParameterSet parameterSet) { | ||
// Retrieve the Vault credentials (token) from the credentials factory | ||
HashiCredentials credentials = HashicorpCredentialsFactory.getInstance() | ||
.request(parameterSet) | ||
.getContent(); | ||
|
||
try { | ||
return request(credentials, parameterSet); | ||
} catch (Exception e) { | ||
throw new IllegalStateException( | ||
"Request failed with parameters: " + parameterSet, e); | ||
} | ||
} | ||
|
||
/** | ||
* Subclasses implement to request the resource from Vault using | ||
* the given credentials and parameters. | ||
*/ | ||
public abstract Resource<T> request( | ||
HashiCredentials credentials, ParameterSet parameterSet); | ||
} |
16 changes: 16 additions & 0 deletions
16
...shicorp/src/main/java/oracle/jdbc/provider/hashicorp/authentication/HashiCredentials.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package oracle.jdbc.provider.hashicorp.authentication; | ||
|
||
/** | ||
* Simple credentials object for HashiCorp Vault that holds a token. | ||
*/ | ||
public final class HashiCredentials { | ||
private final String vaultToken; | ||
|
||
public HashiCredentials(String vaultToken) { | ||
this.vaultToken = vaultToken; | ||
} | ||
|
||
public String getVaultToken() { | ||
return vaultToken; | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
...ain/java/oracle/jdbc/provider/hashicorp/authentication/HashicorpAuthenticationMethod.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package oracle.jdbc.provider.hashicorp.authentication; | ||
|
||
/** | ||
* A method of authentication using HashiCorp Vault. | ||
*/ | ||
public enum HashicorpAuthenticationMethod { | ||
/** | ||
* Authentication using a Vault token (e.g., read from environment variable). | ||
*/ | ||
TOKEN | ||
} |
69 changes: 69 additions & 0 deletions
69
.../main/java/oracle/jdbc/provider/hashicorp/authentication/HashicorpCredentialsFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package oracle.jdbc.provider.hashicorp.authentication; | ||
|
||
import oracle.jdbc.provider.factory.Resource; | ||
import oracle.jdbc.provider.factory.ResourceFactory; | ||
import oracle.jdbc.provider.hashicorp.secrets.HashiVaultSecretsManagerFactory; | ||
import oracle.jdbc.provider.parameter.Parameter; | ||
import oracle.jdbc.provider.parameter.ParameterSet; | ||
|
||
import static oracle.jdbc.provider.parameter.Parameter.CommonAttribute.REQUIRED; | ||
|
||
/** | ||
* A factory for creating {@link HashiCredentials} objects for Vault. | ||
*/ | ||
public final class HashicorpCredentialsFactory implements ResourceFactory<HashiCredentials> { | ||
|
||
// Example parameter referencing the authentication method | ||
public static final Parameter<HashicorpAuthenticationMethod> AUTHENTICATION_METHOD = | ||
Parameter.create(REQUIRED); | ||
|
||
private static final HashicorpCredentialsFactory INSTANCE = | ||
new HashicorpCredentialsFactory(); | ||
|
||
private HashicorpCredentialsFactory() { } | ||
|
||
public static HashicorpCredentialsFactory getInstance() { | ||
return INSTANCE; | ||
} | ||
|
||
@Override | ||
public Resource<HashiCredentials> request(ParameterSet parameterSet) { | ||
HashiCredentials credentials = getCredential(parameterSet); | ||
return Resource.createPermanentResource(credentials, true); | ||
} | ||
|
||
private static HashiCredentials getCredential(ParameterSet parameterSet) { | ||
System.out.println("parameterSet = " + parameterSet); | ||
// Check which authentication method is requested | ||
HashicorpAuthenticationMethod method = | ||
parameterSet.getRequired(AUTHENTICATION_METHOD); | ||
|
||
switch (method) { | ||
case TOKEN: | ||
return tokenCredentials(parameterSet); | ||
default: | ||
throw new IllegalArgumentException( | ||
"Unrecognized authentication method: " + method); | ||
} | ||
} | ||
|
||
/** | ||
* Example: read Vault token from an environment variable "VAULT_TOKEN". | ||
*/ | ||
private static HashiCredentials tokenCredentials(ParameterSet parameterSet) { | ||
// (1) Try parameter | ||
String paramToken = parameterSet.getOptional(HashiVaultSecretsManagerFactory.VAULT_TOKEN); | ||
if (paramToken != null && !paramToken.isEmpty()) { | ||
return new HashiCredentials(paramToken); | ||
} | ||
|
||
// (2) Fallback to system property or env | ||
String vaultToken = System.getProperty("VAULT_TOKEN", System.getenv("VAULT_TOKEN")); | ||
if (vaultToken == null || vaultToken.isEmpty()) { | ||
throw new IllegalStateException("Vault token not provided in tokenCredentials()"); | ||
} | ||
|
||
return new HashiCredentials(vaultToken); | ||
} | ||
|
||
} |
76 changes: 76 additions & 0 deletions
76
...rp/src/main/java/oracle/jdbc/provider/hashicorp/configuration/HashiJsonVaultProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package oracle.jdbc.provider.hashicorp.configuration; | ||
|
||
import oracle.jdbc.provider.configuration.JsonSecretUtil; | ||
import oracle.jdbc.provider.hashicorp.secrets.HashiVaultSecretsManagerFactory; | ||
import oracle.jdbc.provider.parameter.ParameterSet; | ||
import oracle.jdbc.spi.OracleConfigurationJsonSecretProvider; | ||
import oracle.sql.json.OracleJsonObject; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.Base64; | ||
|
||
import static oracle.jdbc.provider.hashicorp.configuration.HashiVaultSecretsManagerConfigurationProvider.PARAMETER_SET_PARSER; | ||
import static oracle.jdbc.provider.hashicorp.secrets.HashiVaultSecretsManagerFactory.FIELD_NAME; | ||
|
||
/** | ||
* Mirrors the AWS pattern for retrieving a single secret | ||
* field from HashiCorp Vault, base64-encoding it. | ||
* | ||
* Example JSON input might look like: | ||
* { | ||
* "password": { | ||
* "type": "hashicorpvault", | ||
* "value": "/v1/secret/data/test-config2" | ||
* } | ||
* } | ||
* | ||
* The provider will retrieve the secret from Vault, then | ||
* base64-encode it and return as a char[]. | ||
*/ | ||
public class HashiJsonVaultProvider implements OracleConfigurationJsonSecretProvider { | ||
|
||
@Override | ||
public char[] getSecret(OracleJsonObject jsonObject) { | ||
// 1) Convert the JSON object to named key-value pairs | ||
ParameterSet parameterSet = | ||
PARAMETER_SET_PARSER.parseNamedValues( | ||
JsonSecretUtil.toNamedValues(jsonObject) | ||
); | ||
|
||
// 2) Call the Vault factory to fetch the raw secret string | ||
String secretString = HashiVaultSecretsManagerFactory | ||
.getInstance() | ||
.request(parameterSet) | ||
.getContent(); | ||
|
||
ByteArrayInputStream inputStream = new ByteArrayInputStream(secretString.getBytes(StandardCharsets.UTF_8)); | ||
|
||
|
||
// 3) Parse that JSON to find "myPassword" | ||
// Using the Oracle JSON library, for example: | ||
OracleJsonObject secretJsonObj = | ||
new oracle.sql.json.OracleJsonFactory() | ||
.createJsonTextValue(inputStream) | ||
.asJsonObject(); | ||
|
||
System.out.println(secretJsonObj); | ||
|
||
// 4) Retrieve the field we want | ||
//String myPasswordValue = secretJsonObj.getString("myPassword"); | ||
String myPasswordValue = parameterSet.getOptional(FIELD_NAME); | ||
System.out.println(myPasswordValue); | ||
|
||
// 5) Base64-encode just that field | ||
return Base64.getEncoder() | ||
.encodeToString(myPasswordValue.getBytes()) | ||
.toCharArray(); | ||
} | ||
|
||
@Override | ||
public String getSecretType() { | ||
// Must match the "type" field in your JSON. | ||
// E.g. "hashicorpvault" or "hashicorsecret"—your choice. | ||
return "hashicorpvault"; | ||
} | ||
} |
64 changes: 64 additions & 0 deletions
64
.../jdbc/provider/hashicorp/configuration/HashiVaultSecretsManagerConfigurationProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package oracle.jdbc.provider.hashicorp.configuration; | ||
|
||
import oracle.jdbc.driver.OracleConfigurationJsonProvider; | ||
import oracle.jdbc.provider.hashicorp.secrets.HashiVaultSecretsManagerFactory; | ||
import oracle.jdbc.provider.parameter.ParameterSet; | ||
import oracle.jdbc.provider.parameter.ParameterSetParser; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.InputStream; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
/** | ||
* A provider for JSON payload from Vault, analogous to AWS Secrets Manager version. | ||
*/ | ||
public class HashiVaultSecretsManagerConfigurationProvider extends OracleConfigurationJsonProvider { | ||
|
||
// Reuse a ParameterSetParser approach | ||
// If you need more parameters, add them below. | ||
static final ParameterSetParser PARAMETER_SET_PARSER = | ||
HashicorpConfigurationParameters.configureBuilder( | ||
ParameterSetParser.builder() | ||
.addParameter("value", HashiVaultSecretsManagerFactory.SECRET_PATH) | ||
.addParameter("key_name", HashiVaultSecretsManagerFactory.KEY_NAME) | ||
.addParameter( | ||
"VAULT_ADDR", | ||
HashiVaultSecretsManagerFactory.VAULT_ADDRESS | ||
) | ||
.addParameter( | ||
"VAULT_TOKEN", | ||
HashiVaultSecretsManagerFactory.VAULT_TOKEN | ||
) | ||
.addParameter("FILED_NAME", | ||
HashiVaultSecretsManagerFactory.FIELD_NAME) | ||
).build(); | ||
|
||
@Override | ||
public InputStream getJson(String secretPath) { | ||
// 'secretPath' is the location or name of the Vault secret | ||
final String valueFieldName = "value"; | ||
|
||
// Build a map of user-provided options | ||
Map<String, String> optionsWithSecret = new HashMap<>(options); | ||
optionsWithSecret.put(valueFieldName, secretPath); | ||
|
||
// Parse into a ParameterSet | ||
ParameterSet parameters = PARAMETER_SET_PARSER.parseNamedValues(optionsWithSecret); | ||
|
||
// Fetch the secret from Vault | ||
String secretString = HashiVaultSecretsManagerFactory | ||
.getInstance() | ||
.request(parameters) | ||
.getContent(); | ||
|
||
// Return the JSON as an InputStream | ||
return new ByteArrayInputStream(secretString.getBytes()); | ||
} | ||
|
||
@Override | ||
public String getType() { | ||
// We'll reference this in our JDBC URL, e.g. "jdbc:oracle:thin:@config-hashicorpvault://..." | ||
return "hashicorpvault"; | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
...n/java/oracle/jdbc/provider/hashicorp/configuration/HashicorpConfigurationParameters.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package oracle.jdbc.provider.hashicorp.configuration; | ||
|
||
import oracle.jdbc.provider.hashicorp.authentication.HashicorpAuthenticationMethod; | ||
import oracle.jdbc.provider.hashicorp.authentication.HashicorpCredentialsFactory; | ||
import oracle.jdbc.provider.hashicorp.secrets.HashiVaultSecretsManagerFactory; | ||
import oracle.jdbc.provider.parameter.ParameterSetParser; | ||
|
||
/** | ||
* Defines how we parse common Vault parameters (similar to AWS approach). | ||
*/ | ||
public final class HashicorpConfigurationParameters { | ||
|
||
private HashicorpConfigurationParameters() {} | ||
|
||
public static ParameterSetParser.Builder configureBuilder(ParameterSetParser.Builder builder) { | ||
return builder.addParameter( | ||
// The parameter name is "AUTHENTICATION" | ||
"AUTHENTICATION", | ||
// Tied to HashicorpCredentialsFactory.AUTHENTICATION_METHOD | ||
HashicorpCredentialsFactory.AUTHENTICATION_METHOD, | ||
// Default value if none is specified: | ||
HashicorpAuthenticationMethod.TOKEN, | ||
HashicorpConfigurationParameters::parseAuthentication) | ||
; | ||
} | ||
|
||
private static HashicorpAuthenticationMethod parseAuthentication(String value) { | ||
// Map user-provided string to enum | ||
if ("TOKEN".equalsIgnoreCase(value) || "VAULT_TOKEN".equalsIgnoreCase(value)) { | ||
return HashicorpAuthenticationMethod.TOKEN; | ||
} | ||
throw new IllegalArgumentException( | ||
"Unrecognized Hashicorp authentication value: " + value); | ||
} | ||
} |
Oops, something went wrong.