azure auth - moved from plugin into API

This commit is contained in:
Jan Prochazka 2024-08-08 10:30:39 +02:00
parent a9352f2a93
commit 9132bfb656
7 changed files with 47 additions and 31 deletions

View File

@ -17,6 +17,7 @@
"dbgate" "dbgate"
], ],
"dependencies": { "dependencies": {
"@azure/msal-node": "^2.12.0",
"activedirectory2": "^2.1.0", "activedirectory2": "^2.1.0",
"async-lock": "^1.2.4", "async-lock": "^1.2.4",
"axios": "^0.21.1", "axios": "^0.21.1",

View File

@ -3,6 +3,7 @@ const fs = require('fs');
const { pluginsdir, packagedPluginsDir, getPluginBackendPath } = require('../utility/directories'); const { pluginsdir, packagedPluginsDir, getPluginBackendPath } = require('../utility/directories');
const nativeModules = require('../nativeModules'); const nativeModules = require('../nativeModules');
const platformInfo = require('../utility/platformInfo'); const platformInfo = require('../utility/platformInfo');
const azureAuth = require('../utility/azureAuth');
const { getLogger } = require('dbgate-tools'); const { getLogger } = require('dbgate-tools');
const logger = getLogger('requirePlugin'); const logger = getLogger('requirePlugin');
@ -12,6 +13,7 @@ const dbgateEnv = {
dbgateApi: null, dbgateApi: null,
nativeModules, nativeModules,
platformInfo, platformInfo,
azureAuth,
}; };
function requirePlugin(packageName, requiredPlugin = null) { function requirePlugin(packageName, requiredPlugin = null) {
if (!packageName) throw new Error('Missing packageName in plugin'); if (!packageName) throw new Error('Missing packageName in plugin');

View File

@ -0,0 +1,17 @@
function isAzureAuthSupported() {
return false;
}
async function azureGetRedirectAuthUrl(options) {
return null;
}
async function azureGetAuthTokenFromCode(options) {
return null;
}
module.exports = {
isAzureAuthSupported,
azureGetRedirectAuthUrl,
azureGetAuthTokenFromCode,
};

View File

@ -32,7 +32,6 @@
}, },
"devDependencies": { "devDependencies": {
"async-lock": "^1.2.6", "async-lock": "^1.2.6",
"@azure/msal-node": "^2.12.0",
"dbgate-plugin-tools": "^1.0.7", "dbgate-plugin-tools": "^1.0.7",
"dbgate-query-splitter": "^4.10.1", "dbgate-query-splitter": "^4.10.1",
"dbgate-tools": "^5.0.0-alpha.1", "dbgate-tools": "^5.0.0-alpha.1",

View File

@ -1,22 +0,0 @@
function getAzureAuthTypes(platformInfo) {
return null;
}
async function azureGetRedirectAuthUrl(connection) {
return null;
}
async function azureGetAuthTokenFromCode(connection, code) {
return null;
}
function getAzureAuthOptions(connection) {
return null;
}
module.exports = {
getAzureAuthTypes,
azureGetRedirectAuthUrl,
azureGetAuthTokenFromCode,
getAzureAuthOptions,
};

View File

@ -8,11 +8,11 @@ const AsyncLock = require('async-lock');
const nativeDriver = require('./nativeDriver'); const nativeDriver = require('./nativeDriver');
const lock = new AsyncLock(); const lock = new AsyncLock();
const { tediousConnect, tediousQueryCore, tediousReadQuery, tediousStream } = require('./tediousDriver'); const { tediousConnect, tediousQueryCore, tediousReadQuery, tediousStream } = require('./tediousDriver');
const { getAzureAuthTypes, azureGetRedirectAuthUrl, azureGetAuthTokenFromCode } = require('./azureAuth');
const { nativeConnect, nativeQueryCore, nativeReadQuery, nativeStream } = nativeDriver; const { nativeConnect, nativeQueryCore, nativeReadQuery, nativeStream } = nativeDriver;
let requireMsnodesqlv8; let requireMsnodesqlv8;
let platformInfo; let platformInfo;
let azureAuth;
const versionQuery = ` const versionQuery = `
SELECT SELECT
@ -57,8 +57,20 @@ const driver = {
getAuthTypes() { getAuthTypes() {
const res = []; const res = [];
if (requireMsnodesqlv8) res.push(...windowsAuthTypes); if (requireMsnodesqlv8) res.push(...windowsAuthTypes);
const azureAuthTypes = getAzureAuthTypes(platformInfo);
if (azureAuthTypes) res.push(...azureAuthTypes); if (azureAuth.isAzureAuthSupported()) {
res.push(
{
title: 'NodeJs portable driver (tedious) - recomended',
name: 'tedious',
},
{
title: 'Microsoft Entra ID (with MFA support)',
name: 'msentra',
disabledFields: ['user', 'password'],
}
);
}
if (res.length > 0) { if (res.length > 0) {
return _.uniqBy(res, 'name'); return _.uniqBy(res, 'name');
} }
@ -126,10 +138,11 @@ const driver = {
return rows; return rows;
}, },
getRedirectAuthUrl(connection, options) { getRedirectAuthUrl(connection, options) {
return azureGetRedirectAuthUrl(connection, options); if (connection.authType != 'msentra') return null;
return azureAuth.azureGetRedirectAuthUrl(options);
}, },
getAuthTokenFromCode(connection, options) { getAuthTokenFromCode(connection, options) {
return azureGetAuthTokenFromCode(connection, options); return azureAuth.azureGetAuthTokenFromCode(options);
}, },
}; };
@ -138,6 +151,7 @@ driver.initialize = dbgateEnv => {
requireMsnodesqlv8 = dbgateEnv.nativeModules.msnodesqlv8; requireMsnodesqlv8 = dbgateEnv.nativeModules.msnodesqlv8;
} }
platformInfo = dbgateEnv.platformInfo; platformInfo = dbgateEnv.platformInfo;
azureAuth = dbgateEnv.azureAuth;
nativeDriver.initialize(dbgateEnv); nativeDriver.initialize(dbgateEnv);
}; };

View File

@ -2,7 +2,6 @@ const _ = require('lodash');
const stream = require('stream'); const stream = require('stream');
const tedious = require('tedious'); const tedious = require('tedious');
const makeUniqueColumnNames = require('./makeUniqueColumnNames'); const makeUniqueColumnNames = require('./makeUniqueColumnNames');
const { getAzureAuthOptions } = require('./azureAuth');
function extractTediousColumns(columns, addDriverNativeColumn = false) { function extractTediousColumns(columns, addDriverNativeColumn = false) {
const res = columns.map(col => { const res = columns.map(col => {
@ -24,7 +23,8 @@ function extractTediousColumns(columns, addDriverNativeColumn = false) {
} }
async function tediousConnect(storedConnection) { async function tediousConnect(storedConnection) {
const { server, port, user, password, database, ssl, trustServerCertificate, windowsDomain, authType } = storedConnection; const { server, port, user, password, database, ssl, trustServerCertificate, windowsDomain, authType, accessToken } =
storedConnection;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const connectionOptions = { const connectionOptions = {
encrypt: !!ssl || authType == 'msentra', encrypt: !!ssl || authType == 'msentra',
@ -44,7 +44,12 @@ async function tediousConnect(storedConnection) {
const authentication = const authentication =
authType == 'msentra' authType == 'msentra'
? getAzureAuthOptions(storedConnection) ? {
type: 'azure-active-directory-access-token',
options: {
token: accessToken,
},
}
: { : {
type: windowsDomain ? 'ntlm' : 'default', type: windowsDomain ? 'ntlm' : 'default',
options: { options: {