diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml index 576022c5..665ec417 100644 --- a/.github/workflows/run-tests.yaml +++ b/.github/workflows/run-tests.yaml @@ -33,11 +33,16 @@ jobs: - name: Install dependencies run: mvn install -DskipTests + + - name: Set GCP environment variables + run : | + echo "GOOGLE_APPLICATION_CREDENTIALS=$HOME/.gcp/config.json" >> $GITHUB_ENV - name: Prepare certificate and properties files run: | mkdir -p $HOME/.azure mkdir -p $HOME/.oci + mkdir -p $HOME/.gcp # Prepare certificate echo "${{ secrets.TEST_AZURE_CERTIFICATE }}" > $HOME/.azure/ojdbc-plugin-test-app.pem @@ -131,6 +136,9 @@ jobs: AWS_SECRETS_MANAGER_URL=${{ secrets.TEST_AWS_SECRETS_MANAGER_URL }}\n " >> ojdbc-provider-aws/test.properties + # Generate GCP config + echo "${{ secrets.TEST_GCP_CONFIG }}" > $HOME/.gcp/config.json + echo "${{ secrets.GCP_TEST_PROPERTIES }}" > ojdbc-provider-gcp/test.properties # Generate ojdbc-provider-hashicorp/test.properties echo -e "VAULT_ADDR=${{ secrets.TEST_VAULT_ADDR }}\n @@ -165,6 +173,9 @@ jobs: rm ojdbc-provider-azure/ojdbc-provider-test-app.pfx rm ojdbc-provider-azure/test.properties + rm $HOME/.gcp/config.json + rm ojdbc-provider-gcp/test.properties + rm ojdbc-provider-jackson-oson/test.properties rm ojdbc-provider-aws/test.properties diff --git a/README.md b/README.md index 7e582c7c..e8443118 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ Each module of this project contains a set of providers.
Providers for integration with Oracle Cloud Infrastructure (OCI).
Oracle JDBC Azure Providers
Providers for integration with Microsoft Azure
+
Oracle JDBC GCP Providers
+
Providers for integration with Google Cloud Platform
Oracle JDBC HashiCorp Providers
Providers for integration with Hashicorp
@@ -130,6 +132,8 @@ this project: [ojdbc-provider-azure](ojdbc-provider-azure/README.md#installation) +[ojdbc-provider-gcp](ojdbc-provider-gcp/README.md#installation) + [ojdbc-provider-opentelemetry](ojdbc-provider-opentelemetry/README.md#installation) [ojdbc-provider-jackson-oson](ojdbc-provider-jackson-oson/README.md#installation) diff --git a/ojdbc-provider-gcp/README.md b/ojdbc-provider-gcp/README.md new file mode 100644 index 00000000..37713445 --- /dev/null +++ b/ojdbc-provider-gcp/README.md @@ -0,0 +1,371 @@ +# Oracle JDBC Providers for GCP + +This module contains providers for integration between Oracle JDBC and +Google Cloud Platform (GCP). + +## Centralized Config Providers + +
+
GCP Cloud Storage Config +Provider
+
Provides connection properties managed by the Cloud Storage service
+
GCP Secret Manager Config +Provider
+
Provides connection properties managed by the Secret Manager service
+
Caching configuration
+
Caching mechanism adopted by Centralized Config Providers
+
+ +## Resource Providers + +
+
Secret Manager Password Provider
+
Provides passwords managed by the Secret Manager service
+
Secret Manager Username Provider
+
Provides usernames managed by the Secret Manager service
+
Secret Manager TCPS Wallet Provider
+
Provides TCPS/TLS wallet for secure connections to an Autonomous Database from the Secret Manager service
+
Secret Manager SEPS Wallet Provider
+
Provides SEPS (Secure External Password Store) wallets for secure username and password retrieval from the Secret Manager service
+
Secret Manager Connection String Provider
+
Provides connection strings for secure database connectivity based on aliases, retrieved from the `tnsnames.ora` +file stored in GCP Secret Manager.
+
+ +Visit any of the links above to find information and usage examples for a +particular provider. + +## Installation + +All providers in this module are distributed as single jar on the Maven Central +Repository. The jar is compiled for JDK 8, and is forward compatible with later +JDK versions. The coordinates for the latest release are: +```xml + + com.oracle.database.jdbc + ojdbc-provider-gcp + 1.0.1 + +``` + +## Authentication + +Providers use Google Cloud APIs which support +[Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials); +the libraries look for credentials in a set of defined locations and use those +credentials to authenticate requests to the API. + +ADC searches for credentials in one of the following locations: + +1. GOOGLE_APPLICATION_CREDENTIALS environment variable +2. User credentials set up by using the Google Cloud CLI +3. The attached service account, returned by the metadata server + +When your code is running in a local development environment, such as a development workstation, the best option is to use the credentials associated with your user account. + +### Configure ADC with your Google Account +To configure ADC with a Google Account, you use the Google Cloud CLI: + +1. Install and initialize the gcloud CLI. + +When you initialize the gcloud CLI, be sure to specify a Google Cloud project in which you have permission to access the resources your application needs. + +2. Configure ADC: +``` +gcloud auth application-default login +``` +A sign-in screen appears. After you sign in, your credentials are stored in the local credential file used by ADC. + +## GCP Cloud Storage Config Provider +The Oracle DataSource uses a new prefix `jdbc:oracle:thin:@config-gcpstorage:` to be able to identify that the configuration parameters should be loaded using GCP Object Storage. Users only need to indicate the project, bucket and object containing the JSON payload, with the following syntax: + +
+jdbc:oracle:thin:@config-gcpstorage://project={project};bucket={bucket};object={object}
+
+ +### JSON Payload format + +There are 3 fixed values that are looked at the root level. + +- connect_descriptor (required) +- user (optional) +- password (optional) + +The rest are dependent on the driver, in our case `/jdbc`. The key-value pairs that are with sub-prefix `/jdbc` will be applied to a DataSource. The key values are constant keys which are equivalent to the properties defined in the [OracleConnection](https://docs.oracle.com/en/database/oracle/oracle-database/23/jajdb/oracle/jdbc/OracleConnection.html) interface. + +For example, let's suppose an url like: + +
+jdbc:oracle:thin:@config-gcpstorage://project=myproject;bucket=mybucket;object=payload_ojdbc_objectstorage.json
+
+ +And the JSON Payload for the file **payload_ojdbc_objectstorage.json** in the **mybucket** which belongs to the project **myproject** is as following: + +```json +{ + "connect_descriptor": "(description=(retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1521)(host=adb.us-phoenix-1.oraclecloud.com))(connect_data=(service_name=xsxsxs_dbtest_medium.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)))", + "user": "scott", + "password": { + "type": "gcpsecretmanager", + "value": "projects/138028249883/secrets/test-secret/versions/1" + }, + "jdbc": { + "oracle.jdbc.ReadTimeout": 1000, + "defaultRowPrefetch": 20, + "autoCommit": "false" + } +} +``` + +The sample code below executes as expected with the previous configuration. + +```java + OracleDataSource ds = new OracleDataSource(); + ds.setURL("jdbc:oracle:thin:@config-gcpstorage://project=myproject;bucket=mybucket;object=payload_ojdbc_objectstorage.json"); + Connection cn = ds.getConnection(); + Statement st = cn.createStatement(); + ResultSet rs = st.executeQuery("select sysdate from dual"); + if (rs.next()) + System.out.println("select sysdate from dual: " + rs.getString(1)); +``` + +### Password JSON Object + +For the JSON type of provider (GCP Object Storage, HTTP/HTTPS, File) the password is an object itself with the following spec: + +- type + - Mandatory + - Possible values + - ocivault + - azurevault + - base64 + - gcpsecretmanager +- value + - Mandatory + - Possible values + - OCID of the secret (if ocivault) + - Azure Key Vault URI (if azurevault) + - Base64 Encoded password (if base64) + - GCP resource name (if gcpsecretmanager) + - Text +- authentication + - Optional + - Possible Values + - method + - optional parameters (depends on the cloud provider). + +## GCP Secret Manager Config Provider +Apart from GCP Cloud Storage, users can also store JSON Payload in the content of GCP Secret Manager secret. Users need to indicate the resource name: + +
+jdbc:oracle:thin:@config-gcpsecretmanager:{resource-name}
+
+ +The JSON Payload retrieved by GCP Vault Config Provider follows the same format in [GCP Object Storage Config Provider](#json-payload-format). + +## Caching configuration + +Config providers in this module store the configuration in caches to minimize +the number of RPC requests to remote location. See +[Caching configuration](../ojdbc-provider-azure/README.md#caching-configuration) for more +details of the caching mechanism. + +## Vault Password Provider +The Vault Password Provider provides Oracle JDBC with a password that is managed +by the GCP Secret Manager service. This is a Resource Provider identified by the +name `ojdbc-provider-gcp-secret-password`. + +This provider requires the parameters listed below. + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesDefault Value
secretVersionNameIdentifies the secret that is provided.The resource name of the secret.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.properties](example-vault.properties). + +## Vault Username Provider +The Vault Username Provider provides Oracle JDBC with a username that is managed by the +GCP Secret Manager service. This is a Resource Provider identified by the name +`ojdbc-provider-gcp-secret-username`. + +In addition to the set of [common parameters](#common-parameters-for-resource-providers), this provider +also supports the parameters listed below. + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesDefault Value
secretVersionNameIdentifies the secret that is provided.The resource name of the secret.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.properties](example-vault.properties). + +## Secret Manager TCPS Wallet Provider + +The TCPS Wallet Provider provides Oracle JDBC with keys and certificates managed by the GCP Secret Manager service to establish secure TLS connections with an Autonomous Database. This is a Resource Provider identified by the name `ojdbc-provider-gcp-secretmanager-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 (e.g., `cwallet.sso`, `ewallet.p12`, `ewallet.pem`), you may store it in a GCP Secret Manager secret for additional security. You can then use this provider to retrieve the wallet content from GCP Secret Manager using the GCP SDK and pass it to the JDBC thin driver. + +- The type parameter must be specified to indicate the wallet format: SSO, PKCS12, or PEM. +- The wallet password must be provided for wallets that require a password (e.g., PKCS12 or password-protected PEM files). +- This provider handles both cases where the wallet is stored as a base64-encoded string or directly as an imported file in GCP Secret Manager. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesDefault Value
secretVersionNameThe name of the secret version in GCP Secret Manager that contains the TCPS wallet file. The GCP Secret Manager Secret Version, typically in the form: +
projects/{project-id}/secrets/{secret-id}/versions/{version-id}
+
+No default value. A value must be configured for this parameter. +
walletPassword +Optional password for PKCS12 or protected PEM files. If omitted, the file is assumed to be SSO or a non-protected PEM file. +Any valid password for the wallet +No default value. PKCS12 and password-protected PEM files require a password. +
type +Specifies the type of the file being used. +SSO, PKCS12, PEM +No default value. The file type must be specified. +
+ +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-secret-manager-wallet.properties](example-secret-manager-wallet.properties). + +This provider automatically handles cases where the wallet is stored as either a base64-encoded string or an imported file in GCP Secret Manager. It detects the format and processes the wallet accordingly, ensuring flexibility in how users manage and retrieve their wallet data. + + +## Secret Manager SEPS Wallet Provider + +The SEPS Wallet Provider provides Oracle JDBC with a username and password managed by the GCP Secret Manager service, stored in a Secure External Password Store (SEPS) wallet. This is a Resource Provider identified by the name `ojdbc-provider-gcp-secretmanager-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** and **oracle.security.client.default_password**, or as indexed credentials, for example, **oracle.security.client.username1**, **oracle.security.client.password1**, and **oracle.security.client.connect_string1**. + +- The provider retrieves credentials based on the following logic: If `connectionStringIndex` is not specified, it first attempts to retrieve the default credentials (`oracle.security.client.default_username` and `oracle.security.client.default_password`). If default credentials are not found, it checks for a single set of credentials associated with a connection string. If exactly one connection string is found, it uses the associated credentials. However, if multiple connection strings are found, an error is thrown, prompting you to specify a `connectionStringIndex`. 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}**). If credentials for the specified index are not found, an error is thrown indicating that no connection string was found with that index. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesDefault Value
secretVersionNameThe name of the secret version in GCP Secret Manager that contains the SEPS wallet file. The GCP Secret Manager Secret Version, typically in the form: +
projects/{project-id}/secrets/{secret-id}/versions/{version-id}
+
+No default value. A value must be configured for this parameter. +
walletPassword +Optional password for wallets stored as PKCS12 keystores. If omitted, the wallet is assumed to be an SSO wallet. +Any valid password for the SEPS wallet +No default value. PKCS12 wallets require a password. +
connectionStringIndex +Optional parameter to specify 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-secret-manager-wallet.properties](example-secret-manager-wallet.properties). + +This provider supports wallets stored in GCP Secret Manager as both base64-encoded strings and imported files. It automatically detects the storage format and processes the wallet accordingly, ensuring flexibility in managing your SEPS credentials. + +## Secret Manager Connection String Provider + +The Connection String Provider provides Oracle JDBC with a connection string managed by the GCP Secret Manager service. +This is a Resource Provider identified by the name `ojdbc-provider-gcp-secretmanager-tnsnames`. + +This provider retrieves a `tnsnames.ora` file stored in GCP Secret Manager, allowing selection of connection strings +based on specified aliases. The `tnsnames.ora` file can be stored as a base64-encoded string or as a raw file, +and the provider automatically detects the format. + +This enables flexible configuration for secure database connections using the alias names defined in your `tnsnames.ora` file. + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter NameDescriptionAccepted ValuesDefault Value
secretVersionNameThe version name of the secret in GCP Secret Manager that contains the tnsnames.ora file.The GCP Secret Manager Secret Version, typically in the form:
projects/{project-id}/secrets/{secret-id}/versions/{version-id}
No default value. A value must be configured for this parameter.
tnsAliasSpecifies the alias to retrieve the appropriate connection string from the tnsnames.ora file.Any valid alias present in your 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.properties](example-vault.properties). diff --git a/ojdbc-provider-gcp/example-secret-manager-wallet.properties b/ojdbc-provider-gcp/example-secret-manager-wallet.properties new file mode 100644 index 00000000..ab804076 --- /dev/null +++ b/ojdbc-provider-gcp/example-secret-manager-wallet.properties @@ -0,0 +1,77 @@ +################################################################################ +# Copyright (c) 2024 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 GCP Secret Manager. +# +# 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 GCP Secret Manager TLS (TCPS) File Provider. The secret version name is +# configured as an environment variable or JVM system property named "GCP_TLS_WALLET_SECRET_VERSION": +oracle.jdbc.provider.tlsConfiguration=ojdbc-provider-gcp-secretmanager-tls +oracle.jdbc.provider.tlsConfiguration.secretVersionName=${GCP_TLS_WALLET_SECRET_VERSION} + +# Configures the GCP Secret Manager TLS File Password Provider. The password for the +# file is optional and can be configured as an environment variable or JVM +# system property named "GCP_TLS_FILE_PASSWORD": +oracle.jdbc.provider.tlsConfiguration.walletPassword=${GCP_TLS_FILE_PASSWORD} + +# Specifies the file type (SSO, PKCS12, or PEM). This determines how the file is processed. +# This can be configured as an environment variable or JVM system property named "GCP_TLS_FILE_TYPE": +oracle.jdbc.provider.tlsConfiguration.type=${GCP_TLS_FILE_TYPE} + +# Configures the GCP Secret Manager SEPS (Secure External Password Store) Provider. +# The secret version name is configured as an environment variable or JVM system property +# named "GCP_SEPS_WALLET_SECRET_VERSION": +oracle.jdbc.provider.username=ojdbc-provider-gcp-secretmanager-seps +oracle.jdbc.provider.password=ojdbc-provider-gcp-secretmanager-seps + +# Configures the secret version name for SEPS. +oracle.jdbc.provider.username.secretVersionName=${GCP_SEPS_WALLET_SECRET_VERSION} +oracle.jdbc.provider.password.secretVersionName=${GCP_SEPS_WALLET_SECRET_VERSION} + +# Optional password for SEPS Wallet stored in GCP Secret Manager +oracle.jdbc.provider.username.walletPassword=${GCP_SEPS_WALLET_PASSWORD} +oracle.jdbc.provider.password.walletPassword=${GCP_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=${GCP_SEPS_CONNECTION_STRING_INDEX} +oracle.jdbc.provider.password.connectionStringIndex=${GCP_SEPS_CONNECTION_STRING_INDEX} diff --git a/ojdbc-provider-gcp/example-test.properties b/ojdbc-provider-gcp/example-test.properties new file mode 100644 index 00000000..1b4b8a5a --- /dev/null +++ b/ojdbc-provider-gcp/example-test.properties @@ -0,0 +1,133 @@ +################################################################################ +# Copyright (c) 2024 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. +################################################################################ + +# This file provides examples of properties that configure tests for GCP in this +# module. +# +# QUICK GUIDE TO RUNNING TESTS: +# 1. Create a copy of this file named "test.properties": +# cp example-test.properties test.properties +# 2. In test.properties, replace example values with real values (the file is +# .gitignore'd, so sensitive info won't be checked in to the repo) +# 3. Comment out any lines for which a value can not be provided (tests are +# skipped if no value is configured). +# 4. mvn clean verify +# +# CONFIGURING TEST PROPERTIES +# Test properties are read from a properties file by the TestProperties class. +# The TestProperties class can be found in: +# ojdbc-provider-common/src/testFixtures/java/oracle/jdbc/provider/TestProperties.java +# The default behavior of TestProperties is to read a file named +# "test.properties" in the current directory. A non-default location may be +# specified as a JVM system property: +# mvn clean verify -Doracle.jdbc.provider.TestProperties=/path/to/my-test.properties +# +# MAINTAINING THIS FILE +# Project maintainers should add an example to this file anytime they write a +# test which requires a new property. Not doing so will inflict pain and +# suffering upon our fellow programmers, and will also lead to increased +# maintenance costs. + +# IGNORING UNCONFIGURED PROPERTIES +# No test should cause a build failure due to an unconfigured property. +# Using JUnit terminology: A test should "abort" rather than "fail" when a +# property is not configured. This means that the test does not pass, but it +# does not cause the build to fail either. +# Methods of the TestProperties class will automatically abort a test if a +# property is not configured. The org.junit.jupiter.api.Assumptions class may +# also be used directly to abort a test. +# +# There is NO environment in which ALL tests can be run. Some tests may +# require authentication and configurations for GCP, while others may require +# Azure or OCI setups; these environments are mutually exclusive. +# +# This flexibility ensures that developers can work on specific modules without +# needing to configure all cloud environments. For instance, a developer working +# on GCP provider features should not be required to configure OCI or Azure +# environments in order to run tests for their changes. + +# The URL of the GCP Object Storage +GCP_OBJECT_STORAGE_URL=https://storage.googleapis.com/example-bucket + +# The version name of a secret stored in GCP Secret Manager for configuration +SECRET_VERSION_NAME_CONFIG=projects/project-id/secrets/my-secret/versions/1 + +# Secret version name for Username in GCP Secret Manager +GCP_SECRET_MANAGER_USERNAME_SECRET_VERSION=projects/project-id/secrets/username-secret/versions/1 + +# Secret version name for Password in GCP Secret Manager +GCP_SECRET_MANAGER_PASSWORD_SECRET_VERSION=projects/project-id/secrets/password-secret/versions/1 + +# PKCS12 TLS Wallet Secret stored in GCP Secret Manager +GCP_PKCS12_TLS_WALLET_SECRET_VERSION_NAME=projects/project-id/secrets/pkcs12-wallet-secret/versions/1 + +# Password for the PKCS12 Wallet stored in GCP Secret Manager +GCP_PKCS12_TLS_WALLET_PASSWORD=*********** + +# SSO TLS Wallet Secret stored in GCP Secret Manager +GCP_SSO_TLS_WALLET_SECRET_VERSION_NAME=projects/project-id/secrets/sso-wallet-secret/versions/1 + +# PEM TLS Wallet Secret stored in GCP Secret Manager +GCP_PEM_TLS_WALLET_SECRET_VERSION_NAME=projects/project-id/secrets/pem-wallet-secret/versions/1 + +# Password for the PEM Wallet stored in GCP Secret Manager +GCP_PEM_TLS_WALLET_PASSWORD=************ + +# Corrupted TLS Wallet Secret stored in GCP Secret Manager for negative test cases +GCP_CORRUPTED_TLS_WALLET_SECRET_VERSION_NAME=projects/project-id/secrets/corrupted-wallet-secret/versions/1 + +# PKCS12 SEPS Secret stored in GCP Secret Manager +GCP_PKCS12_SEPS_SECRET_VERSION_NAME=projects/project-id/secrets/pkcs12-seps-secret/versions/1 + +# Password for the PKCS12 SEPS Wallet stored in GCP Secret Manager +GCP_PKCS12_SEPS_WALLET_PASSWORD=************ + +# Optional index to select credentials from the SEPS wallet +GCP_SEPS_CONNECTION_STRING_INDEX=1 + +# SSO SEPS Secret stored in GCP Secret Manager +GCP_SSO_SEPS_SECRET_VERSION_NAME=projects/project-id/secrets/sso-seps-secret/versions/1 + +# Corrupted SEPS Wallet Secret stored in GCP Secret Manager for negative test cases +GCP_CORRUPTED_SEPS_WALLET_SECRET_VERSION_NAME=projects/project-id/secrets/corrupted-seps-secret/versions/1 + +# Secret version name for tnsnames.ora file in GCP Secret Manager +GCP_SECRET_MANAGER_TNS_NAMES_SECRET_VERSION=projects/project-id/secrets/tnsnames-ora-secret/versions/1 + +# Alias to retrieve specific connection string from tnsnames.ora in GCP Secret Manager +GCP_SECRET_MANAGER_TNS_ALIAS_SECRET_NAME=your_tns_alias diff --git a/ojdbc-provider-gcp/example-vault.properties b/ojdbc-provider-gcp/example-vault.properties new file mode 100644 index 00000000..c2c68ec7 --- /dev/null +++ b/ojdbc-provider-gcp/example-vault.properties @@ -0,0 +1,65 @@ +################################################################################ +# Copyright (c) 2024 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 username and password from OCI's 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 GCP Vault Secret Username Provider. The resurce name of the +# username secret is configured as an environment variable or JVM system +# property named "USERNAME_SECRET_VERSION_NAME": +oracle.jdbc.provider.username=ojdbc-provider-gcp-secretmanager-username +oracle.jdbc.provider.username.secretVersionName=${USERNAME_SECRET_VERSION_NAME} + +# Configures the OCI Vault Secret Password Provider. The resource name of the +# password secret is configured as an environment variable or JVM system +# property named "PASSWORD_SECRET_VERSION_NAME": +oracle.jdbc.provider.password=ojdbc-provider-gcp-secretmanager-password +oracle.jdbc.provider.password.secretVersionName=${PASSWORD_SECRET_VERSION_NAME} + +# Configures the GCP Secret Manager Connection String Provider. The secret version name and +# tns alias are configured as environment variables or JVM system properties +# named "GCP_SECRET_VERSION_NAME" and "TNS_ALIAS". +oracle.jdbc.provider.connectionString=ojdbc-provider-gcp-secretmanager-tnsnames +oracle.jdbc.provider.connectionString.secretVersionName=${GCP_SECRET_VERSION_NAME} +oracle.jdbc.provider.connectionString.tnsAlias=${TNS_ALIAS} + + diff --git a/ojdbc-provider-gcp/pom.xml b/ojdbc-provider-gcp/pom.xml new file mode 100644 index 00000000..40dc6817 --- /dev/null +++ b/ojdbc-provider-gcp/pom.xml @@ -0,0 +1,72 @@ + + + 4.0.0 + + Oracle JDBC GCP Providers + + ojdbc-provider-gcp + jar + + + com.oracle.database.jdbc + ojdbc-extensions + 1.0.3 + + + + + + com.google.cloud + libraries-bom + 26.54.0 + pom + import + + + + + + + com.oracle.database.jdbc + ojdbc-provider-common + + + com.oracle.database.jdbc + ojdbc8 + + + com.google.cloud + google-cloud-secretmanager + + + com.google.cloud + google-cloud-storage + + + + + + com.oracle.database.jdbc + ojdbc-provider-common + tests + test-jar + + + com.oracle.database.jdbc + ojdbc-provider-common + tests + test-jar + + + org.junit.jupiter + junit-jupiter-api + + + org.junit.jupiter + junit-jupiter-engine + + + + \ No newline at end of file diff --git a/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/configuration/GcpCloudStorageConfigurationProvider.java b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/configuration/GcpCloudStorageConfigurationProvider.java new file mode 100644 index 00000000..b6f5b010 --- /dev/null +++ b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/configuration/GcpCloudStorageConfigurationProvider.java @@ -0,0 +1,105 @@ +/* + ** Copyright (c) 2024 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.gcp.configuration; + +import java.io.InputStream; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +import oracle.jdbc.driver.configuration.OracleConfigurationParsableProvider; +import oracle.jdbc.provider.gcp.objectstorage.GcpCloudStorageFactory; +import oracle.jdbc.provider.parameter.ParameterSet; +import oracle.jdbc.util.OracleConfigurationCache; + +/** + * A provider for JSON payload which contains configuration from GCP Cloud + * Storage. See {@link #getInputStream(String)} for the spec of the JSON payload. + */ +public class GcpCloudStorageConfigurationProvider + extends OracleConfigurationParsableProvider { + + public static final String PROJECT_PARAMETER = "project"; + public static final String BUCKET_PARAMETER = "bucket"; + public static final String OBJECT_PARAMETER = "object"; + + @Override + public String getType() { + return "gcpstorage"; + } + + /** + * {@inheritDoc} + *

