allow usage of wallet for oracleDB on self hosted instances

This commit is contained in:
x032205
2025-11-15 18:49:01 -05:00
parent 624c268210
commit 066ab9cd5c
5 changed files with 165 additions and 34 deletions

2
backend/.gitignore vendored
View File

@@ -1 +1,3 @@
dist
/wallet

View File

@@ -155,6 +155,7 @@
"@types/lodash.isequal": "^4.5.8",
"@types/node": "^20.19.0",
"@types/nodemailer": "^6.4.14",
"@types/oracledb": "^6.10.0",
"@types/passport-google-oauth20": "^2.0.14",
"@types/pg": "^8.10.9",
"@types/picomatch": "^2.3.3",
@@ -15367,6 +15368,16 @@
"@types/node": "*"
}
},
"node_modules/@types/oracledb": {
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/@types/oracledb/-/oracledb-6.10.0.tgz",
"integrity": "sha512-dRaEYKRkJhSSM/uKrscE7zXC5D75JSkBgdye5kSxzTRwrMAUI5V675cD3fqCdMuSOiGo2K9Ng3CjjRI4rzeuAg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/passport": {
"version": "1.0.17",
"resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz",

View File

@@ -101,6 +101,7 @@
"@types/lodash.isequal": "^4.5.8",
"@types/node": "^20.19.0",
"@types/nodemailer": "^6.4.14",
"@types/oracledb": "^6.10.0",
"@types/passport-google-oauth20": "^2.0.14",
"@types/pg": "^8.10.9",
"@types/picomatch": "^2.3.3",

View File

@@ -1,4 +1,6 @@
import fs from "fs";
import knex, { Knex } from "knex";
import oracledb from "oracledb";
import { verifyHostInputValidity } from "@app/ee/services/dynamic-secret/dynamic-secret-fns";
import { TGatewayServiceFactory } from "@app/ee/services/gateway/gateway-service";
@@ -79,12 +81,51 @@ const getConnectionConfig = ({
}
};
const ORACLE_WALLET_REGEX = /^[a-z0-9]+_[a-z]+$/i;
const isOracleWalletConnection = (app: AppConnection, database: string): boolean => {
return app === AppConnection.OracleDB && ORACLE_WALLET_REGEX.test(database);
};
const getOracleWalletKnexClient = (
credentials: Pick<TSqlConnection["credentials"], "username" | "password" | "database">
): Knex => {
if (!process.env.TNS_ADMIN || !fs.existsSync(process.env.TNS_ADMIN)) {
throw new BadRequestError({
message:
"Oracle wallet is not configured correctly. See documentation for instructions: https://infisical.com/docs/integrations/app-connections/oracledb#mtls-wallet"
});
}
if (oracledb.thin) {
try {
oracledb.initOracleClient();
} catch (err) {
const errorMessage = err instanceof Error ? err.message : String(err);
throw new BadRequestError({
message: `Failed to initialize Oracle client: ${errorMessage}. See documentation for instructions: https://infisical.com/docs/integrations/app-connections/oracledb#mtls-wallet`
});
}
}
return knex({
client: "oracledb",
connection: {
user: credentials.username,
password: credentials.password,
connectString: credentials.database
}
});
};
export const getSqlConnectionClient = async (appConnection: Pick<TSqlConnection, "credentials" | "app">) => {
const {
app,
credentials: { host: baseHost, database, port, password, username }
} = appConnection;
if (isOracleWalletConnection(app, database)) {
return getOracleWalletKnexClient({ username, password, database });
}
const [host] = await verifyHostInputValidity(baseHost);
const client = knex({
@@ -119,21 +160,30 @@ export const executeWithPotentialGateway = async <T>(
targetPort: credentials.port
});
const createClient = (proxyPort: number): Knex => {
const { database, username, password } = credentials;
if (isOracleWalletConnection(app, database)) {
return getOracleWalletKnexClient({ username, password, database });
}
return knex({
client: SQL_CONNECTION_CLIENT_MAP[app],
connection: {
database: credentials.database,
port: proxyPort,
host: "localhost",
user: credentials.username,
password: credentials.password,
connectionTimeoutMillis: EXTERNAL_REQUEST_TIMEOUT,
...getConnectionConfig({ app, credentials })
}
});
};
if (platformConnectionDetails) {
return withGatewayV2Proxy(
async (proxyPort) => {
const client = knex({
client: SQL_CONNECTION_CLIENT_MAP[app],
connection: {
database: credentials.database,
port: proxyPort,
host: "localhost",
user: credentials.username,
password: credentials.password,
connectionTimeoutMillis: EXTERNAL_REQUEST_TIMEOUT,
...getConnectionConfig({ app, credentials })
}
});
const client = createClient(proxyPort);
try {
return await operation(client);
} finally {
@@ -154,18 +204,7 @@ export const executeWithPotentialGateway = async <T>(
return withGatewayProxy(
async (proxyPort) => {
const client = knex({
client: SQL_CONNECTION_CLIENT_MAP[app],
connection: {
database: credentials.database,
port: proxyPort,
host: "localhost",
user: credentials.username,
password: credentials.password,
connectionTimeoutMillis: EXTERNAL_REQUEST_TIMEOUT,
...getConnectionConfig({ app, credentials })
}
});
const client = createClient(proxyPort);
try {
return await operation(client);
} finally {

View File

@@ -44,17 +44,95 @@ Infisical supports connecting to OracleDB using a database user.
</Tabs>
</Step>
<Step title="Get Connection Details">
You'll need the following information to create your Oracle Database connection:
- `host` - The hostname or IP address of your Oracle Database server
- `port` - The port number your Oracle Database server is listening on (default: 1521)
- `database` - The Oracle Service Name or SID (System Identifier) for the database you are connecting to. For example: `ORCL`, `FREEPDB1`, `XEPDB1`
- `username` - The user name of the login created in the steps above
- `password` - The user password of the login created in the steps above
- `sslCertificate` (optional) - The SSL certificate required for connection (if configured)
<Tabs>
<Tab title="Without mTLS">
You'll need the following information to create your Oracle Database connection:
- `host` - The hostname or IP address of your Oracle Database server
- `port` - The port number your Oracle Database server is listening on (default: 1521)
- `database` - The Oracle Service Name or SID (System Identifier) for the database you are connecting to. For example: `ORCL`, `FREEPDB1`, `XEPDB1`
- `username` - The user name of the login created in the steps above
- `password` - The user password of the login created in the steps above
- `sslCertificate` (optional) - The SSL certificate required for connection (if configured)
<Note>
If you are self-hosting Infisical and intend to connect to an internal/private IP address, be sure to set the `ALLOW_INTERNAL_IP_CONNECTIONS` environment variable to `true`.
</Note>
<Note>
If you are self-hosting Infisical and intend to connect to an internal/private IP address, be sure to set the `ALLOW_INTERNAL_IP_CONNECTIONS` environment variable to `true`.
</Note>
</Tab>
<Tab title="mTLS (Wallet)">
<Info>
This configuration can only be done on self-hosted or dedicated instances of Infisical.
</Info>
To connect to an Oracle Database using mTLS with a wallet, you'll need to modify your self-hosted Infisical instance's Docker image.
1. Place your Oracle Wallet folder, which must be named `wallet`, inside the `/backend` directory of your Infisical installation source code.
2. Add the following instructions to your `Dockerfile`. These instructions install the Oracle Instant Client and configure the environment for the wallet. Choose the tab that matches your server's architecture.
<Tabs>
<Tab title="AMD64 / x86_64">
```Dockerfile
# Install dependencies for Oracle Instant Client
RUN apt-get update && apt-get install -y \
libaio1 \
unzip \
&& rm -rf /var/lib/apt/lists/*
# Download and install Oracle Instant Client for x86_64
RUN wget https://download.oracle.com/otn_software/linux/instantclient/2326000/instantclient-basic-linux.x64-23.26.0.0.0.zip && \
unzip instantclient-basic-linux.x64-23.26.0.0.0.zip -d /opt/oracle && \
rm instantclient-basic-linux.x64-23.26.0.0.0.zip && \
echo /opt/oracle/instantclient_23_26 > /etc/ld.so.conf.d/oracle-instantclient.conf && \
ldconfig
# Configure environment variables for Oracle Instant Client and the wallet
ENV LD_LIBRARY_PATH=/opt/oracle/instantclient_23_26:$LD_LIBRARY_PATH
ENV TNS_ADMIN=/app/wallet
# Update sqlnet.ora to point to the correct wallet directory
RUN sed -i 's|DIRECTORY="?/network/admin"|DIRECTORY="/app/wallet"|g' /app/wallet/sqlnet.ora
```
</Tab>
<Tab title="ARM64">
```Dockerfile
# Install dependencies for Oracle Instant Client
RUN apt-get update && apt-get install -y \
libaio1t64 \
unzip \
&& ln -s /lib/aarch64-linux-gnu/libaio.so.1t64 /lib/aarch64-linux-gnu/libaio.so.1 \
&& rm -rf /var/lib/apt/lists/*
# Download and install Oracle Instant Client for ARM64
RUN wget https://download.oracle.com/otn_software/linux/instantclient/2326000/instantclient-basic-linux.arm64-23.26.0.0.0.zip && \
unzip instantclient-basic-linux.arm64-23.26.0.0.0.zip -d /opt/oracle && \
rm instantclient-basic-linux.arm64-23.26.0.0.0.zip && \
echo /opt/oracle/instantclient_23_26 > /etc/ld.so.conf.d/oracle-instantclient.conf && \
ldconfig
# Configure environment variables for Oracle Instant Client and the wallet
ENV LD_LIBRARY_PATH=/opt/oracle/instantclient_23_26:$LD_LIBRARY_PATH
ENV TNS_ADMIN=/app/wallet
# Update sqlnet.ora to point to the correct wallet directory
RUN sed -i 's|DIRECTORY="?/network/admin"|DIRECTORY="/app/wallet"|g' /app/wallet/sqlnet.ora
```
</Tab>
</Tabs>
3. After rebuilding and deploying your custom Docker image, you'll need the following information to create the connection in Infisical:
- `host` - The hostname or IP address of your Oracle Database server. This is required for the Infisical Gateway to function.
- `port` - The port number your Oracle Database server is listening on. This is required for the Infisical Gateway to function.
- `database` - The connection alias for your Oracle Database from your `tnsnames.ora` file. (e.g. `tyk9ovdixe1dvaj8_high`)
- `username` - The user name of the login created in the steps above.
- `password` - The user password of the login created in the steps above.
Note that when a wallet is being used, any configured SSL settings are ignored.
<Note>
If you are self-hosting Infisical and intend to connect to an internal/private IP address, be sure to set the `ALLOW_INTERNAL_IP_CONNECTIONS` environment variable to `true`.
</Note>
</Tab>
</Tabs>
</Step>
</Steps>