From 428dbcaafc33383f8e62fddb6a1b9512037ef657 Mon Sep 17 00:00:00 2001 From: Mouhsin Elmajdouby Date: Thu, 20 Mar 2025 12:57:41 +0000 Subject: [PATCH 1/6] Add Resource Providers for HCP Vault Dedicated --- ojdbc-provider-hashicorp/README.md | 509 +++++++++++++++++- .../example-test.properties | 30 ++ .../example-vault-dedicated-wallet.properties | 82 +++ .../example-vault-dedicated.properties | 68 +++ .../DedicatedVaultParameters.java | 24 +- .../DedicatedVaultJsonSecretProvider.java | 16 +- ...aultDedicatedConnectionStringProvider.java | 129 +++++ .../HcpVaultDedicatedPasswordProvider.java | 71 +++ .../HcpVaultDedicatedResourceProvider.java | 184 +++++++ .../HcpVaultDedicatedSEPSProvider.java | 123 +++++ .../HcpVaultDedicatedSecretProvider.java | 109 ++++ .../HcpVaultDedicatedTCPSProvider.java | 126 +++++ .../HcpVaultDedicatedUsernameProvider.java | 71 +++ .../provider/hashicorp/util/JsonUtil.java | 28 + .../oracle.jdbc.spi.ConnectionStringProvider | 1 + .../services/oracle.jdbc.spi.PasswordProvider | 2 + .../oracle.jdbc.spi.TlsConfigurationProvider | 1 + .../services/oracle.jdbc.spi.UsernameProvider | 2 + .../DedicatedVaultTestProperty.java | 14 +- .../HcpVaultDedicatedTestUtil.java | 126 +++++ ...dicatedVaultConfigurationProviderTest.java | 1 + ...DedicatedConnectionStringProviderTest.java | 149 +++++ ...HcpVaultDedicatedPasswordProviderTest.java | 114 ++++ .../HcpVaultDedicatedSEPSProviderTest.java | 183 +++++++ .../HcpVaultDedicatedTCPSProviderTest.java | 199 +++++++ ...HcpVaultDedicatedUsernameProviderTest.java | 116 ++++ 26 files changed, 2451 insertions(+), 27 deletions(-) create mode 100644 ojdbc-provider-hashicorp/example-vault-dedicated-wallet.properties create mode 100644 ojdbc-provider-hashicorp/example-vault-dedicated.properties create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedConnectionStringProvider.java create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedPasswordProvider.java create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedResourceProvider.java create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSEPSProvider.java create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSecretProvider.java create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedTCPSProvider.java create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedUsernameProvider.java create mode 100644 ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.ConnectionStringProvider create mode 100644 ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.PasswordProvider create mode 100644 ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.TlsConfigurationProvider create mode 100644 ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.UsernameProvider rename ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/{configuration => }/DedicatedVaultTestProperty.java (92%) create mode 100644 ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/HcpVaultDedicatedTestUtil.java create mode 100644 ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedConnectionStringProviderTest.java create mode 100644 ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedPasswordProviderTest.java create mode 100644 ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSEPSProviderTest.java create mode 100644 ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedTCPSProviderTest.java create mode 100644 ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedUsernameProviderTest.java diff --git a/ojdbc-provider-hashicorp/README.md b/ojdbc-provider-hashicorp/README.md index 4922d48b..e1a97e46 100644 --- a/ojdbc-provider-hashicorp/README.md +++ b/ojdbc-provider-hashicorp/README.md @@ -13,6 +13,25 @@ and HashiCorp Vault (HCP).
Caching mechanism adopted by Centralized Config Providers
+## Resource Providers +
+
Dedicated Vault Username Provider
+
Provides a username stored in a HashiCorp Vault Dedicated secret.
+
Dedicated Vault Password Provider
+
Provides a password stored in a HashiCorp Vault Dedicated secret.
+
Dedicated Vault TCPS Wallet Provider
+
Provides a TCPS/TLS wallet for secure database connections using credentials stored in HashiCorp Vault Dedicated.
+
Dedicated Vault SEPS Wallet Provider
+
Provides SEPS (Secure External Password Store) wallets for secure username and password retrieval from HashiCorp Vault Dedicated.
+
Dedicated Vault Connection String Provider
+
Provides connection strings based on aliases stored in a `tnsnames.ora` file within HashiCorp Vault Dedicated.
+
Common Parameters for HCP Vault Dedicated Resource Providers
+
Defines common configuration parameters for providers using HCP Vault Dedicated.
+
Configuring Authentication for HCP Vault Dedicated
+
Details the supported authentication methods for HCP Vault Dedicated.
+
+ + Visit any of the links above to find information and usage examples for a particular provider. ## Installation @@ -534,7 +553,495 @@ For the JSON type of provider (HCP Vault Dedicated, HCP Vault Secrets, HTTP/HTTP - method - optional parameters (depends on the cloud provider). -## Caching configuration +## Dedicated Vault Username Provider + +The **Dedicated Vault Username Provider** provides Oracle JDBC with a **database username** that is managed by **HashiCorp Vault Dedicated**. +This is a **Resource Provider** identified by the name `ojdbc-provider-hcpvault-dedicated-username`. + +In addition to the set of [common parameters](#common-parameters-for-hcp-vault-dedicated-resource-providers), this provider also supports the parameters listed below. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesDefault Value
vaultAddrThe URL of the HashiCorp Vault Dedicated instance. +The URL will typically have the following form: +
https://{vault-name}.hashicorp.cloud:8200/
+
+No default value. A value must be configured for this parameter. +
secretPathThe path to the secret containing the username.Any valid secret path. +No default value. A value must be configured for this parameter. +
fieldName (Optional) +The field inside the JSON secret that contains the required value. +If the secret contains multiple keys, this parameter specifies which key to extract. +If the secret contains only one key, the value is automatically used. +If omitted and multiple keys exist, an error is thrown. +Any valid field name. +No default value. If not specified, the provider selects the only key if a single key exists. +
+ +An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-dedicated.properties](example-vault-dedicated.properties). + +--- + +## Dedicated Vault Password Provider + +The **Dedicated Vault Password Provider** provides Oracle JDBC with a **database password** that is managed by **HashiCorp Vault Dedicated**. +This is a **Resource Provider** identified by the name `ojdbc-provider-hcpvault-dedicated-password`. + +In addition to the set of [common parameters](#common-parameters-for-hcp-vault-dedicated-resource-providers), this provider also supports the parameters listed below. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesDefault Value
vaultAddrThe URL of the HashiCorp Vault Dedicated instance. +The URL will typically have the following form: +
https://{vault-name}.hashicorp.cloud:8200/
+
+No default value. A value must be configured for this parameter. +
secretPathThe path to the secret containing the password.Any valid secret path. +No default value. A value must be configured for this parameter. +
fieldName (Optional) +The field inside the JSON secret that contains the required value. +If the secret contains multiple keys, this parameter specifies which key to extract. +If the secret contains only one key, the value is automatically used. +If omitted and multiple keys exist, an error is thrown. +Any valid field name. +No default value. If not specified, the provider selects the only key if a single key exists. +
+ +An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-dedicated.properties](example-vault-dedicated.properties). + +--- + +## Dedicated Vault TCPS Wallet Provider + +The **Dedicated Vault TCPS Wallet Provider** provides Oracle JDBC with **keys and certificates** managed by **HashiCorp Vault Dedicated** to establish secure **TLS connections** with an Autonomous Database. +This is a **Resource Provider** identified by the name `ojdbc-provider-hcpvault-dedicated-tls`. + +For example, when connecting to an Autonomous Database Serverless with **mutual TLS (mTLS)**, +you need to configure the JDBC-thin driver with its client certificate. +If this certificate is stored in a wallet file (`cwallet.sso`, `ewallet.p12`, `ewallet.pem`), +you may store it in **HCP Vault Dedicated** for additional security. +This provider retrieves the wallet content from **HCP Vault Dedicated** and passes it to the JDBC thin driver. + +- The **type** parameter must be specified to indicate the wallet format: **SSO, PKCS12, or PEM**. +- The **walletPassword** must be provided for wallets that require a password (**PKCS12** or password-protected **PEM** files). + +In addition to the set of [common parameters](#common-parameters-for-hcp-vault-dedicated-resource-providers), this provider also supports the parameters listed below. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesDefault Value
vaultAddrThe URL of the HashiCorp Vault Dedicated instance. +
https://{vault-name}.hashicorp.cloud:8200/
+
+No default value. A value must be configured for this parameter. +
secretPathThe path to the wallet file.Any valid secret path. +No default value. A value must be configured for this parameter. +
typeThe wallet format.SSO, PKCS12, PEM +No default value. The file type must be specified. +
walletPassword +Optional password for **PKCS12** or protected **PEM** files. +If omitted, the file is assumed to be **SSO** or an **unprotected PEM** file. +Any valid password. +No default value. PKCS12 and password-protected PEM files require a password. +
fieldName (Optional) +The field inside the JSON secret that contains the required value. +If the secret contains multiple keys, this parameter specifies which key to extract. +If the secret contains only one key, the value is automatically used. +If omitted and multiple keys exist, an error is thrown. +Any valid field name. +No default value. If not specified, the provider selects the only key if a single key exists. +
+ +An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-dedicated-wallet.properties](example-vault-dedicated-wallet.properties). + +--- + +## Dedicated Vault SEPS Wallet Provider + +The **Dedicated Vault SEPS Wallet Provider** provides Oracle JDBC with **username and password credentials** stored in a **Secure External Password Store (SEPS) wallet** within **HCP Vault Dedicated**. + +This is a **Resource Provider** identified by the name `ojdbc-provider-hcpvault-dedicated-seps`. + +- The SEPS wallet securely stores **encrypted database credentials**, including the **username, password, and connection strings**. + These credentials can be stored as **default values**, such as: + - `oracle.security.client.default_username` + - `oracle.security.client.default_password` + + or as indexed credentials, for example: + - `oracle.security.client.username1` + - `oracle.security.client.password1` + - `oracle.security.client.connect_string1`. + +- The provider retrieves credentials using the following logic: + 1. If `connectionStringIndex` is **not specified**, the provider attempts to retrieve the **default credentials** (`oracle.security.client.default_username` and `oracle.security.client.default_password`). + 2. If **default credentials are missing**, the provider checks for a single **set of credentials** associated with a **connection string**. + 3. If **exactly one connection string** is found, the associated credentials are used. + 4. If **multiple connection strings** exist, an **error is thrown**, prompting you to specify a `connectionStringIndex`. + 5. If `connectionStringIndex` is specified, the provider attempts to retrieve the credentials associated with the **specified connection string index** (e.g., `oracle.security.client.username{idx}`, `oracle.security.client.password{idx}`, `oracle.security.client.connect_string{idx}`). + 6. If credentials for the **specified index** are not found, an **error is thrown**, indicating that no connection string exists with that index. + +In addition to the set of [common parameters](#common-parameters-for-hcp-vault-dedicated-resource-providers), this provider also supports the parameters listed below. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesDefault Value
vaultAddrThe URL of the HashiCorp Vault Dedicated instance. +The URL will typically have the following form: +
https://{vault-name}.hashicorp.cloud:8200/
+
+No default value. A value must be configured for this parameter. +
secretPathThe path to the SEPS wallet file in HashiCorp Vault Dedicated.Any valid secret path. +No default value. A value must be configured for this parameter. +
walletPassword +Optional password for **PKCS12 SEPS wallets**. If omitted, the wallet is assumed to be **SSO**. +Any valid password for the SEPS wallet. +No default value. PKCS12 wallets require a password. +
connectionStringIndex (Optional) +Specifies the **index** of the connection string to use when retrieving credentials from the wallet. +A positive integer representing the index of the desired credential set (e.g., 1, 2, 3, etc.). +No default value. If not specified, the provider follows the default behavior as described above. +
fieldName (Optional) +The field inside the JSON secret that contains the required value. +If the secret contains multiple keys, this parameter specifies which key to extract. +If the secret contains only one key, the value is automatically used. +If omitted and multiple keys exist, an error is thrown. +Any valid field name. +No default value. If not specified, the provider selects the only key if a single key exists. +
+ +An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-dedicated-wallet.properties](example-vault-dedicated-wallet.properties). + + +## Dedicated Vault Connection String Provider + +The **Dedicated Vault Connection String Provider** provides Oracle JDBC with a **connection string** +retrieved from a `tnsnames.ora` file stored in **HCP Vault Dedicated**. + +This is a **Resource Provider** identified by the name `ojdbc-provider-hcpvault-dedicated-tnsnames`. + +This provider retrieves and decodes a `tnsnames.ora` file stored as a **base64-encoded secret** or **plain text** in **HCP Vault Dedicated**, allowing selection of connection strings based on specified aliases. + +This enables flexible configuration for **secure database connections** using the alias names defined in your `tnsnames.ora` file. + +In addition to the set of [common parameters](#common-parameters-for-hcp-vault-dedicated-resource-providers), this provider also requires the parameters listed below. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesDefault Value
vaultAddrThe URL of the HashiCorp Vault Dedicated instance. +
https://{vault-name}.hashicorp.cloud:8200/
+
+No default value. A value must be configured for this parameter. +
secretPathThe path to the `tnsnames.ora` file.Any valid secret path. +No default value. A value must be configured for this parameter. +
tnsAliasThe alias to retrieve the connection string.Any valid alias present in the `tnsnames.ora` file. +No default value. A value must be configured for this parameter. +
fieldName (Optional) +The field inside the JSON secret that contains the required value. +If the secret contains multiple keys, this parameter specifies which key to extract. +If the secret contains only one key, the value is automatically used. +If omitted and multiple keys exist, an error is thrown. +Any valid field name. +No default value. If not specified, the provider selects the only key if a single key exists. +
+ +An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-dedicated.properties](example-vault-dedicated.properties). + +## Common Parameters for HCP Vault Dedicated Resource Providers + +Providers classified as Resource Providers in this module all support a common set of parameters. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesSystem Property / Environment VariableDefault Value
authenticationMethodConfigures a method of authentication for HCP Vault Dedicated.Accepted values are defined in: Configuring Authentication for HCP Vault Dedicated.does not allow System Property / Environment Variableauto-detect
vaultAddrThe URL of the HashiCorp Vault Dedicated instance.A valid Vault endpoint, typically in the form:
https://vault.example.com:8200
VAULT_ADDRNo default value.
vaultNamespaceThe namespace in the Vault (only required if using namespaces).Any valid Vault namespace.VAULT_NAMESPACEadmin (if not explicitly set)
vaultTokenConfigures authentication using a Vault token.A valid Vault authentication token.VAULT_TOKENNo default value.
vaultUsernameConfigures authentication using the Userpass method.A valid Vault username. VAULT_USERNAMENo default value.
vaultPasswordThe password for Userpass authentication.A valid Vault password.VAULT_PASSWORDNo default value.
roleIdConfigures authentication using the AppRole method.A valid Role ID for the AppRole authentication method.ROLE_IDNo default value.
secretIdThe secret ID for AppRole authentication.A valid Secret ID for the AppRole authentication method.SECRET_IDNo default value.
githubTokenConfigures authentication using a GitHub token.A valid GitHub personal access token.GITHUB_TOKENNo default value.
userPassAuthPathThe authentication path in the Vault for Userpass authentication.Any valid Vault authentication path.USERPASS_AUTH_PATHuserpass (if not explicitly set)
appRoleAuthPathThe authentication path in the Vault for AppRole authentication.Any valid Vault authentication path.APPROLE_AUTH_PATHapprole (if not explicitly set)
githubAuthPathThe authentication path in the Vault for GitHub authentication.Any valid Vault authentication path. GITHUB_AUTH_PATHgithub (if not explicitly set)
+ + +## Configuring Authentication for Resource Providers + +### HCP Vault Dedicated + +Resource Providers in this module must authenticate with HCP Vault Dedicated. +By default, the provider will automatically detect any available credentials. +A specific authentication method may be configured using the "authenticationMethod" parameter. + +The parameter may be set to any of the following values: + +
+
vault-token
+
Authenticate using a **pre-existing Vault token**.
+
userpass
+
Authenticate using a **username and password**.
+
approle
+
Authenticate using **AppRole credentials** (requires roleId and secretId).
+
github
+
Authenticate using a **GitHub personal access token**.
+
auto-detect
+
This is the **default authentication method**. The provider will attempt the following **authentication methods**, in this **priority order**: +
    +
  1. vault-token (if available)
  2. +
  3. userpass (if username & password are provided)
  4. +
  5. approle (if roleId & secretId are provided)
  6. +
  7. github (if no other method succeeds)
  8. +
+
+
+ +## caching-configuration Config providers in this module store the configuration in caches to minimize the number of RPC requests to remote location. See diff --git a/ojdbc-provider-hashicorp/example-test.properties b/ojdbc-provider-hashicorp/example-test.properties index 31b862fe..23f03302 100644 --- a/ojdbc-provider-hashicorp/example-test.properties +++ b/ojdbc-provider-hashicorp/example-test.properties @@ -124,6 +124,36 @@ GITHUB_TOKEN=your-github-personal-access-token # Optional path for GitHub authentication in Vault (default: github) GITHUB_AUTH_PATH=github +# The secret path for the username provider in HCP Vault Dedicated. +USERNAME_SECRET_PATH=/v1/namespace/secret/data/username + +# The secret path for the password provider in HCP Vault Dedicated. +PASSWORD_SECRET_PATH=/v1/namespace/secret/data/password + +# The secret path for the connection string provider in HCP Vault Dedicated. +TNSNAMES_SECRET_PATH=/v1/namespace/secret/data/tnsnames + +# The alias in the tnsnames.ora file to use for the connection string. +TNS_ALIAS=your_tns_alias + +# The secret path for the TCPS (TLS) wallet in HCP Vault Dedicated. +TLS_WALLET_SECRET_PATH=/v1/namespace/secret/data/tcps-wallet + +# The type of the file stored in HCP Vault Dedicated (SSO, PKCS12, PEM). +TLS_FILE_TYPE=PKCS12 + +# Optional password for the TLS file stored in HCP Vault Dedicated. +TLS_FILE_PASSWORD=****** + +# The secret path for the SEPS wallet in HCP Vault Dedicated. +SEPS_WALLET_SECRET_PATH=/v1/namespace/secret/data/seps-wallet + +# Optional password for the SEPS wallet stored in HCP Vault Dedicated. +SEPS_WALLET_PASSWORD=***** + +# Optional index to select specific credentials from the SEPS wallet. +SEPS_CONNECTION_STRING_INDEX=1 + ################################################################################ # HCP VAULT SECRETS CONFIGURATION ################################################################################ diff --git a/ojdbc-provider-hashicorp/example-vault-dedicated-wallet.properties b/ojdbc-provider-hashicorp/example-vault-dedicated-wallet.properties new file mode 100644 index 00000000..c51113d1 --- /dev/null +++ b/ojdbc-provider-hashicorp/example-vault-dedicated-wallet.properties @@ -0,0 +1,82 @@ +################################################################################ +# 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. +################################################################################ + +# An example of a connection properties file that configures Oracle JDBC to +# obtain a TLS wallet and SEPS credentials from Azure Key Vault. +# +# This file can be located by Oracle JDBC using the "oracle.jdbc.config.file" +# connection property. For details, see: +# https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE + +# Configures the HCP Vault Dedicated TCPS (TLS) Wallet Provider. The vault URL and +# secret path are configured as environment variables or JVM system properties named +# "VAULT_ADDR" and "TLS_WALLET_SECRET_PATH". +oracle.jdbc.provider.tlsConfiguration=ojdbc-provider-hcpvault-dedicated-tls +oracle.jdbc.provider.tlsConfiguration.vaultAddr=${VAULT_ADDR} +oracle.jdbc.provider.tlsConfiguration.secretPath=${TLS_WALLET_SECRET_PATH} + +# Configures the HCP Vault Dedicated TLS Wallet Password. The password for the +# file is optional and can be configured as an environment variable or JVM +# system property named "TLS_FILE_PASSWORD". +oracle.jdbc.provider.tlsConfiguration.walletPassword=${TLS_FILE_PASSWORD} + +# Specifies the file type (SSO, PKCS12, or PEM) for the TCPS wallet. +# This can be configured as an environment variable or JVM system property named "TLS_FILE_TYPE". +oracle.jdbc.provider.tlsConfiguration.type=${TLS_FILE_TYPE} + +# Configures the HCP Vault Dedicated SEPS (Secure External Password Store) Provider. +# The vault URL and secret path are configured as environment variables or JVM system properties +# named "VAULT_ADDR" and "SEPS_WALLET_SECRET_PATH". +oracle.jdbc.provider.username=ojdbc-provider-hcpvault-dedicated-seps +oracle.jdbc.provider.password=ojdbc-provider-hcpvault-dedicated-seps + +# Configures the vault URL and secret path for SEPS. +oracle.jdbc.provider.username.vaultAddr=${VAULT_ADDR} +oracle.jdbc.provider.username.secretPath=${SEPS_WALLET_SECRET_PATH} +oracle.jdbc.provider.password.vaultAddr=${VAULT_ADDR} +oracle.jdbc.provider.password.secretPath=${SEPS_WALLET_SECRET_PATH} + +# Optional password for SEPS Wallet stored in HCP Vault Dedicated. +oracle.jdbc.provider.username.walletPassword=${SEPS_WALLET_PASSWORD} +oracle.jdbc.provider.password.walletPassword=${SEPS_WALLET_PASSWORD} + +# Optional connection string index for SEPS Wallet. +# This determines which set of credentials (username/password) to use from the SEPS Wallet. +oracle.jdbc.provider.username.connectionStringIndex=${SEPS_CONNECTION_STRING_INDEX} +oracle.jdbc.provider.password.connectionStringIndex=${SEPS_CONNECTION_STRING_INDEX} + diff --git a/ojdbc-provider-hashicorp/example-vault-dedicated.properties b/ojdbc-provider-hashicorp/example-vault-dedicated.properties new file mode 100644 index 00000000..707f6f28 --- /dev/null +++ b/ojdbc-provider-hashicorp/example-vault-dedicated.properties @@ -0,0 +1,68 @@ +################################################################################ +# 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. +################################################################################ + +# An example of a connection properties file that configures Oracle JDBC to +# login using a username and password managed by Azure's Key Vault service. +# +# This file can be located by Oracle JDBC using the "oracle.jdbc.config.file" +# connection property. For details, see: +# https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE + +# Configures the HCP Vault Dedicated Username Provider. The vault Address and secret path +# are configured as environment variables or JVM system properties +# named "VAULT_ADDR" and "USERNAME_SECRET_PATH". +oracle.jdbc.provider.username=ojdbc-provider-hcpvault-dedicated-username +oracle.jdbc.provider.username.vaultAddr=${VAULT_ADDR} +oracle.jdbc.provider.username.secretPath=${USERNAME_SECRET_PATH} + +# Configures the HCP Vault Dedicated Password Provider. The vault Address and secret path +# are configured as environment variables or JVM system properties +# named "VAULT_ADDR" and "PASSWORD_SECRET_PATH". +oracle.jdbc.provider.password=ojdbc-provider-hcpvault-dedicated-password +oracle.jdbc.provider.password.vaultAddr=${VAULT_ADDR} +oracle.jdbc.provider.password.secretPath=${PASSWORD_SECRET_PATH} + +# Configures the HCP Vault Dedicated Connection String Provider. The vault Address, secret path, +# and tns alias are configured as environment variables or JVM system properties +# named "VAULT_ADDR", "TNSNAMES_SECRET_PATH", and "TNS_ALIAS". +oracle.jdbc.provider.connectionString=ojdbc-provider-hcpvault-dedicated-tnsnames +oracle.jdbc.provider.connectionString.vaultAddr=${VAULT_ADDR} +oracle.jdbc.provider.connectionString.secretPath=${TNSNAMES_SECRET_PATH} +oracle.jdbc.provider.connectionString.tnsAlias=${TNS_ALIAS} + + diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/authentication/DedicatedVaultParameters.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/authentication/DedicatedVaultParameters.java index 8610e0c6..bdf85fba 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/authentication/DedicatedVaultParameters.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/authentication/DedicatedVaultParameters.java @@ -81,10 +81,10 @@ public class DedicatedVaultParameters { // Default values - static final String DEFAULT_NAMESPACE = "admin"; - static final String DEFAULT_USERPASS_PATH = "userpass"; - static final String DEFAULT_APPROLE_PATH = "approle"; - static final String DEFAULT_GITHUB_PATH = "github"; + public static final String DEFAULT_NAMESPACE = "admin"; + public static final String DEFAULT_USERPASS_PATH = "userpass"; + public static final String DEFAULT_APPROLE_PATH = "approle"; + public static final String DEFAULT_GITHUB_PATH = "github"; /** *