+ * Returns the JSON payload stored in GCP Cloud Storage. + *

+ * + * @param location semi-colon separated list of key value pairs + * containing the following keys: + * + * Unknown keys will be ignored. + * Ex: project=myProject;bucket=myBucket;object=myfile.json + * @return JSON payload + */ + @Override + public InputStream getInputStream(String location) throws SQLException { + Map namedValues = new HashMap<>(); + String[] keyValuePairs = location.split(";"); + for (String keyValuePair : keyValuePairs) { + String[] keyValue = keyValuePair.split("=", 2); + namedValues.putIfAbsent(keyValue[0], keyValue[1]); + } + ParameterSet parameterSet = GcpConfigurationParameters.getParser().parseNamedValues(namedValues); + + return GcpCloudStorageFactory.getInstance().request(parameterSet).getContent(); + } + + /** + * {@inheritDoc} + * @return cache of this provider which is used to store configuration + */ + @Override + public OracleConfigurationCache getCache() { + return CACHE; + } +} diff --git a/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/configuration/GcpConfigurationParameters.java b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/configuration/GcpConfigurationParameters.java new file mode 100644 index 00000000..2aa8146d --- /dev/null +++ b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/configuration/GcpConfigurationParameters.java @@ -0,0 +1,75 @@ +/* + ** Copyright (c) 2024 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.gcp.configuration; + +import static oracle.jdbc.provider.gcp.secrets.GcpSecretManagerFactory.SECRET_VERSION_NAME; + +import oracle.jdbc.provider.gcp.objectstorage.GcpCloudStorageFactory; +import oracle.jdbc.provider.parameter.Parameter; +import oracle.jdbc.provider.parameter.ParameterSetParser;; + +public class GcpConfigurationParameters { + /** + *

+ * A parser that recognizes parameters of key/value pairs received by + * {@link GcpCloudStorageConfigurationProvider}, and resource names received + * by {@link GcpSecretManagerConfigurationProvider}. + *

+ */ + private static final ParameterSetParser PARAMETER_SET_PARSER = ParameterSetParser.builder() + .addParameter("value", SECRET_VERSION_NAME) + .addParameter("secretVersionName", SECRET_VERSION_NAME) + .addParameter( + GcpCloudStorageConfigurationProvider.PROJECT_PARAMETER, GcpCloudStorageFactory.PROJECT) + .addParameter( + GcpCloudStorageConfigurationProvider.BUCKET_PARAMETER, GcpCloudStorageFactory.BUCKET) + .addParameter( + GcpCloudStorageConfigurationProvider.OBJECT_PARAMETER, GcpCloudStorageFactory.OBJECT) + .addParameter("type", Parameter.create()) + .build(); + + /** + * @return A parser that recognizes parameters of URIs received by + * {@link GcpCloudStorageConfigurationProvider}, and JSON objects + * received by + * {@link GcpSecretManagerConfigurationProvider}. + */ + public static ParameterSetParser getParser() { + return PARAMETER_SET_PARSER; + } +} diff --git a/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/configuration/GcpJsonSecretManagerProvider.java b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/configuration/GcpJsonSecretManagerProvider.java new file mode 100644 index 00000000..8d4b7c16 --- /dev/null +++ b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/configuration/GcpJsonSecretManagerProvider.java @@ -0,0 +1,86 @@ +/* + ** Copyright (c) 2024 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.gcp.configuration; + +import com.google.protobuf.ByteString; + +import java.util.Base64; +import java.util.Map; + +import oracle.jdbc.provider.gcp.secrets.GcpSecretManagerFactory; +import oracle.jdbc.provider.parameter.ParameterSet; +import oracle.jdbc.spi.OracleConfigurationSecretProvider; + +public class GcpJsonSecretManagerProvider implements OracleConfigurationSecretProvider { + + /** + * {@inheritDoc} + *

+ * Returns the password of the Secret that is retrieved from GCP Secrets. + *

+ *

+ * The JSON object has the following form: + *

+ * + *
{@code
+   *   "password": {
+  *       "type": "gcpsecretmanager",
+  *       "value": "projects//secrets//versions/",
+   *   }
+   * }
+ * + * @param secretProperties a map containing the flattened key/value pairs of + * the JSON object. + * @return encoded char array in base64 format that represents the retrieved + * Secret. + */ + @Override + public char[] getSecret(Map secretProperties) { + ParameterSet parameterSet = GcpConfigurationParameters.getParser().parseNamedValues( + secretProperties); + + ByteString stringData = GcpSecretManagerFactory.getInstance().request(parameterSet).getContent().getData(); + return Base64.getEncoder().encodeToString(stringData.toByteArray()).toCharArray(); + } + + @Override + public String getSecretType() { + return "gcpsecretmanager"; + } + +} diff --git a/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/configuration/GcpSecretManagerConfigurationProvider.java b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/configuration/GcpSecretManagerConfigurationProvider.java new file mode 100644 index 00000000..d506f02e --- /dev/null +++ b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/configuration/GcpSecretManagerConfigurationProvider.java @@ -0,0 +1,96 @@ +/* + ** Copyright (c) 2024 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.gcp.configuration; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +import oracle.jdbc.driver.configuration.OracleConfigurationParsableProvider; +import oracle.jdbc.provider.gcp.secrets.GcpSecretManagerFactory; +import oracle.jdbc.provider.parameter.ParameterSet; +import oracle.jdbc.util.OracleConfigurationCache; + +/** + * A provider for JSON payload which contains configuration from GCP Secret + * Manager. + * See {@link #getInputStream(String)} for the spec of the JSON payload. + **/ +public class GcpSecretManagerConfigurationProvider + extends OracleConfigurationParsableProvider { + + @Override + public String getType() { + return "gcpsecretmanager"; + } + + /** + * {@inheritDoc} + *

+ * Returns the JSON payload stored in GCP Secret Manager secret. + *

+ * + * @param location resource name of the secret version (to obtain the resource + * name, click on "Actions" and "Copy resource name") + * @return JSON payload + */ + @Override + public InputStream getInputStream(String location) throws SQLException { + Map namedValues = new HashMap<>(); + namedValues.put("secretVersionName", location); + ParameterSet parameterSet = GcpConfigurationParameters.getParser().parseNamedValues(namedValues); + return new ByteArrayInputStream( + GcpSecretManagerFactory.getInstance().request(parameterSet).getContent().getData().toByteArray()); + } + + /** + * {@inheritDoc} + * @return cache of this provider which is used to store configuration + */ + @Override + public OracleConfigurationCache getCache() { + return CACHE; + } + + @Override + public String getParserType(String arg0) { + return "json"; + } +} diff --git a/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/objectstorage/GcpCloudStorageFactory.java b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/objectstorage/GcpCloudStorageFactory.java new file mode 100644 index 00000000..b2382897 --- /dev/null +++ b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/objectstorage/GcpCloudStorageFactory.java @@ -0,0 +1,86 @@ +/* + ** Copyright (c) 2024 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.gcp.objectstorage; + +import static oracle.jdbc.provider.parameter.Parameter.CommonAttribute.REQUIRED; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import com.google.cloud.storage.Storage; +import com.google.cloud.storage.StorageOptions; + +import oracle.jdbc.provider.cache.CachedResourceFactory; +import oracle.jdbc.provider.factory.Resource; +import oracle.jdbc.provider.factory.ResourceFactory; +import oracle.jdbc.provider.parameter.Parameter; +import oracle.jdbc.provider.parameter.ParameterSet; + +public class GcpCloudStorageFactory implements ResourceFactory { + /** The secret version name for the secret */ + public static final Parameter PROJECT = Parameter.create(REQUIRED); + public static final Parameter BUCKET = Parameter.create(REQUIRED); + public static final Parameter OBJECT = Parameter.create(REQUIRED); + + private static final ResourceFactory INSTANCE = CachedResourceFactory + .create(new GcpCloudStorageFactory()); + + private GcpCloudStorageFactory() { + } + + /** + * Returns a singleton of {@code GcpVaultSecretFactory}. + * + * @return a singleton of {@code GcpVaultSecretFactory} + */ + public static ResourceFactory getInstance() { + return INSTANCE; + } + + public Resource request(ParameterSet parameterSet) + throws IllegalStateException, IllegalArgumentException { + String projectName = parameterSet.getRequired(PROJECT); + String bucketName = parameterSet.getRequired(BUCKET); + String objectName = parameterSet.getRequired(OBJECT); + + Storage storage = (Storage) StorageOptions.newBuilder().setProjectId(projectName).build().getService(); + byte[] data = storage.readAllBytes(bucketName, objectName); + InputStream stream = new ByteArrayInputStream(data); + return Resource.createPermanentResource(stream, false); + } +} diff --git a/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerConnectionStringProvider.java b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerConnectionStringProvider.java new file mode 100644 index 00000000..54cd0d0d --- /dev/null +++ b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerConnectionStringProvider.java @@ -0,0 +1,137 @@ +/* + ** Copyright (c) 2024 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.gcp.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 GCP Secret Manager for use with an Oracle Autonomous Database. + * The tnsnames.ora file can be stored either as a base64-encoded secret or in + * raw binary format in GCP Secret Manager. This provider automatically + * detects and decodes base64-encoded content as needed before parsing the + * file to retrieve connection strings based on specified aliases. + *

+ *

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

+ */ +public class GcpSecretManagerConnectionStringProvider + extends GcpSecretManagerProvider + 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 GcpSecretManagerConnectionStringProvider() { + super("secretmanager-tnsnames", TNS_NAMES_PARAMETERS); + } + + /** + * Retrieves a database connection string from the tnsnames.ora file stored + * in GCP Secret Manager. + *

+ * This method accesses the file in GCP Secret Manager, detects if the content + * is base64-encoded, and decodes it if necessary. The tnsnames.ora content is + * then parsed to locate the connection string associated with the specified + * alias. + *

+ * + * @param parameterValues The parameters required to access the tnsnames.ora + * file in GCP Secret Manager, including the secret name and the tns-alias. + * @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 the GCP Secret Manager. + * @throws IllegalArgumentException If the specified alias is invalid or + * does not exist in the tnsnames.ora file. + */ + @Override + public String getConnectionString(Map parameterValues) { + + byte[] fileBytes = getSecret(parameterValues).toByteArray(); + + if (FileUtils.isBase64Encoded(fileBytes)) { + fileBytes = Base64.getDecoder().decode(fileBytes); + } + + 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 alias; + try { + alias = parseParameterValues(parameterValues).getRequired(TNS_ALIAS); + } catch (IllegalStateException e) { + throw new IllegalArgumentException( + "Required parameter 'tnsAlias' is missing", e + ); + } + + String connectionString = tnsNames.getConnectionStringByAlias(alias); + if (connectionString == null) { + throw new IllegalArgumentException( + "Alias specified does not exist in tnsnames.ora: " + alias + ); + } + return connectionString; + } +} \ No newline at end of file diff --git a/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerPasswordProvider.java b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerPasswordProvider.java new file mode 100644 index 00000000..ef1d9d7d --- /dev/null +++ b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerPasswordProvider.java @@ -0,0 +1,69 @@ +/* + ** Copyright (c) 2024 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.gcp.resource; + +import java.util.Map; + +import com.google.protobuf.ByteString; + +import oracle.jdbc.spi.PasswordProvider; + +/** + *

+ * A provider of passwords from the GCP Secret Manager service. + *

+ *

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

+ */ +public class GcpSecretManagerPasswordProvider extends GcpSecretManagerProvider implements PasswordProvider { + + public GcpSecretManagerPasswordProvider() { + super("secretmanager-password"); + } + + @Override + public char[] getPassword(Map parameterValues) { + ByteString secret = getSecret(parameterValues); + String password = secret.toStringUtf8(); + return password.toCharArray(); + } + +} diff --git a/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerProvider.java b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerProvider.java new file mode 100644 index 00000000..9c02401d --- /dev/null +++ b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerProvider.java @@ -0,0 +1,94 @@ +/* + ** Copyright (c) 2024 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.gcp.resource; + +import java.util.Map; + +import com.google.protobuf.ByteString; + +import oracle.jdbc.provider.gcp.secrets.GcpSecretManagerFactory; +import oracle.jdbc.provider.parameter.ParameterSet; +import oracle.jdbc.provider.resource.AbstractResourceProvider; +import oracle.jdbc.provider.resource.ResourceParameter; +import oracle.jdbc.provider.util.ResourceParameterUtils; + +/** + * Internal class to be inherited by other resource providers using secrets. + */ +class GcpSecretManagerProvider extends AbstractResourceProvider { + + private static final ResourceParameter[] PARAMETERS = { + new ResourceParameter("secretVersionName", GcpSecretManagerFactory.SECRET_VERSION_NAME) + }; + + protected GcpSecretManagerProvider(String valueType) { + super("gcp", valueType, PARAMETERS); + } + + public GcpSecretManagerProvider(String valueType, ResourceParameter[] additionalParameters) { + super("gcp", valueType, ResourceParameterUtils + .combineParameters(PARAMETERS, additionalParameters)); + } + + /** + *

+ * Retrieves a secret from GCP Secret Manager based on parameters provided + * in {@code parameterValues}. This method centralizes secret retrieval logic + *

+ *

+ * The method uses the {@code getResource} method to parse the + * {@code parameterValues} and request the secret from GCP Secret Manager + * via the {@link GcpSecretManagerFactory} instance. + * The secret is returned as a {@code ByteString}. + *

+ *

+ * This method is designed to be called from subclasses which implement an + * {@link oracle.jdbc.spi.OracleResourceProvider} SPI. + *

+ * + * @param parameterValues Text values of parameters. Not null. + * @return The identified secret. Not null. + */ + protected final ByteString getSecret( + Map parameterValues) { + + return getResource(GcpSecretManagerFactory.getInstance(), parameterValues) + .getData(); + } + +} diff --git a/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerSEPSProvider.java b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerSEPSProvider.java new file mode 100644 index 00000000..b2e8a2d4 --- /dev/null +++ b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerSEPSProvider.java @@ -0,0 +1,129 @@ +/* + ** Copyright (c) 2024 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.gcp.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.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 retrieving both the username and password from a Secure + * External Password Store (SEPS) wallet stored in Google Cloud Platform (GCP) + * Secret Manager. The wallet can be in either SSO or PKCS12 format. If a + * password is provided, the wallet is treated as PKCS12, otherwise, it + * is assumed to be in SSO format. + *

+ *

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

+ * + *

+ * The SEPS wallet is stored in GCP Secret Manager as a base64-encoded string, + * or it may be stored in binary format. This provider decodes the wallet if it + * is base64-encoded and retrieves the username and password required for + * database authentication. + *

+ */ +public class GcpSecretManagerSEPSProvider + extends GcpSecretManagerProvider + 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 GcpSecretManagerSEPSProvider() { + super("secretmanager-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 OracleWallet by fetching the wallet stored in GCP Secret Manager. + * The wallet can be stored either as a base64-encoded string or as an imported file. + * It is opened as either SSO or PKCS12, based on whether a password is + * provided. + * If no password is provided, the wallet is treated as an SSO wallet. A connection + * string index can also be specified to select the correct credentials from the wallet. + */ + private WalletUtils.Credentials getWalletCredentials( + Map parameterValues) { + + ParameterSet parameterSet = parseParameterValues(parameterValues); + + byte[] walletBytes = getSecret(parameterValues).toByteArray(); + + if (FileUtils.isBase64Encoded(walletBytes)) { + walletBytes = Base64.getDecoder().decode(walletBytes); + } + + 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-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerTCPSProvider.java b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerTCPSProvider.java new file mode 100644 index 00000000..cf65201d --- /dev/null +++ b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerTCPSProvider.java @@ -0,0 +1,130 @@ +/* + ** Copyright (c) 2024 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.gcp.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 GCP Secret Manager, + * where it is stored either as a base64-encoded string or directly in binary + * format (e.g., a wallet imported as a file). 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 GcpSecretManagerTCPSProvider + extends GcpSecretManagerProvider + 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 GcpSecretManagerTCPSProvider() { + super("secretmanager-tls", TCPS_PARAMETERS); + } + + /** + * Retrieves an SSLContext by loading a file from GCP Secret Manager and + * configuring it for secure TLS communication with Autonomous Database. + *

+ * The file is stored in GCP Secret Manager either as a base64-encoded string + * or in its raw binary format. + * 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 secret version 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); + + byte[] fileBytes = getSecret(parameterValues).toByteArray(); + + if (FileUtils.isBase64Encoded(fileBytes)) { + fileBytes = Base64.getDecoder().decode(fileBytes); + } + + 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-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerUsernameProvider.java b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerUsernameProvider.java new file mode 100644 index 00000000..01b08d24 --- /dev/null +++ b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/resource/GcpSecretManagerUsernameProvider.java @@ -0,0 +1,66 @@ +/* + ** Copyright (c) 2024 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.gcp.resource; + +import java.nio.charset.Charset; +import java.util.Map; + +import oracle.jdbc.spi.UsernameProvider; + +/** + *

+ * A provider of usernames from the GCP Secret Manager service. + *

+ *

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

+ */ +public class GcpSecretManagerUsernameProvider extends GcpSecretManagerProvider implements UsernameProvider { + + public GcpSecretManagerUsernameProvider() { + super("secretmanager-username"); + } + + @Override + public String getUsername(Map parameterValues) { + return getSecret(parameterValues).toStringUtf8(); + } + +} diff --git a/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/secrets/GcpSecretManagerFactory.java b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/secrets/GcpSecretManagerFactory.java new file mode 100644 index 00000000..b6d9274a --- /dev/null +++ b/ojdbc-provider-gcp/src/main/java/oracle/jdbc/provider/gcp/secrets/GcpSecretManagerFactory.java @@ -0,0 +1,116 @@ +/* + ** Copyright (c) 2024 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.gcp.secrets; + +import static oracle.jdbc.provider.parameter.Parameter.CommonAttribute.REQUIRED; + +import java.io.IOException; +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneId; + +import com.google.cloud.secretmanager.v1.AccessSecretVersionResponse; +import com.google.cloud.secretmanager.v1.Secret; +import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; +import com.google.cloud.secretmanager.v1.SecretName; +import com.google.cloud.secretmanager.v1.SecretPayload; +import com.google.cloud.secretmanager.v1.SecretVersionName; + +import oracle.jdbc.provider.cache.CachedResourceFactory; +import oracle.jdbc.provider.factory.Resource; +import oracle.jdbc.provider.factory.ResourceFactory; +import oracle.jdbc.provider.parameter.Parameter; +import oracle.jdbc.provider.parameter.ParameterSet; + +/** + *

+ * Factory for requesting secrets from the Vault service. Secrets are + * represented as {@link SecretPayload} objects. Oracle JDBC can use the content + * of a secret as a database password, or any other security sensitive value. + *

+ */ +public class GcpSecretManagerFactory implements ResourceFactory { + + /** The secret version name for the secret */ + public static final Parameter SECRET_VERSION_NAME = Parameter.create(REQUIRED); + + private static final ResourceFactory INSTANCE = CachedResourceFactory + .create(new GcpSecretManagerFactory()); + + private GcpSecretManagerFactory() { + } + + /** + * Returns a singleton of {@code GcpVaultSecretFactory}. + * + * @return a singleton of {@code GcpVaultSecretFactory} + */ + public static ResourceFactory getInstance() { + return INSTANCE; + } + + /** + * {@inheritDoc} + *

+ * Requests the content of a secret bundle from the Vault service. The + * {@code parameterSet} is required to include a {@link #SECRET_VERSION_NAME}. + *

+ */ + @Override + public Resource request(ParameterSet parameterSet) + throws IllegalStateException, IllegalArgumentException { + String paramerter = parameterSet.getRequired(SECRET_VERSION_NAME); + + try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) { + SecretVersionName secretVersionName = SecretVersionName.parse(paramerter); + SecretName secretName = SecretName.of(secretVersionName.getProject(), secretVersionName.getSecret()); + Secret secret = client.getSecret(secretName); + AccessSecretVersionResponse response = client.accessSecretVersion(secretVersionName); + if (secret.hasExpireTime()) { + OffsetDateTime expireTime = OffsetDateTime + .ofInstant(Instant.ofEpochMilli(secret.getExpireTime().getNanos() * 1000000), ZoneId.systemDefault()); + return Resource.createExpiringResource(response.getPayload(), expireTime, true); + } else { + return Resource.createPermanentResource(response.getPayload(), true); + } + } catch (IOException io) { + throw new IllegalStateException(io); + } + } + +} diff --git a/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.ConnectionStringProvider b/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.ConnectionStringProvider new file mode 100644 index 00000000..25b37cc9 --- /dev/null +++ b/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.ConnectionStringProvider @@ -0,0 +1 @@ +oracle.jdbc.provider.gcp.resource.GcpSecretManagerConnectionStringProvider diff --git a/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.OracleConfigurationProvider b/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.OracleConfigurationProvider new file mode 100644 index 00000000..e19b4cd4 --- /dev/null +++ b/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.OracleConfigurationProvider @@ -0,0 +1,2 @@ +oracle.jdbc.provider.gcp.configuration.GcpCloudStorageConfigurationProvider +oracle.jdbc.provider.gcp.configuration.GcpSecretManagerConfigurationProvider diff --git a/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.OracleConfigurationSecretProvider b/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.OracleConfigurationSecretProvider new file mode 100644 index 00000000..edcf482c --- /dev/null +++ b/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.OracleConfigurationSecretProvider @@ -0,0 +1 @@ +oracle.jdbc.provider.gcp.configuration.GcpJsonSecretManagerProvider \ No newline at end of file diff --git a/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.PasswordProvider b/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.PasswordProvider new file mode 100644 index 00000000..cf942ead --- /dev/null +++ b/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.PasswordProvider @@ -0,0 +1,2 @@ +oracle.jdbc.provider.gcp.resource.GcpSecretManagerPasswordProvider +oracle.jdbc.provider.gcp.resource.GcpSecretManagerSEPSProvider diff --git a/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.TlsConfigurationProvider b/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.TlsConfigurationProvider new file mode 100644 index 00000000..ac1f8ac6 --- /dev/null +++ b/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.TlsConfigurationProvider @@ -0,0 +1 @@ +oracle.jdbc.provider.gcp.resource.GcpSecretManagerTCPSProvider \ No newline at end of file diff --git a/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.UsernameProvider b/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.UsernameProvider new file mode 100644 index 00000000..572b7658 --- /dev/null +++ b/ojdbc-provider-gcp/src/main/resources/META-INF/services/oracle.jdbc.spi.UsernameProvider @@ -0,0 +1,2 @@ +oracle.jdbc.provider.gcp.resource.GcpSecretManagerUsernameProvider +oracle.jdbc.provider.gcp.resource.GcpSecretManagerSEPSProvider diff --git a/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/GcpTestProperty.java b/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/GcpTestProperty.java new file mode 100644 index 00000000..81f3a5f2 --- /dev/null +++ b/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/GcpTestProperty.java @@ -0,0 +1,83 @@ +/* + ** Copyright (c) 2024 Oracle and/or its affiliates. + ** + ** The Universal Permissive License (UPL), Version 1.0 + ** + ** Subject to the condition set forth below, permission is hereby granted to any + ** person obtaining a copy of this software, associated documentation and/or data + ** (collectively the "Software"), free of charge and under any and all copyright + ** rights in the Software, and any and all patent rights owned or freely + ** licensable by each licensor hereunder covering either (i) the unmodified + ** Software as contributed to or provided by such licensor, or (ii) the Larger + ** Works (as defined below), to deal in both + ** + ** (a) the Software, and + ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + ** one is included with the Software (each a "Larger Work" to which the Software + ** is contributed by such licensors), + ** + ** without restriction, including without limitation the rights to copy, create + ** derivative works of, display, perform, and distribute the Software and make, + ** use, sell, offer for sale, import, export, have made, and have sold the + ** Software and the Larger Work(s), and to sublicense the foregoing rights on + ** either these or other terms. + ** + ** This license is subject to the following condition: + ** The above copyright notice and either this complete permission notice or at + ** a minimum a reference to the UPL must be included in all copies or + ** substantial portions of the Software. + ** + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + ** SOFTWARE. + */ + +package oracle.provider.gcp; + +/** + * Names of properties that configure GCP tests. Descriptions and examples of + * each property can be found in the "example-test.properties" file within the + * root directory of the project. + */ +public enum GcpTestProperty { + + GCP_OBJECT_STORAGE_URL, + + SECRET_VERSION_NAME_CONFIG, + + GCP_SECRET_MANAGER_USERNAME_SECRET_VERSION, + + GCP_SECRET_MANAGER_PASSWORD_SECRET_VERSION, + + GCP_PKCS12_TLS_WALLET_SECRET_VERSION_NAME, + + GCP_PKCS12_TLS_WALLET_PASSWORD, + + GCP_SSO_TLS_WALLET_SECRET_VERSION_NAME, + + GCP_PEM_TLS_WALLET_SECRET_VERSION_NAME, + + GCP_PEM_TLS_WALLET_PASSWORD, + + GCP_CORRUPTED_TLS_WALLET_SECRET_VERSION_NAME, + + GCP_PKCS12_SEPS_SECRET_VERSION_NAME, + + GCP_PKCS12_SEPS_WALLET_PASSWORD, + + GCP_SEPS_CONNECTION_STRING_INDEX, + + GCP_SSO_SEPS_SECRET_VERSION_NAME, + + GCP_CORRUPTED_SEPS_WALLET_SECRET_VERSION_NAME, + + GCP_SECRET_MANAGER_TNS_NAMES_SECRET_VERSION, + + GCP_SECRET_MANAGER_TNS_ALIAS_SECRET_NAME, + + GCP_NON_BASE64_TNS_NAMES_SECRET_VERSION; +} diff --git a/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/configuration/GcpCloudStorageProviderTest.java b/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/configuration/GcpCloudStorageProviderTest.java new file mode 100644 index 00000000..83a39bc6 --- /dev/null +++ b/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/configuration/GcpCloudStorageProviderTest.java @@ -0,0 +1,70 @@ +/* + ** Copyright (c) 2024 Oracle and/or its affiliates. + ** + ** The Universal Permissive License (UPL), Version 1.0 + ** + ** Subject to the condition set forth below, permission is hereby granted to any + ** person obtaining a copy of this software, associated documentation and/or data + ** (collectively the "Software"), free of charge and under any and all copyright + ** rights in the Software, and any and all patent rights owned or freely + ** licensable by each licensor hereunder covering either (i) the unmodified + ** Software as contributed to or provided by such licensor, or (ii) the Larger + ** Works (as defined below), to deal in both + ** + ** (a) the Software, and + ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + ** one is included with the Software (each a "Larger Work" to which the Software + ** is contributed by such licensors), + ** + ** without restriction, including without limitation the rights to copy, create + ** derivative works of, display, perform, and distribute the Software and make, + ** use, sell, offer for sale, import, export, have made, and have sold the + ** Software and the Larger Work(s), and to sublicense the foregoing rights on + ** either these or other terms. + ** + ** This license is subject to the following condition: + ** The above copyright notice and either this complete permission notice or at + ** a minimum a reference to the UPL must be included in all copies or + ** substantial portions of the Software. + ** + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + ** SOFTWARE. + */ +package oracle.provider.gcp.configuration; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.sql.SQLException; +import java.util.Properties; + +import oracle.provider.gcp.GcpTestProperty; +import org.junit.jupiter.api.Test; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.spi.OracleConfigurationProvider; + +public class GcpCloudStorageProviderTest { + + + static { + OracleConfigurationProvider.allowedProviders.add("gcpstorage"); + } + + private static final OracleConfigurationProvider PROVIDER = OracleConfigurationProvider.find("gcpstorage"); + + @Test + public void testDefaultAuthentication() throws SQLException { + String location = TestProperties.getOrAbort(GcpTestProperty.GCP_OBJECT_STORAGE_URL); + Properties properties = PROVIDER + .getConnectionProperties(location); + assertTrue(properties.containsKey("URL"), "Contains property URL"); + assertTrue(properties.containsKey("user"), "Contains property user"); + assertTrue(properties.containsKey("password"), "Contains property password"); + } + +} diff --git a/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/configuration/GcpSecretManagerConfigurationProviderTest.java b/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/configuration/GcpSecretManagerConfigurationProviderTest.java new file mode 100644 index 00000000..3becb422 --- /dev/null +++ b/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/configuration/GcpSecretManagerConfigurationProviderTest.java @@ -0,0 +1,69 @@ +/* + ** Copyright (c) 2024 Oracle and/or its affiliates. + ** + ** The Universal Permissive License (UPL), Version 1.0 + ** + ** Subject to the condition set forth below, permission is hereby granted to any + ** person obtaining a copy of this software, associated documentation and/or data + ** (collectively the "Software"), free of charge and under any and all copyright + ** rights in the Software, and any and all patent rights owned or freely + ** licensable by each licensor hereunder covering either (i) the unmodified + ** Software as contributed to or provided by such licensor, or (ii) the Larger + ** Works (as defined below), to deal in both + ** + ** (a) the Software, and + ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + ** one is included with the Software (each a "Larger Work" to which the Software + ** is contributed by such licensors), + ** + ** without restriction, including without limitation the rights to copy, create + ** derivative works of, display, perform, and distribute the Software and make, + ** use, sell, offer for sale, import, export, have made, and have sold the + ** Software and the Larger Work(s), and to sublicense the foregoing rights on + ** either these or other terms. + ** + ** This license is subject to the following condition: + ** The above copyright notice and either this complete permission notice or at + ** a minimum a reference to the UPL must be included in all copies or + ** substantial portions of the Software. + ** + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + ** SOFTWARE. + */ +package oracle.provider.gcp.configuration; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.sql.SQLException; +import java.util.Properties; + +import oracle.provider.gcp.GcpTestProperty; +import org.junit.jupiter.api.Test; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.spi.OracleConfigurationProvider; + +public class GcpSecretManagerConfigurationProviderTest { + + static { + OracleConfigurationProvider.allowedProviders.add("gcpsecretmanager"); + } + + private static final OracleConfigurationProvider PROVIDER = OracleConfigurationProvider.find("gcpsecretmanager"); + + @Test + public void testGetProperties() throws SQLException { + String secretVersionName = + TestProperties.getOrAbort(GcpTestProperty.SECRET_VERSION_NAME_CONFIG); + Properties properties = PROVIDER + .getConnectionProperties(secretVersionName); + assertTrue(properties.containsKey("URL"), "Contains property URL"); + assertTrue(properties.containsKey("user"), "Contains property user"); + assertTrue(properties.containsKey("password"), "Contains property password"); + } +} diff --git a/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/resource/GcpSecretManagerConnectionStringProviderTest.java b/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/resource/GcpSecretManagerConnectionStringProviderTest.java new file mode 100644 index 00000000..f522eb65 --- /dev/null +++ b/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/resource/GcpSecretManagerConnectionStringProviderTest.java @@ -0,0 +1,160 @@ +/* + ** Copyright (c) 2024 Oracle and/or its affiliates. + ** + ** The Universal Permissive License (UPL), Version 1.0 + ** + ** Subject to the condition set forth below, permission is hereby granted to any + ** person obtaining a copy of this software, associated documentation and/or data + ** (collectively the "Software"), free of charge and under any and all copyright + ** rights in the Software, and any and all patent rights owned or freely + ** licensable by each licensor hereunder covering either (i) the unmodified + ** Software as contributed to or provided by such licensor, or (ii) the Larger + ** Works (as defined below), to deal in both + ** + ** (a) the Software, and + ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + ** one is included with the Software (each a "Larger Work" to which the Software + ** is contributed by such licensors), + ** + ** without restriction, including without limitation the rights to copy, create + ** derivative works of, display, perform, and distribute the Software and make, + ** use, sell, offer for sale, import, export, have made, and have sold the + ** Software and the Larger Work(s), and to sublicense the foregoing rights on + ** either these or other terms. + ** + ** This license is subject to the following condition: + ** The above copyright notice and either this complete permission notice or at + ** a minimum a reference to the UPL must be included in all copies or + ** substantial portions of the Software. + ** + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + ** SOFTWARE. + */ + +package oracle.provider.gcp.resource; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.spi.ConnectionStringProvider; +import oracle.jdbc.spi.OracleResourceProvider; +import oracle.jdbc.spi.OracleResourceProvider.Parameter; +import oracle.provider.gcp.GcpTestProperty; +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 GcpSecretManagerConnectionStringProviderTest { + + private static final ConnectionStringProvider PROVIDER = + findProvider( + ConnectionStringProvider.class, + "ojdbc-provider-gcp-secretmanager-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); + + OracleResourceProvider.Parameter vaultUrlParameter = + parameters.stream() + .filter(parameter -> "secretVersionName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(vaultUrlParameter.isSensitive()); + assertTrue(vaultUrlParameter.isRequired()); + assertNull(vaultUrlParameter.defaultValue()); + + Parameter aliasParameter = + parameters.stream() + .filter(parameter -> "tnsAlias".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(aliasParameter.isSensitive()); + assertTrue(aliasParameter.isRequired()); + assertNull(aliasParameter.defaultValue()); + } + + @Test + public void testValidAlias() { + Map testParameters = new HashMap<>(); + testParameters.put("secretVersionName", + TestProperties.getOrAbort( + GcpTestProperty + .GCP_SECRET_MANAGER_TNS_NAMES_SECRET_VERSION) + ); + + testParameters.put("tnsAlias", + TestProperties.getOrAbort(GcpTestProperty.GCP_SECRET_MANAGER_TNS_ALIAS_SECRET_NAME)); + + Map parameterValues = + createParameterValues(PROVIDER, testParameters); + + String connectionString = PROVIDER.getConnectionString(parameterValues); + assertNotNull(connectionString); + } + + @Test + public void testInvalidOrNonExistentAlias() { + Map testParameters = new HashMap<>(); + testParameters.put("secretVersionName", + TestProperties.getOrAbort( + GcpTestProperty + .GCP_SECRET_MANAGER_TNS_NAMES_SECRET_VERSION) + ); + + testParameters.put("tnsAlias", "INVALID_ALIAS"); + + Map parameterValues = + createParameterValues(PROVIDER, testParameters); + + assertThrows(IllegalArgumentException.class, + () -> PROVIDER.getConnectionString(parameterValues), + "Expected IllegalArgumentException for invalid alias" + ); + } + + @Test + public void testMissingAliasParameter() { + Map testParameters = new HashMap<>(); + testParameters.put("secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_SECRET_MANAGER_TNS_NAMES_SECRET_VERSION)); + + Map parameterValues = + createParameterValues(PROVIDER, testParameters); + + assertThrows(IllegalArgumentException.class, + () -> PROVIDER.getConnectionString(parameterValues), + "Expected IllegalArgumentException when tnsAlias parameter is missing" + ); + } + + @Test + public void testNonBase64EncodedTnsnamesContent() { + Map testParameters = new HashMap<>(); + testParameters.put("secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_NON_BASE64_TNS_NAMES_SECRET_VERSION)); + + testParameters.put("tnsAlias", + TestProperties.getOrAbort(GcpTestProperty.GCP_SECRET_MANAGER_TNS_ALIAS_SECRET_NAME)); + + Map parameterValues = createParameterValues(PROVIDER, testParameters); + + String connectionString = PROVIDER.getConnectionString(parameterValues); + assertNotNull(connectionString); + } + +} diff --git a/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/resource/GcpSecretManagerPasswordProviderTest.java b/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/resource/GcpSecretManagerPasswordProviderTest.java new file mode 100644 index 00000000..ff747016 --- /dev/null +++ b/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/resource/GcpSecretManagerPasswordProviderTest.java @@ -0,0 +1,97 @@ +/* + ** Copyright (c) 2024 Oracle and/or its affiliates. + ** + ** The Universal Permissive License (UPL), Version 1.0 + ** + ** Subject to the condition set forth below, permission is hereby granted to any + ** person obtaining a copy of this software, associated documentation and/or data + ** (collectively the "Software"), free of charge and under any and all copyright + ** rights in the Software, and any and all patent rights owned or freely + ** licensable by each licensor hereunder covering either (i) the unmodified + ** Software as contributed to or provided by such licensor, or (ii) the Larger + ** Works (as defined below), to deal in both + ** + ** (a) the Software, and + ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + ** one is included with the Software (each a "Larger Work" to which the Software + ** is contributed by such licensors), + ** + ** without restriction, including without limitation the rights to copy, create + ** derivative works of, display, perform, and distribute the Software and make, + ** use, sell, offer for sale, import, export, have made, and have sold the + ** Software and the Larger Work(s), and to sublicense the foregoing rights on + ** either these or other terms. + ** + ** This license is subject to the following condition: + ** The above copyright notice and either this complete permission notice or at + ** a minimum a reference to the UPL must be included in all copies or + ** substantial portions of the Software. + ** + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + ** SOFTWARE. + */ +package oracle.provider.gcp.resource; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import oracle.provider.gcp.GcpTestProperty; +import org.junit.jupiter.api.Test; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.spi.OracleResourceProvider.Parameter; +import oracle.jdbc.spi.PasswordProvider; +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.createParameterValues; +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.findProvider; + +public class GcpSecretManagerPasswordProviderTest { + private static final PasswordProvider PROVIDER = findProvider( + PasswordProvider.class, "ojdbc-provider-gcp-secretmanager-password"); + + /** + * Verifies that {@link PasswordProvider#getParameters()} includes parameters + * to configure a vault URL and secret name. + */ + @Test + public void testGetParameters() { + Collection parameters = PROVIDER.getParameters(); + assertNotNull(parameters); + + Parameter secretVersionNameParameter = parameters.stream() + .filter(parameter -> "secretVersionName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(secretVersionNameParameter.isSensitive()); + assertTrue(secretVersionNameParameter.isRequired()); + assertNull(secretVersionNameParameter.defaultValue()); + + } + + /** + * Verifies that {@link oracle.jdbc.spi.PasswordProvider#getPassword(Map)} + * returns the username identified by a vault URL and secret name. + */ + @Test + public void testGetPassword() { + + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", TestProperties.getOrAbort(GcpTestProperty.GCP_SECRET_MANAGER_PASSWORD_SECRET_VERSION)); + + Map parameterValues = createParameterValues(PROVIDER, + testParameters); + + assertNotNull(PROVIDER.getPassword(parameterValues)); + } +} diff --git a/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/resource/GcpSecretManagerSEPSProviderTest.java b/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/resource/GcpSecretManagerSEPSProviderTest.java new file mode 100644 index 00000000..9599aabe --- /dev/null +++ b/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/resource/GcpSecretManagerSEPSProviderTest.java @@ -0,0 +1,278 @@ +/* + ** Copyright (c) 2024 Oracle and/or its affiliates. + ** + ** The Universal Permissive License (UPL), Version 1.0 + ** + ** Subject to the condition set forth below, permission is hereby granted to any + ** person obtaining a copy of this software, associated documentation and/or data + ** (collectively the "Software"), free of charge and under any and all copyright + ** rights in the Software, and any and all patent rights owned or freely + ** licensable by each licensor hereunder covering either (i) the unmodified + ** Software as contributed to or provided by such licensor, or (ii) the Larger + ** Works (as defined below), to deal in both + ** + ** (a) the Software, and + ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + ** one is included with the Software (each a "Larger Work" to which the Software + ** is contributed by such licensors), + ** + ** without restriction, including without limitation the rights to copy, create + ** derivative works of, display, perform, and distribute the Software and make, + ** use, sell, offer for sale, import, export, have made, and have sold the + ** Software and the Larger Work(s), and to sublicense the foregoing rights on + ** either these or other terms. + ** + ** This license is subject to the following condition: + ** The above copyright notice and either this complete permission notice or at + ** a minimum a reference to the UPL must be included in all copies or + ** substantial portions of the Software. + ** + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + ** SOFTWARE. + */ + +package oracle.provider.gcp.resource; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.provider.gcp.resource.GcpSecretManagerSEPSProvider; +import oracle.jdbc.spi.OracleResourceProvider; +import oracle.jdbc.spi.PasswordProvider; +import oracle.jdbc.spi.UsernameProvider; +import oracle.provider.gcp.GcpTestProperty; +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 GcpSecretManagerSEPSProviderTest { + private static final UsernameProvider USERNAME_PROVIDER = + findProvider( + UsernameProvider.class, "ojdbc-provider-gcp-secretmanager-seps"); + + private static final PasswordProvider PASSWORD_PROVIDER = + findProvider( + PasswordProvider.class, "ojdbc-provider-gcp-secretmanager-seps"); + + + /** + * Verifies that + * {@link GcpSecretManagerSEPSProvider#getParameters()} includes parameters + * to configure a vault URL, secret name, wallet password, and connection + * string index. + */ + @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); + + OracleResourceProvider.Parameter vaultUrlParameter = + usernameParameters.stream() + .filter(parameter -> "secretVersionName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(vaultUrlParameter.isSensitive()); + assertTrue(vaultUrlParameter.isRequired()); + assertNull(vaultUrlParameter.defaultValue()); + + OracleResourceProvider.Parameter walletPasswordParameter = + usernameParameters.stream() + .filter(parameter -> "walletPassword".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertTrue(walletPasswordParameter.isSensitive()); + assertFalse(walletPasswordParameter.isRequired()); + assertNull(walletPasswordParameter.defaultValue()); + + OracleResourceProvider.Parameter connStringParameter = + usernameParameters.stream() + .filter(parameter -> "connectionStringIndex".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(connStringParameter.isSensitive()); + assertFalse(connStringParameter.isRequired()); + assertNull(connStringParameter.defaultValue()); + } + + @Test + public void testPKCS12PasswordWithConnectionStringIndex() { + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_PKCS12_SEPS_SECRET_VERSION_NAME)); + testParameters.put( + "walletPassword", + TestProperties.getOrAbort(GcpTestProperty.GCP_PKCS12_SEPS_WALLET_PASSWORD)); + testParameters.put( + "connectionStringIndex", + TestProperties.getOrAbort(GcpTestProperty.GCP_SEPS_CONNECTION_STRING_INDEX)); + + Map parameterValues = createParameterValues(PASSWORD_PROVIDER, testParameters); + char[] password = PASSWORD_PROVIDER.getPassword(parameterValues); + assertNotNull(password); + } + + @Test + public void testPKCS12PasswordWithoutConnectionStringIndex() { + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_PKCS12_SEPS_SECRET_VERSION_NAME)); + testParameters.put( + "walletPassword", + TestProperties.getOrAbort(GcpTestProperty.GCP_PKCS12_SEPS_WALLET_PASSWORD)); + + Map parameterValues = createParameterValues(PASSWORD_PROVIDER, testParameters); + char[] password = PASSWORD_PROVIDER.getPassword(parameterValues); + assertNotNull(password); + } + + @Test + public void testSSOPasswordWithConnectionStringIndex() { + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_SSO_SEPS_SECRET_VERSION_NAME)); + testParameters.put( + "connectionStringIndex", + TestProperties.getOrAbort(GcpTestProperty.GCP_SEPS_CONNECTION_STRING_INDEX)); + + Map parameterValues = + createParameterValues(PASSWORD_PROVIDER, testParameters); + + char[] password = PASSWORD_PROVIDER.getPassword(parameterValues); + assertNotNull(password); + } + + @Test + public void testSSOPasswordWithoutConnectionStringIndex() { + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_SSO_SEPS_SECRET_VERSION_NAME)); + + Map parameterValues = + createParameterValues(PASSWORD_PROVIDER, testParameters); + + char[] password = PASSWORD_PROVIDER.getPassword(parameterValues); + assertNotNull(password); + } + + @Test + public void testPKCS12UsernameWithConnectionStringIndex() { + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_PKCS12_SEPS_SECRET_VERSION_NAME)); + testParameters.put( + "walletPassword", + TestProperties.getOrAbort(GcpTestProperty.GCP_PKCS12_SEPS_WALLET_PASSWORD)); + testParameters.put( + "connectionStringIndex", + TestProperties.getOrAbort(GcpTestProperty.GCP_SEPS_CONNECTION_STRING_INDEX)); + + Map parameterValues = + createParameterValues(USERNAME_PROVIDER, testParameters); + + String username = USERNAME_PROVIDER.getUsername(parameterValues); + assertNotNull(username); + } + + @Test + public void testPKCS12UsernameWithoutConnectionStringIndex() { + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_PKCS12_SEPS_SECRET_VERSION_NAME)); + testParameters.put( + "walletPassword", + TestProperties.getOrAbort(GcpTestProperty.GCP_PKCS12_SEPS_WALLET_PASSWORD)); + + Map parameterValues = + createParameterValues(USERNAME_PROVIDER, testParameters); + + String username = USERNAME_PROVIDER.getUsername(parameterValues); + assertNotNull(username); + } + + @Test + public void testSSOUsernameWithConnectionStringIndex() { + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_SSO_SEPS_SECRET_VERSION_NAME)); + testParameters.put( + "connectionStringIndex", + TestProperties.getOrAbort(GcpTestProperty.GCP_SEPS_CONNECTION_STRING_INDEX)); + + Map parameterValues = + createParameterValues(USERNAME_PROVIDER, testParameters); + + String username = USERNAME_PROVIDER.getUsername(parameterValues); + assertNotNull(username); + } + + @Test + public void testSSOUsernameWithoutConnectionStringIndex() { + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_SSO_SEPS_SECRET_VERSION_NAME)); + + Map parameterValues = + createParameterValues(USERNAME_PROVIDER, testParameters); + + String username = USERNAME_PROVIDER.getUsername(parameterValues); + assertNotNull(username); + } + + @Test + public void testPKCS12WalletMissingPassword() { + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_PKCS12_SEPS_SECRET_VERSION_NAME)); + + Map parameterValues + = createParameterValues(PASSWORD_PROVIDER, testParameters); + + assertThrows(IllegalStateException.class, () -> { + PASSWORD_PROVIDER.getPassword(parameterValues); + }); + } + + @Test + public void testCorruptedBase64SEPSWallet() { + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_CORRUPTED_SEPS_WALLET_SECRET_VERSION_NAME)); + + Map parameterValues = + createParameterValues(PASSWORD_PROVIDER, testParameters); + + assertThrows(IllegalStateException.class, () -> { + PASSWORD_PROVIDER.getPassword(parameterValues); + }); + } + +} diff --git a/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/resource/GcpSecretManagerTCPSProviderTest.java b/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/resource/GcpSecretManagerTCPSProviderTest.java new file mode 100644 index 00000000..a1fe587d --- /dev/null +++ b/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/resource/GcpSecretManagerTCPSProviderTest.java @@ -0,0 +1,193 @@ +/* + ** Copyright (c) 2024 Oracle and/or its affiliates. + ** + ** The Universal Permissive License (UPL), Version 1.0 + ** + ** Subject to the condition set forth below, permission is hereby granted to any + ** person obtaining a copy of this software, associated documentation and/or data + ** (collectively the "Software"), free of charge and under any and all copyright + ** rights in the Software, and any and all patent rights owned or freely + ** licensable by each licensor hereunder covering either (i) the unmodified + ** Software as contributed to or provided by such licensor, or (ii) the Larger + ** Works (as defined below), to deal in both + ** + ** (a) the Software, and + ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + ** one is included with the Software (each a "Larger Work" to which the Software + ** is contributed by such licensors), + ** + ** without restriction, including without limitation the rights to copy, create + ** derivative works of, display, perform, and distribute the Software and make, + ** use, sell, offer for sale, import, export, have made, and have sold the + ** Software and the Larger Work(s), and to sublicense the foregoing rights on + ** either these or other terms. + ** + ** This license is subject to the following condition: + ** The above copyright notice and either this complete permission notice or at + ** a minimum a reference to the UPL must be included in all copies or + ** substantial portions of the Software. + ** + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + ** SOFTWARE. + */ +package oracle.provider.gcp.resource; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.provider.gcp.resource.GcpSecretManagerTCPSProvider; +import oracle.jdbc.spi.OracleResourceProvider; +import oracle.jdbc.spi.TlsConfigurationProvider; +import oracle.provider.gcp.GcpTestProperty; +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 GcpSecretManagerTCPSProviderTest { + private static final TlsConfigurationProvider PROVIDER = findProvider( + TlsConfigurationProvider.class, "ojdbc-provider-gcp-secretmanager-tls"); + + /** + * Verifies that + * {@link GcpSecretManagerTCPSProvider#getParameters()} + * includes parameters to configure the secret version name, wallet + * password, and type. + */ + @Test + public void testGetParameters() { + Collection parameters = PROVIDER.getParameters(); + assertNotNull(parameters); + + OracleResourceProvider.Parameter secretVersionNameParameter = + parameters.stream() + .filter(parameter -> "secretVersionName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(secretVersionNameParameter.isSensitive()); + assertTrue(secretVersionNameParameter.isRequired()); + assertNull(secretVersionNameParameter.defaultValue()); + + OracleResourceProvider.Parameter typeParameter = + parameters.stream() + .filter(parameter -> "type".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(typeParameter.isSensitive()); + assertTrue(typeParameter.isRequired()); + assertNull(typeParameter.defaultValue()); + + OracleResourceProvider.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 testPKCS12TcpsWallet() { + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_PKCS12_TLS_WALLET_SECRET_VERSION_NAME)); + testParameters.put("type", "PKCS12"); + testParameters.put("walletPassword", + TestProperties.getOrAbort(GcpTestProperty.GCP_PKCS12_TLS_WALLET_PASSWORD)); + + Map parameterValues = + createParameterValues(PROVIDER, testParameters); + + SSLContext sslContext = PROVIDER.getSSLContext(parameterValues); + assertNotNull(sslContext); + } + + @Test + public void testSSOTcpsWallet() { + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_SSO_TLS_WALLET_SECRET_VERSION_NAME)); + testParameters.put("type", "SSO"); + + Map parameterValues = + createParameterValues(PROVIDER, testParameters); + + SSLContext sslContext = PROVIDER.getSSLContext(parameterValues); + assertNotNull(sslContext); + } + + @Test + public void testPEMTcpsWallet() { + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_PEM_TLS_WALLET_SECRET_VERSION_NAME)); + testParameters.put("type", "PEM"); + testParameters.put("walletPassword", + TestProperties.getOrAbort(GcpTestProperty.GCP_PEM_TLS_WALLET_PASSWORD)); + + Map parameterValues = + createParameterValues(PROVIDER, testParameters); + + SSLContext sslContext = PROVIDER.getSSLContext(parameterValues); + assertNotNull(sslContext); + } + + @Test + public void testPKCS12MissingPassword() { + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_PKCS12_TLS_WALLET_SECRET_VERSION_NAME)); + testParameters.put("type", "PKCS12"); + + Map parameterValues = createParameterValues(PROVIDER, testParameters); + + assertThrows(IllegalStateException.class, () -> { + PROVIDER.getSSLContext(parameterValues); + }); + } + + @Test + public void testPemMissingPassword() { + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_PEM_TLS_WALLET_SECRET_VERSION_NAME)); + testParameters.put("type", "PEM"); + + Map parameterValues = createParameterValues(PROVIDER, testParameters); + + assertThrows(IllegalStateException.class, () -> { + PROVIDER.getSSLContext(parameterValues); + }); + } + + @Test + public void testCorruptedBase64TCPSWallet() { + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", + TestProperties.getOrAbort(GcpTestProperty.GCP_CORRUPTED_TLS_WALLET_SECRET_VERSION_NAME)); + testParameters.put("type", "SSO"); + + Map parameterValues = createParameterValues(PROVIDER, testParameters); + + assertThrows(IllegalStateException.class, () -> { + PROVIDER.getSSLContext(parameterValues); + }); + } +} + diff --git a/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/resource/GcpSecretManagerUsernameProviderTest.java b/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/resource/GcpSecretManagerUsernameProviderTest.java new file mode 100644 index 00000000..2a8f61a8 --- /dev/null +++ b/ojdbc-provider-gcp/src/test/java/oracle/provider/gcp/resource/GcpSecretManagerUsernameProviderTest.java @@ -0,0 +1,98 @@ +/* + ** Copyright (c) 2024 Oracle and/or its affiliates. + ** + ** The Universal Permissive License (UPL), Version 1.0 + ** + ** Subject to the condition set forth below, permission is hereby granted to any + ** person obtaining a copy of this software, associated documentation and/or data + ** (collectively the "Software"), free of charge and under any and all copyright + ** rights in the Software, and any and all patent rights owned or freely + ** licensable by each licensor hereunder covering either (i) the unmodified + ** Software as contributed to or provided by such licensor, or (ii) the Larger + ** Works (as defined below), to deal in both + ** + ** (a) the Software, and + ** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + ** one is included with the Software (each a "Larger Work" to which the Software + ** is contributed by such licensors), + ** + ** without restriction, including without limitation the rights to copy, create + ** derivative works of, display, perform, and distribute the Software and make, + ** use, sell, offer for sale, import, export, have made, and have sold the + ** Software and the Larger Work(s), and to sublicense the foregoing rights on + ** either these or other terms. + ** + ** This license is subject to the following condition: + ** The above copyright notice and either this complete permission notice or at + ** a minimum a reference to the UPL must be included in all copies or + ** substantial portions of the Software. + ** + ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + ** SOFTWARE. + */ +package oracle.provider.gcp.resource; + +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.createParameterValues; +import static oracle.jdbc.provider.resource.ResourceProviderTestUtil.findProvider; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import oracle.provider.gcp.GcpTestProperty; +import org.junit.jupiter.api.Test; + +import oracle.jdbc.provider.TestProperties; +import oracle.jdbc.spi.OracleResourceProvider.Parameter; +import oracle.jdbc.spi.UsernameProvider; + +public class GcpSecretManagerUsernameProviderTest { + private static final UsernameProvider PROVIDER = findProvider( + UsernameProvider.class, "ojdbc-provider-gcp-secretmanager-username"); + + /** + * Verifies that {@link UsernameProvider#getParameters()} includes parameters + * to configure a vault URL and secret name. + */ + @Test + public void testGetParameters() { + Collection parameters = PROVIDER.getParameters(); + assertNotNull(parameters); + + Parameter secretVersionNameParameter = parameters.stream() + .filter(parameter -> "secretVersionName".equals(parameter.name())) + .findFirst() + .orElseThrow(AssertionError::new); + assertFalse(secretVersionNameParameter.isSensitive()); + assertTrue(secretVersionNameParameter.isRequired()); + assertNull(secretVersionNameParameter.defaultValue()); + + } + + /** + * Verifies that {@link oracle.jdbc.spi.PasswordProvider#getPassword(Map)} + * returns the username identified by a vault URL and secret name. + */ + @Test + public void testGetUsername() { + + Map testParameters = new HashMap<>(); + testParameters.put( + "secretVersionName", TestProperties.getOrAbort(GcpTestProperty.GCP_SECRET_MANAGER_USERNAME_SECRET_VERSION)); + + Map parameterValues = createParameterValues(PROVIDER, + testParameters); + + String username = PROVIDER.getUsername(parameterValues); + assertNotNull(username); + } +} diff --git a/ojdbc-provider-samples/example-configuration.properties b/ojdbc-provider-samples/example-configuration.properties index ceae20c2..44923df0 100644 --- a/ojdbc-provider-samples/example-configuration.properties +++ b/ojdbc-provider-samples/example-configuration.properties @@ -109,9 +109,9 @@ client_certificate_password=$3cr3t azure_redirect_url=http://localhost:7071 # Google Cloud Platform -gcp_secret_version_name=projects/138028249883/secrets/test-secret/versions/2 -gcp_secret_version_name_config=projects/138028249883/secrets/config-secret/versions/4 -gcp_cloud_storage_properties=project=onyx-eye-426013-i5;bucket=fm-test-bucket-123564;object=testObjectStorage.json +gcp_secret_version_name=projects/xxxxx/secrets/xxxxx/versions/X +gcp_secret_version_name_config=projects/xxxxx/secrets/xxxxx/versions/X +gcp_cloud_storage_properties=project=xxxxx;bucket=xxxxx;object=xxxxx # Jackson OSON samples properties jackson_oson_url=jdbc:oracle:thin:@... diff --git a/ojdbc-provider-samples/pom.xml b/ojdbc-provider-samples/pom.xml index d8bd27db..63ddfcac 100644 --- a/ojdbc-provider-samples/pom.xml +++ b/ojdbc-provider-samples/pom.xml @@ -30,6 +30,11 @@ ojdbc-provider-oci ${project.parent.version} + + com.oracle.database.jdbc + ojdbc-provider-gcp + ${project.parent.version} + com.oracle.database.jdbc ojdbc-provider-jackson-oson diff --git a/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/configuration/CloudStorageExample.java b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/configuration/CloudStorageExample.java new file mode 100644 index 00000000..964f0944 --- /dev/null +++ b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/configuration/CloudStorageExample.java @@ -0,0 +1,99 @@ +/* + ** Copyright (c) 2024 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.gcp.configuration; + +import oracle.jdbc.datasource.impl.OracleDataSource; +import oracle.jdbc.provider.Configuration; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * A standalone example that configures Oracle JDBC to be provided with the + * connection properties retrieved from GCP Cloud Storage. + */ +public class CloudStorageExample { + /** + * An GCP Cloud Storage properties configured as a JVM system property, + * environment variable, or configuration.properties file entry named + * "gcp_cloud_storage_properties". + */ + private static final String OBJECT_PROPERTIES = Configuration + .getRequired("gcp_cloud_storage_properties"); + + /** + *

+ * Connects to a database using connection properties retrieved from GCP + * Cloud Storage. + *

+ *

+ * Providers use Google Cloud APIs which support Application Default + * Credentials; the libraries look for credentials in a set of defined + * locations and use those credentials to authenticate requests to the API. + *

+ * + * @see + * Application Default Credentials + * + * @param args the command line arguments + * @throws SQLException if an error occurs during the database calls + */ + public static void main(String[] args) throws SQLException { + String url = "jdbc:oracle:thin:@config-gcpstorage://" + OBJECT_PROPERTIES; + + // Standard JDBC code + OracleDataSource ds = new OracleDataSource(); + ds.setURL(url); + + System.out.println("Connection URL: " + url); + + try (Connection cn = ds.getConnection()) { + String connectionString = cn.getMetaData().getURL(); + System.out.println("Connected to: " + connectionString); + + Statement st = cn.createStatement(); + ResultSet rs = st.executeQuery("SELECT 'Hello, db' FROM sys.dual"); + if (rs.next()) + System.out.println(rs.getString(1)); + } + } + +} diff --git a/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/configuration/SecretManagerExample.java b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/configuration/SecretManagerExample.java new file mode 100644 index 00000000..93334e6b --- /dev/null +++ b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/configuration/SecretManagerExample.java @@ -0,0 +1,110 @@ +/* + ** Copyright (c) 2024 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.gcp.configuration; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import oracle.jdbc.datasource.impl.OracleDataSource; +import oracle.jdbc.provider.Configuration; + +/** + * A standalone example that configures Oracle JDBC to be provided with the + * connection properties retrieved from GCP Secret Manager. + */ +public class SecretManagerExample { + + /** + * An GCP SecretManager resource name configured as a JVM system property, + * environment variable, or configuration.properties file entry named + * "gcp_secret_version_name_config". + */ + private static final String RESOURCE_NAME = Configuration + .getRequired("gcp_secret_version_name_config"); + + /** + *

+ * Simple example to retrieve connection properties from GCP Secret Manager. + *

+ *

+ * To run this example, the payload needs to be stored in GCP Secret Manager. + * The payload examples can be found in + * {@link oracle.jdbc.spi.OracleConfigurationProvider}. + *

+ * Users need to indicate the resource name of the Secret with the following + * syntax: + * + *
+   * jdbc:oracle:thin:@config-gcpsecretmanager:{resource-name}
+   * 
+ * + *

+ * Providers use Google Cloud APIs which support Application Default + * Credentials; the libraries look for credentials in a set of defined + * locations and use those credentials to authenticate requests to the API. + *

+ * + * @see + * Application Default Credentials + * + * @param args the command line arguments + * @throws SQLException if an error occurs during the database calls + **/ + public static void main(String[] args) throws SQLException { + String url = "jdbc:oracle:thin:@config-gcpsecretmanager://" + RESOURCE_NAME; + // Sample default URL if non present + if (args.length > 0) { + url = args[0]; + } + + // No changes required, configuration provider is loaded at runtime + OracleDataSource ds = new OracleDataSource(); + ds.setURL(url); + + // Standard JDBC code + try (Connection cn = ds.getConnection()) { + Statement st = cn.createStatement(); + ResultSet rs = st.executeQuery("SELECT 'Hello, db' FROM sys.dual"); + if (rs.next()) + System.out.println(rs.getString(1)); + } + } +} diff --git a/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/configuration/SimpleCloudStorageExample.java b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/configuration/SimpleCloudStorageExample.java new file mode 100644 index 00000000..af2b2731 --- /dev/null +++ b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/configuration/SimpleCloudStorageExample.java @@ -0,0 +1,100 @@ +/* + ** Copyright (c) 2024 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.gcp.configuration; + +import oracle.jdbc.datasource.impl.OracleDataSource; +import oracle.jdbc.provider.Configuration; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * A standalone example that configures Oracle JDBC to be provided with the + * connection properties retrieved from OCI Cloud Storage. + */ +public class SimpleCloudStorageExample { + + /** + * An GCP Storage object properties as a JVM system property, + * environment variable, or configuration.properties file entry named + * "gcp_cloud_storage_properties". + */ + private static final String STORAGE_OBJECT = Configuration + .getRequired("gcp_cloud_storage_properties"); + + /** + *

+ * Connects to a database using connection properties retrieved from GCP + * Object Storage. + *

+ *

+ * Providers use Google Cloud APIs which support Application Default + * Credentials; the libraries look for credentials in a set of defined + * locations and use those credentials to authenticate requests to the API. + *

+ * + * @see + * Application Default Credentials + * + * @param args the command line arguments + * @throws SQLException if an error occurs during the database calls + */ + public static void main(String[] args) throws SQLException { + String url = "jdbc:oracle:thin:@config-gcpstorage://" + STORAGE_OBJECT; + + // Standard JDBC code + OracleDataSource ds = new OracleDataSource(); + ds.setURL(url); + + System.out.println("Connection URL: " + url); + + try (Connection cn = ds.getConnection()) { + String connectionString = cn.getMetaData().getURL(); + System.out.println("Connected to: " + connectionString); + + Statement st = cn.createStatement(); + ResultSet rs = st.executeQuery("SELECT 'Hello, db' FROM sys.dual"); + if (rs.next()) + System.out.println(rs.getString(1)); + } + } + +} diff --git a/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/configuration/SimpleSecretManagerExample.java b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/configuration/SimpleSecretManagerExample.java new file mode 100644 index 00000000..7e036c0a --- /dev/null +++ b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/configuration/SimpleSecretManagerExample.java @@ -0,0 +1,110 @@ +/* + ** Copyright (c) 2024 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.gcp.configuration; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import oracle.jdbc.datasource.impl.OracleDataSource; +import oracle.jdbc.provider.Configuration; + +/** + * A standalone example that configures Oracle JDBC to be provided with the + * connection properties retrieved from GCP Secret Manager. + */ +public class SimpleSecretManagerExample { + + + /** + * An GCP SecretManager resource name configured as a JVM system property, + * environment variable, or configuration.properties file entry named + * "gcp_secret_version_name_config". + */ + private static final String SECRET_VERSION_NAME = Configuration + .getRequired("gcp_secret_version_name_config"); + + /** + *

+ * Simple example to retrieve connection properties from GCP Secret Manager. + *

+ *

+ * To run this example, the payload needs to be stored in GCP Secret Manager. + * The payload examples can be found in + * {@link oracle.jdbc.spi.OracleConfigurationProvider}. + *

+ * Users need to indicate the resource name of the Secret with the following + * syntax: + * + *
+   * jdbc:oracle:thin:@config-gcpsecretmanager:{resource-name}
+   * 
+ *

+ * Providers use Google Cloud APIs which support Application Default + * Credentials; the libraries look for credentials in a set of defined + * locations and use those credentials to authenticate requests to the API. + *

+ * + * @see + * Application Default Credentials + * + * @param args the command line arguments + * @throws SQLException if an error occurs during the database calls + **/ + public static void main(String[] args) throws SQLException { + String url = "jdbc:oracle:thin:@config-gcpsecretmanager://" + SECRET_VERSION_NAME; + // Sample default URL if non present + if (args.length > 0) { + url = args[0]; + } + + // No changes required, configuration provider is loaded at runtime + OracleDataSource ds = new OracleDataSource(); + ds.setURL(url); + + // Standard JDBC code + try (Connection cn = ds.getConnection()) { + Statement st = cn.createStatement(); + ResultSet rs = st.executeQuery("SELECT 'Hello, db' FROM sys.dual"); + if (rs.next()) + System.out.println(rs.getString(1)); + } + } +} diff --git a/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleConnectionStringProviderExample.java b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleConnectionStringProviderExample.java new file mode 100644 index 00000000..9b11e762 --- /dev/null +++ b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleConnectionStringProviderExample.java @@ -0,0 +1,99 @@ +/* + ** Copyright (c) 2024 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.gcp.resource; + +import oracle.jdbc.datasource.impl.OracleDataSource; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; + +/** + * Example demonstrating how to configure Oracle JDBC with the GCP Secret Manager + * Connection String Provider to retrieve connection strings from a tnsnames.ora + * file stored in GCP Secret Manager. + */ +public class SimpleConnectionStringProviderExample { + public static void main(String[] args) throws SQLException { + try { + OracleDataSource ds = new OracleDataSource(); + ds.setURL("jdbc:oracle:thin:@"); + ds.setUser("DB_USERNAME"); + ds.setPassword("DB_PASSWORD"); + + Properties connectionProps = new Properties(); + + // Connection String Provider for retrieving tnsnames.ora content + // from GCP Secret Manager + connectionProps.put("oracle.jdbc.provider.connectionString", + "ojdbc-provider-gcp-secretmanager-tnsnames"); + + connectionProps.put("oracle.jdbc.provider.connectionString.secretVersionName", + "projects/your-project-id/secrets/your-tnsnames-secret/versions/1"); + + // Specify the tns-alias to retrieve the corresponding connection string + connectionProps.put("oracle.jdbc.provider.connectionString.tnsAlias", + "YOUR_TNS_ALIAS"); + + // TLS Configuration for secure connection + connectionProps.put("oracle.jdbc.provider.tlsConfiguration", + "ojdbc-provider-gcp-secretmanager-tls"); + connectionProps.put("oracle.jdbc.provider.tlsConfiguration.secretVersionName", + "projects/your-project-id/secrets/your-wallet-secret/versions/1"); + connectionProps.put("oracle.jdbc.provider.tlsConfiguration.type", "SSO"); + + ds.setConnectionProperties(connectionProps); + + try (Connection cn = ds.getConnection()) { + + String query = "SELECT 'Hello, db' FROM sys.dual"; + try (Statement st = cn.createStatement(); + ResultSet rs = st.executeQuery(query)) { + + if (rs.next()) { + System.out.println(rs.getString(1)); + } + } + } + } catch (SQLException e) { + throw new RuntimeException("Connection failed: ", e); + } + } +} diff --git a/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleSEPSWalletProviderExample.java b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleSEPSWalletProviderExample.java new file mode 100644 index 00000000..95dc02db --- /dev/null +++ b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleSEPSWalletProviderExample.java @@ -0,0 +1,108 @@ +/* + ** Copyright (c) 2024 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.gcp.resource; + +import oracle.jdbc.datasource.impl.OracleDataSource; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; + +/** + * A standalone example that configures Oracle JDBC to be provided with the + * connection properties retrieved from a GCP Secret Manager SEPS Wallet. + *

+ * This example demonstrates how to use the SEPS Wallet Provider with Oracle JDBC + * to connect to an Oracle Autonomous Database (ADB). + * It retrieves the database credentials from a Secure External Password Store + * (SEPS) wallet stored in GCP Secret Manager. + *

+ *

+ * The SEPS wallet securely stores encrypted database credentials. + *

+ */ +public class SimpleSEPSWalletProviderExample { + private static final String DB_URL = "(description=(retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host=your_db_host))(connect_data=(service_name=your_service_name))(security=(ssl_server_dn_match=yes)))"; + private static final String JDBC_URL = "jdbc:oracle:thin:@" + DB_URL; + + + public static void main(String[] args) { + try { + OracleDataSource ds = new OracleDataSource(); + ds.setURL(JDBC_URL); + + Properties connectionProps = new Properties(); + connectionProps.put("oracle.jdbc.provider.username", + "ojdbc-provider-gcp-secretmanager-seps"); + connectionProps.put("oracle.jdbc.provider.password", + "ojdbc-provider-gcp-secretmanager-seps"); + + // Set the secret version name of your SEPS wallet stored in GCP Secret Manager + connectionProps.put("oracle.jdbc.provider.username.secretVersionName", + "projects/{your-project-id}/secrets/{your-secret-name}/versions/{version-number}"); + connectionProps.put("oracle.jdbc.provider.password.secretVersionName", + "projects/{your-project-id}/secrets/{your-secret-name}/versions/{version-number}"); + + // TLS Configuration Provider + connectionProps.put("oracle.jdbc.provider.tlsConfiguration", + "ojdbc-provider-gcp-secretmanager-tls"); + connectionProps.put("oracle.jdbc.provider.tlsConfiguration.type","SSO"); + connectionProps.put("oracle.jdbc.provider.tlsConfiguration.secretVersionName", + "projects/{your-project-id}/secrets/{your-secret-name}/versions/{version-number}"); + + ds.setConnectionProperties(connectionProps); + + try (Connection cn = ds.getConnection()) { + String connectionString = cn.getMetaData().getURL(); + System.out.println("Connected to: " + connectionString); + + Statement st = cn.createStatement(); + ResultSet rs = st.executeQuery("SELECT 'Hello, db' FROM sys.dual"); + if (rs.next()) + System.out.println(rs.getString(1)); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + } +} + + diff --git a/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleSEPSWalletProviderWithIndexExample.java b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleSEPSWalletProviderWithIndexExample.java new file mode 100644 index 00000000..13b60d52 --- /dev/null +++ b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleSEPSWalletProviderWithIndexExample.java @@ -0,0 +1,114 @@ +/* + ** Copyright (c) 2024 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.gcp.resource; + +import oracle.jdbc.datasource.impl.OracleDataSource; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; + +/** + * A standalone example that configures Oracle JDBC to be provided with a + * specified connection string index to retrieve credentials from a GCP + * Secret Manager SEPS wallet. + *

+ * This example demonstrates how to use the SEPS Wallet Provider with Oracle JDBC + * to connect to an Oracle Autonomous Database (ADB) using credentials stored + * in a Secure External Password Store (SEPS) wallet managed by GCP Secret Manager. + * It retrieves the database credentials from the SEPS wallet stored in GCP Secret Manager, + * specifying a connection string index to select a specific credential set. + *

+ *

+ * The SEPS wallet securely stores encrypted database credentials. + *

+ * + */ +public class SimpleSEPSWalletProviderWithIndexExample { + private static final String DB_URL = "(description=(retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host=your_db_host))(connect_data=(service_name=your_service_name))(security=(ssl_server_dn_match=yes)))"; + private static final String JDBC_URL = "jdbc:oracle:thin:@" + DB_URL; + + + public static void main(String[] args) { + try { + OracleDataSource ds = new OracleDataSource(); + ds.setURL(JDBC_URL); + + Properties connectionProps = new Properties(); + connectionProps.put("oracle.jdbc.provider.username", + "ojdbc-provider-gcp-secretmanager-seps"); + connectionProps.put("oracle.jdbc.provider.password", + "ojdbc-provider-gcp-secretmanager-seps"); + + // Set the secret version name of your SEPS wallet stored in GCP Secret Manager + connectionProps.put("oracle.jdbc.provider.username.secretVersionName", + "projects/{your-project-id}/secrets/{your-secret-name}/versions/{version-number}"); + connectionProps.put("oracle.jdbc.provider.password.secretVersionName", + "projects/{your-project-id}/secrets/{your-secret-name}/versions/{version-number}"); + + // Specify the connection string index + connectionProps.put("oracle.jdbc.provider.username.connectionStringIndex","1"); + connectionProps.put("oracle.jdbc.provider.password.connectionStringIndex","1"); + + connectionProps.put("oracle.jdbc.provider.tlsConfiguration", + "ojdbc-provider-gcp-secretmanager-tls"); + connectionProps.put("oracle.jdbc.provider.tlsConfiguration.secretVersionName", + "projects/{your-project-id}/secrets/{your-secret-name}/versions/{version-number}"); + connectionProps.put("oracle.jdbc.provider.tlsConfiguration.type","SSO"); + + ds.setConnectionProperties(connectionProps); + + try (Connection cn = ds.getConnection()) { + String connectionString = cn.getMetaData().getURL(); + System.out.println("Connected to: " + connectionString); + + Statement st = cn.createStatement(); + ResultSet rs = st.executeQuery("SELECT 'Hello, db' FROM sys.dual"); + if (rs.next()) + System.out.println(rs.getString(1)); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + } +} + + diff --git a/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleSecretManagerUsernameProviderExample.java b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleSecretManagerUsernameProviderExample.java new file mode 100644 index 00000000..6613b211 --- /dev/null +++ b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleSecretManagerUsernameProviderExample.java @@ -0,0 +1,94 @@ +/* + ** Copyright (c) 2024 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.gcp.resource; + +import oracle.jdbc.datasource.impl.OracleDataSource; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; + +/** + * Example demonstrating how to use the Secret Manager Username Provider + * with Oracle JDBC to securely retrieve a database username from GCP Secret Manager. + *

+ * This example shows how to configure Oracle JDBC to retrieve the username + * stored in GCP Secret Manager. + *

+ */ +public class SimpleSecretManagerUsernameProviderExample { + private static final String DB_URL = "(description=(retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host=your_db_host))(connect_data=(service_name=your_service_name))(security=(ssl_server_dn_match=yes)))"; + private static final String JDBC_URL = "jdbc:oracle:thin:@" + DB_URL; + + + public static void main(String[] args) throws SQLException { + try { + OracleDataSource ds = new OracleDataSource(); + ds.setURL(JDBC_URL); + ds.setPassword("DB_PASSWORD"); + + Properties connectionProps = new Properties(); + connectionProps.put("oracle.jdbc.provider.username", + "ojdbc-provider-gcp-secretmanager-username"); + connectionProps.put("oracle.jdbc.provider.username.secretVersionName", + "projects/{your-project-id}/secrets/{your-secret-name}/versions/{version-number}"); + // TLS Configuration Provider + connectionProps.put("oracle.jdbc.provider.tlsConfiguration", + "ojdbc-provider-gcp-secretmanager-tls"); + connectionProps.put("oracle.jdbc.provider.tlsConfiguration.type","SSO"); + connectionProps.put("oracle.jdbc.provider.tlsConfiguration.secretVersionName", + "projects/{your-project-id}/secrets/{your-secret-name}/versions/{version-number}"); + ds.setConnectionProperties(connectionProps); + + try (Connection cn = ds.getConnection()) { + String connectionString = cn.getMetaData().getURL(); + System.out.println("Connected to: " + connectionString); + + Statement st = cn.createStatement(); + ResultSet rs = st.executeQuery("SELECT 'Hello, db' FROM sys.dual"); + if (rs.next()) + System.out.println(rs.getString(1)); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + } +} diff --git a/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleTCPSWalletProviderExample.java b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleTCPSWalletProviderExample.java new file mode 100644 index 00000000..072155c5 --- /dev/null +++ b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleTCPSWalletProviderExample.java @@ -0,0 +1,92 @@ +/* + ** Copyright (c) 2024 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.gcp.resource; + +import oracle.jdbc.datasource.impl.OracleDataSource; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; + +/** + * Example demonstrating how to configure Oracle JDBC with the TCPS Wallet + * Provider to establish a secure TLS connection to an Oracle Autonomous + * Database. + *

+ * The wallet is retrieved from GCP Secret Manager to enable secure TLS communication. + *

+ */ +public class SimpleTCPSWalletProviderExample { + private static final String DB_URL = "(description=(retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host=your_db_host))(connect_data=(service_name=your_service_name))(security=(ssl_server_dn_match=yes)))"; + private static final String JDBC_URL = "jdbc:oracle:thin:@" + DB_URL; + private static final String USERNAME = "DB_USER"; + private static final String PASSWORD = "DB_PASSWORD"; + + + public static void main(String[] args) throws SQLException { + try { + OracleDataSource ds = new OracleDataSource(); + ds.setURL(JDBC_URL); + ds.setUser(USERNAME); + ds.setPassword(PASSWORD); + + Properties connectionProps = new Properties(); + connectionProps.put("oracle.jdbc.provider.tlsConfiguration", + "ojdbc-provider-gcp-secretmanager-tls"); + connectionProps.put("oracle.jdbc.provider.tlsConfiguration.secretVersionName", + "projects/{your-project-id}/secrets/{your-secret-name}/versions/{version-number}"); + connectionProps.put("oracle.jdbc.provider.tlsConfiguration.type","SSO"); + ds.setConnectionProperties(connectionProps); + + try (Connection cn = ds.getConnection()) { + String connectionString = cn.getMetaData().getURL(); + System.out.println("Connected to: " + connectionString); + + Statement st = cn.createStatement(); + ResultSet rs = st.executeQuery("SELECT 'Hello, db' FROM sys.dual"); + if (rs.next()) + System.out.println(rs.getString(1)); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleVaultSecretPasswordResourceExample.java b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleVaultSecretPasswordResourceExample.java new file mode 100644 index 00000000..a986dc28 --- /dev/null +++ b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/SimpleVaultSecretPasswordResourceExample.java @@ -0,0 +1,98 @@ +/* + ** Copyright (c) 2024 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.gcp.resource; + +import oracle.jdbc.datasource.impl.OracleDataSource; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; + +/** + * A standalone example that configures Oracle JDBC to be provided with the + * connection properties retrieved from OCI Object Storage. + */ +public class SimpleVaultSecretPasswordResourceExample { + + private static final String DB_URL = "(description=(retry_count=2)(retry_delay=3)(address=(protocol=tcps)(port=1521)(host=adb.us-phoenix-1.oraclecloud.com))(connect_data=(service_name=gebqqvpozhjbqbs_awyonurbg0gp0smq_tp.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)))"; + private static final String RESOURCE_NAME = "projects/138028249883/secrets/test-secret/versions/2"; + + /** + *

+ * Connects to a database using connection properties retrieved from GCP + * Object Storage. + *

+ *

+ * Providers use Google Cloud APIs which support Application Default + * Credentials; the libraries look for credentials in a set of defined + * locations and use those credentials to authenticate requests to the API. + *

+ * + * @see + * Application Default Credentials + * + * @param args the command line arguments + * @throws SQLException if an error occurs during the database calls + */ + public static void main(String[] args) throws SQLException { + String url = "jdbc:oracle:thin:@" + DB_URL; + + // Standard JDBC code + OracleDataSource ds = new OracleDataSource(); + ds.setURL(url); + ds.setUser("DB_USER"); + Properties properties = new Properties(); + properties.put("oracle.jdbc.provider.password", "ojdbc-provider-gcp-secretmanager-password"); + properties.put("oracle.jdbc.provider.password.secretVersionName", RESOURCE_NAME); + ds.setConnectionProperties(properties); + + try (Connection cn = ds.getConnection()) { + String connectionString = cn.getMetaData().getURL(); + System.out.println("Connected to: " + connectionString); + + Statement st = cn.createStatement(); + ResultSet rs = st.executeQuery("SELECT 'Hello, db' FROM sys.dual"); + if (rs.next()) + System.out.println(rs.getString(1)); + } + } + +} diff --git a/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/VaultSecretPasswordResourceExample.java b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/VaultSecretPasswordResourceExample.java new file mode 100644 index 00000000..57d74fed --- /dev/null +++ b/ojdbc-provider-samples/src/main/java/oracle/jdbc/provider/gcp/resource/VaultSecretPasswordResourceExample.java @@ -0,0 +1,105 @@ +/* + ** Copyright (c) 2024 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.gcp.resource; + +import oracle.jdbc.datasource.impl.OracleDataSource; +import oracle.jdbc.provider.Configuration; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; + +/** + * A standalone example that configures Oracle JDBC to be provided with the + * connection properties retrieved from OCI Object Storage. + */ +public class VaultSecretPasswordResourceExample { + /** + * An GCP SecretManager resource name configured as a JVM system property, + * environment variable, or configuration.properties file entry named + * "gcp_secret_version_name". + */ + private static final String RESOURCE_NAME = Configuration + .getRequired("gcp_secret_version_name"); + + private static final String DB_URL = "(description=(retry_count=2)(retry_delay=3)(address=(protocol=tcps)(port=1521)(host=adb.us-phoenix-1.oraclecloud.com))(connect_data=(service_name=gebqqvpozhjbqbs_awyonurbg0gp0smq_tp.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)))"; + + /** + *

+ * Connects to a database using connection properties retrieved from GCP + * Object Storage. + *

+ *

+ * Providers use Google Cloud APIs which support Application Default + * Credentials; the libraries look for credentials in a set of defined + * locations and use those credentials to authenticate requests to the API. + *

+ * + * @see + * Application Default Credentials + * + * @param args the command line arguments + * @throws SQLException if an error occurs during the database calls + */ + public static void main(String[] args) throws SQLException { + String url = "jdbc:oracle:thin:@" + DB_URL; + + // Standard JDBC code + OracleDataSource ds = new OracleDataSource(); + ds.setURL(url); + ds.setUser("DB_USER"); + Properties properties = new Properties(); + properties.put("oracle.jdbc.provider.password", "ojdbc-provider-gcp-secretmanager-password"); + properties.put("oracle.jdbc.provider.password.secretVersionName", RESOURCE_NAME); + ds.setConnectionProperties(properties); + + try (Connection cn = ds.getConnection()) { + String connectionString = cn.getMetaData().getURL(); + System.out.println("Connected to: " + connectionString); + + Statement st = cn.createStatement(); + ResultSet rs = st.executeQuery("SELECT 'Hello, db' FROM sys.dual"); + if (rs.next()) + System.out.println(rs.getString(1)); + } + } + +} diff --git a/pom.xml b/pom.xml index d14264a2..2dc9d61c 100644 --- a/pom.xml +++ b/pom.xml @@ -62,6 +62,7 @@ ojdbc-provider-samples ojdbc-provider-opentelemetry ojdbc-provider-aws + ojdbc-provider-gcp ojdbc-provider-jackson-oson ojdbc-provider-hashicorp