azure auth WIP

This commit is contained in:
Jan Prochazka
2024-08-02 14:32:28 +02:00
parent f777530b1c
commit fc448ed578
10 changed files with 91 additions and 20 deletions

View File

@@ -16,6 +16,7 @@ const { safeJsonParse, getLogger } = require('dbgate-tools');
const platformInfo = require('../utility/platformInfo');
const { connectionHasPermission, testConnectionPermission } = require('../utility/hasPermission');
const pipeForkLogs = require('../utility/pipeForkLogs');
const requireEngineDriver = require('../utility/requireEngineDriver');
const logger = getLogger('connections');
@@ -345,7 +346,7 @@ module.exports = {
const storage = require('./storage');
const storageConnection = await storage.getConnection({conid});
const storageConnection = await storage.getConnection({ conid });
if (storageConnection) {
return storageConnection;
}
@@ -379,4 +380,16 @@ module.exports = {
});
return res;
},
dblogin_meta: {
raw: true,
method: 'get',
},
async dblogin(req, res) {
const { conid } = req.query;
const connection = await this.getCore({ conid });
const driver = requireEngineDriver(connection);
const authUrl = driver.getRedirectAuthUrl(connection);
res.redirect(authUrl);
},
};

View File

@@ -89,6 +89,9 @@ module.exports = {
if (connection.passwordMode == 'askPassword' || connection.passwordMode == 'askUser') {
throw new MissingCredentialsError({ conid, passwordMode: connection.passwordMode });
}
if (connection.useRedirectDbLogin) {
throw new MissingCredentialsError({ conid, redirectToDbLogin: true });
}
const subprocess = fork(
global['API_PACKAGE'] || process.argv[1],
[

View File

@@ -149,6 +149,7 @@ export interface EngineDriver {
summaryCommand(pool, command, row): Promise<void>;
startProfiler(pool, options): Promise<any>;
stopProfiler(pool, profiler): Promise<void>;
getRedirectAuthUrl(connection): Promise<string>;
analyserClass?: any;
dumperClass?: any;

View File

@@ -31,7 +31,8 @@
$: showConnectionFieldArgs = { config: $config };
$: showUser = driver?.showConnectionField('user', $values, showConnectionFieldArgs) && $values.passwordMode != 'askUser';
$: showUser =
driver?.showConnectionField('user', $values, showConnectionFieldArgs) && $values.passwordMode != 'askUser';
$: showPassword =
driver?.showConnectionField('password', $values, showConnectionFieldArgs) &&
$values.passwordMode != 'askPassword' &&
@@ -83,17 +84,19 @@
{/if}
{#if $authTypes && driver?.showConnectionField('authType', $values, showConnectionFieldArgs)}
<FormSelectField
label={driver?.authTypeLabel ?? 'Authentication'}
name="authType"
isNative
disabled={isConnected}
defaultValue={driver?.defaultAuthTypeName}
options={$authTypes.map(auth => ({
value: auth.name,
label: auth.title,
}))}
/>
{#key $authTypes}
<FormSelectField
label={driver?.authTypeLabel ?? 'Authentication'}
name="authType"
isNative
disabled={isConnected}
defaultValue={driver?.defaultAuthTypeName}
options={$authTypes.map(auth => ({
value: auth.name,
label: auth.title,
}))}
/>
{/key}
{/if}
{#if driver?.showConnectionField('clientLibraryPath', $values, showConnectionFieldArgs)}

View File

@@ -9,6 +9,7 @@ import { showModal } from '../modals/modalTools';
import DatabaseLoginModal, { isDatabaseLoginVisible } from '../modals/DatabaseLoginModal.svelte';
import _ from 'lodash';
import uuidv1 from 'uuid/v1';
import { openWebLink } from './exportFileTools';
export const strmid = uuidv1();
@@ -63,7 +64,9 @@ function processApiResponse(route, args, resp) {
// }
if (resp?.missingCredentials) {
if (!isDatabaseLoginVisible()) {
if (resp.detail.redirectToDbLogin) {
openWebLink('connections/dblogin');
} else if (!isDatabaseLoginVisible()) {
showModal(DatabaseLoginModal, resp.detail);
}
return null;

View File

@@ -31,12 +31,13 @@
"plugout": "dbgate-plugout dbgate-plugin-mssql"
},
"devDependencies": {
"async-lock": "^1.2.6",
"@azure/msal-node": "^2.12.0",
"dbgate-plugin-tools": "^1.0.7",
"dbgate-query-splitter": "^4.10.1",
"webpack": "^5.91.0",
"webpack-cli": "^5.1.4",
"dbgate-tools": "^5.0.0-alpha.1",
"tedious": "^18.2.0",
"async-lock": "^1.2.6"
"webpack": "^5.91.0",
"webpack-cli": "^5.1.4"
}
}
}

View File

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

View File

@@ -8,8 +8,11 @@ const AsyncLock = require('async-lock');
const nativeDriver = require('./nativeDriver');
const lock = new AsyncLock();
const { tediousConnect, tediousQueryCore, tediousReadQuery, tediousStream } = require('./tediousDriver');
const { getAzureAuthTypes } = require('./azureAuth');
const { nativeConnect, nativeQueryCore, nativeReadQuery, nativeStream } = nativeDriver;
let requireMsnodesqlv8;
let platformInfo;
const versionQuery = `
SELECT
@@ -52,7 +55,14 @@ const driver = {
analyserClass: MsSqlAnalyser,
getAuthTypes() {
return requireMsnodesqlv8 ? windowsAuthTypes : null;
const res = [];
if (requireMsnodesqlv8) res.push(...windowsAuthTypes);
const azureAuthTypes = getAzureAuthTypes(platformInfo);
if (azureAuthTypes) res.push(...azureAuthTypes);
if (res.length > 0) {
return _.uniqBy(res, 'name');
}
return null;
},
async connect(conn) {
@@ -115,12 +125,16 @@ const driver = {
const { rows } = await this.query(pool, 'SELECT name FROM sys.databases order by name');
return rows;
},
getRedirectAuthUrl(connection) {
return azureGetRedirectAuthUrl(connection);
}
};
driver.initialize = dbgateEnv => {
if (dbgateEnv.nativeModules && dbgateEnv.nativeModules.msnodesqlv8) {
requireMsnodesqlv8 = dbgateEnv.nativeModules.msnodesqlv8;
}
platformInfo = dbgateEnv.platformInfo;
nativeDriver.initialize(dbgateEnv);
};

View File

@@ -130,7 +130,7 @@ const driver = {
field
) ||
(field == 'trustServerCertificate' && values.authType != 'sql' && values.authType != 'sspi') ||
(field == 'windowsDomain' && values.authType != 'sql' && values.authType != 'sspi'),
(field == 'windowsDomain' && values.authType != 'sql' && values.authType != 'sspi' && values.authType != 'msentra'),
// (field == 'useDatabaseUrl' && values.authType != 'sql' && values.authType != 'sspi')
getQuerySplitterOptions: usage =>
usage == 'editor'
@@ -154,6 +154,13 @@ const driver = {
},
];
},
beforeConnectionSave: connection => {
return {
...connection,
useRedirectDbLogin: connection.authType == 'msentra' ? 1 : 0,
};
},
};
module.exports = driver;

View File

@@ -164,6 +164,20 @@
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.10.0.tgz#215449726717b53d549953db77562cad6cb8421c"
integrity sha512-Zk6DPDz7e1wPgLoLgAp0349Yay9RvcjPM5We/ehuenDNsz/t9QEFI7tRoHpp/e47I4p20XE3FiDlhKwAo3utDA==
"@azure/msal-common@14.14.0":
version "14.14.0"
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.14.0.tgz#31a015070d5864ebcf9ebb988fcbc5c5536f22d1"
integrity sha512-OxcOk9H1/1fktHh6//VCORgSNJc2dCQObTm6JNmL824Z6iZSO6eFo/Bttxe0hETn9B+cr7gDouTQtsRq3YPuSQ==
"@azure/msal-node@^2.12.0":
version "2.12.0"
resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.12.0.tgz#57ee6b6011a320046d72dc0828fec46278f2ab2c"
integrity sha512-jmk5Im5KujRA2AcyCb0awA3buV8niSrwXZs+NBJWIvxOz76RvNlusGIqi43A0h45BPUy93Qb+CPdpJn82NFTIg==
dependencies:
"@azure/msal-common" "14.14.0"
jsonwebtoken "^9.0.0"
uuid "^8.3.0"
"@azure/msal-node@^2.5.1":
version "2.8.0"
resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.8.0.tgz#ef6e4a76bcd0851f7b1240d94b00fe1f9a52d559"