mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
feat(Snowflake Node): Add support for Key-Pair authentication (#14833)
This commit is contained in:
committed by
GitHub
parent
c02696241b
commit
4302c5f474
@@ -30,11 +30,33 @@ export class Snowflake implements ICredentialType {
|
||||
description:
|
||||
'The default virtual warehouse to use for the session after connecting. Used for performing queries, loading data, etc.',
|
||||
},
|
||||
{
|
||||
displayName: 'Authentication',
|
||||
name: 'authentication',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Password',
|
||||
value: 'password',
|
||||
},
|
||||
{
|
||||
name: 'Key-Pair',
|
||||
value: 'keyPair',
|
||||
},
|
||||
],
|
||||
default: 'password',
|
||||
description: 'The way to authenticate with Snowflake',
|
||||
},
|
||||
{
|
||||
displayName: 'Username',
|
||||
name: 'username',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
authentication: ['password'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Password',
|
||||
@@ -44,6 +66,28 @@ export class Snowflake implements ICredentialType {
|
||||
password: true,
|
||||
},
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
authentication: ['password'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Private Key',
|
||||
name: 'privateKey',
|
||||
type: 'string',
|
||||
typeOptions: {
|
||||
password: true,
|
||||
rows: 4,
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
authentication: ['keyPair'],
|
||||
},
|
||||
},
|
||||
description: 'Private PEM key for Key-pair authentication with Snowflake',
|
||||
},
|
||||
{
|
||||
displayName: 'Schema',
|
||||
|
||||
@@ -1,5 +1,43 @@
|
||||
import pick from 'lodash/pick';
|
||||
import type snowflake from 'snowflake-sdk';
|
||||
|
||||
const commonConnectionFields = [
|
||||
'account',
|
||||
'database',
|
||||
'schema',
|
||||
'warehouse',
|
||||
'role',
|
||||
'clientSessionKeepAlive',
|
||||
] as const;
|
||||
|
||||
export type SnowflakeCredential = Pick<
|
||||
snowflake.ConnectionOptions,
|
||||
(typeof commonConnectionFields)[number]
|
||||
> &
|
||||
(
|
||||
| {
|
||||
authentication: 'password';
|
||||
username?: string;
|
||||
password?: string;
|
||||
}
|
||||
| {
|
||||
authentication: 'keyPair';
|
||||
privateKey: string;
|
||||
}
|
||||
);
|
||||
|
||||
export const getConnectionOptions = (credential: SnowflakeCredential) => {
|
||||
const connectionOptions: snowflake.ConnectionOptions = pick(credential, commonConnectionFields);
|
||||
if (credential.authentication === 'keyPair') {
|
||||
connectionOptions.authenticator = 'SNOWFLAKE_JWT';
|
||||
connectionOptions.privateKey = credential.privateKey;
|
||||
} else {
|
||||
connectionOptions.username = credential.username;
|
||||
connectionOptions.password = credential.password;
|
||||
}
|
||||
return connectionOptions;
|
||||
};
|
||||
|
||||
export async function connect(conn: snowflake.Connection) {
|
||||
return await new Promise<void>((resolve, reject) => {
|
||||
conn.connect((error) => (error ? reject(error) : resolve()));
|
||||
|
||||
@@ -10,7 +10,13 @@ import snowflake from 'snowflake-sdk';
|
||||
|
||||
import { getResolvables } from '@utils/utilities';
|
||||
|
||||
import { connect, destroy, execute } from './GenericFunctions';
|
||||
import {
|
||||
connect,
|
||||
destroy,
|
||||
execute,
|
||||
getConnectionOptions,
|
||||
type SnowflakeCredential,
|
||||
} from './GenericFunctions';
|
||||
|
||||
export class Snowflake implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
@@ -164,16 +170,14 @@ export class Snowflake implements INodeType {
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const credentials = (await this.getCredentials(
|
||||
'snowflake',
|
||||
)) as unknown as snowflake.ConnectionOptions;
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
let responseData;
|
||||
const credentials = await this.getCredentials<SnowflakeCredential>('snowflake');
|
||||
|
||||
const connection = snowflake.createConnection(credentials);
|
||||
const connectionOptions = getConnectionOptions(credentials);
|
||||
const connection = snowflake.createConnection(connectionOptions);
|
||||
|
||||
await connect(connection);
|
||||
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
const items = this.getInputData();
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
|
||||
@@ -189,7 +193,7 @@ export class Snowflake implements INodeType {
|
||||
query = query.replace(resolvable, this.evaluateExpression(resolvable, i) as string);
|
||||
}
|
||||
|
||||
responseData = await execute(connection, query, []);
|
||||
const responseData = await execute(connection, query, []);
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData: { item: i } },
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import { getConnectionOptions } from '../GenericFunctions';
|
||||
|
||||
describe('getConnectionOptions', () => {
|
||||
const commonOptions = {
|
||||
account: 'test-account',
|
||||
database: 'test-database',
|
||||
schema: 'test-schema',
|
||||
warehouse: 'test-warehouse',
|
||||
role: 'test-role',
|
||||
clientSessionKeepAlive: true,
|
||||
};
|
||||
|
||||
describe('should return connection options', () => {
|
||||
it('with username and password for password authentication', () => {
|
||||
const result = getConnectionOptions({
|
||||
...commonOptions,
|
||||
authentication: 'password',
|
||||
username: 'test-username',
|
||||
password: 'test-password',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
...commonOptions,
|
||||
username: 'test-username',
|
||||
password: 'test-password',
|
||||
});
|
||||
});
|
||||
|
||||
it('with private key for keyPair authentication', () => {
|
||||
const result = getConnectionOptions({
|
||||
...commonOptions,
|
||||
authentication: 'keyPair',
|
||||
privateKey: 'test-private-key',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
...commonOptions,
|
||||
authenticator: 'SNOWFLAKE_JWT',
|
||||
privateKey: 'test-private-key',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user