Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 23 additions & 2 deletions reverse_engineering/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,41 @@ module.exports = {
},

async testConnection(connectionInfo, logger, callback, app) {
const sshService = app.require('@hackolade/ssh-service');

try {
await this.connect(connectionInfo, logger, () => {}, app);
logInfo('Test connection', connectionInfo, logger);
oracleHelper.logEnvironment(logger);
await oracleHelper.disconnect(sshService);
await oracleHelper.connect(connectionInfo, sshService, message => {
logger.log('info', message, 'Connection');
});
callback(null);
} catch (error) {
logger.log('error', { message: error.message, stack: error.stack, error }, 'Test connection');
callback({ message: error.message, stack: error.stack });
} finally {
try {
await oracleHelper.disconnect(sshService);
} catch (disconnectError) {
logger.log(
'warn',
{ message: disconnectError.message, stack: disconnectError.stack },
'Disconnect after test connection',
);
}
}
},

async getSchemaNames(connectionInfo, logger, callback, app) {
try {
logInfo('Get schemas', connectionInfo, logger);
await this.connect(connectionInfo, logger, () => {}, app);
const schemas = await oracleHelper.getSchemaNames();
const schemas = await oracleHelper.getSchemaNames(connectionInfo, {
info: data => logger.log('info', data, 'Get schemas'),
error: error =>
logger.log('error', { message: error.message, stack: error.stack, error }, 'Get schemas'),
});
logger.log('info', schemas, 'All schemas list', connectionInfo.hiddenKeys);
return callback(null, schemas);
} catch (error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@
}
},
{
"inputLabel": "Wallet file",
"inputLabel": "Wallet archive",
"inputKeyword": "walletFile",
"description": "Specify the full path location and name of the wallet zip file",
"description": "Specify the full path location and name of the wallet zip file.",
"inputType": "file",
"extensions": ["zip"],
"dependency": {
Expand All @@ -110,11 +110,23 @@
}
},
{
"inputLabel": "Tnsnames Directory",
"inputLabel": "Tnsnames file",
"inputKeyword": "TNSpath",
"description": "Specify the full path to directory with tnsnames.ora file",
"description": "Specify the full path to tnsnames.ora.",
"inputType": "file",
"openType": "openDirectory",
"extensions": ["ora", "txt"],
"dependency": {
"key": "connectionMethod",
"value": ["TNS"]
}
},
{
"inputLabel": "Mutual TLS (mTLS)",
"inputKeyword": "mutualTLS",
"description": "Enable only when the database requires a client certificate (cloud wallet, mutual TLS).",
"inputType": "checkbox",
"defaultValue": false,
"dependency": {
"key": "connectionMethod",
"value": ["TNS"]
Expand All @@ -137,55 +149,79 @@
{
"inputLabel": "Service Name",
"inputKeyword": "serviceName",
"description": "Specify the service name of the Oracle Instance",
"description": "Specify the service name of the Oracle Instance.",
"inputType": "text",
"regex": "([^\\s])",
"dependency": {
"type": "or",
"type": "and",
"values": [
{
"key": "connectionMethod",
"value": ["TNS"]
"value": ["Basic"]
},
{
"type": "and",
"values": [
{
"key": "connectionMethod",
"value": ["Basic"]
},
{
"key": "identifierType",
"value": ["serviceName"]
}
]
"key": "identifierType",
"value": ["serviceName"]
}
]
}
},
{
"inputLabel": "Wallet Password",
"inputKeyword": "walletPassword",
"description": "Specify the password used to protect the wallet",
"inputType": "password",
"isHiddenKey": true,
"dependency": {
"type": "and",
"type": "or",
"values": [
{
"key": "connectionMethod",
"value": ["Wallet"]
"type": "and",
"values": [
{
"key": "connectionMethod",
"value": ["Wallet"]
},
{
"key": "mode",
"value": ["thin"]
}
]
},
{
"key": "mode",
"value": ["thin"]
"type": "and",
"values": [
{
"key": "connectionMethod",
"value": ["TNS"]
},
{
"key": "mode",
"value": ["thin"]
},
{
"key": "mutualTLS",
"value": [true, "true"]
}
]
}
]
}
},
{
"inputLabel": "TNS alias",
"inputKeyword": "serviceName",
"description": "Leave empty to use the first entry in tnsnames.ora (e.g. <database name>_high).",
"inputType": "text",
"inputPlaceholder": "Optional TNS alias",
"dependency": {
"key": "connectionMethod",
"value": ["TNS"]
}
},
{
"inputLabel": "SID",
"inputKeyword": "sid",
"description": "Optionally specify the SID of the Oracle Instance",
"description": "Optionally specify the SID of the Oracle Instance.",
"inputType": "text",
"dependency": {
"type": "and",
Expand All @@ -209,21 +245,24 @@
{
"inputLabel": "Authentication method",
"inputKeyword": "authMethod",
"description": "OS and Kerberos require Thick mode and a configured Oracle client (Instant Client or Oracle Home).",
"inputType": "select",
"defaultValue": "Username / Password",
"options": [{ "value": "Username / Password", "label": "Username / Password" }]
"options": [
{ "value": "Username / Password", "label": "Username / Password" },
{ "value": "OS", "label": "OS" },
{ "value": "Kerberos", "label": "Kerberos" }
]
},
{
"inputLabel": "User Name",
"inputKeyword": "userName",
"inputType": "text",
"inputPlaceholder": "User Name",
"description": "For Kerberos proxy connections, use the [username] format.",
"dependency": {
"key": "authMethod",
"value": ["Username / Password", "Kerberos"]
},
"validation": {
"regex": "([^\\s])"
}
},
{
Expand All @@ -233,7 +272,7 @@
"inputPlaceholder": "Password",
"dependency": {
"key": "authMethod",
"value": ["Username / Password", "Kerberos"]
"value": ["Username / Password"]
},
"isHiddenKey": true,
"validation": {
Expand Down
32 changes: 32 additions & 0 deletions reverse_engineering/helpers/connectStringDescription.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const combine = (val, str) => (val ? str : '');

const normalizeConnectString = connectString =>
typeof connectString === 'string' ? connectString.replace(/\s+/g, '') : connectString;

const getConnectionDescription = (
{ protocol, host, port, sid, service, httpsProxy, httpsProxyPort, retryCount, retryDelay, sslServerDnMatch },
logger,
) => {
const connectionString = normalizeConnectString(`(DESCRIPTION=
${combine(retryCount, `(RETRY_COUNT=${retryCount})`)}
${combine(retryDelay, `(RETRY_DELAY=${retryDelay})`)}
(ADDRESS=
(PROTOCOL=${protocol || 'tcp'})
(HOST=${host})
(PORT=${port}))
${combine(httpsProxy, `(HTTPS_PROXY=${httpsProxy})`)}
${combine(httpsProxyPort, `(HTTPS_PROXY_PORT=${httpsProxyPort})`)}
(CONNECT_DATA=
${combine(sid, `(SID=${sid})`)}
${combine(service, `(SERVICE_NAME=${service})`)}
)
${combine(sslServerDnMatch, `(SECURITY=(SSL_SERVER_DN_MATCH=${sslServerDnMatch}))`)}
)`);
logger({ message: 'connectString', connectString: connectionString });
return connectionString;
};

module.exports = {
normalizeConnectString,
getConnectionDescription,
};
66 changes: 66 additions & 0 deletions reverse_engineering/helpers/connectionAuth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
const _ = require('lodash');
const { normalizeTnsAlias } = require('./tns/tnsConnectString');

const AUTH_METHOD_USERNAME_PASSWORD = 'Username / Password';
const AUTH_METHOD_OS = 'OS';
const AUTH_METHOD_KERBEROS = 'Kerberos';

const normalizeAuthMethod = authMethod => authMethod || AUTH_METHOD_USERNAME_PASSWORD;

const assertExternalAuthMode = (authMethod, mode) => {
if (authMethod === AUTH_METHOD_USERNAME_PASSWORD) {
return;
}

if (mode === 'thin') {
throw new Error(
`${authMethod} authentication requires Thick mode with Oracle Instant Client or Oracle Home configured for external authentication.`,
);
}
};

const buildConnectionAuthParams = (authMethod, userName, userPassword) => {
if (authMethod === AUTH_METHOD_USERNAME_PASSWORD) {
if (!normalizeTnsAlias(userName) || !userPassword) {
throw new Error('User name and password are required for Username / Password authentication.');
}

return { username: userName, password: userPassword };
}

if (authMethod === AUTH_METHOD_OS) {
return { externalAuth: true };
}

if (authMethod === AUTH_METHOD_KERBEROS) {
const trimmedUserName = normalizeTnsAlias(userName);
const proxyUserName =
trimmedUserName && !trimmedUserName.startsWith('[') ? `[${trimmedUserName}]` : trimmedUserName;

return _.omitBy(
{
externalAuth: true,
username: proxyUserName || undefined,
},
_.isUndefined,
);
}

return { username: userName, password: userPassword };
};

const logAuthMethodNotes = (authMethod, userPassword, logger) => {
if (authMethod === AUTH_METHOD_KERBEROS && userPassword) {
logger({
message:
'Password is not sent for Kerberos external authentication (oracledb uses the OS Kerberos ticket).',
});
}
};

module.exports = {
normalizeAuthMethod,
assertExternalAuthMode,
buildConnectionAuthParams,
logAuthMethodNotes,
};
1 change: 1 addition & 0 deletions reverse_engineering/helpers/extractWallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,4 @@ const extractWallet = async ({ walletFile, tempFolder, name }) => {
};

module.exports = extractWallet;
module.exports.fixSqlNetOraWalletPath = replaceSqlNetOraDirectoryPath;
Loading