@@ -93,7 +93,7 @@ public class DedicatedVaultParameters { *

*/ public static final Parameter AUTHENTICATION_METHOD = - Parameter.create(REQUIRED); + Parameter.create(); /** The path of the secret in Vault. Required. */ public static final Parameter SECRET_PATH = Parameter.create(REQUIRED); @@ -112,7 +112,7 @@ public class DedicatedVaultParameters { /** * The Vault token. If not specified, fallback to system property or environment var. */ - public static final Parameter VAULT_TOKEN = Parameter.create(REQUIRED); + public static final Parameter VAULT_TOKEN = Parameter.create(); /** * The field name for extracting a specific value from the JSON. @@ -122,12 +122,12 @@ public class DedicatedVaultParameters { /** * The username for Userpass authentication. Required for Userpass method. */ - public static final Parameter USERNAME = Parameter.create(REQUIRED); + public static final Parameter USERNAME = Parameter.create(); /** * The password for Userpass authentication. Required for Userpass method. */ - public static final Parameter PASSWORD = Parameter.create(REQUIRED); + public static final Parameter PASSWORD = Parameter.create(); /** * The path for Userpass authentication. Optional. @@ -146,7 +146,7 @@ public class DedicatedVaultParameters { * configured in Vault as part of the AppRole authentication setup. *

*/ - public static final Parameter ROLE_ID = Parameter.create(REQUIRED); + public static final Parameter ROLE_ID = Parameter.create(); /** * The Secret ID for AppRole authentication. Required for AppRole method. @@ -155,7 +155,7 @@ public class DedicatedVaultParameters { * conjunction with the Role ID for AppRole authentication. *

*/ - public static final Parameter SECRET_ID = Parameter.create(REQUIRED); + public static final Parameter SECRET_ID = Parameter.create(); /** * The path for AppRole authentication. Optional. @@ -176,7 +176,7 @@ public class DedicatedVaultParameters { * the Vault policy. *

*/ - public static final Parameter GITHUB_TOKEN = Parameter.create(REQUIRED); + public static final Parameter GITHUB_TOKEN = Parameter.create(); /** * The path for GitHub authentication. Optional. @@ -259,7 +259,7 @@ public static ParameterSet buildResolvedParameterSet(Map inputOp * @return the parsed {@link DedicatedVaultAuthenticationMethod}. * @throws IllegalArgumentException if the value is unrecognized. */ - private static DedicatedVaultAuthenticationMethod parseAuthentication(String value) { + public static DedicatedVaultAuthenticationMethod parseAuthentication(String value) { try { return DedicatedVaultAuthenticationMethod.valueOf(value.toUpperCase()); } catch (IllegalArgumentException e) { diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/configuration/DedicatedVaultJsonSecretProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/configuration/DedicatedVaultJsonSecretProvider.java index e719e021..731d54ff 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/configuration/DedicatedVaultJsonSecretProvider.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/configuration/DedicatedVaultJsonSecretProvider.java @@ -49,6 +49,7 @@ import static oracle.jdbc.provider.hashicorp.hcpvaultdedicated.authentication.DedicatedVaultParameters.FIELD_NAME; import static oracle.jdbc.provider.hashicorp.hcpvaultdedicated.authentication.DedicatedVaultParameters.PARAMETER_SET_PARSER; +import static oracle.jdbc.provider.hashicorp.util.JsonUtil.extractSecret; /** *

@@ -95,20 +96,11 @@ public char[] getSecret(Map map) { OracleJsonObject secretJsonObj = JsonUtil.convertJsonToOracleJsonObject(secretString); String fieldName = parameterSet.getOptional(FIELD_NAME); - String extractedPassword; - if (fieldName != null && secretJsonObj.containsKey(fieldName)) { - extractedPassword = secretJsonObj.getString(fieldName); - } else if (secretJsonObj.size() == 1) { - extractedPassword = secretJsonObj.values().iterator().next().toString(); - } else { - throw new IllegalStateException( - "FIELD_NAME is required when multiple keys exist in the secret." - ); - } + String extractedSecret = extractSecret(secretJsonObj, fieldName); return Base64.getEncoder() - .encodeToString(extractedPassword.getBytes()) - .toCharArray(); + .encodeToString(extractedSecret.getBytes()) + .toCharArray(); } @Override diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedConnectionStringProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedConnectionStringProvider.java new file mode 100644 index 00000000..9d535007 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedConnectionStringProvider.java @@ -0,0 +1,129 @@ +/* + ** 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.hashicorp.hcpvaultdedicated.resource; + +import oracle.jdbc.provider.resource.ResourceParameter; +import oracle.jdbc.provider.util.FileUtils; +import oracle.jdbc.provider.util.TNSNames; +import oracle.jdbc.spi.ConnectionStringProvider; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Base64; +import java.util.Map; + +import static oracle.jdbc.provider.util.CommonParameters.TNS_ALIAS; + +/** + *

+ * A provider for securely retrieving the connection string from a tnsnames.ora + * file stored in HashiCorp Vault Dedicated for use with an Oracle Autonomous Database. + * The tnsnames.ora file can be stored as a base64-encoded secret or as plain + * text. The provider automatically detects the format and processes the + * content accordingly to extract connection strings by alias. + *

+ *

+ * This class implements the {@link ConnectionStringProvider} SPI defined by + * Oracle JDBC. + * It is designed to be instantiated via {@link java.util.ServiceLoader}. + *

+ */ +public class HcpVaultDedicatedConnectionStringProvider + extends HcpVaultDedicatedSecretProvider + implements ConnectionStringProvider { + + private static final ResourceParameter[] TNS_NAMES_PARAMETERS = { + new ResourceParameter("tnsAlias", TNS_ALIAS) + }; + + /** + * A public no-arg constructor used by {@link java.util.ServiceLoader} to + * construct an instance of this provider. + */ + public HcpVaultDedicatedConnectionStringProvider() { + super("tnsnames", TNS_NAMES_PARAMETERS); + } + + + /** + * Retrieves a database connection string from the tnsnames.ora file stored + * in HashiCorp Vault Dedicated. + *

+ * This method accesses the file in Vault, decodes it, and parses + * the tnsnames.ora content. It returns the connection string associated + * with the specified alias from the tnsnames.ora file. + *

+ * + * @param parameterValues The parameters required to access the tnsnames.ora + * file in HashiCorp Vault Dedicated. + * @return The connection string associated with the specified alias + * in the tnsnames.ora file. + * @throws IllegalStateException If there is an error reading the tnsnames.ora + * file or accessing HashiCorp Vault Dedicated. + * @throws IllegalArgumentException If the specified alias is invalid or + * does not exist in the tnsnames.ora file. + */ + @Override + public String getConnectionString(Map parameterValues) { + String alias = parseParameterValues(parameterValues).getRequired(TNS_ALIAS); + + byte[] secretBytes = getSecret(parameterValues).getBytes(); + + byte[] fileBytes; + if (FileUtils.isBase64Encoded(secretBytes)) { + fileBytes = Base64.getDecoder().decode(secretBytes); + } else { + fileBytes = secretBytes; + } + + TNSNames tnsNames; + try (InputStream inputStream = new ByteArrayInputStream(fileBytes)) { + tnsNames = TNSNames.read(inputStream); + } catch (IOException e) { + throw new IllegalStateException("Failed to read tnsnames.ora content", e); + } + + String connectionString = tnsNames.getConnectionStringByAlias(alias); + if (connectionString == null) { + throw new IllegalArgumentException( + "Alias specified does not exist in tnsnames.ora: " + alias); + } + return connectionString; + } +} diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedPasswordProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedPasswordProvider.java new file mode 100644 index 00000000..6e8c03df --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedPasswordProvider.java @@ -0,0 +1,71 @@ +/* + ** 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.hashicorp.hcpvaultdedicated.resource; + +import oracle.jdbc.spi.PasswordProvider; + +import java.util.Map; + +/** + *

+ * A provider for retrieving passwords securely stored in HashiCorp Vault Dedicated. + * This provider fetches the password from the Vault and returns it as a character array. + *

+ *

+ * This class implements the {@link PasswordProvider} SPI defined by Oracle JDBC + * and is designed to be instantiated via {@link java.util.ServiceLoader}. + *

+ */ +public class HcpVaultDedicatedPasswordProvider + extends HcpVaultDedicatedSecretProvider + implements PasswordProvider { + + /** + * A public no-arg constructor used by {@link java.util.ServiceLoader} to + * construct an instance of this provider. + */ + public HcpVaultDedicatedPasswordProvider() { + super("password"); + } + + @Override + public char[] getPassword(Map parameterValues) { + return getSecret(parameterValues).toCharArray(); + } +} diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedResourceProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedResourceProvider.java new file mode 100644 index 00000000..c7430fc8 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedResourceProvider.java @@ -0,0 +1,184 @@ +/* + ** 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.hashicorp.hcpvaultdedicated.resource; + +import oracle.jdbc.provider.hashicorp.hcpvaultdedicated.authentication.DedicatedVaultAuthenticationMethod; +import oracle.jdbc.provider.hashicorp.hcpvaultdedicated.authentication.DedicatedVaultParameters; +import oracle.jdbc.provider.resource.AbstractResourceProvider; +import oracle.jdbc.provider.resource.ResourceParameter; + +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +import static oracle.jdbc.provider.hashicorp.hcpvaultdedicated.authentication.DedicatedVaultParameters.*; +import static oracle.jdbc.provider.hashicorp.hcpvaultdedicated.authentication.DedicatedVaultParameters.PASSWORD; + +/** + * Super class of all {@code OracleResourceProvider} implementations + * that request a resource from Hcp Vault Dedicated. This super class defines + * parameters for authentication with Hcp Vault Dedicated. + */ +public class HcpVaultDedicatedResourceProvider extends AbstractResourceProvider { + + static final ResourceParameter[] PARAMETERS = { + new ResourceParameter("authenticationMethod", AUTHENTICATION_METHOD, + "auto-detect", + HcpVaultDedicatedResourceProvider::parseAuthenticationMethod), + new ResourceParameter("vaultAddr", VAULT_ADDR), + new ResourceParameter("vaultNamespace", NAMESPACE, DEFAULT_NAMESPACE), + new ResourceParameter("vaultUsername", USERNAME), + new ResourceParameter("vaultPassword", PASSWORD), + new ResourceParameter("vaultToken", VAULT_TOKEN), + new ResourceParameter("roleId", ROLE_ID), + new ResourceParameter("secretId", SECRET_ID), + new ResourceParameter("userPassAuthPath", USERPASS_AUTH_PATH, DEFAULT_USERPASS_PATH), + new ResourceParameter("appRoleAuthPath", APPROLE_AUTH_PATH, DEFAULT_APPROLE_PATH), + new ResourceParameter("githubToken", GITHUB_TOKEN), + new ResourceParameter("githubAuthPath", GITHUB_AUTH_PATH, DEFAULT_GITHUB_PATH), + }; + + /** + *

+ * Constructs a provider identified by the name: + *

+ *
{@code
+   *   ojdbc-provider-hcpvault-dedicated-{resourceType}
+   * }
+ *

+ * This constructor defines all parameters related to authentication with + * HashiCorp Vault Dedicated. + * Subclasses must call this constructor with any additional parameters for + * the specific resource they provide. + *

+ * + * @param resourceType The resource type identifier that appears in the name of + * the provider. Not null. + * @param parameters Additional parameters specific to the subclass provider. + */ + protected HcpVaultDedicatedResourceProvider( + String resourceType, ResourceParameter... parameters) { + super("hcpvault-dedicated", resourceType, + Stream.concat( + Stream.of(PARAMETERS), + Stream.of(parameters)) + .toArray(ResourceParameter[]::new)); + } + + /** + * Parses the "authentication-method" parameter into a recognized + * {@link DedicatedVaultAuthenticationMethod}. + * + * @param authenticationMethod The authentication method as a string. + * @return The corresponding {@link DedicatedVaultAuthenticationMethod}. + * @throws IllegalArgumentException if the authentication method is unrecognized. + */ + private static DedicatedVaultAuthenticationMethod parseAuthenticationMethod(String authenticationMethod) { + switch (authenticationMethod) { + case "vault-token": + return DedicatedVaultAuthenticationMethod.VAULT_TOKEN; + case "userpass": + return DedicatedVaultAuthenticationMethod.USERPASS; + case "approle": + return DedicatedVaultAuthenticationMethod.APPROLE; + case "github": + return DedicatedVaultAuthenticationMethod.GITHUB; + case "auto-detect": + return DedicatedVaultAuthenticationMethod.AUTO_DETECT; + default: + throw new IllegalArgumentException("Unrecognized authentication method: " + authenticationMethod); + } + } + + + /** + * Resolves missing parameters using system properties or environment variables, + * ensuring parameters are populated before executing Vault requests. + * + * @param parameterValues The original parameter map. + * @return A new map with resolved missing parameters. + */ + Map resolveMissingParameters(Map parameterValues) { + Map resolvedParameters = new HashMap<>(parameterValues); + for (ResourceParameter param : HcpVaultDedicatedResourceProvider.PARAMETERS) { + resolveParameter(resolvedParameters, param); + } + return resolvedParameters; + } + + + /** + * Resolves a single parameter by mapping its name to a corresponding + * system property or environment variable. + * + * @param parameterValues The parameter map where the resolved value will be set. + * @param parameter The ResourceParameter key to check and resolve. + */ + private void resolveParameter(Map parameterValues, ResourceParameter parameter) { + if (!parameterValues.containsKey(parameter)) { + String envVariable = getEnvVariableForParameter(parameter.name()); + String fallbackValue = System.getProperty(envVariable, System.getenv(envVariable)); + if (fallbackValue != null) { + parameterValues.put(parameter, fallbackValue); + } + } + } + + /** + * Maps ResourceParameter names to their corresponding environment variable keys. + * + * @param paramName The ResourceParameter name (e.g., "vaultAddr"). + * @return The corresponding environment variable key (e.g., "VAULT_ADDR"). + */ + private String getEnvVariableForParameter(String paramName) { + switch (paramName) { + case "vaultAddr": return PARAM_VAULT_ADDR; + case "vaultNamespace": return PARAM_VAULT_NAMESPACE; + case "vaultUsername": return PARAM_VAULT_USERNAME; + case "vaultPassword": return PARAM_VAULT_PASSWORD; + case "vaultToken": return PARAM_VAULT_TOKEN; + case "roleId": return PARAM_VAULT_ROLE_ID; + case "secretId": return PARAM_VAULT_SECRET_ID; + case "userPassAuthPath": return PARAM_USERPASS_AUTH_PATH; + case "appRoleAuthPath": return PARAM_APPROLE_AUTH_PATH; + default: return paramName; + } + } + +} diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSEPSProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSEPSProvider.java new file mode 100644 index 00000000..048e1a5b --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSEPSProvider.java @@ -0,0 +1,123 @@ +/* + ** 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.hashicorp.hcpvaultdedicated.resource; + +import oracle.jdbc.provider.parameter.ParameterSet; +import oracle.jdbc.provider.resource.ResourceParameter; +import oracle.jdbc.provider.util.FileUtils; +import oracle.jdbc.provider.util.WalletUtils; +import oracle.jdbc.spi.OracleResourceProvider; +import oracle.jdbc.spi.PasswordProvider; +import oracle.jdbc.spi.UsernameProvider; + +import java.util.Base64; +import java.util.Map; + +import static oracle.jdbc.provider.util.CommonParameters.CONNECTION_STRING_INDEX; +import static oracle.jdbc.provider.util.CommonParameters.PASSWORD; + +/** + *

+ * A provider for Secure External Password Store (SEPS) credentials used + * to establish secure authentication with an Oracle database. The wallet is + * retrieved from HashiCorp Vault Dedicated, where it is stored as a + * base64-encoded string. + *

+ *

+ * This provider supports retrieving both **username** and **password** from + * the wallet. It can handle both **SSO** and **PKCS12**-based wallets. + *

+ *

+ * This class implements the {@link UsernameProvider} and + * {@link PasswordProvider} SPIs defined by Oracle JDBC and is designed to be + * instantiated via {@link java.util.ServiceLoader}. + *

+ */ +public class HcpVaultDedicatedSEPSProvider + extends HcpVaultDedicatedSecretProvider + implements UsernameProvider, PasswordProvider { + + private static final ResourceParameter[] SEPS_PARAMETERS = { + new ResourceParameter("walletPassword", PASSWORD), + new ResourceParameter("connectionStringIndex", CONNECTION_STRING_INDEX) + }; + + /** + * A public no-arg constructor used by {@link java.util.ServiceLoader} to + * construct an instance of this provider. + */ + public HcpVaultDedicatedSEPSProvider() { + super("seps", SEPS_PARAMETERS); + } + + @Override + public String getUsername(Map parameterValues) { + return getWalletCredentials(parameterValues).username(); + } + + @Override + public char[] getPassword(Map parameterValues) { + return getWalletCredentials(parameterValues).password(); + } + + /** + * Retrieves the Oracle Wallet credentials by decoding the base64-encoded + * wallet stored in HashiCorp Vault Dedicated and opening it as either SSO + * or PKCS12, based on whether a password is provided. + * + * @param parameterValues The parameters required to access the wallet file. + * @return The extracted credentials containing username and password. + */ + private WalletUtils.Credentials getWalletCredentials( + Map parameterValues) { + ParameterSet parameterSet = parseParameterValues(parameterValues); + + String secretValue = getSecret(parameterValues); + + byte[] walletBytes = FileUtils.isBase64Encoded(secretValue.getBytes()) ? + Base64.getDecoder().decode(secretValue) : secretValue.getBytes(); + + char[] walletPassword = parameterSet.getOptional(PASSWORD) != null + ? parameterSet.getOptional(PASSWORD).toCharArray() : null; + + String connectionStringIndex = parameterSet.getOptional(CONNECTION_STRING_INDEX); + return WalletUtils.getCredentials(walletBytes, walletPassword, connectionStringIndex); + } + +} diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSecretProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSecretProvider.java new file mode 100644 index 00000000..1f0a0768 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSecretProvider.java @@ -0,0 +1,109 @@ +/* + ** 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.hashicorp.hcpvaultdedicated.resource; + +import oracle.jdbc.provider.hashicorp.hcpvaultdedicated.secrets.DedicatedVaultSecretsManagerFactory; +import oracle.jdbc.provider.hashicorp.util.JsonUtil; +import oracle.jdbc.provider.resource.ResourceParameter; +import oracle.jdbc.provider.util.ResourceParameterUtils; +import oracle.sql.json.OracleJsonObject; + +import java.util.Map; +import java.util.stream.Stream; + +import static oracle.jdbc.provider.hashicorp.hcpvaultdedicated.authentication.DedicatedVaultParameters.*; + +/** + *

+ * A provider of secrets from HashiCorp Vault Dedicated. This class is designed + * for inheritance by subclasses that implement an + * {@link oracle.jdbc.spi.OracleResourceProvider} SPI defined by the Oracle JDBC + * driver. This class defines parameters that configure the Secret path, + * and optional field selection for extracting values from JSON-based secrets. + *

+ */ +public class HcpVaultDedicatedSecretProvider extends HcpVaultDedicatedResourceProvider { + + private static final ResourceParameter[] PARAMETERS = { + new ResourceParameter("secretPath", SECRET_PATH), + new ResourceParameter("fieldName", FIELD_NAME), + }; + + protected HcpVaultDedicatedSecretProvider(String valueType) { + super(valueType, PARAMETERS); + } + + protected HcpVaultDedicatedSecretProvider(String valueType, ResourceParameter[] additionalParameters) { + super(valueType, ResourceParameterUtils.combineParameters(PARAMETERS, additionalParameters)); + } + + /** + *

+ * Retrieves a secret from HashiCorp Vault Dedicated based on parameters + * provided in {@code parameterValues}. This method centralizes secret + * retrieval logic and is used by subclasses implementing + * the {@link oracle.jdbc.spi.OracleResourceProvider} SPI. + *

+ *

+ * If the secret is stored in JSON format with multiple fields, a specific field + * can be extracted using the "fieldName" parameter. If no field name is provided + * and the JSON contains a single key, that key’s value is returned. If + * multiple keys exist and no field name is specified, an exception is thrown. + *

+ * + * @param parameterValues A map of parameter names and their corresponding + * -values required for secret retrieval. Must not be null. + * @return The extracted secret value as a {@code String}. + */ + protected final String getSecret(Map parameterValues) { + Map resolvedValues = resolveMissingParameters(parameterValues); + String secretJson = getResource( + DedicatedVaultSecretsManagerFactory.getInstance(), resolvedValues); + OracleJsonObject secretJsonObj = JsonUtil.convertJsonToOracleJsonObject(secretJson); + ResourceParameter fieldNameParam = Stream.of(PARAMETERS) + .filter(param -> param.name().equals("fieldName")) + .findFirst() + .orElse(null); + + String fieldName = parameterValues.containsKey(fieldNameParam) ? + parameterValues.get(fieldNameParam).toString() : null; + return JsonUtil.extractSecret(secretJsonObj, fieldName); + } + +} diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedTCPSProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedTCPSProvider.java new file mode 100644 index 00000000..01ef96fb --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedTCPSProvider.java @@ -0,0 +1,126 @@ +/* + ** 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.hashicorp.hcpvaultdedicated.resource; + +import oracle.jdbc.provider.parameter.ParameterSet; +import oracle.jdbc.provider.resource.ResourceParameter; +import oracle.jdbc.provider.util.FileUtils; +import oracle.jdbc.provider.util.TlsUtils; +import oracle.jdbc.spi.TlsConfigurationProvider; + +import javax.net.ssl.SSLContext; +import java.util.Base64; +import java.util.Map; + +import static oracle.jdbc.provider.util.CommonParameters.PASSWORD; +import static oracle.jdbc.provider.util.CommonParameters.TYPE; + +/** + *

+ * A provider for TCPS/TLS files used to establish secure TLS communication + * with an Autonomous Database. The file is retrieved from HashiCorp Vault Dedicated, + * where it is stored as a base64-encoded string. This provider supports + * different file types including SSO, PKCS12, and PEM formats. + *

+ *

+ * The type of the file must be explicitly specified using the {@code type} + * parameter. Based on the type, the file may contain private keys and + * certificates for establishing secure communication. A password is only + * required for PKCS12 or encrypted PEM files. + *

+ *

+ * This class implements the {@link TlsConfigurationProvider} SPI defined by + * Oracle JDBC and is designed to be instantiated via + * {@link java.util.ServiceLoader}. + *

+ */ +public class HcpVaultDedicatedTCPSProvider + extends HcpVaultDedicatedSecretProvider + implements TlsConfigurationProvider { + + private static final ResourceParameter[] TCPS_PARAMETERS = { + new ResourceParameter("walletPassword", PASSWORD), + new ResourceParameter("type", TYPE) + }; + + /** + * A public no-arg constructor used by {@link java.util.ServiceLoader} to + * construct an instance of this provider. + */ + public HcpVaultDedicatedTCPSProvider() { + super("tls", TCPS_PARAMETERS); + } + + /** + * Retrieves an SSLContext by loading a file from HashiCorp Vault Dedicated and + * configuring it for secure TLS communication with Autonomous Database. + *

+ * The file is stored in HashiCorp Vault Dedicated as a base64-encoded string. + * The type of the file (SSO, PKCS12, or PEM) must be explicitly provided, + * and the method processes the file data accordingly, extracting keys and + * certificates, and creating an SSLContext. + *

+ * + * @param parameterValues The parameters required to access the file, + * including the vault URL, the secret name, password (if applicable), and + * file type (SSO, PKCS12, PEM). + * @return An initialized SSLContext for establishing secure communications. + * @throws IllegalStateException If the SSLContext cannot be created due to + * errors during processing. + */ + @Override + public SSLContext getSSLContext(Map parameterValues) { + try { + ParameterSet parameterSet = parseParameterValues(parameterValues); + String secretValue = getSecret(parameterValues); + byte[] fileBytes = FileUtils.isBase64Encoded(secretValue.getBytes()) ? + Base64.getDecoder().decode(secretValue) : secretValue.getBytes(); + + char[] password = parameterSet.getOptional(PASSWORD) != null + ? parameterSet.getOptional(PASSWORD).toCharArray() : null; + + String type = parameterSet.getRequired(TYPE); + return TlsUtils.createSSLContext(fileBytes, password, type); + } catch (Exception e) { + throw new IllegalStateException + ("Failed to create SSLContext from the file", e); + } + } + +} diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedUsernameProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedUsernameProvider.java new file mode 100644 index 00000000..84f15830 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedUsernameProvider.java @@ -0,0 +1,71 @@ +/* + ** 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.hashicorp.hcpvaultdedicated.resource; + +import oracle.jdbc.spi.UsernameProvider; + +import java.util.Map; + +/** + *

+ * A provider for securely retrieving a username stored as a secret + * in HashiCorp Vault Dedicated. + *

+ *

+ * This class implements the {@link UsernameProvider} SPI defined by + * Oracle JDBC and is designed to be instantiated via {@link java.util.ServiceLoader}. + *

+ */ +public class HcpVaultDedicatedUsernameProvider + extends HcpVaultDedicatedSecretProvider + implements UsernameProvider { + + /** + * A public no-arg constructor used by {@link java.util.ServiceLoader} to + * construct an instance of this provider. + */ + public HcpVaultDedicatedUsernameProvider() { + super("username"); + } + + @Override + public String getUsername(Map parameterValues) { + return getSecret(parameterValues); + } +} diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/util/JsonUtil.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/util/JsonUtil.java index 8c12dd5d..5735187a 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/util/JsonUtil.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/util/JsonUtil.java @@ -80,4 +80,32 @@ public static String extractField(OracleJsonObject jsonObject, String fieldName) } throw new IllegalStateException("Missing field '" + fieldName + "' in the response JSON."); } + + /** + * Extracts the secret value from the given JSON object based on the field name. + * + *

Logic:

+ *
    + *
  • If {@code fieldName} is provided and exists in the JSON, return its value.
  • + *
  • If the JSON contains only one key-value pair, return that value automatically.
  • + *
  • If multiple keys exist and no {@code fieldName} is provided, throw an error.
  • + *
+ * + * @param secretJsonObj The JSON object containing the secret. + * @param fieldName The field name to extract (optional). + * @return The extracted secret value as a string. + * @throws IllegalStateException If multiple keys exist but no `fieldName` is specified. + */ + public static String extractSecret(OracleJsonObject secretJsonObj, String fieldName) { + if (fieldName != null && secretJsonObj.containsKey(fieldName)) { + return secretJsonObj.getString(fieldName); + } else if (secretJsonObj.size() == 1) { + String firstKey = secretJsonObj.keySet().iterator().next(); + return secretJsonObj.getString(firstKey); + } else { + throw new IllegalStateException( + "FIELD_NAME is required when multiple keys exist in the secret." + ); + } + } } \ No newline at end of file diff --git a/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.ConnectionStringProvider b/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.ConnectionStringProvider new file mode 100644 index 00000000..41b28094 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.ConnectionStringProvider @@ -0,0 +1 @@ +oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource.HcpVaultDedicatedConnectionStringProvider \ No newline at end of file diff --git a/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.PasswordProvider b/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.PasswordProvider new file mode 100644 index 00000000..a06f28d6 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.PasswordProvider @@ -0,0 +1,2 @@ +oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource.HcpVaultDedicatedPasswordProvider +oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource.HcpVaultDedicatedSEPSProvider diff --git a/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.TlsConfigurationProvider b/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.TlsConfigurationProvider new file mode 100644 index 00000000..fdbf2db3 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.TlsConfigurationProvider @@ -0,0 +1 @@ +oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource.HcpVaultDedicatedTCPSProvider \ No newline at end of file diff --git a/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.UsernameProvider b/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.UsernameProvider new file mode 100644 index 00000000..0a935a45 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.UsernameProvider @@ -0,0 +1,2 @@ +oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource.HcpVaultDedicatedUsernameProvider +oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource.HcpVaultDedicatedSEPSProvider \ No newline at end of file diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/configuration/DedicatedVaultTestProperty.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/DedicatedVaultTestProperty.java similarity index 92% rename from ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/configuration/DedicatedVaultTestProperty.java rename to ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/DedicatedVaultTestProperty.java index 97212117..ef162011 100644 --- a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/configuration/DedicatedVaultTestProperty.java +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/DedicatedVaultTestProperty.java @@ -36,7 +36,7 @@ ** SOFTWARE. */ -package oracle.jdbc.provider.hashicorp.hcpvaultdedicated.configuration; +package oracle.jdbc.provider.hashicorp.hcpvaultdedicated; /** * Enumeration of test properties for Dedicated Vault. @@ -62,5 +62,15 @@ public enum DedicatedVaultTestProperty { SECRET_ID, - GITHUB_TOKEN + PASSWORD_SECRET_PATH, + + TNSNAMES_SECRET_PATH, + + TNSNAMES_ALIAS, + + GITHUB_TOKEN, + + WALLET_SECRET_PATH, + + WALLET_PASSWORD } diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/HcpVaultDedicatedTestUtil.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/HcpVaultDedicatedTestUtil.java new file mode 100644 index 00000000..5d912219 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/HcpVaultDedicatedTestUtil.java @@ -0,0 +1,126 @@ +/* + ** 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.hashicorp.hcpvaultdedicated; + +import oracle.jdbc.provider.TestProperties; +import org.junit.jupiter.api.Assumptions; + +import java.util.Map; + +import static oracle.jdbc.provider.TestProperties.getOptional; +import static oracle.jdbc.provider.TestProperties.getOrAbort; + +/** + * Utility class for configuring authentication parameters in tests that verify + * implementations of {@link oracle.jdbc.spi.OracleResourceProvider} in the + * ojdbc-provider-hcpvault-dedicated provider. + */ +public final class HcpVaultDedicatedTestUtil { + + private HcpVaultDedicatedTestUtil() { } + + /** + * Configures authentication parameters for HashiCorp Vault Dedicated based on + * values from a test.properties file. If the "authenticationMethod" is already set, + * it verifies required parameters. If "auto-detect" is used, it selects the first + * available method from the test properties. + * + * @param testParameters The parameter map used for authentication. + */ + public static void configureAuthentication(Map testParameters) { + testParameters.putIfAbsent("authenticationMethod", "auto-detect"); + String authMethod = testParameters.get("authenticationMethod"); + + switch (authMethod) { + case "vault-token": + testParameters.put("vaultToken", TestProperties.getOrAbort(DedicatedVaultTestProperty.VAULT_TOKEN)); + break; + case "approle": + testParameters.put("roleId", getOrAbort(DedicatedVaultTestProperty.ROLE_ID)); + testParameters.put("secretId", getOrAbort(DedicatedVaultTestProperty.SECRET_ID)); + break; + case "userpass": + testParameters.put("vaultUsername", getOrAbort(DedicatedVaultTestProperty.VAULT_USERNAME)); + testParameters.put("vaultPassword", getOrAbort(DedicatedVaultTestProperty.VAULT_PASSWORD)); + break; + case "github": + testParameters.put("githubToken", getOrAbort(DedicatedVaultTestProperty.GITHUB_TOKEN)); + break; + case "auto-detect": + if (!configureAutoDetect(testParameters)) + Assumptions.abort("No valid authentication method found for auto-detect."); + break; + default: + throw new IllegalArgumentException("Unsupported authentication method: " + authMethod); + } + } + + /** + * Auto-detects the first available authentication method and configures the necessary parameters. + * If no valid method is found, it returns {@code false}. + * + * @param testParameters The parameter map to populate. + * @return {@code true} if a valid authentication method was found, otherwise {@code false}. + */ + private static boolean configureAutoDetect(Map testParameters) { + return setIfAvailable(testParameters, "vaultToken", DedicatedVaultTestProperty.VAULT_TOKEN) || + (setIfAvailable(testParameters, "roleId", DedicatedVaultTestProperty.ROLE_ID) && + setIfAvailable(testParameters, "secretId", DedicatedVaultTestProperty.SECRET_ID)) || + (setIfAvailable(testParameters, "vaultUsername", DedicatedVaultTestProperty.VAULT_USERNAME) && + setIfAvailable(testParameters, "vaultPassword", DedicatedVaultTestProperty.VAULT_PASSWORD)) || + setIfAvailable(testParameters, "githubToken", DedicatedVaultTestProperty.GITHUB_TOKEN); + } + + /** + * Retrieves an optional test property and adds it to the parameters if available. + * + * @param testParameters The parameter map to populate. + * @param key The parameter key. + * @param property The test property to retrieve. + * @return {@code true} if the value was added, otherwise {@code false}. + */ + private static boolean setIfAvailable(Map testParameters, String key, DedicatedVaultTestProperty property) { + String value = getOptional(property); + if (value != null) { + testParameters.put(key, value); + return true; + } + return false; + } +} diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/configuration/DedicatedVaultConfigurationProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/configuration/DedicatedVaultConfigurationProviderTest.java index b321543c..d3de44ad 100644 --- a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/configuration/DedicatedVaultConfigurationProviderTest.java +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/configuration/DedicatedVaultConfigurationProviderTest.java @@ -39,6 +39,7 @@ package oracle.jdbc.provider.hashicorp.hcpvaultdedicated.configuration; import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.provider.hashicorp.hcpvaultdedicated.DedicatedVaultTestProperty; import oracle.jdbc.spi.OracleConfigurationProvider; import org.junit.jupiter.api.Test; diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedConnectionStringProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedConnectionStringProviderTest.java new file mode 100644 index 00000000..9317942b --- /dev/null +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedConnectionStringProviderTest.java @@ -0,0 +1,149 @@ +/* + ** 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.hashicorp.hcpvaultdedicated.resource; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.provider.hashicorp.hcpvaultdedicated.DedicatedVaultTestProperty; +import oracle.jdbc.provider.hashicorp.hcpvaultdedicated.HcpVaultDedicatedTestUtil; +import oracle.jdbc.spi.ConnectionStringProvider; +import oracle.jdbc.spi.OracleResourceProvider.Parameter; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.createParameterValues; +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.findProvider; +import static org.junit.jupiter.api.Assertions.*; + +public class HcpVaultDedicatedConnectionStringProviderTest { + + private static final ConnectionStringProvider PROVIDER = + findProvider(ConnectionStringProvider.class, "ojdbc-provider-hcpvault-dedicated-tnsnames"); + + /** + * Verifies that {@link ConnectionStringProvider#getParameters()} includes parameters + * to configure a vault URL and secret name. + */ + @Test + public void testGetParameters() { + Collection parameters = PROVIDER.getParameters(); + assertNotNull(parameters); + + Parameter vaultAddrParameter = + parameters.stream() + .filter(parameter -> "vaultAddr".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(vaultAddrParameter.isSensitive()); + assertTrue(vaultAddrParameter.isRequired()); + assertNull(vaultAddrParameter.defaultValue()); + + Parameter secretPathParameter = + parameters.stream() + .filter(parameter -> "secretPath".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(secretPathParameter.isSensitive()); + assertTrue(secretPathParameter.isRequired()); + assertNull(secretPathParameter.defaultValue()); + + Parameter aliasParameter = + parameters.stream() + .filter(parameter -> "tnsAlias".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(aliasParameter.isSensitive()); + assertTrue(aliasParameter.isRequired()); + assertNull(aliasParameter.defaultValue()); + } + + /** + * Retrieves a connection string using a valid alias from a plain + * text tnsnames.ora. + */ + @Test + public void testRetrieveConnectionStringFromPlainText() { + Map testParameters = new HashMap<>(); + + testParameters.put("vaultAddr", + TestProperties.getOrAbort(DedicatedVaultTestProperty.VAULT_ADDR)); + testParameters.put("secretPath", + TestProperties.getOrAbort(DedicatedVaultTestProperty.TNSNAMES_SECRET_PATH)); + testParameters.put("tnsAlias", + TestProperties.getOrAbort(DedicatedVaultTestProperty.TNSNAMES_ALIAS)); + testParameters.put("fieldName", "tnsnames_plain_text"); + + // Automatically configure authentication + HcpVaultDedicatedTestUtil.configureAuthentication(testParameters); + + Map parameterValues = createParameterValues(PROVIDER, testParameters); + + String connectionString = PROVIDER.getConnectionString(parameterValues); + + assertNotNull(connectionString, "Connection string should not be null"); + } + + /** + * Retrieves a connection string using a valid alias from a base64-encoded tnsnames.ora. + */ + @Test + public void testRetrieveConnectionStringFromBase64Encoded() { + Map testParameters = new HashMap<>(); + + testParameters.put("vaultAddr", + TestProperties.getOrAbort(DedicatedVaultTestProperty.VAULT_ADDR)); + testParameters.put("secretPath", + TestProperties.getOrAbort(DedicatedVaultTestProperty.TNSNAMES_SECRET_PATH)); + testParameters.put("tnsAlias", + TestProperties.getOrAbort(DedicatedVaultTestProperty.TNSNAMES_ALIAS)); + testParameters.put("fieldName", "tnsnames_base64"); + + // Automatically configure authentication + HcpVaultDedicatedTestUtil.configureAuthentication(testParameters); + + Map parameterValues = createParameterValues(PROVIDER, testParameters); + + String connectionString = PROVIDER.getConnectionString(parameterValues); + + assertNotNull(connectionString, "Connection string should not be null"); + } + +} diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedPasswordProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedPasswordProviderTest.java new file mode 100644 index 00000000..555937f2 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedPasswordProviderTest.java @@ -0,0 +1,114 @@ +/* + ** 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.hashicorp.hcpvaultdedicated.resource; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.provider.hashicorp.hcpvaultdedicated.DedicatedVaultTestProperty; +import oracle.jdbc.provider.hashicorp.hcpvaultdedicated.HcpVaultDedicatedTestUtil; +import oracle.jdbc.spi.OracleResourceProvider.Parameter; +import oracle.jdbc.spi.PasswordProvider; +import oracle.jdbc.spi.UsernameProvider; +import org.junit.jupiter.api.Test; + + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.createParameterValues; +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.findProvider; +import static org.junit.jupiter.api.Assertions.*; + +public class HcpVaultDedicatedPasswordProviderTest { + + private static final PasswordProvider PROVIDER = + findProvider(PasswordProvider.class, "ojdbc-provider-hcpvault-dedicated-password"); + + /** + * Verifies that {@link UsernameProvider#getParameters()} includes parameters + * to configure authentication and secret retrieval. + */ + @Test + public void testGetParameters() { + Collection parameters = PROVIDER.getParameters(); + assertNotNull(parameters); + + Parameter vaultAddrParameter = + parameters.stream() + .filter(parameter -> "vaultAddr".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(vaultAddrParameter.isRequired()); + assertNull(vaultAddrParameter.defaultValue()); + + Parameter secretPathParameter = + parameters.stream() + .filter(parameter -> "secretPath".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(secretPathParameter.isRequired()); + assertNull(secretPathParameter.defaultValue()); + + Parameter fieldNameParameter = + parameters.stream() + .filter(parameter -> "fieldName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(fieldNameParameter.isRequired()); + assertNull(fieldNameParameter.defaultValue()); + } + + @Test + public void testRetrievePassword() { + Map testParameters = new HashMap<>(); + testParameters.put("vaultAddr", TestProperties.getOrAbort(DedicatedVaultTestProperty.VAULT_ADDR)); + testParameters.put("secretPath", TestProperties.getOrAbort(DedicatedVaultTestProperty.PASSWORD_SECRET_PATH)); + testParameters.put("fieldName", "password"); + + HcpVaultDedicatedTestUtil.configureAuthentication(testParameters); + + Map parameterValues = + createParameterValues(PROVIDER, testParameters); + + char[] password = PROVIDER.getPassword(parameterValues); + + assertNotNull(password, "Password should not be null"); + } + +} diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSEPSProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSEPSProviderTest.java new file mode 100644 index 00000000..4312b068 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSEPSProviderTest.java @@ -0,0 +1,183 @@ +/* + ** 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.hashicorp.hcpvaultdedicated.resource; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.provider.hashicorp.hcpvaultdedicated.DedicatedVaultTestProperty; +import oracle.jdbc.provider.hashicorp.hcpvaultdedicated.HcpVaultDedicatedTestUtil; +import oracle.jdbc.spi.OracleResourceProvider.Parameter; +import oracle.jdbc.spi.PasswordProvider; +import oracle.jdbc.spi.UsernameProvider; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.createParameterValues; +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.findProvider; +import static org.junit.jupiter.api.Assertions.*; + +public class HcpVaultDedicatedSEPSProviderTest { + + private static final UsernameProvider USERNAME_PROVIDER = findProvider( + UsernameProvider.class, "ojdbc-provider-hcpvault-dedicated-seps"); + + private static final PasswordProvider PASSWORD_PROVIDER = findProvider( + PasswordProvider.class, "ojdbc-provider-hcpvault-dedicated-seps"); + + @Test + public void testProviderParameters() { + Collection usernameParameters = + USERNAME_PROVIDER.getParameters(); + Collection passwordParameters = + PASSWORD_PROVIDER.getParameters(); + + // Verify both providers have the same parameters + assertEquals(usernameParameters, passwordParameters, + "Username and Password providers should have identical parameters"); + + assertNotNull(usernameParameters); + assertNotNull(passwordParameters); + + Parameter vaultAddrParameter = + usernameParameters.stream() + .filter(parameter -> "vaultAddr".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(vaultAddrParameter.isSensitive()); + assertTrue(vaultAddrParameter.isRequired()); + assertNull(vaultAddrParameter.defaultValue()); + + Parameter secretPathParameter = + usernameParameters.stream() + .filter(parameter -> "secretPath".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(secretPathParameter.isSensitive()); + assertTrue(secretPathParameter.isRequired()); + assertNull(secretPathParameter.defaultValue()); + + Parameter walletPasswordParameter = + usernameParameters.stream() + .filter(parameter -> "walletPassword".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(walletPasswordParameter.isSensitive()); + assertNull(walletPasswordParameter.defaultValue()); + + Parameter connStringParameter = + usernameParameters.stream() + .filter(parameter -> "connectionStringIndex".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(connStringParameter.isSensitive()); + assertNull(connStringParameter.defaultValue()); + } + + @Test + public void testRetrieveUsernameFromPKCS12() { + Map testParameters = new HashMap<>(); + testParameters.put("vaultAddr", TestProperties.getOrAbort(DedicatedVaultTestProperty.VAULT_ADDR)); + testParameters.put("secretPath", TestProperties.getOrAbort(DedicatedVaultTestProperty.WALLET_SECRET_PATH)); + testParameters.put("fieldName", "base64-seps-p12"); + testParameters.put("walletPassword", TestProperties.getOrAbort(DedicatedVaultTestProperty.WALLET_PASSWORD)); + + HcpVaultDedicatedTestUtil.configureAuthentication(testParameters); + + Map parameterValues = createParameterValues(USERNAME_PROVIDER, testParameters); + String username = USERNAME_PROVIDER.getUsername(parameterValues); + + assertNotNull(username); + } + + @Test + public void testRetrievePasswordFromPKCS12() { + Map testParameters = new HashMap<>(); + testParameters.put("vaultAddr", TestProperties.getOrAbort(DedicatedVaultTestProperty.VAULT_ADDR)); + testParameters.put("secretPath", TestProperties.getOrAbort(DedicatedVaultTestProperty.WALLET_SECRET_PATH)); + testParameters.put("fieldName", "base64-seps-p12"); + testParameters.put("walletPassword", TestProperties.getOrAbort(DedicatedVaultTestProperty.WALLET_PASSWORD)); + + HcpVaultDedicatedTestUtil.configureAuthentication(testParameters); + + Map parameterValues = createParameterValues(PASSWORD_PROVIDER, testParameters); + char[] password = PASSWORD_PROVIDER.getPassword(parameterValues); + + assertNotNull(password); + } + + /** + * Test retrieving a password from an SSO SEPS wallet with a connection + * string index. + */ + @Test + public void testRetrievePasswordFromSSO() { + Map testParameters = new HashMap<>(); + testParameters.put("vaultAddr", TestProperties.getOrAbort(DedicatedVaultTestProperty.VAULT_ADDR)); + testParameters.put("secretPath", TestProperties.getOrAbort(DedicatedVaultTestProperty.WALLET_SECRET_PATH)); + testParameters.put("fieldName", "base64-seps-sso"); + + HcpVaultDedicatedTestUtil.configureAuthentication(testParameters); + + Map parameterValues = createParameterValues(PASSWORD_PROVIDER, testParameters); + char[] password = PASSWORD_PROVIDER.getPassword(parameterValues); + assertNotNull(password); + } + + /** + * Test retrieving a username from an SSO SEPS wallet without specifying a connection string index. + */ + @Test + public void testRetrieveUsernameFromSSO() { + Map testParameters = new HashMap<>(); + testParameters.put("vaultAddr", TestProperties.getOrAbort(DedicatedVaultTestProperty.VAULT_ADDR)); + testParameters.put("secretPath", TestProperties.getOrAbort(DedicatedVaultTestProperty.WALLET_SECRET_PATH)); + testParameters.put("fieldName", "base64-seps-sso"); + + HcpVaultDedicatedTestUtil.configureAuthentication(testParameters); + + Map parameterValues = createParameterValues(USERNAME_PROVIDER, testParameters); + String username = USERNAME_PROVIDER.getUsername(parameterValues); + assertNotNull(username); + } + + + +} diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedTCPSProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedTCPSProviderTest.java new file mode 100644 index 00000000..a7d92c65 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedTCPSProviderTest.java @@ -0,0 +1,199 @@ +/* + ** 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.hashicorp.hcpvaultdedicated.resource; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.provider.hashicorp.hcpvaultdedicated.DedicatedVaultTestProperty; +import oracle.jdbc.provider.hashicorp.hcpvaultdedicated.HcpVaultDedicatedTestUtil; +import oracle.jdbc.spi.OracleResourceProvider.Parameter; +import oracle.jdbc.spi.TlsConfigurationProvider; +import org.junit.jupiter.api.Test; + +import javax.net.ssl.SSLContext; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.createParameterValues; +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.findProvider; +import static org.junit.jupiter.api.Assertions.*; + +public class HcpVaultDedicatedTCPSProviderTest { + + private static final TlsConfigurationProvider PROVIDER = findProvider( + TlsConfigurationProvider.class, "ojdbc-provider-hcpvault-dedicated-tls"); + + @Test + public void testGetParameters() { + Collection parameters = PROVIDER.getParameters(); + assertNotNull(parameters); + + Parameter vaultAddrParameter = + parameters.stream() + .filter(parameter -> "vaultAddr".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(vaultAddrParameter.isSensitive()); + assertTrue(vaultAddrParameter.isRequired()); + assertNull(vaultAddrParameter.defaultValue()); + + Parameter secretPathParameter = + parameters.stream() + .filter(parameter -> "secretPath".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(secretPathParameter.isSensitive()); + assertTrue(secretPathParameter.isRequired()); + assertNull(secretPathParameter.defaultValue()); + + Parameter typeParameter = + parameters.stream() + .filter(parameter -> "type".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(typeParameter.isSensitive()); + assertTrue(typeParameter.isRequired()); + assertNull(typeParameter.defaultValue()); + + Parameter walletPasswordParameter = + parameters.stream() + .filter(parameter -> "walletPassword".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(walletPasswordParameter.isSensitive()); + assertFalse(walletPasswordParameter.isRequired()); + assertNull(walletPasswordParameter.defaultValue()); + } + + /** + * Test retrieving an SSLContext from a PKCS12 TCPS wallet. + */ + @Test + public void testRetrieveSSLContextFromPKCS12() { + Map testParameters = new HashMap<>(); + testParameters.put("vaultAddr", TestProperties.getOrAbort(DedicatedVaultTestProperty.VAULT_ADDR)); + testParameters.put("secretPath", TestProperties.getOrAbort(DedicatedVaultTestProperty.WALLET_SECRET_PATH)); + testParameters.put("type", "PKCS12"); + testParameters.put("fieldName", "base64-wallet-p12"); + testParameters.put("walletPassword", TestProperties.getOrAbort(DedicatedVaultTestProperty.WALLET_PASSWORD)); + + HcpVaultDedicatedTestUtil.configureAuthentication(testParameters); + + Map parameterValues = createParameterValues(PROVIDER, testParameters); + SSLContext sslContext = PROVIDER.getSSLContext(parameterValues); + + assertNotNull(sslContext); + } + + /** + * Test retrieving an SSLContext from an SSO TCPS wallet. + */ + @Test + public void testRetrieveSSLContextFromSSO() { + Map testParameters = new HashMap<>(); + testParameters.put("vaultAddr", TestProperties.getOrAbort(DedicatedVaultTestProperty.VAULT_ADDR)); + testParameters.put("secretPath", TestProperties.getOrAbort(DedicatedVaultTestProperty.WALLET_SECRET_PATH)); + testParameters.put("type", "SSO"); + testParameters.put("fieldName", "base64-wallet-sso"); + + HcpVaultDedicatedTestUtil.configureAuthentication(testParameters); + + Map parameterValues = createParameterValues(PROVIDER, testParameters); + SSLContext sslContext = PROVIDER.getSSLContext(parameterValues); + + assertNotNull(sslContext); + } + + /** + * Test retrieving an SSLContext from a PEM TCPS wallet. + */ + @Test + public void testRetrieveSSLContextFromPEM() { + Map testParameters = new HashMap<>(); + testParameters.put("vaultAddr", TestProperties.getOrAbort(DedicatedVaultTestProperty.VAULT_ADDR)); + testParameters.put("secretPath", TestProperties.getOrAbort(DedicatedVaultTestProperty.WALLET_SECRET_PATH)); + testParameters.put("type", "PEM"); + testParameters.put("fieldName", "base64-wallet-pem"); + testParameters.put("walletPassword", TestProperties.getOrAbort(DedicatedVaultTestProperty.WALLET_PASSWORD)); + + + HcpVaultDedicatedTestUtil.configureAuthentication(testParameters); + + Map parameterValues = createParameterValues(PROVIDER, testParameters); + SSLContext sslContext = PROVIDER.getSSLContext(parameterValues); + + assertNotNull(sslContext); + } + + /** + * Test missing password for a PKCS12 TCPS wallet. + */ + @Test + public void testPKCS12MissingPassword() { + Map testParameters = new HashMap<>(); + testParameters.put("vaultAddr", TestProperties.getOrAbort(DedicatedVaultTestProperty.VAULT_ADDR)); + testParameters.put("secretPath", TestProperties.getOrAbort(DedicatedVaultTestProperty.WALLET_SECRET_PATH)); + testParameters.put("type", "PKCS12"); + testParameters.put("fieldName", "base64-wallet-p12"); + + Map parameterValues = createParameterValues(PROVIDER, testParameters); + + assertThrows(IllegalStateException.class, () -> { + PROVIDER.getSSLContext(parameterValues); + }); + } + + /** + * Test missing password for a PEM TCPS wallet. + */ + @Test + public void testPemMissingPassword() { + Map testParameters = new HashMap<>(); + testParameters.put("vaultAddr", TestProperties.getOrAbort(DedicatedVaultTestProperty.VAULT_ADDR)); + testParameters.put("secretPath", TestProperties.getOrAbort(DedicatedVaultTestProperty.WALLET_SECRET_PATH)); + testParameters.put("type", "PEM"); + testParameters.put("fieldName", "base64-wallet-pem"); + + Map parameterValues = createParameterValues(PROVIDER, testParameters); + + assertThrows(IllegalStateException.class, () -> { + PROVIDER.getSSLContext(parameterValues); + }); + } +} diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedUsernameProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedUsernameProviderTest.java new file mode 100644 index 00000000..64fa32aa --- /dev/null +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedUsernameProviderTest.java @@ -0,0 +1,116 @@ +/* + ** 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.hashicorp.hcpvaultdedicated.resource; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.provider.hashicorp.hcpvaultdedicated.DedicatedVaultTestProperty; +import oracle.jdbc.provider.hashicorp.hcpvaultdedicated.HcpVaultDedicatedTestUtil; +import oracle.jdbc.spi.OracleResourceProvider.Parameter; +import oracle.jdbc.spi.UsernameProvider; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.createParameterValues; +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.findProvider; +import static org.junit.jupiter.api.Assertions.*; + + +public class HcpVaultDedicatedUsernameProviderTest { + + private static final UsernameProvider PROVIDER = + findProvider(UsernameProvider.class, "ojdbc-provider-hcpvault-dedicated-username"); + + /** + * Verifies that {@link UsernameProvider#getParameters()} includes parameters + * to configure authentication and secret retrieval. + */ + @Test + public void testGetParameters() { + Collection parameters = PROVIDER.getParameters(); + assertNotNull(parameters); + + Parameter vaultAddrParameter = + parameters.stream() + .filter(parameter -> "vaultAddr".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(vaultAddrParameter.isRequired()); + assertNull(vaultAddrParameter.defaultValue()); + + Parameter secretPathParameter = + parameters.stream() + .filter(parameter -> "secretPath".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(secretPathParameter.isRequired()); + assertNull(secretPathParameter.defaultValue()); + + Parameter fieldNameParameter = + parameters.stream() + .filter(parameter -> "fieldName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(fieldNameParameter.isRequired()); + assertNull(fieldNameParameter.defaultValue()); + } + + @Test + public void testRetrieveUsername() { + Map testParameters = new HashMap<>(); + + testParameters.put("vaultAddr", + TestProperties.getOrAbort(DedicatedVaultTestProperty.VAULT_ADDR)); + testParameters.put("secretPath", + TestProperties.getOrAbort(DedicatedVaultTestProperty.PASSWORD_SECRET_PATH)); + testParameters.put("fieldName", "username"); + + // Automatically configure authentication + HcpVaultDedicatedTestUtil.configureAuthentication(testParameters); + + Map parameterValues = + createParameterValues(PROVIDER, testParameters); + + String username = PROVIDER.getUsername(parameterValues); + + assertNotNull(username, "Username should not be null"); + } +} From 8df18f14bea7691ad7da4f38f76d091832aba59d Mon Sep 17 00:00:00 2001 From: Mouhsin Elmajdouby Date: Tue, 25 Mar 2025 13:37:14 +0000 Subject: [PATCH 2/6] Add Resource Providers for HCP Vault Secrets --- ojdbc-provider-hashicorp/README.md | 359 ++++++++++++++++-- .../example-vault-dedicated-wallet.properties | 2 +- .../example-vault-dedicated.properties | 3 +- .../example-vault-secrets-wallet.properties | 78 ++++ .../example-vault-secrets.properties | 61 +++ .../DedicatedVaultParameters.java | 2 +- .../HcpVaultDedicatedResourceProvider.java | 45 +-- .../HcpVaultDedicatedSecretProvider.java | 3 +- .../HcpVaultSecretParameters.java | 2 +- ...cpVaultSecretConnectionStringProvider.java | 109 ++++++ .../HcpVaultSecretPasswordProvider.java | 71 ++++ .../resource/HcpVaultSecretProvider.java | 88 +++++ .../HcpVaultSecretResourceProvider.java | 101 +++++ .../resource/HcpVaultSecretSEPSProvider.java | 115 ++++++ .../resource/HcpVaultSecretTCPSProvider.java | 110 ++++++ .../HcpVaultSecretUsernameProvider.java | 71 ++++ .../util/AbstractVaultResourceProvider.java | 91 +++++ .../oracle.jdbc.spi.ConnectionStringProvider | 3 +- .../services/oracle.jdbc.spi.PasswordProvider | 2 + .../oracle.jdbc.spi.TlsConfigurationProvider | 3 +- .../services/oracle.jdbc.spi.UsernameProvider | 4 +- ...DedicatedConnectionStringProviderTest.java | 1 - ...HcpVaultDedicatedPasswordProviderTest.java | 1 - .../HcpVaultDedicatedSEPSProviderTest.java | 1 - .../HcpVaultDedicatedTCPSProviderTest.java | 1 - ...HcpVaultDedicatedUsernameProviderTest.java | 1 - .../HcpVaultTestProperty.java | 22 +- .../hcpvaultsecret/HcpVaultTestUtil.java | 97 +++++ .../HcpVaultConfigurationProviderTest.java | 1 + .../HcpVaultConnectionStringProviderTest.java | 143 +++++++ .../HcpVaultPasswordProviderTest.java | 119 ++++++ .../resource/HcpVaultSEPSProviderTest.java | 164 ++++++++ .../resource/HcpVaultTCPSProviderTest.java | 176 +++++++++ .../HcpVaultUsernameProviderTest.java | 118 ++++++ 34 files changed, 2085 insertions(+), 83 deletions(-) create mode 100644 ojdbc-provider-hashicorp/example-vault-secrets-wallet.properties create mode 100644 ojdbc-provider-hashicorp/example-vault-secrets.properties create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretConnectionStringProvider.java create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretPasswordProvider.java create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretProvider.java create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretResourceProvider.java create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretSEPSProvider.java create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretTCPSProvider.java create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretUsernameProvider.java create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/util/AbstractVaultResourceProvider.java rename ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/{configuration => }/HcpVaultTestProperty.java (87%) create mode 100644 ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/HcpVaultTestUtil.java create mode 100644 ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultConnectionStringProviderTest.java create mode 100644 ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultPasswordProviderTest.java create mode 100644 ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSEPSProviderTest.java create mode 100644 ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultTCPSProviderTest.java create mode 100644 ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultUsernameProviderTest.java diff --git a/ojdbc-provider-hashicorp/README.md b/ojdbc-provider-hashicorp/README.md index e1a97e46..7dc3617a 100644 --- a/ojdbc-provider-hashicorp/README.md +++ b/ojdbc-provider-hashicorp/README.md @@ -16,19 +16,31 @@ and HashiCorp Vault (HCP). ## Resource Providers
Dedicated Vault Username Provider
-
Provides a username stored in a HashiCorp Vault Dedicated secret.
+
Provides a username stored in a HashiCorp Vault Dedicated.
+
HCP Vault Secrets Username Provider
+
Provides a username stored in HashiCorp Vault Secrets.
Dedicated Vault Password Provider
-
Provides a password stored in a HashiCorp Vault Dedicated secret.
+
Provides a password stored in a HashiCorp Vault Dedicated.
+
HCP Vault Secrets Password Provider
+
Provides a password stored in HashiCorp Vault Secrets.
Dedicated Vault TCPS Wallet Provider
-
Provides a TCPS/TLS wallet for secure database connections using credentials stored in HashiCorp Vault Dedicated.
+
Provides TLS wallets from HashiCorp Vault Dedicated for secure connections.
+
HCP Vault Secrets TCPS Wallet Provider
+
Provides TLS wallets from HashiCorp Vault Secrets for secure connections.
Dedicated Vault SEPS Wallet Provider
Provides SEPS (Secure External Password Store) wallets for secure username and password retrieval from HashiCorp Vault Dedicated.
+
HCP Vault Secrets SEPS Wallet Provider
+
Provides SEPS (Secure External Password Store) wallets for secure username and password retrieval from HashiCorp Vault Secrets.
Dedicated Vault Connection String Provider
-
Provides connection strings based on aliases stored in a `tnsnames.ora` file within HashiCorp Vault Dedicated.
+
Provides connection strings based on aliases stored in a `tnsnames.ora` file within HashiCorp Vault Dedicated.
+
HCP Vault Secrets Connection String Provider
+
Provides connection strings based on aliases stored in a `tnsnames.ora` file within HashiCorp Vault Secrets.
Common Parameters for HCP Vault Dedicated Resource Providers
Defines common configuration parameters for providers using HCP Vault Dedicated.
-
Configuring Authentication for HCP Vault Dedicated
-
Details the supported authentication methods for HCP Vault Dedicated.
+
Common Parameters for HCP Vault Secrets Resource Providers
+
Defines common parameters for all providers using HCP Vault Secrets.
+
Configuring Authentication for Resource Providers
+
Details supported authentication methods and usage instructions.
@@ -607,6 +619,34 @@ If omitted and multiple keys exist, an error is thrown. An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-dedicated.properties](example-vault-dedicated.properties). +## HCP Vault Secrets Username Provider + +The **HCP Vault Secrets Username Provider** provides Oracle JDBC with a **database username** that is managed by **HashiCorp Vault Secrets**. +This is a **Resource Provider** identified by the name `ojdbc-provider-hcpvault-secrets-username`. + +In addition to the set of [common parameters](#common-parameters-for-hcp-vault-secrets-resource-providers), this provider also supports the parameters listed below. + + + + + + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesDefault Value
secretNameThe name of the secret in HCP Vault Secrets containing the username.Any valid secret name within the app. No default value. A value must be configured for this parameter.
+ +An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-secrets.properties](example-vault-secrets.properties). + --- ## Dedicated Vault Password Provider @@ -664,6 +704,34 @@ If omitted and multiple keys exist, an error is thrown. An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-dedicated.properties](example-vault-dedicated.properties). +## HCP Vault Secrets Password Provider + +The **HCP Vault Secrets Password Provider** provides Oracle JDBC with a **database password** that is managed by **HashiCorp Vault Secrets**. +This is a **Resource Provider** identified by the name `ojdbc-provider-hcpvault-secrets-password`. + +In addition to the set of [common parameters](#common-parameters-for-hcp-vault-secrets-resource-providers), this provider also supports the parameters listed below. + + + + + + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesDefault Value
secretNameThe name of the secret in HCP Vault Secrets containing the password.Any valid secret name within the app. No default value. A value must be configured for this parameter.
+ +An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-secrets.properties](example-vault-secrets.properties). + --- ## Dedicated Vault TCPS Wallet Provider @@ -747,6 +815,55 @@ If omitted and multiple keys exist, an error is thrown. An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-dedicated-wallet.properties](example-vault-dedicated-wallet.properties). +## HCP Vault Secrets TCPS Wallet Provider + +The **HCP Vault Secrets TCPS Wallet Provide** provides Oracle JDBC with **keys and certificates** managed by **HashiCorp Vault Secrets** to establish secure **TLS connections** with an Autonomous Database. +This is a **Resource Provider** identified by the name `ojdbc-provider-hcpvault-secrets-tls`. + +For example, when connecting to an Autonomous Database Serverless with **mutual TLS (mTLS)**, +you need to configure the JDBC-thin driver with its client certificate. +If this certificate is stored in a wallet file (`cwallet.sso`, `ewallet.p12`, `ewallet.pem`), +you may store it in **HCP Vault Secrets** for additional security. +This provider retrieves the wallet content from **HCP Vault Secrets** and passes it to the JDBC thin driver. + +- The **type** parameter must be specified to indicate the wallet format: **SSO, PKCS12, or PEM**. +- The **walletPassword** must be provided for wallets that require a password (**PKCS12** or password-protected **PEM** files). + +In addition to the set of [common parameters](#common-parameters-for-hcp-vault-secrets-resource-providers), this provider also supports the parameters listed below. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesDefault Value
secretNameThe name of the secret in HCP Vault Secrets containing the wallet.Any valid secret name within the app. No default value. A value must be configured for this parameter.
typeThe wallet format.SSO, PKCS12, PEM No default value. The file type must be specified.
walletPassword Optional password for **PKCS12** or protected **PEM** files. If omitted, the file is assumed to be **SSO** or an **unprotected PEM** file. Any valid password. No default value. Required for password-protected files.
+ +An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-secrets-wallet.properties](example-vault-secrets-wallet.properties). + --- ## Dedicated Vault SEPS Wallet Provider @@ -842,6 +959,66 @@ If omitted and multiple keys exist, an error is thrown. An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-dedicated-wallet.properties](example-vault-dedicated-wallet.properties). +## HCP Vault Secrets SEPS Wallet Provider + +The **HCP Vault Secrets SEPS Wallet Provider** provides Oracle JDBC with **username and password credentials** stored in a **Secure External Password Store (SEPS) wallet** within **HCP Vault Secrets**. + +This is a **Resource Provider** identified by the name `ojdbc-provider-hcpvault-secrets-seps`. + +- The SEPS wallet securely stores **encrypted database credentials**, including the **username, password, and connection strings**. + These credentials can be stored as **default values**, such as: + - `oracle.security.client.default_username` + - `oracle.security.client.default_password` + + or as indexed credentials, for example: + - `oracle.security.client.username1` + - `oracle.security.client.password1` + - `oracle.security.client.connect_string1`. + +- The provider retrieves credentials using the following logic: + 1. If `connectionStringIndex` is **not specified**, the provider attempts to retrieve the **default credentials** (`oracle.security.client.default_username` and `oracle.security.client.default_password`). + 2. If **default credentials are missing**, the provider checks for a single **set of credentials** associated with a **connection string**. + 3. If **exactly one connection string** is found, the associated credentials are used. + 4. If **multiple connection strings** exist, an **error is thrown**, prompting you to specify a `connectionStringIndex`. + 5. If `connectionStringIndex` is specified, the provider attempts to retrieve the credentials associated with the **specified connection string index** (e.g., `oracle.security.client.username{idx}`, `oracle.security.client.password{idx}`, `oracle.security.client.connect_string{idx}`). + 6. If credentials for the **specified index** are not found, an **error is thrown**, indicating that no connection string exists with that index. + +In addition to the set of [common parameters](#common-parameters-for-hcp-vault-secrets-resource-providers), this provider also supports the parameters listed below. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesDefault Value
secretNameThe name of the SEPS wallet secret in HCP Vault Secrets.Any valid secret name within the app.No default value. A value must be configured for this parameter.
walletPassword Optional password for **PKCS12 SEPS wallets**. If omitted, the wallet is assumed to be **SSO**. Any valid password for the SEPS wallet.No default value. PKCS12 wallets require a password.
connectionStringIndex (Optional) Specifies the **index** of the connection string to use when retrieving credentials from the wallet. A positive integer representing the index of the desired credential set (e.g., 1, 2, 3, etc.).No default value. If not specified, the provider follows the default behavior as described above.
+ +An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-secrets-wallet.properties](example-vault-secrets-wallet.properties). + +--- ## Dedicated Vault Connection String Provider @@ -910,6 +1087,46 @@ If omitted and multiple keys exist, an error is thrown. An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-dedicated.properties](example-vault-dedicated.properties). +## HCP Vault Secrets Connection String Provider + +The **HCP Vault Secrets Connection String Provider** provides Oracle JDBC with a **connection string** +retrieved from a `tnsnames.ora` file stored in **HCP Vault Secrets**. + +This is a **Resource Provider** identified by the name `ojdbc-provider-hcpvault-secrets-tnsnames`. + +This provider retrieves and decodes a `tnsnames.ora` file stored as a **base64-encoded secret** or **plain text** in **HCP Vault Secrets**, allowing selection of connection strings based on specified aliases. + +This enables flexible configuration for **secure database connections** using the alias names defined in your `tnsnames.ora` file. + +In addition to the set of [common parameters](#common-parameters-for-hcp-vault-secrets-resource-providers), this provider also requires the parameters listed below. + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesDefault Value
secretNameThe name of the secret in HCP Vault Secrets containing the tnsnames.ora file.Any valid secret name within the app. No default value. A value must be configured for this parameter.
tnsAliasThe alias to retrieve the connection string.Any valid alias present in the `tnsnames.ora` file. No default value. A value must be configured for this parameter.
+ +An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-secrets.properties](example-vault-secrets.properties). + ## Common Parameters for HCP Vault Dedicated Resource Providers Providers classified as Resource Providers in this module all support a common set of parameters. @@ -929,7 +1146,7 @@ Providers classified as Resource Providers in this module all support a common s authenticationMethod Configures a method of authentication for HCP Vault Dedicated. Accepted values are defined in: Configuring Authentication for HCP Vault Dedicated. -does not allow System Property / Environment Variable +Not supported auto-detect @@ -1010,36 +1227,122 @@ Providers classified as Resource Providers in this module all support a common s +--- + +## Common Parameters for HCP Vault Secrets Resource Providers + +Providers classified as Resource Providers for HCP Vault Secrets support a common set of parameters used for authenticating with the HCP Vault Secrets API. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesSystem Property / Environment VariableDefault Value
authenticationMethodConfigures a method of authentication for HCP Vault Secrets.client_credentials, cli_credentials_file, auto-detectNot supportedauto-detect
orgIdThe organization ID associated with the HCP Vault Secrets project.A valid HCP organization ID.HCP_ORG_IDNo default value.
projectIdThe project ID associated with the HCP Vault Secrets app.A valid HCP project ID.HCP_PROJECT_IDNo default value.
appNameThe name of the application registered in HCP Vault Secrets.A valid HCP application name.HCP_APP_NAMENo default value.
clientIdThe client ID used for client credentials OAuth 2.0 authentication.A valid HCP Client ID.HCP_CLIENT_IDNo default value.
clientSecretThe client secret associated with the client ID.A valid HCP Client Secret.HCP_CLIENT_SECRETNo default value.
credentialsFileThe path to the local HCP CLI credentials file.A valid file path (e.g., ~/.config/hcp/creds-cache.json)HCP_CREDENTIALS_FILE~/.config/hcp/creds-cache.json
## Configuring Authentication for Resource Providers ### HCP Vault Dedicated -Resource Providers in this module must authenticate with HCP Vault Dedicated. +Resource Providers in this module must authenticate with **HashiCorp Vault Dedicated**. By default, the provider will automatically detect any available credentials. A specific authentication method may be configured using the "authenticationMethod" parameter. -The parameter may be set to any of the following values: +Supported values for `authenticationMethod`: -
-
vault-token
-
Authenticate using a **pre-existing Vault token**.
-
userpass
-
Authenticate using a **username and password**.
-
approle
-
Authenticate using **AppRole credentials** (requires roleId and secretId).
-
github
-
Authenticate using a **GitHub personal access token**.
-
auto-detect
-
This is the **default authentication method**. The provider will attempt the following **authentication methods**, in this **priority order**: -
    -
  1. vault-token (if available)
  2. -
  3. userpass (if username & password are provided)
  4. -
  5. approle (if roleId & secretId are provided)
  6. -
  7. github (if no other method succeeds)
  8. -
-
-
+- **`vault-token`** + Authenticate using a pre-existing Vault token. + +- **`userpass`** + Authenticate using a username and password. + +- **`approle`** + Authenticate using AppRole credentials (requires `roleId` and `secretId`). + +- **`github`** + Authenticate using a GitHub personal access token. + +- **`auto-detect`** (default) + Automatically selects the method based on the following priority: + 1. `vault-token` + 2. `userpass` + 3. `approle` + 4. `github` + +### HCP Vault Secrets + +Resource Providers that access **HCP Vault Secrets** also require authentication. +By default, the provider will **auto-detect** the method to use. +You may override this using the `authenticationMethod` parameter. + +Supported values for `authenticationMethod`: + +- **`client-credentials`** + Uses OAuth 2.0 Client Credentials Flow. Requires `clientId` and `clientSecret`. + +- **`cli-credentials-file`** + Uses the local HCP CLI credentials file (`~/.config/hcp/creds-cache.json`), which contains `access_token` and `refresh_token`. + +- **`auto-detect`** (default) + Automatically selects based on: + 1. `cli-credentials-file` (if file exists or is configured) + 2. `client-credentials` (if both `clientId` and `clientSecret` are available) ## caching-configuration diff --git a/ojdbc-provider-hashicorp/example-vault-dedicated-wallet.properties b/ojdbc-provider-hashicorp/example-vault-dedicated-wallet.properties index c51113d1..b32c0bae 100644 --- a/ojdbc-provider-hashicorp/example-vault-dedicated-wallet.properties +++ b/ojdbc-provider-hashicorp/example-vault-dedicated-wallet.properties @@ -37,7 +37,7 @@ ################################################################################ # An example of a connection properties file that configures Oracle JDBC to -# obtain a TLS wallet and SEPS credentials from Azure Key Vault. +# obtain a TLS wallet and SEPS credentials from HashiCorp Vault Dedicated. # # This file can be located by Oracle JDBC using the "oracle.jdbc.config.file" # connection property. For details, see: diff --git a/ojdbc-provider-hashicorp/example-vault-dedicated.properties b/ojdbc-provider-hashicorp/example-vault-dedicated.properties index 707f6f28..5fad700e 100644 --- a/ojdbc-provider-hashicorp/example-vault-dedicated.properties +++ b/ojdbc-provider-hashicorp/example-vault-dedicated.properties @@ -37,8 +37,7 @@ ################################################################################ # An example of a connection properties file that configures Oracle JDBC to -# login using a username and password managed by Azure's Key Vault service. -# +# login using a username and password managed by HashiCorp Vault Dedicated service. # This file can be located by Oracle JDBC using the "oracle.jdbc.config.file" # connection property. For details, see: # https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE diff --git a/ojdbc-provider-hashicorp/example-vault-secrets-wallet.properties b/ojdbc-provider-hashicorp/example-vault-secrets-wallet.properties new file mode 100644 index 00000000..fb463555 --- /dev/null +++ b/ojdbc-provider-hashicorp/example-vault-secrets-wallet.properties @@ -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. +################################################################################ + +# An example of a connection properties file that configures Oracle JDBC to +# obtain a TLS wallet and SEPS credentials from HCP Vault Secrets Service. +# +# This file can be located by Oracle JDBC using the "oracle.jdbc.config.file" +# connection property. For details, see: +# https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE + +# Configures the HCP Vault Secrets TCPS (TLS) Wallet Provider. The secret name is +# configured as an environment variable or JVM system property named "TLS_WALLET_SECRET_NAME". +oracle.jdbc.provider.tlsConfiguration=ojdbc-provider-hcpvault-secrets-tls +oracle.jdbc.provider.tlsConfiguration.secretName=${TLS_WALLET_SECRET_NAME} + +# Configures the HCP Vault Secrets TLS Wallet Password. The password for the +# file is optional and can be configured as an environment variable or JVM +# system property named "TLS_FILE_PASSWORD". +oracle.jdbc.provider.tlsConfiguration.walletPassword=${TLS_FILE_PASSWORD} + +# Specifies the file type (SSO, PKCS12, or PEM) for the TCPS wallet. +# This can be configured as an environment variable or JVM system property named "TLS_FILE_TYPE". +oracle.jdbc.provider.tlsConfiguration.type=${TLS_FILE_TYPE} + +# Configures the HCP Vault Secrets SEPS (Secure External Password Store) Provider. +# Secret Name is configured as environment variables or JVM system properties +# named "SEPS_WALLET_SECRET_NAME". +oracle.jdbc.provider.username=ojdbc-provider-hcpvault-secrets-seps +oracle.jdbc.provider.password=ojdbc-provider-hcpvault-secrets-seps + +# Configures the Secret Name for SEPS. +oracle.jdbc.provider.username.secretPath=${SEPS_WALLET_SECRET_NAME} +oracle.jdbc.provider.password.secretPath=${SEPS_WALLET_SECRET_NAME} + +# Optional password for SEPS Wallet stored in HCP Vault Secret. +oracle.jdbc.provider.username.walletPassword=${SEPS_WALLET_PASSWORD} +oracle.jdbc.provider.password.walletPassword=${SEPS_WALLET_PASSWORD} + +# Optional connection string index for SEPS Wallet. +# This determines which set of credentials (username/password) to use from the SEPS Wallet. +oracle.jdbc.provider.username.connectionStringIndex=${SEPS_CONNECTION_STRING_INDEX} +oracle.jdbc.provider.password.connectionStringIndex=${SEPS_CONNECTION_STRING_INDEX} + diff --git a/ojdbc-provider-hashicorp/example-vault-secrets.properties b/ojdbc-provider-hashicorp/example-vault-secrets.properties new file mode 100644 index 00000000..19e3f957 --- /dev/null +++ b/ojdbc-provider-hashicorp/example-vault-secrets.properties @@ -0,0 +1,61 @@ +################################################################################ +# 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. +################################################################################ + +# An example of a connection properties file that configures Oracle JDBC to +# login using a username and password managed by HashiCorp Vault Secrets service. +# This file can be located by Oracle JDBC using the "oracle.jdbc.config.file" +# connection property. For details, see: +# https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE + +# Configures the HCP Vault Secrets Username Provider.The secret name is +# configured as an environment variable or JVM system property named "USERNAME_SECRET_NAME". +oracle.jdbc.provider.username=ojdbc-provider-hcpvault-secrets-username +oracle.jdbc.provider.username.secretName=${USERNAME_SECRET_NAME} + +# Configures the HCP Vault Secrets Password Provider.The secret name is +# configured as an environment variable or JVM system property named "PASSWORD_SECRET_NAME". +oracle.jdbc.provider.password=ojdbc-provider-hcpvault-secrets-password +oracle.jdbc.provider.password.secretName=${PASSWORD_SECRET_NAME} + +# Configures the HCP Vault Secrets Connection String Provider. The secret name and alias +# are configured as environment variables or JVM system properties named "TNSNAMES_SECRET_NAME" and "TNS_ALIAS". +oracle.jdbc.provider.connectionString=ojdbc-provider-hcpvault-secrets-tnsnames +oracle.jdbc.provider.connectionString.secretName=${TNSNAMES_SECRET_NAME} +oracle.jdbc.provider.connectionString.tnsAlias=${TNS_ALIAS} + + diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/authentication/DedicatedVaultParameters.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/authentication/DedicatedVaultParameters.java index bdf85fba..5216984b 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/authentication/DedicatedVaultParameters.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/authentication/DedicatedVaultParameters.java @@ -107,7 +107,7 @@ public class DedicatedVaultParameters { /** * The Vault address. If not specified, fallback to system property or environment var. */ - public static final Parameter VAULT_ADDR = Parameter.create(REQUIRED); + public static final Parameter VAULT_ADDR = Parameter.create(); /** * The Vault token. If not specified, fallback to system property or environment var. diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedResourceProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedResourceProvider.java index c7430fc8..4eaefaef 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedResourceProvider.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedResourceProvider.java @@ -39,12 +39,9 @@ package oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource; import oracle.jdbc.provider.hashicorp.hcpvaultdedicated.authentication.DedicatedVaultAuthenticationMethod; -import oracle.jdbc.provider.hashicorp.hcpvaultdedicated.authentication.DedicatedVaultParameters; -import oracle.jdbc.provider.resource.AbstractResourceProvider; +import oracle.jdbc.provider.hashicorp.util.AbstractVaultResourceProvider; import oracle.jdbc.provider.resource.ResourceParameter; -import java.util.HashMap; -import java.util.Map; import java.util.stream.Stream; import static oracle.jdbc.provider.hashicorp.hcpvaultdedicated.authentication.DedicatedVaultParameters.*; @@ -55,7 +52,7 @@ * that request a resource from Hcp Vault Dedicated. This super class defines * parameters for authentication with Hcp Vault Dedicated. */ -public class HcpVaultDedicatedResourceProvider extends AbstractResourceProvider { +public class HcpVaultDedicatedResourceProvider extends AbstractVaultResourceProvider { static final ResourceParameter[] PARAMETERS = { new ResourceParameter("authenticationMethod", AUTHENTICATION_METHOD, @@ -126,47 +123,14 @@ private static DedicatedVaultAuthenticationMethod parseAuthenticationMethod(Stri } } - - /** - * Resolves missing parameters using system properties or environment variables, - * ensuring parameters are populated before executing Vault requests. - * - * @param parameterValues The original parameter map. - * @return A new map with resolved missing parameters. - */ - Map resolveMissingParameters(Map parameterValues) { - Map resolvedParameters = new HashMap<>(parameterValues); - for (ResourceParameter param : HcpVaultDedicatedResourceProvider.PARAMETERS) { - resolveParameter(resolvedParameters, param); - } - return resolvedParameters; - } - - - /** - * Resolves a single parameter by mapping its name to a corresponding - * system property or environment variable. - * - * @param parameterValues The parameter map where the resolved value will be set. - * @param parameter The ResourceParameter key to check and resolve. - */ - private void resolveParameter(Map parameterValues, ResourceParameter parameter) { - if (!parameterValues.containsKey(parameter)) { - String envVariable = getEnvVariableForParameter(parameter.name()); - String fallbackValue = System.getProperty(envVariable, System.getenv(envVariable)); - if (fallbackValue != null) { - parameterValues.put(parameter, fallbackValue); - } - } - } - /** * Maps ResourceParameter names to their corresponding environment variable keys. * * @param paramName The ResourceParameter name (e.g., "vaultAddr"). * @return The corresponding environment variable key (e.g., "VAULT_ADDR"). */ - private String getEnvVariableForParameter(String paramName) { + @Override + protected String getEnvVariableForParameter(String paramName) { switch (paramName) { case "vaultAddr": return PARAM_VAULT_ADDR; case "vaultNamespace": return PARAM_VAULT_NAMESPACE; @@ -177,6 +141,7 @@ private String getEnvVariableForParameter(String paramName) { case "secretId": return PARAM_VAULT_SECRET_ID; case "userPassAuthPath": return PARAM_USERPASS_AUTH_PATH; case "appRoleAuthPath": return PARAM_APPROLE_AUTH_PATH; + case "githubAuthPath": return PARAM_GITHUB_AUTH_PATH; default: return paramName; } } diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSecretProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSecretProvider.java index 1f0a0768..870284b0 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSecretProvider.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSecretProvider.java @@ -92,7 +92,8 @@ protected HcpVaultDedicatedSecretProvider(String valueType, ResourceParameter[] * @return The extracted secret value as a {@code String}. */ protected final String getSecret(Map parameterValues) { - Map resolvedValues = resolveMissingParameters(parameterValues); + Map resolvedValues = + resolveMissingParameters(parameterValues, HcpVaultDedicatedResourceProvider.PARAMETERS); String secretJson = getResource( DedicatedVaultSecretsManagerFactory.getInstance(), resolvedValues); OracleJsonObject secretJsonObj = JsonUtil.convertJsonToOracleJsonObject(secretJson); diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultSecretParameters.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultSecretParameters.java index 80da8158..99109ce9 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultSecretParameters.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultSecretParameters.java @@ -72,7 +72,7 @@ public class HcpVaultSecretParameters { public static final String PARAM_HCP_CLIENT_SECRET = "HCP_CLIENT_SECRET"; public static final String PARAM_HCP_CREDENTIALS_FILE = "HCP_CREDENTIALS_FILE"; - private static final String DEFAULT_CREDENTIALS_FILE_PATH = + public static final String DEFAULT_CREDENTIALS_FILE_PATH = System.getProperty("user.home") + "/.config/hcp/creds-cache.json"; private static final String PARAM_AUTHENTICATION = "AUTHENTICATION"; diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretConnectionStringProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretConnectionStringProvider.java new file mode 100644 index 00000000..60f2b8ea --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretConnectionStringProvider.java @@ -0,0 +1,109 @@ +/* + ** 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.hashicorp.hcpvaultsecret.resource; + +import oracle.jdbc.provider.resource.ResourceParameter; +import oracle.jdbc.provider.util.TNSNames; +import oracle.jdbc.spi.ConnectionStringProvider; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Base64; +import java.util.Map; + +import static oracle.jdbc.provider.util.CommonParameters.TNS_ALIAS; +import static oracle.jdbc.provider.util.FileUtils.isBase64Encoded; + +/** + *

+ * A provider for securely retrieving the connection string from a tnsnames.ora + * file stored in HCP Vault Secrets for use with an Oracle Autonomous Database. + * The tnsnames.ora file can be stored as a base64-encoded secret or as plain + * text. The provider automatically detects the format and processes the + * content accordingly to extract connection strings by alias. + *

+ *

+ * This class implements the {@link ConnectionStringProvider} SPI defined by + * Oracle JDBC and is designed to be instantiated via {@link java.util.ServiceLoader}. + *

+ */ +public class HcpVaultSecretConnectionStringProvider + extends HcpVaultSecretProvider + implements ConnectionStringProvider { + + private static final ResourceParameter[] TNS_NAMES_PARAMETERS = { + new ResourceParameter("tnsAlias", TNS_ALIAS) + }; + + /** + * A public no-arg constructor used by {@link java.util.ServiceLoader} to + * construct an instance of this provider. + */ + public HcpVaultSecretConnectionStringProvider() { + super("tnsnames", TNS_NAMES_PARAMETERS); + } + + @Override + public String getConnectionString(Map parameterValues) { + String alias = parseParameterValues(parameterValues).getRequired(TNS_ALIAS); + byte[] secretBytes = getSecret(parameterValues).getBytes(); + + byte[] fileBytes; + if (isBase64Encoded(secretBytes)) { + fileBytes = Base64.getDecoder().decode(secretBytes); + } else { + fileBytes = secretBytes; + } + + TNSNames tnsNames; + try (InputStream inputStream = new ByteArrayInputStream(fileBytes)) { + tnsNames = TNSNames.read(inputStream); + } catch (IOException e) { + throw new IllegalStateException("Failed to read tnsnames.ora content", e); + } + + String connectionString = tnsNames.getConnectionStringByAlias(alias); + if (connectionString == null) { + throw new IllegalArgumentException( + "Alias specified does not exist in tnsnames.ora: " + alias); + } + return connectionString; + } +} diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretPasswordProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretPasswordProvider.java new file mode 100644 index 00000000..de4f3142 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretPasswordProvider.java @@ -0,0 +1,71 @@ +/* + ** 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.hashicorp.hcpvaultsecret.resource; + +import oracle.jdbc.spi.PasswordProvider; + +import java.util.Map; + +/** + *

+ * A provider for retrieving password securely stored in HCP Vault Secrets. + * This provider fetches the password from the Vault and returns it as a character array. + *

+ *

+ * This class implements the {@link PasswordProvider} SPI defined by Oracle JDBC + * and is designed to be instantiated via {@link java.util.ServiceLoader}. + *

+ */ +public class HcpVaultSecretPasswordProvider + extends HcpVaultSecretProvider + implements PasswordProvider { + + /** + * A public no-arg constructor used by {@link java.util.ServiceLoader} to + * construct an instance of this provider. + */ + public HcpVaultSecretPasswordProvider() { + super("password"); + } + + @Override + public char[] getPassword(Map parameterValues) { + return getSecret(parameterValues).toCharArray(); + } +} diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretProvider.java new file mode 100644 index 00000000..160ddeb0 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretProvider.java @@ -0,0 +1,88 @@ +/* + ** 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.hashicorp.hcpvaultsecret.resource; + +import oracle.jdbc.provider.hashicorp.hcpvaultsecret.secrets.HcpVaultSecretsManagerFactory; +import oracle.jdbc.provider.resource.ResourceParameter; +import oracle.jdbc.provider.util.ResourceParameterUtils; + +import java.util.Map; + +import static oracle.jdbc.provider.hashicorp.hcpvaultsecret.authentication.HcpVaultSecretParameters.*; + +/** + *

+ * A provider of secrets from HashiCorp HCP Vault Secrets. This class is designed + * for inheritance by subclasses that implement an + * {@link oracle.jdbc.spi.OracleResourceProvider} SPI defined by the Oracle JDBC + * driver. + *

+ */ +public class HcpVaultSecretProvider extends HcpVaultSecretResourceProvider { + + private static final ResourceParameter[] PARAMETERS = { + new ResourceParameter("secretName", SECRET_NAME), + }; + + protected HcpVaultSecretProvider(String valueType) { + super(valueType, PARAMETERS); + } + + protected HcpVaultSecretProvider(String valueType, ResourceParameter[] additionalParameters) { + super(valueType, ResourceParameterUtils.combineParameters(PARAMETERS, additionalParameters)); + } + + /** + *

+ * Retrieves a secret from HashiCorp HCP Vault Secrets based on parameters + * provided in {@code parameterValues}. This method centralizes secret + * retrieval logic and is used by subclasses implementing + * the {@link oracle.jdbc.spi.OracleResourceProvider} SPI. + *

+ * + * @param parameterValues A map of parameter names and their corresponding + * -values required for secret retrieval. Must not be null. + * @return The raw secret value as a {@code String}. + */ + protected final String getSecret(Map parameterValues) { + Map resolvedValues = + resolveMissingParameters(parameterValues, HcpVaultSecretResourceProvider.PARAMETERS); + return getResource(HcpVaultSecretsManagerFactory.getInstance(), resolvedValues); + } +} diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretResourceProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretResourceProvider.java new file mode 100644 index 00000000..8e1d20b7 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretResourceProvider.java @@ -0,0 +1,101 @@ +/* + ** 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.hashicorp.hcpvaultsecret.resource; + +import oracle.jdbc.provider.hashicorp.hcpvaultsecret.authentication.HcpVaultAuthenticationMethod; +import oracle.jdbc.provider.hashicorp.util.AbstractVaultResourceProvider; +import oracle.jdbc.provider.resource.ResourceParameter; + +import java.util.stream.Stream; + +import static oracle.jdbc.provider.hashicorp.hcpvaultsecret.authentication.HcpVaultSecretParameters.*; + +/** + * Super class of all {@code OracleResourceProvider} implementations + * that request a resource from HCP Vault Secrets. This class defines + * parameters for authentication with HCP Vault Secrets. + */ +public class HcpVaultSecretResourceProvider extends AbstractVaultResourceProvider { + + static final ResourceParameter[] PARAMETERS = { + new ResourceParameter("authenticationMethod", AUTHENTICATION_METHOD, + "auto-detect", + HcpVaultSecretResourceProvider::parseAuthenticationMethod), + new ResourceParameter("orgId", HCP_ORG_ID), + new ResourceParameter("projectId", HCP_PROJECT_ID), + new ResourceParameter("appName", HCP_APP_NAME), + new ResourceParameter("clientId", HCP_CLIENT_ID), + new ResourceParameter("clientSecret", HCP_CLIENT_SECRET), + new ResourceParameter("credentialsFile", HCP_CREDENTIALS_FILE, DEFAULT_CREDENTIALS_FILE_PATH), + }; + + protected HcpVaultSecretResourceProvider(String resourceType, ResourceParameter... additionalParameters) { + super("hcpvault-secrets", resourceType, + Stream.concat( + Stream.of(PARAMETERS), + Stream.of(additionalParameters)) + .toArray(ResourceParameter[]::new)); + } + + private static HcpVaultAuthenticationMethod parseAuthenticationMethod(String method) { + switch (method) { + case "client-credentials": + return HcpVaultAuthenticationMethod.CLIENT_CREDENTIALS; + case "cli-credentials-file": + return HcpVaultAuthenticationMethod.CLI_CREDENTIALS_FILE; + case "auto-detect": + return HcpVaultAuthenticationMethod.AUTO_DETECT; + default: + throw new IllegalArgumentException("Unrecognized authentication method: " + method); + } + } + + @Override + protected String getEnvVariableForParameter(String paramName) { + switch (paramName) { + case "orgId": return PARAM_HCP_ORG_ID; + case "projectId": return PARAM_HCP_PROJECT_ID; + case "appName": return PARAM_HCP_APP_NAME; + case "clientId": return PARAM_HCP_CLIENT_ID; + case "clientSecret": return PARAM_HCP_CLIENT_SECRET; + case "credentialsFile": return PARAM_HCP_CREDENTIALS_FILE; + default: return paramName; + } + } +} diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretSEPSProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretSEPSProvider.java new file mode 100644 index 00000000..50afe27f --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretSEPSProvider.java @@ -0,0 +1,115 @@ +/* + ** 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.hashicorp.hcpvaultsecret.resource; + +import oracle.jdbc.provider.parameter.ParameterSet; +import oracle.jdbc.provider.resource.ResourceParameter; +import oracle.jdbc.provider.util.FileUtils; +import oracle.jdbc.provider.util.WalletUtils; +import oracle.jdbc.spi.OracleResourceProvider; +import oracle.jdbc.spi.PasswordProvider; +import oracle.jdbc.spi.UsernameProvider; + +import java.util.Base64; +import java.util.Map; + +import static oracle.jdbc.provider.util.CommonParameters.CONNECTION_STRING_INDEX; +import static oracle.jdbc.provider.util.CommonParameters.PASSWORD; + +/** + *

+ * A provider for Secure External Password Store (SEPS) credentials used + * to establish secure authentication with an Oracle database. The wallet is + * retrieved from HCP Vault Secrets, where it is stored as a base64-encoded string. + *

+ *

+ * This provider supports retrieving both **username** and **password** from + * the wallet. It can handle both **SSO** and **PKCS12**-based wallets. + *

+ *

+ * This class implements the {@link UsernameProvider} and + * {@link PasswordProvider} SPIs defined by Oracle JDBC and is designed to be + * instantiated via {@link java.util.ServiceLoader}. + *

+ */ +public class HcpVaultSecretSEPSProvider + extends HcpVaultSecretProvider + implements UsernameProvider, PasswordProvider { + + private static final ResourceParameter[] SEPS_PARAMETERS = { + new ResourceParameter("walletPassword", PASSWORD), + new ResourceParameter("connectionStringIndex", CONNECTION_STRING_INDEX) + }; + + /** + * A public no-arg constructor used by {@link java.util.ServiceLoader} to + * construct an instance of this provider. + */ + public HcpVaultSecretSEPSProvider() { + super("seps", SEPS_PARAMETERS); + } + + @Override + public String getUsername(Map parameterValues) { + return getWalletCredentials(parameterValues).username(); + } + + @Override + public char[] getPassword(Map parameterValues) { + return getWalletCredentials(parameterValues).password(); + } + + private WalletUtils.Credentials getWalletCredentials( + Map parameterValues) { + ParameterSet parameterSet = parseParameterValues(parameterValues); + + String secretValue = getSecret(parameterValues); + + byte[] walletBytes = FileUtils.isBase64Encoded(secretValue.getBytes()) + ? Base64.getDecoder().decode(secretValue) + : secretValue.getBytes(); + + char[] walletPassword = parameterSet.getOptional(PASSWORD) != null + ? parameterSet.getOptional(PASSWORD).toCharArray() + : null; + + String connectionStringIndex = parameterSet.getOptional(CONNECTION_STRING_INDEX); + return WalletUtils.getCredentials(walletBytes, walletPassword, connectionStringIndex); + } +} diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretTCPSProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretTCPSProvider.java new file mode 100644 index 00000000..13db83fd --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretTCPSProvider.java @@ -0,0 +1,110 @@ +/* + ** 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.hashicorp.hcpvaultsecret.resource; + +import oracle.jdbc.provider.parameter.ParameterSet; +import oracle.jdbc.provider.resource.ResourceParameter; +import oracle.jdbc.provider.util.FileUtils; +import oracle.jdbc.provider.util.TlsUtils; +import oracle.jdbc.spi.TlsConfigurationProvider; + +import javax.net.ssl.SSLContext; +import java.util.Base64; +import java.util.Map; + +import static oracle.jdbc.provider.util.CommonParameters.PASSWORD; +import static oracle.jdbc.provider.util.CommonParameters.TYPE; + +/** + *

+ * A provider for TCPS/TLS files used to establish secure TLS communication + * with an Autonomous Database. The file is retrieved from HCP Vault Secrets, + * where it is stored as a base64-encoded string. This provider supports + * different file types including SSO, PKCS12, and PEM formats. + *

+ *

+ * The type of the file must be explicitly specified using the {@code type} + * parameter. Based on the type, the file may contain private keys and + * certificates for establishing secure communication. A password is only + * required for PKCS12 or encrypted PEM files. + *

+ *

+ * This class implements the {@link TlsConfigurationProvider} SPI defined by + * Oracle JDBC and is designed to be instantiated via + * {@link java.util.ServiceLoader}. + *

+ */ +public class HcpVaultSecretTCPSProvider + extends HcpVaultSecretProvider + implements TlsConfigurationProvider { + + private static final ResourceParameter[] TCPS_PARAMETERS = { + new ResourceParameter("walletPassword", PASSWORD), + new ResourceParameter("type", TYPE) + }; + + /** + * A public no-arg constructor used by {@link java.util.ServiceLoader} to + * construct an instance of this provider. + */ + public HcpVaultSecretTCPSProvider() { + super("tls", TCPS_PARAMETERS); + } + + @Override + public SSLContext getSSLContext(Map parameterValues) { + try { + ParameterSet parameterSet = parseParameterValues(parameterValues); + String secretValue = getSecret(parameterValues); + + byte[] fileBytes = FileUtils.isBase64Encoded(secretValue.getBytes()) + ? Base64.getDecoder().decode(secretValue) + : secretValue.getBytes(); + + char[] password = parameterSet.getOptional(PASSWORD) != null + ? parameterSet.getOptional(PASSWORD).toCharArray() + : null; + + String type = parameterSet.getRequired(TYPE); + return TlsUtils.createSSLContext(fileBytes, password, type); + } catch (Exception e) { + throw new IllegalStateException("Failed to create SSLContext from the file", e); + } + } +} diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretUsernameProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretUsernameProvider.java new file mode 100644 index 00000000..c0d24dbf --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretUsernameProvider.java @@ -0,0 +1,71 @@ +/* + ** 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.hashicorp.hcpvaultsecret.resource; + +import oracle.jdbc.spi.UsernameProvider; + +import java.util.Map; + +/** + *

+ * A provider for securely retrieving a username stored as a secret + * in HashiCorp HCP Vault Secrets. + *

+ *

+ * This class implements the {@link UsernameProvider} SPI defined by + * Oracle JDBC and is designed to be instantiated via {@link java.util.ServiceLoader}. + *

+ */ +public class HcpVaultSecretUsernameProvider + extends HcpVaultSecretProvider + implements UsernameProvider { + + /** + * A public no-arg constructor used by {@link java.util.ServiceLoader} to + * construct an instance of this provider. + */ + public HcpVaultSecretUsernameProvider() { + super("username"); + } + + @Override + public String getUsername(Map parameterValues) { + return getSecret(parameterValues); + } +} diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/util/AbstractVaultResourceProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/util/AbstractVaultResourceProvider.java new file mode 100644 index 00000000..ea3ae8eb --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/util/AbstractVaultResourceProvider.java @@ -0,0 +1,91 @@ +/* + ** 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.hashicorp.util; + +import oracle.jdbc.provider.resource.AbstractResourceProvider; +import oracle.jdbc.provider.resource.ResourceParameter; + +import java.util.HashMap; +import java.util.Map; + +/** + * Abstract class that encapsulates common behavior for resolving parameters + * from system properties or environment variables. + */ +public abstract class AbstractVaultResourceProvider extends AbstractResourceProvider { + + protected AbstractVaultResourceProvider(String providerType, String resourceType, ResourceParameter[] parameters) { + super(providerType, resourceType, parameters); + } + + /** + * Resolves missing parameters using system properties or environment variables. + * + * @param parameterValues The original parameter map. + * @param parameters The parameters to check. + * @return A map with resolved parameters. + */ + protected Map resolveMissingParameters( + Map parameterValues, ResourceParameter[] parameters) { + + Map resolved = new HashMap<>(parameterValues); + for (ResourceParameter param : parameters) { + resolveParameter(resolved, param); + } + return resolved; + } + + private void resolveParameter(Map parameterValues, ResourceParameter parameter) { + if (!parameterValues.containsKey(parameter)) { + String envKey = getEnvVariableForParameter(parameter.name()); + String value = System.getProperty(envKey, System.getenv(envKey)); + if (value != null) { + parameterValues.put(parameter, value); + } + } + } + + /** + * Subclasses must define how parameter names map to env vars or sys props. + * + * @param paramName The parameter name + * @return Corresponding environment variable or system property key + */ + protected abstract String getEnvVariableForParameter(String paramName); +} diff --git a/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.ConnectionStringProvider b/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.ConnectionStringProvider index 41b28094..4d20243a 100644 --- a/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.ConnectionStringProvider +++ b/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.ConnectionStringProvider @@ -1 +1,2 @@ -oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource.HcpVaultDedicatedConnectionStringProvider \ No newline at end of file +oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource.HcpVaultDedicatedConnectionStringProvider +oracle.jdbc.provider.hashicorp.hcpvaultsecret.resource.HcpVaultSecretConnectionStringProvider \ No newline at end of file diff --git a/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.PasswordProvider b/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.PasswordProvider index a06f28d6..a57a51ad 100644 --- a/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.PasswordProvider +++ b/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.PasswordProvider @@ -1,2 +1,4 @@ oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource.HcpVaultDedicatedPasswordProvider oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource.HcpVaultDedicatedSEPSProvider +oracle.jdbc.provider.hashicorp.hcpvaultsecret.resource.HcpVaultSecretPasswordProvider +oracle.jdbc.provider.hashicorp.hcpvaultsecret.resource.HcpVaultSecretSEPSProvider diff --git a/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.TlsConfigurationProvider b/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.TlsConfigurationProvider index fdbf2db3..b60fb543 100644 --- a/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.TlsConfigurationProvider +++ b/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.TlsConfigurationProvider @@ -1 +1,2 @@ -oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource.HcpVaultDedicatedTCPSProvider \ No newline at end of file +oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource.HcpVaultDedicatedTCPSProvider +oracle.jdbc.provider.hashicorp.hcpvaultsecret.resource.HcpVaultSecretTCPSProvider \ No newline at end of file diff --git a/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.UsernameProvider b/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.UsernameProvider index 0a935a45..7709bdb2 100644 --- a/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.UsernameProvider +++ b/ojdbc-provider-hashicorp/src/main/resources/META-INF/services/oracle.jdbc.spi.UsernameProvider @@ -1,2 +1,4 @@ oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource.HcpVaultDedicatedUsernameProvider -oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource.HcpVaultDedicatedSEPSProvider \ No newline at end of file +oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource.HcpVaultDedicatedSEPSProvider +oracle.jdbc.provider.hashicorp.hcpvaultsecret.resource.HcpVaultSecretUsernameProvider +oracle.jdbc.provider.hashicorp.hcpvaultsecret.resource.HcpVaultSecretSEPSProvider \ No newline at end of file diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedConnectionStringProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedConnectionStringProviderTest.java index 9317942b..08f9e297 100644 --- a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedConnectionStringProviderTest.java +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedConnectionStringProviderTest.java @@ -73,7 +73,6 @@ public void testGetParameters() { .findFirst() .orElseThrow(AssertionError::new); assertFalse(vaultAddrParameter.isSensitive()); - assertTrue(vaultAddrParameter.isRequired()); assertNull(vaultAddrParameter.defaultValue()); Parameter secretPathParameter = diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedPasswordProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedPasswordProviderTest.java index 555937f2..8749f0c1 100644 --- a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedPasswordProviderTest.java +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedPasswordProviderTest.java @@ -74,7 +74,6 @@ public void testGetParameters() { .filter(parameter -> "vaultAddr".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(vaultAddrParameter.isRequired()); assertNull(vaultAddrParameter.defaultValue()); Parameter secretPathParameter = diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSEPSProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSEPSProviderTest.java index 4312b068..22a72be0 100644 --- a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSEPSProviderTest.java +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSEPSProviderTest.java @@ -82,7 +82,6 @@ public void testProviderParameters() { .findFirst() .orElseThrow(AssertionError::new); assertFalse(vaultAddrParameter.isSensitive()); - assertTrue(vaultAddrParameter.isRequired()); assertNull(vaultAddrParameter.defaultValue()); Parameter secretPathParameter = diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedTCPSProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedTCPSProviderTest.java index a7d92c65..be2eb131 100644 --- a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedTCPSProviderTest.java +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedTCPSProviderTest.java @@ -70,7 +70,6 @@ public void testGetParameters() { .findFirst() .orElseThrow(AssertionError::new); assertFalse(vaultAddrParameter.isSensitive()); - assertTrue(vaultAddrParameter.isRequired()); assertNull(vaultAddrParameter.defaultValue()); Parameter secretPathParameter = diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedUsernameProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedUsernameProviderTest.java index 64fa32aa..f8e4e817 100644 --- a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedUsernameProviderTest.java +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedUsernameProviderTest.java @@ -73,7 +73,6 @@ public void testGetParameters() { .filter(parameter -> "vaultAddr".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(vaultAddrParameter.isRequired()); assertNull(vaultAddrParameter.defaultValue()); Parameter secretPathParameter = diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/configuration/HcpVaultTestProperty.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/HcpVaultTestProperty.java similarity index 87% rename from ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/configuration/HcpVaultTestProperty.java rename to ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/HcpVaultTestProperty.java index c69eb5de..52f0c770 100644 --- a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/configuration/HcpVaultTestProperty.java +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/HcpVaultTestProperty.java @@ -36,7 +36,7 @@ ** SOFTWARE. */ -package oracle.jdbc.provider.hashicorp.hcpvaultsecret.configuration; +package oracle.jdbc.provider.hashicorp.hcpvaultsecret; /** * Enumeration of test properties for HCP Vault. @@ -58,5 +58,25 @@ public enum HcpVaultTestProperty { KEY, + CONNECTION_STRING_BASE64, + + CONNECTION_STRING_PLAIN_TEXT, + + TNSNAMES_ALIAS, + + USERNAME_SECRET_NAME, + + WALLET_P12_SECRET_NAME, + + WALLET_PASSWORD, + + WALLET_SSO_SECRET_NAME, + + WALLET_PEM_SECRET_NAME, + + WALLET_SECRET_PKCS12_NAME, + + WALLET_SECRET_SSO_NAME, + HCP_CREDENTIALS_FILE } diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/HcpVaultTestUtil.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/HcpVaultTestUtil.java new file mode 100644 index 00000000..54fd0190 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/HcpVaultTestUtil.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.hashicorp.hcpvaultsecret; + +import oracle.jdbc.provider.TestProperties; +import org.junit.jupiter.api.Assumptions; + +import java.util.Map; + +/** + * Utility class for configuring authentication parameters in tests that verify + * implementations of {@link oracle.jdbc.spi.OracleResourceProvider} in the + * ojdbc-provider-hcpvault-secrets provider. + */ +public final class HcpVaultTestUtil { + + private HcpVaultTestUtil() { } + + public static void configureAuthentication(Map testParameters) { + testParameters.putIfAbsent("authenticationMethod", "auto-detect"); + String authMethod = testParameters.get("authenticationMethod"); + + switch (authMethod) { + case "client-credentials": + testParameters.put("clientId", TestProperties.getOrAbort(HcpVaultTestProperty.HCP_CLIENT_ID)); + testParameters.put("clientSecret", TestProperties.getOrAbort(HcpVaultTestProperty.HCP_CLIENT_SECRET)); + break; + case "cli-credentials-file": + testParameters.put("credentialsFile", TestProperties.getOrAbort(HcpVaultTestProperty.HCP_CREDENTIALS_FILE)); + break; + case "auto-detect": + if (!configureAutoDetect(testParameters)) + Assumptions.abort("No valid authentication method found for auto-detect."); + break; + default: + throw new IllegalArgumentException("Unsupported authentication method: " + authMethod); + } + + testParameters.put("orgId", + TestProperties.getOrAbort(HcpVaultTestProperty.HCP_ORG_ID)); + testParameters.put("projectId", + TestProperties.getOrAbort(HcpVaultTestProperty.HCP_PROJECT_ID)); + testParameters.put("appName", + TestProperties.getOrAbort(HcpVaultTestProperty.HCP_APP_NAME)); + } + + private static boolean configureAutoDetect(Map testParameters) { + return setIfAvailable(testParameters, "clientId", HcpVaultTestProperty.HCP_CLIENT_ID) && + setIfAvailable(testParameters, "clientSecret", HcpVaultTestProperty.HCP_CLIENT_SECRET) || + setIfAvailable(testParameters, "credentialsFile", HcpVaultTestProperty.HCP_CREDENTIALS_FILE); + } + + private static boolean setIfAvailable(Map testParameters, String key, HcpVaultTestProperty property) { + String value = TestProperties.getOptional(property); + if (value != null) { + testParameters.put(key, value); + return true; + } + return false; + } +} diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/configuration/HcpVaultConfigurationProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/configuration/HcpVaultConfigurationProviderTest.java index dcee9b56..afc05f9b 100644 --- a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/configuration/HcpVaultConfigurationProviderTest.java +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/configuration/HcpVaultConfigurationProviderTest.java @@ -39,6 +39,7 @@ package oracle.jdbc.provider.hashicorp.hcpvaultsecret.configuration; import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.provider.hashicorp.hcpvaultsecret.HcpVaultTestProperty; import oracle.jdbc.spi.OracleConfigurationProvider; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultConnectionStringProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultConnectionStringProviderTest.java new file mode 100644 index 00000000..3ca32be2 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultConnectionStringProviderTest.java @@ -0,0 +1,143 @@ +/* + ** 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.hashicorp.hcpvaultsecret.resource; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.provider.hashicorp.hcpvaultsecret.HcpVaultTestUtil; +import oracle.jdbc.provider.hashicorp.hcpvaultsecret.HcpVaultTestProperty; +import oracle.jdbc.spi.ConnectionStringProvider; +import oracle.jdbc.spi.OracleResourceProvider.Parameter; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.createParameterValues; +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.findProvider; +import static org.junit.jupiter.api.Assertions.*; + +public class HcpVaultConnectionStringProviderTest { + + private static final ConnectionStringProvider PROVIDER = + findProvider(ConnectionStringProvider.class, "ojdbc-provider-hcpvault-secrets-tnsnames"); + + + /** + * Verifies that {@link ConnectionStringProvider#getParameters()} includes parameters + * to configure authentication and secret retrieval. + */ + @Test + public void testGetParameters() { + Collection parameters = PROVIDER.getParameters(); + assertNotNull(parameters); + + Parameter secretNameParameter = + parameters.stream() + .filter(parameter -> "secretName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(secretNameParameter.isRequired()); + assertNull(secretNameParameter.defaultValue()); + + Parameter tnsAliasParameter = + parameters.stream() + .filter(parameter -> "tnsAlias".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(tnsAliasParameter.isRequired()); + assertNull(tnsAliasParameter.defaultValue()); + + Parameter orgIdParameter = + parameters.stream() + .filter(parameter -> "orgId".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(orgIdParameter.isRequired()); + assertNull(orgIdParameter.defaultValue()); + + Parameter appNameParameter = + parameters.stream() + .filter(parameter -> "appName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(appNameParameter.isRequired()); + assertNull(appNameParameter.defaultValue()); + + Parameter projectIdParameter = + parameters.stream() + .filter(parameter -> "projectId".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(projectIdParameter.isRequired()); + assertNull(projectIdParameter.defaultValue()); + } + + @Test + public void testRetrieveConnectionStringFromBase64Encoded() { + Map testParams = new HashMap<>(); + testParams.put("secretName", TestProperties.getOrAbort(HcpVaultTestProperty.CONNECTION_STRING_BASE64)); + testParams.put("tnsAlias", TestProperties.getOrAbort(HcpVaultTestProperty.TNSNAMES_ALIAS)); + testParams.put("orgId", TestProperties.getOrAbort(HcpVaultTestProperty.HCP_ORG_ID)); + testParams.put("projectId", TestProperties.getOrAbort(HcpVaultTestProperty.HCP_PROJECT_ID)); + testParams.put("appName", TestProperties.getOrAbort(HcpVaultTestProperty.HCP_APP_NAME)); + HcpVaultTestUtil.configureAuthentication(testParams); + + Map values = createParameterValues(PROVIDER, testParams); + String connectionString = PROVIDER.getConnectionString(values); + + assertNotNull(connectionString); + } + + @Test + public void testRetrieveConnectionStringFromPlainText() { + Map testParams = new HashMap<>(); + testParams.put("secretName", TestProperties.getOrAbort(HcpVaultTestProperty.CONNECTION_STRING_PLAIN_TEXT)); + testParams.put("tnsAlias", TestProperties.getOrAbort(HcpVaultTestProperty.TNSNAMES_ALIAS)); + testParams.put("orgId", TestProperties.getOrAbort(HcpVaultTestProperty.HCP_ORG_ID)); + testParams.put("projectId", TestProperties.getOrAbort(HcpVaultTestProperty.HCP_PROJECT_ID)); + testParams.put("appName", TestProperties.getOrAbort(HcpVaultTestProperty.HCP_APP_NAME)); + HcpVaultTestUtil.configureAuthentication(testParams); + + Map values = createParameterValues(PROVIDER, testParams); + String connectionString = PROVIDER.getConnectionString(values); + + assertNotNull(connectionString); + } +} diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultPasswordProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultPasswordProviderTest.java new file mode 100644 index 00000000..5ff5de4d --- /dev/null +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultPasswordProviderTest.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.hashicorp.hcpvaultsecret.resource; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.provider.hashicorp.hcpvaultsecret.HcpVaultTestUtil; +import oracle.jdbc.provider.hashicorp.hcpvaultsecret.HcpVaultTestProperty; +import oracle.jdbc.spi.OracleResourceProvider.Parameter; +import oracle.jdbc.spi.PasswordProvider; +import oracle.jdbc.spi.UsernameProvider; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.createParameterValues; +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.findProvider; +import static org.junit.jupiter.api.Assertions.*; + +public class HcpVaultPasswordProviderTest { + + private static final PasswordProvider PROVIDER = + findProvider(PasswordProvider.class, "ojdbc-provider-hcpvault-secrets-password"); + + + /** + * Verifies that {@link UsernameProvider#getParameters()} includes parameters + * to configure authentication and secret retrieval. + */ + @Test + public void testGetParameters() { + Collection parameters = PROVIDER.getParameters(); + assertNotNull(parameters); + + Parameter secretNameParameter = + parameters.stream() + .filter(parameter -> "secretName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(secretNameParameter.isRequired()); + assertNull(secretNameParameter.defaultValue()); + + Parameter orgIdParameter = + parameters.stream() + .filter(parameter -> "orgId".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(orgIdParameter.isRequired()); + assertNull(orgIdParameter.defaultValue()); + + Parameter appNameParameter = + parameters.stream() + .filter(parameter -> "appName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(appNameParameter.isRequired()); + assertNull(appNameParameter.defaultValue()); + + Parameter projectIdParameter = + parameters.stream() + .filter(parameter -> "projectId".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(projectIdParameter.isRequired()); + assertNull(projectIdParameter.defaultValue()); + } + + @Test + public void testRetrievePassword() { + Map testParams = new HashMap<>(); + testParams.put("secretName", TestProperties.getOrAbort(HcpVaultTestProperty.USERNAME_SECRET_NAME)); + testParams.put("orgId", TestProperties.getOrAbort(HcpVaultTestProperty.HCP_ORG_ID)); + testParams.put("projectId", TestProperties.getOrAbort(HcpVaultTestProperty.HCP_PROJECT_ID)); + testParams.put("appName", TestProperties.getOrAbort(HcpVaultTestProperty.HCP_APP_NAME)); + HcpVaultTestUtil.configureAuthentication(testParams); + + Map values = createParameterValues(PROVIDER, testParams); + char[] password = PROVIDER.getPassword(values); + + assertNotNull(password); + } +} diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSEPSProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSEPSProviderTest.java new file mode 100644 index 00000000..97955310 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSEPSProviderTest.java @@ -0,0 +1,164 @@ +/* + ** 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.hashicorp.hcpvaultsecret.resource; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.provider.hashicorp.hcpvaultsecret.HcpVaultTestUtil; +import oracle.jdbc.provider.hashicorp.hcpvaultsecret.HcpVaultTestProperty; +import oracle.jdbc.spi.OracleResourceProvider.Parameter; +import oracle.jdbc.spi.PasswordProvider; +import oracle.jdbc.spi.UsernameProvider; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.createParameterValues; +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.findProvider; +import static org.junit.jupiter.api.Assertions.*; + +public class HcpVaultSEPSProviderTest { + + private static final UsernameProvider USERNAME_PROVIDER = findProvider( + UsernameProvider.class, "ojdbc-provider-hcpvault-secrets-seps"); + + private static final PasswordProvider PASSWORD_PROVIDER = findProvider( + PasswordProvider.class, "ojdbc-provider-hcpvault-secrets-seps"); + + @Test + public void testGetusernameParams() { + Collection usernameParams = USERNAME_PROVIDER.getParameters(); + Collection passwordParams = PASSWORD_PROVIDER.getParameters(); + + assertEquals(usernameParams, passwordParams); + + Parameter secretNameParameter = + usernameParams.stream() + .filter(parameter -> "secretName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(secretNameParameter.isRequired()); + assertNull(secretNameParameter.defaultValue()); + + Parameter orgIdParameter = + usernameParams.stream() + .filter(parameter -> "orgId".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(orgIdParameter.isRequired()); + assertNull(orgIdParameter.defaultValue()); + + Parameter appNameParameter = + usernameParams.stream() + .filter(parameter -> "appName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(appNameParameter.isRequired()); + assertNull(appNameParameter.defaultValue()); + + Parameter projectIdParameter = + usernameParams.stream() + .filter(parameter -> "projectId".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(projectIdParameter.isRequired()); + assertNull(projectIdParameter.defaultValue()); + + + Parameter walletPasswordParameter = + usernameParams.stream() + .filter(parameter -> "walletPassword".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(walletPasswordParameter.isSensitive()); + assertFalse(walletPasswordParameter.isRequired()); + assertNull(walletPasswordParameter.defaultValue()); + } + + @Test + public void testRetrieveUsernameFromPKCS12() { + Map params = new HashMap<>(); + params.put("secretName", TestProperties.getOrAbort(HcpVaultTestProperty.WALLET_SECRET_PKCS12_NAME)); + params.put("walletPassword", TestProperties.getOrAbort(HcpVaultTestProperty.WALLET_PASSWORD)); + HcpVaultTestUtil.configureAuthentication(params); + + Map values = createParameterValues(USERNAME_PROVIDER, params); + String username = USERNAME_PROVIDER.getUsername(values); + + assertNotNull(username); + } + + @Test + public void testRetrievePasswordFromPKCS12() { + Map params = new HashMap<>(); + params.put("secretName", TestProperties.getOrAbort(HcpVaultTestProperty.WALLET_SECRET_PKCS12_NAME)); + params.put("walletPassword", TestProperties.getOrAbort(HcpVaultTestProperty.WALLET_PASSWORD)); + HcpVaultTestUtil.configureAuthentication(params); + + Map values = createParameterValues(PASSWORD_PROVIDER, params); + char[] password = PASSWORD_PROVIDER.getPassword(values); + assertNotNull(password); + } + + @Test + public void testRetrieveUsernameFromSSO() { + Map params = new HashMap<>(); + params.put("secretName", TestProperties.getOrAbort(HcpVaultTestProperty.WALLET_SECRET_SSO_NAME)); + HcpVaultTestUtil.configureAuthentication(params); + + Map values = createParameterValues(USERNAME_PROVIDER, params); + String username = USERNAME_PROVIDER.getUsername(values); + + assertNotNull(username); + } + + @Test + public void testRetrievePasswordFromSSO() { + Map params = new HashMap<>(); + params.put("secretName", TestProperties.getOrAbort(HcpVaultTestProperty.WALLET_SECRET_SSO_NAME)); + HcpVaultTestUtil.configureAuthentication(params); + + Map values = createParameterValues(PASSWORD_PROVIDER, params); + char[] password = PASSWORD_PROVIDER.getPassword(values); + + assertNotNull(password); + } + +} \ No newline at end of file diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultTCPSProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultTCPSProviderTest.java new file mode 100644 index 00000000..6367384c --- /dev/null +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultTCPSProviderTest.java @@ -0,0 +1,176 @@ +/* + ** 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.hashicorp.hcpvaultsecret.resource; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.provider.hashicorp.hcpvaultsecret.HcpVaultTestUtil; +import oracle.jdbc.provider.hashicorp.hcpvaultsecret.HcpVaultTestProperty; +import oracle.jdbc.spi.OracleResourceProvider.Parameter; +import oracle.jdbc.spi.TlsConfigurationProvider; +import org.junit.jupiter.api.Test; + +import javax.net.ssl.SSLContext; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.createParameterValues; +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.findProvider; +import static org.junit.jupiter.api.Assertions.*; + +public class HcpVaultTCPSProviderTest { + + private static final TlsConfigurationProvider PROVIDER = findProvider( + TlsConfigurationProvider.class, "ojdbc-provider-hcpvault-secrets-tls"); + + @Test + public void testGetParameters() { + Collection parameters = PROVIDER.getParameters(); + assertNotNull(parameters); + + Parameter secretNameParameter = + parameters.stream() + .filter(parameter -> "secretName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(secretNameParameter.isRequired()); + assertNull(secretNameParameter.defaultValue()); + + Parameter orgIdParameter = + parameters.stream() + .filter(parameter -> "orgId".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(orgIdParameter.isRequired()); + assertNull(orgIdParameter.defaultValue()); + + Parameter appNameParameter = + parameters.stream() + .filter(parameter -> "appName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(appNameParameter.isRequired()); + assertNull(appNameParameter.defaultValue()); + + Parameter projectIdParameter = + parameters.stream() + .filter(parameter -> "projectId".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(projectIdParameter.isRequired()); + assertNull(projectIdParameter.defaultValue()); + + Parameter typeParameter = + parameters.stream() + .filter(parameter -> "type".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(typeParameter.isRequired()); + assertNull(typeParameter.defaultValue()); + + Parameter walletPasswordParameter = + parameters.stream() + .filter(parameter -> "walletPassword".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(walletPasswordParameter.isSensitive()); + assertFalse(walletPasswordParameter.isRequired()); + assertNull(walletPasswordParameter.defaultValue()); + } + + @Test + public void testRetrieveSSLContextFromPKCS12() { + Map testParams = new HashMap<>(); + testParams.put("secretName", TestProperties.getOrAbort(HcpVaultTestProperty.WALLET_P12_SECRET_NAME)); + testParams.put("type", "PKCS12"); + testParams.put("walletPassword", TestProperties.getOrAbort(HcpVaultTestProperty.WALLET_PASSWORD)); + HcpVaultTestUtil.configureAuthentication(testParams); + + Map values = createParameterValues(PROVIDER, testParams); + SSLContext context = PROVIDER.getSSLContext(values); + assertNotNull(context); + } + + @Test + public void testRetrieveSSLContextFromSSO() { + Map testParams = new HashMap<>(); + testParams.put("secretName", TestProperties.getOrAbort(HcpVaultTestProperty.WALLET_SSO_SECRET_NAME)); + testParams.put("type", "SSO"); + HcpVaultTestUtil.configureAuthentication(testParams); + + Map values = createParameterValues(PROVIDER, testParams); + SSLContext context = PROVIDER.getSSLContext(values); + assertNotNull(context); + } + + @Test + public void testRetrieveSSLContextFromPEM() { + Map testParams = new HashMap<>(); + testParams.put("secretName", TestProperties.getOrAbort(HcpVaultTestProperty.WALLET_PEM_SECRET_NAME)); + testParams.put("type", "PEM"); + testParams.put("walletPassword", TestProperties.getOrAbort(HcpVaultTestProperty.WALLET_PASSWORD)); + HcpVaultTestUtil.configureAuthentication(testParams); + + Map values = createParameterValues(PROVIDER, testParams); + SSLContext context = PROVIDER.getSSLContext(values); + assertNotNull(context); + } + + @Test + public void testMissingPasswordForPKCS12() { + Map testParams = new HashMap<>(); + testParams.put("secretName", TestProperties.getOrAbort(HcpVaultTestProperty.WALLET_P12_SECRET_NAME)); + testParams.put("type", "PKCS12"); + HcpVaultTestUtil.configureAuthentication(testParams); + + Map values = createParameterValues(PROVIDER, testParams); + assertThrows(IllegalStateException.class, () -> PROVIDER.getSSLContext(values)); + } + + @Test + public void testMissingPasswordForPEM() { + Map testParams = new HashMap<>(); + testParams.put("secretName", TestProperties.getOrAbort(HcpVaultTestProperty.WALLET_PEM_SECRET_NAME)); + testParams.put("type", "PEM"); + HcpVaultTestUtil.configureAuthentication(testParams); + + Map values = createParameterValues(PROVIDER, testParams); + assertThrows(IllegalStateException.class, () -> PROVIDER.getSSLContext(values)); + } +} \ No newline at end of file diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultUsernameProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultUsernameProviderTest.java new file mode 100644 index 00000000..cca26f15 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultUsernameProviderTest.java @@ -0,0 +1,118 @@ +/* + ** 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.hashicorp.hcpvaultsecret.resource; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.provider.hashicorp.hcpvaultsecret.HcpVaultTestUtil; +import oracle.jdbc.provider.hashicorp.hcpvaultsecret.HcpVaultTestProperty; +import oracle.jdbc.spi.OracleResourceProvider.Parameter; +import oracle.jdbc.spi.UsernameProvider; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.createParameterValues; +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.findProvider; +import static org.junit.jupiter.api.Assertions.*; + +public class HcpVaultUsernameProviderTest { + + private static final UsernameProvider PROVIDER = + findProvider(UsernameProvider.class, "ojdbc-provider-hcpvault-secrets-username"); + + + /** + * Verifies that {@link UsernameProvider#getParameters()} includes parameters + * to configure authentication and secret retrieval. + */ + @Test + public void testGetParameters() { + Collection parameters = PROVIDER.getParameters(); + assertNotNull(parameters); + + Parameter secretNameParameter = + parameters.stream() + .filter(parameter -> "secretName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(secretNameParameter.isRequired()); + assertNull(secretNameParameter.defaultValue()); + + Parameter orgIdParameter = + parameters.stream() + .filter(parameter -> "orgId".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(orgIdParameter.isRequired()); + assertNull(orgIdParameter.defaultValue()); + + Parameter appNameParameter = + parameters.stream() + .filter(parameter -> "appName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(appNameParameter.isRequired()); + assertNull(appNameParameter.defaultValue()); + + Parameter projectIdParameter = + parameters.stream() + .filter(parameter -> "projectId".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(projectIdParameter.isRequired()); + assertNull(projectIdParameter.defaultValue()); + } + + @Test + public void testRetrieveUsername() { + Map testParams = new HashMap<>(); + testParams.put("secretName", TestProperties.getOrAbort(HcpVaultTestProperty.USERNAME_SECRET_NAME)); + testParams.put("orgId", TestProperties.getOrAbort(HcpVaultTestProperty.HCP_ORG_ID)); + testParams.put("projectId", TestProperties.getOrAbort(HcpVaultTestProperty.HCP_PROJECT_ID)); + testParams.put("appName", TestProperties.getOrAbort(HcpVaultTestProperty.HCP_APP_NAME)); + HcpVaultTestUtil.configureAuthentication(testParams); + + Map values = createParameterValues(PROVIDER, testParams); + String username = PROVIDER.getUsername(values); + + assertNotNull(username); + } +} From d82008dc26c8c74a7755c21dab7bb2f73ba7344a Mon Sep 17 00:00:00 2001 From: Mouhsin Elmajdouby Date: Thu, 8 May 2025 14:39:32 +0100 Subject: [PATCH 3/6] Address review comments --- .../oracle/jdbc/provider/util/FileUtils.java | 11 +++ ojdbc-provider-hashicorp/README.md | 63 ++++++++++------- ...aultDedicatedConnectionStringProvider.java | 15 ++--- ...pVaultDedicatedResourceParameterNames.java | 67 +++++++++++++++++++ .../HcpVaultDedicatedResourceProvider.java | 63 +++++++++++------ .../HcpVaultDedicatedSEPSProvider.java | 9 +-- .../HcpVaultDedicatedSecretProvider.java | 8 ++- .../HcpVaultDedicatedTCPSProvider.java | 9 ++- ...cpVaultSecretConnectionStringProvider.java | 14 +--- .../resource/HcpVaultSecretProvider.java | 2 +- .../HcpVaultSecretResourceParameterNames.java | 60 +++++++++++++++++ .../HcpVaultSecretResourceProvider.java | 35 ++++++---- .../resource/HcpVaultSecretSEPSProvider.java | 14 ++-- .../resource/HcpVaultSecretTCPSProvider.java | 12 ++-- .../provider/hashicorp/util/JsonUtil.java | 19 ++++-- 15 files changed, 287 insertions(+), 114 deletions(-) create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedResourceParameterNames.java create mode 100644 ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretResourceParameterNames.java diff --git a/ojdbc-provider-common/src/main/java/oracle/jdbc/provider/util/FileUtils.java b/ojdbc-provider-common/src/main/java/oracle/jdbc/provider/util/FileUtils.java index 6724bc8c..db15ca6e 100644 --- a/ojdbc-provider-common/src/main/java/oracle/jdbc/provider/util/FileUtils.java +++ b/ojdbc-provider-common/src/main/java/oracle/jdbc/provider/util/FileUtils.java @@ -56,4 +56,15 @@ public static boolean isBase64Encoded(byte[] secretBytes) { return false; } } + + /** + * Decodes the given secret bytes if base64 encoded, otherwise returns them as-is. + * + * @param input the secret bytes + * @return the decoded byte array if base64, or the original byte array + */ + public static byte[] decodeIfBase64(byte[] input) { + return isBase64Encoded(input) ? Base64.getDecoder().decode(input) + : input; + } } diff --git a/ojdbc-provider-hashicorp/README.md b/ojdbc-provider-hashicorp/README.md index 7dc3617a..39434c86 100644 --- a/ojdbc-provider-hashicorp/README.md +++ b/ojdbc-provider-hashicorp/README.md @@ -565,7 +565,9 @@ For the JSON type of provider (HCP Vault Dedicated, HCP Vault Secrets, HTTP/HTTP - method - optional parameters (depends on the cloud provider). -## Dedicated Vault Username Provider +## Resource Providers + +### Dedicated Vault Username Provider The **Dedicated Vault Username Provider** provides Oracle JDBC with a **database username** that is managed by **HashiCorp Vault Dedicated**. This is a **Resource Provider** identified by the name `ojdbc-provider-hcpvault-dedicated-username`. @@ -606,7 +608,8 @@ In addition to the set of [common parameters](#common-parameters-for-hcp-vault-d The field inside the JSON secret that contains the required value. If the secret contains multiple keys, this parameter specifies which key to extract. -If the secret contains only one key, the value is automatically used. +If the secret contains only one key and this parameter is not provided, the value is automatically used. +if fieldName is provided but not found, an error is thrown. If omitted and multiple keys exist, an error is thrown. Any valid field name. @@ -619,7 +622,7 @@ If omitted and multiple keys exist, an error is thrown. An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-dedicated.properties](example-vault-dedicated.properties). -## HCP Vault Secrets Username Provider +### HCP Vault Secrets Username Provider The **HCP Vault Secrets Username Provider** provides Oracle JDBC with a **database username** that is managed by **HashiCorp Vault Secrets**. This is a **Resource Provider** identified by the name `ojdbc-provider-hcpvault-secrets-username`. @@ -649,7 +652,7 @@ An example of a [connection properties file](https://docs.oracle.com/en/database --- -## Dedicated Vault Password Provider +### Dedicated Vault Password Provider The **Dedicated Vault Password Provider** provides Oracle JDBC with a **database password** that is managed by **HashiCorp Vault Dedicated**. This is a **Resource Provider** identified by the name `ojdbc-provider-hcpvault-dedicated-password`. @@ -690,7 +693,8 @@ In addition to the set of [common parameters](#common-parameters-for-hcp-vault-d The field inside the JSON secret that contains the required value. If the secret contains multiple keys, this parameter specifies which key to extract. -If the secret contains only one key, the value is automatically used. +If the secret contains only one key and this parameter is not provided, the value is automatically used. +if fieldName is provided but not found, an error is thrown. If omitted and multiple keys exist, an error is thrown. Any valid field name. @@ -704,7 +708,7 @@ If omitted and multiple keys exist, an error is thrown. An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-dedicated.properties](example-vault-dedicated.properties). -## HCP Vault Secrets Password Provider +### HCP Vault Secrets Password Provider The **HCP Vault Secrets Password Provider** provides Oracle JDBC with a **database password** that is managed by **HashiCorp Vault Secrets**. This is a **Resource Provider** identified by the name `ojdbc-provider-hcpvault-secrets-password`. @@ -734,7 +738,7 @@ An example of a [connection properties file](https://docs.oracle.com/en/database --- -## Dedicated Vault TCPS Wallet Provider +### Dedicated Vault TCPS Wallet Provider The **Dedicated Vault TCPS Wallet Provider** provides Oracle JDBC with **keys and certificates** managed by **HashiCorp Vault Dedicated** to establish secure **TLS connections** with an Autonomous Database. This is a **Resource Provider** identified by the name `ojdbc-provider-hcpvault-dedicated-tls`. @@ -781,7 +785,7 @@ In addition to the set of [common parameters](#common-parameters-for-hcp-vault-d type The wallet format. -SSO, PKCS12, PEM +SSO, PKCS12, PEM No default value. The file type must be specified. @@ -800,9 +804,14 @@ If omitted, the file is assumed to be **SSO** or an **unprotected PEM** file. fieldName (Optional) -The field inside the JSON secret that contains the required value. +The field inside the JSON secret that contains the base64-encoded TCPS wallet. +
+HashiCorp Vault Dedicated stores secrets as JSON objects. +For TCPS wallets, this means a secret may contain multiple base64-encoded entries (e.g., sso, pkcs12, pem, etc.). +
If the secret contains multiple keys, this parameter specifies which key to extract. -If the secret contains only one key, the value is automatically used. +If the secret contains only one key and this parameter is not provided, the value is automatically used. +if fieldName is provided but not found, an error is thrown. If omitted and multiple keys exist, an error is thrown. Any valid field name. @@ -815,7 +824,7 @@ If omitted and multiple keys exist, an error is thrown. An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-dedicated-wallet.properties](example-vault-dedicated-wallet.properties). -## HCP Vault Secrets TCPS Wallet Provider +### HCP Vault Secrets TCPS Wallet Provider The **HCP Vault Secrets TCPS Wallet Provide** provides Oracle JDBC with **keys and certificates** managed by **HashiCorp Vault Secrets** to establish secure **TLS connections** with an Autonomous Database. This is a **Resource Provider** identified by the name `ojdbc-provider-hcpvault-secrets-tls`. @@ -866,7 +875,7 @@ An example of a [connection properties file](https://docs.oracle.com/en/database --- -## Dedicated Vault SEPS Wallet Provider +### Dedicated Vault SEPS Wallet Provider The **Dedicated Vault SEPS Wallet Provider** provides Oracle JDBC with **username and password credentials** stored in a **Secure External Password Store (SEPS) wallet** within **HCP Vault Dedicated**. @@ -944,9 +953,14 @@ Specifies the **index** of the connection string to use when retrieving credenti fieldName (Optional) -The field inside the JSON secret that contains the required value. +The field inside the JSON secret that contains the base64-encoded SEPS wallet. +
+HashiCorp Vault Dedicated stores secrets as JSON objects. +For SEPS wallets, this means a secret may contain multiple base64-encoded entries (e.g., sso, pkcs12, etc.). +
If the secret contains multiple keys, this parameter specifies which key to extract. -If the secret contains only one key, the value is automatically used. +If the secret contains only one key and this parameter is not provided, the value is automatically used. +if fieldName is provided but not found, an error is thrown. If omitted and multiple keys exist, an error is thrown. Any valid field name. @@ -959,7 +973,7 @@ If omitted and multiple keys exist, an error is thrown. An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-dedicated-wallet.properties](example-vault-dedicated-wallet.properties). -## HCP Vault Secrets SEPS Wallet Provider +### HCP Vault Secrets SEPS Wallet Provider The **HCP Vault Secrets SEPS Wallet Provider** provides Oracle JDBC with **username and password credentials** stored in a **Secure External Password Store (SEPS) wallet** within **HCP Vault Secrets**. @@ -1020,7 +1034,7 @@ An example of a [connection properties file](https://docs.oracle.com/en/database --- -## Dedicated Vault Connection String Provider +### Dedicated Vault Connection String Provider The **Dedicated Vault Connection String Provider** provides Oracle JDBC with a **connection string** retrieved from a `tnsnames.ora` file stored in **HCP Vault Dedicated**. @@ -1072,9 +1086,10 @@ In addition to the set of [common parameters](#common-parameters-for-hcp-vault-d fieldName (Optional) -The field inside the JSON secret that contains the required value. +The field inside the JSON secret that contains the tnsnames.ora content, either as plain text or base64-encoded. If the secret contains multiple keys, this parameter specifies which key to extract. -If the secret contains only one key, the value is automatically used. +If the secret contains only one key and this parameter is not provided, the value is automatically used. +if fieldName is provided but not found, an error is thrown. If omitted and multiple keys exist, an error is thrown. Any valid field name. @@ -1087,7 +1102,7 @@ If omitted and multiple keys exist, an error is thrown. An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-dedicated.properties](example-vault-dedicated.properties). -## HCP Vault Secrets Connection String Provider +### HCP Vault Secrets Connection String Provider The **HCP Vault Secrets Connection String Provider** provides Oracle JDBC with a **connection string** retrieved from a `tnsnames.ora` file stored in **HCP Vault Secrets**. @@ -1127,7 +1142,7 @@ In addition to the set of [common parameters](#common-parameters-for-hcp-vault-s An example of a [connection properties file](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html#CONNECTION_PROPERTY_CONFIG_FILE) that configures this provider can be found in [example-vault-secrets.properties](example-vault-secrets.properties). -## Common Parameters for HCP Vault Dedicated Resource Providers +### Common Parameters for HCP Vault Dedicated Resource Providers Providers classified as Resource Providers in this module all support a common set of parameters. @@ -1229,7 +1244,7 @@ Providers classified as Resource Providers in this module all support a common s --- -## Common Parameters for HCP Vault Secrets Resource Providers +### Common Parameters for HCP Vault Secrets Resource Providers Providers classified as Resource Providers for HCP Vault Secrets support a common set of parameters used for authenticating with the HCP Vault Secrets API. @@ -1296,9 +1311,9 @@ Providers classified as Resource Providers for HCP Vault Secrets support a commo -## Configuring Authentication for Resource Providers +### Configuring Authentication for Resource Providers -### HCP Vault Dedicated +#### HCP Vault Dedicated Resource Providers in this module must authenticate with **HashiCorp Vault Dedicated**. By default, the provider will automatically detect any available credentials. @@ -1325,7 +1340,7 @@ Supported values for `authenticationMethod`: 3. `approle` 4. `github` -### HCP Vault Secrets +#### HCP Vault Secrets Resource Providers that access **HCP Vault Secrets** also require authentication. By default, the provider will **auto-detect** the method to use. diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedConnectionStringProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedConnectionStringProvider.java index 9d535007..31c7feb3 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedConnectionStringProvider.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedConnectionStringProvider.java @@ -39,16 +39,15 @@ package oracle.jdbc.provider.hashicorp.hcpvaultdedicated.resource; import oracle.jdbc.provider.resource.ResourceParameter; -import oracle.jdbc.provider.util.FileUtils; import oracle.jdbc.provider.util.TNSNames; import oracle.jdbc.spi.ConnectionStringProvider; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.util.Base64; import java.util.Map; import static oracle.jdbc.provider.util.CommonParameters.TNS_ALIAS; +import static oracle.jdbc.provider.util.FileUtils.decodeIfBase64; /** *

@@ -69,7 +68,8 @@ public class HcpVaultDedicatedConnectionStringProvider implements ConnectionStringProvider { private static final ResourceParameter[] TNS_NAMES_PARAMETERS = { - new ResourceParameter("tnsAlias", TNS_ALIAS) + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.TNS_ALIAS, + TNS_ALIAS) }; /** @@ -103,14 +103,7 @@ public HcpVaultDedicatedConnectionStringProvider() { public String getConnectionString(Map parameterValues) { String alias = parseParameterValues(parameterValues).getRequired(TNS_ALIAS); - byte[] secretBytes = getSecret(parameterValues).getBytes(); - - byte[] fileBytes; - if (FileUtils.isBase64Encoded(secretBytes)) { - fileBytes = Base64.getDecoder().decode(secretBytes); - } else { - fileBytes = secretBytes; - } + byte[] fileBytes = decodeIfBase64(getSecret(parameterValues).getBytes()); TNSNames tnsNames; try (InputStream inputStream = new ByteArrayInputStream(fileBytes)) { diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedResourceParameterNames.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedResourceParameterNames.java new file mode 100644 index 00000000..0a5e51fa --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedResourceParameterNames.java @@ -0,0 +1,67 @@ +/* + ** 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.hashicorp.hcpvaultdedicated.resource; + +/** + * Centralized parameter name constants used by HCP Vault Dedicated resource providers. + */ +public class HcpVaultDedicatedResourceParameterNames { + + private HcpVaultDedicatedResourceParameterNames() {} + + public static final String VAULT_ADDR = "vaultAddr"; + public static final String VAULT_NAMESPACE = "vaultNamespace"; + public static final String VAULT_USERNAME = "vaultUsername"; + public static final String VAULT_PASSWORD = "vaultPassword"; + public static final String VAULT_TOKEN = "vaultToken"; + public static final String ROLE_ID = "roleId"; + public static final String SECRET_ID = "secretId"; + public static final String USERPASS_AUTH_PATH = "userPassAuthPath"; + public static final String APPROLE_AUTH_PATH = "appRoleAuthPath"; + public static final String GITHUB_TOKEN = "githubToken"; + public static final String GITHUB_AUTH_PATH = "githubAuthPath"; + + public static final String SECRET_PATH = "secretPath"; + public static final String FIELD_NAME = "fieldName"; + + public static final String TNS_ALIAS = "tnsAlias"; + public static final String CONNECTION_STRING_INDEX = "connectionStringIndex"; + public static final String WALLET_PASSWORD = "walletPassword"; + public static final String TYPE = "type"; +} diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedResourceProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedResourceProvider.java index 4eaefaef..ddc171bd 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedResourceProvider.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedResourceProvider.java @@ -58,17 +58,28 @@ public class HcpVaultDedicatedResourceProvider extends AbstractVaultResourceProv new ResourceParameter("authenticationMethod", AUTHENTICATION_METHOD, "auto-detect", HcpVaultDedicatedResourceProvider::parseAuthenticationMethod), - new ResourceParameter("vaultAddr", VAULT_ADDR), - new ResourceParameter("vaultNamespace", NAMESPACE, DEFAULT_NAMESPACE), - new ResourceParameter("vaultUsername", USERNAME), - new ResourceParameter("vaultPassword", PASSWORD), - new ResourceParameter("vaultToken", VAULT_TOKEN), - new ResourceParameter("roleId", ROLE_ID), - new ResourceParameter("secretId", SECRET_ID), - new ResourceParameter("userPassAuthPath", USERPASS_AUTH_PATH, DEFAULT_USERPASS_PATH), - new ResourceParameter("appRoleAuthPath", APPROLE_AUTH_PATH, DEFAULT_APPROLE_PATH), - new ResourceParameter("githubToken", GITHUB_TOKEN), - new ResourceParameter("githubAuthPath", GITHUB_AUTH_PATH, DEFAULT_GITHUB_PATH), + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.VAULT_ADDR, + VAULT_ADDR), + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.VAULT_NAMESPACE, + NAMESPACE, DEFAULT_NAMESPACE), + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.VAULT_USERNAME, + USERNAME), + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.VAULT_PASSWORD, + PASSWORD), + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.VAULT_TOKEN, + VAULT_TOKEN), + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.ROLE_ID, + ROLE_ID), + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.SECRET_ID, + SECRET_ID), + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.USERPASS_AUTH_PATH, + USERPASS_AUTH_PATH, DEFAULT_USERPASS_PATH), + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.APPROLE_AUTH_PATH, + APPROLE_AUTH_PATH, DEFAULT_APPROLE_PATH), + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.GITHUB_TOKEN, + GITHUB_TOKEN), + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.GITHUB_AUTH_PATH, + GITHUB_AUTH_PATH, DEFAULT_GITHUB_PATH), }; /** @@ -132,16 +143,26 @@ private static DedicatedVaultAuthenticationMethod parseAuthenticationMethod(Stri @Override protected String getEnvVariableForParameter(String paramName) { switch (paramName) { - case "vaultAddr": return PARAM_VAULT_ADDR; - case "vaultNamespace": return PARAM_VAULT_NAMESPACE; - case "vaultUsername": return PARAM_VAULT_USERNAME; - case "vaultPassword": return PARAM_VAULT_PASSWORD; - case "vaultToken": return PARAM_VAULT_TOKEN; - case "roleId": return PARAM_VAULT_ROLE_ID; - case "secretId": return PARAM_VAULT_SECRET_ID; - case "userPassAuthPath": return PARAM_USERPASS_AUTH_PATH; - case "appRoleAuthPath": return PARAM_APPROLE_AUTH_PATH; - case "githubAuthPath": return PARAM_GITHUB_AUTH_PATH; + case HcpVaultDedicatedResourceParameterNames.VAULT_ADDR: + return PARAM_VAULT_ADDR; + case HcpVaultDedicatedResourceParameterNames.VAULT_NAMESPACE: + return PARAM_VAULT_NAMESPACE; + case HcpVaultDedicatedResourceParameterNames.VAULT_USERNAME: + return PARAM_VAULT_USERNAME; + case HcpVaultDedicatedResourceParameterNames.VAULT_PASSWORD: + return PARAM_VAULT_PASSWORD; + case HcpVaultDedicatedResourceParameterNames.VAULT_TOKEN: + return PARAM_VAULT_TOKEN; + case HcpVaultDedicatedResourceParameterNames.ROLE_ID: + return PARAM_VAULT_ROLE_ID; + case HcpVaultDedicatedResourceParameterNames.SECRET_ID: + return PARAM_VAULT_SECRET_ID; + case HcpVaultDedicatedResourceParameterNames.USERPASS_AUTH_PATH: + return PARAM_USERPASS_AUTH_PATH; + case HcpVaultDedicatedResourceParameterNames.APPROLE_AUTH_PATH: + return PARAM_APPROLE_AUTH_PATH; + case HcpVaultDedicatedResourceParameterNames.GITHUB_AUTH_PATH: + return PARAM_GITHUB_AUTH_PATH; default: return paramName; } } diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSEPSProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSEPSProvider.java index 048e1a5b..44c80b72 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSEPSProvider.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSEPSProvider.java @@ -74,8 +74,10 @@ public class HcpVaultDedicatedSEPSProvider implements UsernameProvider, PasswordProvider { private static final ResourceParameter[] SEPS_PARAMETERS = { - new ResourceParameter("walletPassword", PASSWORD), - new ResourceParameter("connectionStringIndex", CONNECTION_STRING_INDEX) + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.WALLET_PASSWORD, + PASSWORD), + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.CONNECTION_STRING_INDEX, + CONNECTION_STRING_INDEX) }; /** @@ -110,8 +112,7 @@ private WalletUtils.Credentials getWalletCredentials( String secretValue = getSecret(parameterValues); - byte[] walletBytes = FileUtils.isBase64Encoded(secretValue.getBytes()) ? - Base64.getDecoder().decode(secretValue) : secretValue.getBytes(); + byte[] walletBytes = Base64.getDecoder().decode(secretValue); char[] walletPassword = parameterSet.getOptional(PASSWORD) != null ? parameterSet.getOptional(PASSWORD).toCharArray() : null; diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSecretProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSecretProvider.java index 870284b0..42ee3b27 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSecretProvider.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedSecretProvider.java @@ -61,8 +61,10 @@ public class HcpVaultDedicatedSecretProvider extends HcpVaultDedicatedResourceProvider { private static final ResourceParameter[] PARAMETERS = { - new ResourceParameter("secretPath", SECRET_PATH), - new ResourceParameter("fieldName", FIELD_NAME), + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.SECRET_PATH, + SECRET_PATH), + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.FIELD_NAME, + FIELD_NAME), }; protected HcpVaultDedicatedSecretProvider(String valueType) { @@ -98,7 +100,7 @@ protected final String getSecret(Map parameterValues) { DedicatedVaultSecretsManagerFactory.getInstance(), resolvedValues); OracleJsonObject secretJsonObj = JsonUtil.convertJsonToOracleJsonObject(secretJson); ResourceParameter fieldNameParam = Stream.of(PARAMETERS) - .filter(param -> param.name().equals("fieldName")) + .filter(param -> param.name().equals(HcpVaultDedicatedResourceParameterNames.FIELD_NAME)) .findFirst() .orElse(null); diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedTCPSProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedTCPSProvider.java index 01ef96fb..87f40836 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedTCPSProvider.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultdedicated/resource/HcpVaultDedicatedTCPSProvider.java @@ -40,7 +40,6 @@ import oracle.jdbc.provider.parameter.ParameterSet; import oracle.jdbc.provider.resource.ResourceParameter; -import oracle.jdbc.provider.util.FileUtils; import oracle.jdbc.provider.util.TlsUtils; import oracle.jdbc.spi.TlsConfigurationProvider; @@ -75,8 +74,9 @@ public class HcpVaultDedicatedTCPSProvider implements TlsConfigurationProvider { private static final ResourceParameter[] TCPS_PARAMETERS = { - new ResourceParameter("walletPassword", PASSWORD), - new ResourceParameter("type", TYPE) + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.WALLET_PASSWORD, + PASSWORD), + new ResourceParameter(HcpVaultDedicatedResourceParameterNames.TYPE, TYPE) }; /** @@ -109,8 +109,7 @@ public SSLContext getSSLContext(Map parameterValues) { try { ParameterSet parameterSet = parseParameterValues(parameterValues); String secretValue = getSecret(parameterValues); - byte[] fileBytes = FileUtils.isBase64Encoded(secretValue.getBytes()) ? - Base64.getDecoder().decode(secretValue) : secretValue.getBytes(); + byte[] fileBytes = Base64.getDecoder().decode(secretValue); char[] password = parameterSet.getOptional(PASSWORD) != null ? parameterSet.getOptional(PASSWORD).toCharArray() : null; diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretConnectionStringProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretConnectionStringProvider.java index 60f2b8ea..a77862c8 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretConnectionStringProvider.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretConnectionStringProvider.java @@ -45,11 +45,10 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.util.Base64; import java.util.Map; import static oracle.jdbc.provider.util.CommonParameters.TNS_ALIAS; -import static oracle.jdbc.provider.util.FileUtils.isBase64Encoded; +import static oracle.jdbc.provider.util.FileUtils.decodeIfBase64; /** *

@@ -69,7 +68,7 @@ public class HcpVaultSecretConnectionStringProvider implements ConnectionStringProvider { private static final ResourceParameter[] TNS_NAMES_PARAMETERS = { - new ResourceParameter("tnsAlias", TNS_ALIAS) + new ResourceParameter(HcpVaultSecretResourceParameterNames.TNS_ALIAS, TNS_ALIAS) }; /** @@ -83,14 +82,7 @@ public HcpVaultSecretConnectionStringProvider() { @Override public String getConnectionString(Map parameterValues) { String alias = parseParameterValues(parameterValues).getRequired(TNS_ALIAS); - byte[] secretBytes = getSecret(parameterValues).getBytes(); - - byte[] fileBytes; - if (isBase64Encoded(secretBytes)) { - fileBytes = Base64.getDecoder().decode(secretBytes); - } else { - fileBytes = secretBytes; - } + byte[] fileBytes = decodeIfBase64(getSecret(parameterValues).getBytes()); TNSNames tnsNames; try (InputStream inputStream = new ByteArrayInputStream(fileBytes)) { diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretProvider.java index 160ddeb0..b8042813 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretProvider.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretProvider.java @@ -57,7 +57,7 @@ public class HcpVaultSecretProvider extends HcpVaultSecretResourceProvider { private static final ResourceParameter[] PARAMETERS = { - new ResourceParameter("secretName", SECRET_NAME), + new ResourceParameter(HcpVaultSecretResourceParameterNames.SECRET_NAME, SECRET_NAME), }; protected HcpVaultSecretProvider(String valueType) { diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretResourceParameterNames.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretResourceParameterNames.java new file mode 100644 index 00000000..b18d6f07 --- /dev/null +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretResourceParameterNames.java @@ -0,0 +1,60 @@ +/* + ** 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.hashicorp.hcpvaultsecret.resource; + +/** + * Centralized parameter name constants used by HCP Vault Secret resource providers. + */ +public final class HcpVaultSecretResourceParameterNames { + + private HcpVaultSecretResourceParameterNames() {} + + public static final String ORG_ID = "orgId"; + public static final String PROJECT_ID = "projectId"; + public static final String APP_NAME = "appName"; + public static final String CLIENT_ID = "clientId"; + public static final String CLIENT_SECRET = "clientSecret"; + public static final String CREDENTIALS_FILE = "credentialsFile"; + + public static final String SECRET_NAME = "secretName"; + public static final String TNS_ALIAS = "tnsAlias"; + public static final String CONNECTION_STRING_INDEX = "connectionStringIndex"; + public static final String WALLET_PASSWORD = "walletPassword"; + public static final String TYPE = "type"; +} diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretResourceProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretResourceProvider.java index 8e1d20b7..845be3b6 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretResourceProvider.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretResourceProvider.java @@ -57,12 +57,17 @@ public class HcpVaultSecretResourceProvider extends AbstractVaultResourceProvide new ResourceParameter("authenticationMethod", AUTHENTICATION_METHOD, "auto-detect", HcpVaultSecretResourceProvider::parseAuthenticationMethod), - new ResourceParameter("orgId", HCP_ORG_ID), - new ResourceParameter("projectId", HCP_PROJECT_ID), - new ResourceParameter("appName", HCP_APP_NAME), - new ResourceParameter("clientId", HCP_CLIENT_ID), - new ResourceParameter("clientSecret", HCP_CLIENT_SECRET), - new ResourceParameter("credentialsFile", HCP_CREDENTIALS_FILE, DEFAULT_CREDENTIALS_FILE_PATH), + new ResourceParameter(HcpVaultSecretResourceParameterNames.ORG_ID, HCP_ORG_ID), + new ResourceParameter(HcpVaultSecretResourceParameterNames.PROJECT_ID, + HCP_PROJECT_ID), + new ResourceParameter(HcpVaultSecretResourceParameterNames.APP_NAME, + HCP_APP_NAME), + new ResourceParameter(HcpVaultSecretResourceParameterNames.CLIENT_ID, + HCP_CLIENT_ID), + new ResourceParameter(HcpVaultSecretResourceParameterNames.CLIENT_SECRET, + HCP_CLIENT_SECRET), + new ResourceParameter(HcpVaultSecretResourceParameterNames.CREDENTIALS_FILE, + HCP_CREDENTIALS_FILE, DEFAULT_CREDENTIALS_FILE_PATH), }; protected HcpVaultSecretResourceProvider(String resourceType, ResourceParameter... additionalParameters) { @@ -89,12 +94,18 @@ private static HcpVaultAuthenticationMethod parseAuthenticationMethod(String met @Override protected String getEnvVariableForParameter(String paramName) { switch (paramName) { - case "orgId": return PARAM_HCP_ORG_ID; - case "projectId": return PARAM_HCP_PROJECT_ID; - case "appName": return PARAM_HCP_APP_NAME; - case "clientId": return PARAM_HCP_CLIENT_ID; - case "clientSecret": return PARAM_HCP_CLIENT_SECRET; - case "credentialsFile": return PARAM_HCP_CREDENTIALS_FILE; + case HcpVaultSecretResourceParameterNames.ORG_ID: + return PARAM_HCP_ORG_ID; + case HcpVaultSecretResourceParameterNames.PROJECT_ID: + return PARAM_HCP_PROJECT_ID; + case HcpVaultSecretResourceParameterNames.APP_NAME: + return PARAM_HCP_APP_NAME; + case HcpVaultSecretResourceParameterNames.CLIENT_ID: + return PARAM_HCP_CLIENT_ID; + case HcpVaultSecretResourceParameterNames.CLIENT_SECRET: + return PARAM_HCP_CLIENT_SECRET; + case HcpVaultSecretResourceParameterNames.CREDENTIALS_FILE: + return PARAM_HCP_CREDENTIALS_FILE; default: return paramName; } } diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretSEPSProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretSEPSProvider.java index 50afe27f..1bc7b0b8 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretSEPSProvider.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretSEPSProvider.java @@ -40,7 +40,6 @@ import oracle.jdbc.provider.parameter.ParameterSet; import oracle.jdbc.provider.resource.ResourceParameter; -import oracle.jdbc.provider.util.FileUtils; import oracle.jdbc.provider.util.WalletUtils; import oracle.jdbc.spi.OracleResourceProvider; import oracle.jdbc.spi.PasswordProvider; @@ -73,8 +72,10 @@ public class HcpVaultSecretSEPSProvider implements UsernameProvider, PasswordProvider { private static final ResourceParameter[] SEPS_PARAMETERS = { - new ResourceParameter("walletPassword", PASSWORD), - new ResourceParameter("connectionStringIndex", CONNECTION_STRING_INDEX) + new ResourceParameter(HcpVaultSecretResourceParameterNames.WALLET_PASSWORD, + PASSWORD), + new ResourceParameter(HcpVaultSecretResourceParameterNames.CONNECTION_STRING_INDEX, + CONNECTION_STRING_INDEX) }; /** @@ -98,12 +99,7 @@ public char[] getPassword(Map parameterValues) { private WalletUtils.Credentials getWalletCredentials( Map parameterValues) { ParameterSet parameterSet = parseParameterValues(parameterValues); - - String secretValue = getSecret(parameterValues); - - byte[] walletBytes = FileUtils.isBase64Encoded(secretValue.getBytes()) - ? Base64.getDecoder().decode(secretValue) - : secretValue.getBytes(); + byte[] walletBytes = Base64.getDecoder().decode(getSecret(parameterValues)); char[] walletPassword = parameterSet.getOptional(PASSWORD) != null ? parameterSet.getOptional(PASSWORD).toCharArray() diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretTCPSProvider.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretTCPSProvider.java index 13db83fd..3920d2d7 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretTCPSProvider.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSecretTCPSProvider.java @@ -40,7 +40,6 @@ import oracle.jdbc.provider.parameter.ParameterSet; import oracle.jdbc.provider.resource.ResourceParameter; -import oracle.jdbc.provider.util.FileUtils; import oracle.jdbc.provider.util.TlsUtils; import oracle.jdbc.spi.TlsConfigurationProvider; @@ -75,8 +74,9 @@ public class HcpVaultSecretTCPSProvider implements TlsConfigurationProvider { private static final ResourceParameter[] TCPS_PARAMETERS = { - new ResourceParameter("walletPassword", PASSWORD), - new ResourceParameter("type", TYPE) + new ResourceParameter(HcpVaultSecretResourceParameterNames.WALLET_PASSWORD, + PASSWORD), + new ResourceParameter(HcpVaultSecretResourceParameterNames.TYPE, TYPE) }; /** @@ -91,11 +91,7 @@ public HcpVaultSecretTCPSProvider() { public SSLContext getSSLContext(Map parameterValues) { try { ParameterSet parameterSet = parseParameterValues(parameterValues); - String secretValue = getSecret(parameterValues); - - byte[] fileBytes = FileUtils.isBase64Encoded(secretValue.getBytes()) - ? Base64.getDecoder().decode(secretValue) - : secretValue.getBytes(); + byte[] fileBytes = Base64.getDecoder().decode(getSecret(parameterValues)); char[] password = parameterSet.getOptional(PASSWORD) != null ? parameterSet.getOptional(PASSWORD).toCharArray() diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/util/JsonUtil.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/util/JsonUtil.java index 5735187a..fb4fb8f5 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/util/JsonUtil.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/util/JsonUtil.java @@ -87,8 +87,12 @@ public static String extractField(OracleJsonObject jsonObject, String fieldName) *

Logic:

*
    *
  • If {@code fieldName} is provided and exists in the JSON, return its value.
  • - *
  • If the JSON contains only one key-value pair, return that value automatically.
  • - *
  • If multiple keys exist and no {@code fieldName} is provided, throw an error.
  • + *
  • If {@code fieldName} is provided but not found, throw an exception (even if only one key exists).
  • + *
  • If {@code fieldName} is not provided:
  • + *
      + *
    • If the JSON contains exactly one key-value pair, return its value.
    • + *
    • If multiple keys exist, throw an error.
    • + *
    *
* * @param secretJsonObj The JSON object containing the secret. @@ -97,14 +101,19 @@ public static String extractField(OracleJsonObject jsonObject, String fieldName) * @throws IllegalStateException If multiple keys exist but no `fieldName` is specified. */ public static String extractSecret(OracleJsonObject secretJsonObj, String fieldName) { - if (fieldName != null && secretJsonObj.containsKey(fieldName)) { - return secretJsonObj.getString(fieldName); + if (fieldName != null ) { + if (secretJsonObj.containsKey(fieldName)) { + return secretJsonObj.getString(fieldName); + } else { + throw new IllegalStateException( + "FIELD_NAME '" + fieldName + "' not found in the secret."); + } } else if (secretJsonObj.size() == 1) { String firstKey = secretJsonObj.keySet().iterator().next(); return secretJsonObj.getString(firstKey); } else { throw new IllegalStateException( - "FIELD_NAME is required when multiple keys exist in the secret." + "FIELD_NAME is required when multiple keys exist in the secret." ); } } From daeaac69dfb8d52f069f18a50f25dda0061d1a57 Mon Sep 17 00:00:00 2001 From: Mouhsin Elmajdouby Date: Thu, 8 May 2025 14:53:58 +0100 Subject: [PATCH 4/6] Fix Javadocs --- .../jdbc/provider/hashicorp/util/JsonUtil.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/util/JsonUtil.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/util/JsonUtil.java index fb4fb8f5..47e99f82 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/util/JsonUtil.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/util/JsonUtil.java @@ -84,15 +84,18 @@ public static String extractField(OracleJsonObject jsonObject, String fieldName) /** * Extracts the secret value from the given JSON object based on the field name. * - *

Logic:

+ *

+ * Logic: + *

*
    *
  • If {@code fieldName} is provided and exists in the JSON, return its value.
  • *
  • If {@code fieldName} is provided but not found, throw an exception (even if only one key exists).
  • - *
  • If {@code fieldName} is not provided:
  • - *
      - *
    • If the JSON contains exactly one key-value pair, return its value.
    • - *
    • If multiple keys exist, throw an error.
    • - *
    + *
  • If {@code fieldName} is not provided: + *
      + *
    • If the JSON contains exactly one key-value pair, return its value.
    • + *
    • If multiple keys exist, throw an error.
    • + *
    + *
  • *
* * @param secretJsonObj The JSON object containing the secret. From 906981ddc993e1b36e58e9ab513c14a12b302b29 Mon Sep 17 00:00:00 2001 From: Mouhsin Elmajdouby Date: Fri, 9 May 2025 09:45:04 +0100 Subject: [PATCH 5/6] update HcpVaultSecretParameters file --- .../authentication/HcpVaultSecretParameters.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultSecretParameters.java b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultSecretParameters.java index 99109ce9..1f70a637 100644 --- a/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultSecretParameters.java +++ b/ojdbc-provider-hashicorp/src/main/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/authentication/HcpVaultSecretParameters.java @@ -84,34 +84,34 @@ public class HcpVaultSecretParameters { /** * Parameter for the OAuth2 client ID. Required. */ - public static final Parameter HCP_CLIENT_ID = Parameter.create(REQUIRED); + public static final Parameter HCP_CLIENT_ID = Parameter.create(); /** * Parameter for the OAuth2 client secret. Required. */ - public static final Parameter HCP_CLIENT_SECRET = Parameter.create(REQUIRED); + public static final Parameter HCP_CLIENT_SECRET = Parameter.create(); /** * Parameter for the credentials file path. * By default, the credentials file is expected at: * System.getProperty("user.home") + "/.config/hcp/creds-cache.json". */ - public static final Parameter HCP_CREDENTIALS_FILE = Parameter.create(REQUIRED); + public static final Parameter HCP_CREDENTIALS_FILE = Parameter.create(); /** * Parameter for the organization ID. Required. */ - public static final Parameter HCP_ORG_ID = Parameter.create(REQUIRED); + public static final Parameter HCP_ORG_ID = Parameter.create(); /** * Parameter for the project ID. Required. */ - public static final Parameter HCP_PROJECT_ID = Parameter.create(REQUIRED); + public static final Parameter HCP_PROJECT_ID = Parameter.create(); /** * Parameter for the application name. Required. */ - public static final Parameter HCP_APP_NAME = Parameter.create(REQUIRED); + public static final Parameter HCP_APP_NAME = Parameter.create(); /** * Parameter for the secret name. Required. From 78c3be7775fe91569ca661863cbad1d16ff66466 Mon Sep 17 00:00:00 2001 From: Mouhsin Elmajdouby Date: Fri, 9 May 2025 09:52:55 +0100 Subject: [PATCH 6/6] Update unit tests for hcp vault secrets --- .../resource/HcpVaultConnectionStringProviderTest.java | 3 --- .../hcpvaultsecret/resource/HcpVaultPasswordProviderTest.java | 3 --- .../hcpvaultsecret/resource/HcpVaultSEPSProviderTest.java | 3 --- .../hcpvaultsecret/resource/HcpVaultTCPSProviderTest.java | 3 --- .../hcpvaultsecret/resource/HcpVaultUsernameProviderTest.java | 3 --- 5 files changed, 15 deletions(-) diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultConnectionStringProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultConnectionStringProviderTest.java index 3ca32be2..d6caac48 100644 --- a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultConnectionStringProviderTest.java +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultConnectionStringProviderTest.java @@ -89,7 +89,6 @@ public void testGetParameters() { .filter(parameter -> "orgId".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(orgIdParameter.isRequired()); assertNull(orgIdParameter.defaultValue()); Parameter appNameParameter = @@ -97,7 +96,6 @@ public void testGetParameters() { .filter(parameter -> "appName".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(appNameParameter.isRequired()); assertNull(appNameParameter.defaultValue()); Parameter projectIdParameter = @@ -105,7 +103,6 @@ public void testGetParameters() { .filter(parameter -> "projectId".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(projectIdParameter.isRequired()); assertNull(projectIdParameter.defaultValue()); } diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultPasswordProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultPasswordProviderTest.java index 5ff5de4d..225f6b8f 100644 --- a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultPasswordProviderTest.java +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultPasswordProviderTest.java @@ -82,7 +82,6 @@ public void testGetParameters() { .filter(parameter -> "orgId".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(orgIdParameter.isRequired()); assertNull(orgIdParameter.defaultValue()); Parameter appNameParameter = @@ -90,7 +89,6 @@ public void testGetParameters() { .filter(parameter -> "appName".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(appNameParameter.isRequired()); assertNull(appNameParameter.defaultValue()); Parameter projectIdParameter = @@ -98,7 +96,6 @@ public void testGetParameters() { .filter(parameter -> "projectId".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(projectIdParameter.isRequired()); assertNull(projectIdParameter.defaultValue()); } diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSEPSProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSEPSProviderTest.java index 97955310..74ed77eb 100644 --- a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSEPSProviderTest.java +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultSEPSProviderTest.java @@ -82,7 +82,6 @@ public void testGetusernameParams() { .filter(parameter -> "orgId".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(orgIdParameter.isRequired()); assertNull(orgIdParameter.defaultValue()); Parameter appNameParameter = @@ -90,7 +89,6 @@ public void testGetusernameParams() { .filter(parameter -> "appName".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(appNameParameter.isRequired()); assertNull(appNameParameter.defaultValue()); Parameter projectIdParameter = @@ -98,7 +96,6 @@ public void testGetusernameParams() { .filter(parameter -> "projectId".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(projectIdParameter.isRequired()); assertNull(projectIdParameter.defaultValue()); diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultTCPSProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultTCPSProviderTest.java index 6367384c..9cebbc60 100644 --- a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultTCPSProviderTest.java +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultTCPSProviderTest.java @@ -77,7 +77,6 @@ public void testGetParameters() { .filter(parameter -> "orgId".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(orgIdParameter.isRequired()); assertNull(orgIdParameter.defaultValue()); Parameter appNameParameter = @@ -85,7 +84,6 @@ public void testGetParameters() { .filter(parameter -> "appName".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(appNameParameter.isRequired()); assertNull(appNameParameter.defaultValue()); Parameter projectIdParameter = @@ -93,7 +91,6 @@ public void testGetParameters() { .filter(parameter -> "projectId".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(projectIdParameter.isRequired()); assertNull(projectIdParameter.defaultValue()); Parameter typeParameter = diff --git a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultUsernameProviderTest.java b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultUsernameProviderTest.java index cca26f15..1df00740 100644 --- a/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultUsernameProviderTest.java +++ b/ojdbc-provider-hashicorp/src/test/java/oracle/jdbc/provider/hashicorp/hcpvaultsecret/resource/HcpVaultUsernameProviderTest.java @@ -81,7 +81,6 @@ public void testGetParameters() { .filter(parameter -> "orgId".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(orgIdParameter.isRequired()); assertNull(orgIdParameter.defaultValue()); Parameter appNameParameter = @@ -89,7 +88,6 @@ public void testGetParameters() { .filter(parameter -> "appName".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(appNameParameter.isRequired()); assertNull(appNameParameter.defaultValue()); Parameter projectIdParameter = @@ -97,7 +95,6 @@ public void testGetParameters() { .filter(parameter -> "projectId".equals(parameter.name())) .findFirst() .orElseThrow(AssertionError::new); - assertTrue(projectIdParameter.isRequired()); assertNull(projectIdParameter.defaultValue()); }