mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 01:56:46 +00:00
fix(Snowflake Node): Fix key-pair credentials (#16635)
Co-authored-by: Elias Meire <elias@meire.dev> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
This commit is contained in:
@@ -52,11 +52,6 @@ export class Snowflake implements ICredentialType {
|
|||||||
name: 'username',
|
name: 'username',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: '',
|
default: '',
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
authentication: ['password'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Password',
|
displayName: 'Password',
|
||||||
@@ -87,7 +82,19 @@ export class Snowflake implements ICredentialType {
|
|||||||
authentication: ['keyPair'],
|
authentication: ['keyPair'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
description: 'Private PEM key for Key-pair authentication with Snowflake',
|
description:
|
||||||
|
'Private PEM key for Key-pair authentication with Snowflake, follow guide <a href="https://docs.snowflake.com/en/user-guide/key-pair-auth" target="_blank">here</a>',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Passphrase',
|
||||||
|
name: 'passphrase',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description:
|
||||||
|
'If the private key is encrypted, you must provide the passphrase used to encrypt it',
|
||||||
|
typeOptions: {
|
||||||
|
password: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Schema',
|
displayName: 'Schema',
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
import { createPrivateKey } from 'crypto';
|
||||||
import pick from 'lodash/pick';
|
import pick from 'lodash/pick';
|
||||||
import type snowflake from 'snowflake-sdk';
|
import type snowflake from 'snowflake-sdk';
|
||||||
|
|
||||||
|
import { formatPrivateKey } from '@utils/utilities';
|
||||||
|
|
||||||
const commonConnectionFields = [
|
const commonConnectionFields = [
|
||||||
'account',
|
'account',
|
||||||
'database',
|
'database',
|
||||||
@@ -22,15 +25,35 @@ export type SnowflakeCredential = Pick<
|
|||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
authentication: 'keyPair';
|
authentication: 'keyPair';
|
||||||
|
username: string;
|
||||||
privateKey: string;
|
privateKey: string;
|
||||||
|
passphrase?: string;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const extractPrivateKey = (credential: { privateKey: string; passphrase?: string }) => {
|
||||||
|
const key = formatPrivateKey(credential.privateKey as string);
|
||||||
|
|
||||||
|
if (!credential.passphrase) return key;
|
||||||
|
|
||||||
|
const privateKeyObject = createPrivateKey({
|
||||||
|
key,
|
||||||
|
format: 'pem',
|
||||||
|
passphrase: credential.passphrase as string,
|
||||||
|
});
|
||||||
|
|
||||||
|
return privateKeyObject.export({
|
||||||
|
format: 'pem',
|
||||||
|
type: 'pkcs8',
|
||||||
|
}) as string;
|
||||||
|
};
|
||||||
|
|
||||||
export const getConnectionOptions = (credential: SnowflakeCredential) => {
|
export const getConnectionOptions = (credential: SnowflakeCredential) => {
|
||||||
const connectionOptions: snowflake.ConnectionOptions = pick(credential, commonConnectionFields);
|
const connectionOptions: snowflake.ConnectionOptions = pick(credential, commonConnectionFields);
|
||||||
if (credential.authentication === 'keyPair') {
|
if (credential.authentication === 'keyPair') {
|
||||||
connectionOptions.authenticator = 'SNOWFLAKE_JWT';
|
connectionOptions.authenticator = 'SNOWFLAKE_JWT';
|
||||||
connectionOptions.privateKey = credential.privateKey;
|
connectionOptions.username = credential.username;
|
||||||
|
connectionOptions.privateKey = extractPrivateKey(credential);
|
||||||
} else {
|
} else {
|
||||||
connectionOptions.username = credential.username;
|
connectionOptions.username = credential.username;
|
||||||
connectionOptions.password = credential.password;
|
connectionOptions.password = credential.password;
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
|
import crypto from 'crypto';
|
||||||
|
|
||||||
import { getConnectionOptions } from '../GenericFunctions';
|
import { getConnectionOptions } from '../GenericFunctions';
|
||||||
|
|
||||||
|
jest.mock('crypto');
|
||||||
|
|
||||||
describe('getConnectionOptions', () => {
|
describe('getConnectionOptions', () => {
|
||||||
const commonOptions = {
|
const commonOptions = {
|
||||||
account: 'test-account',
|
account: 'test-account',
|
||||||
@@ -29,12 +33,43 @@ describe('getConnectionOptions', () => {
|
|||||||
it('with private key for keyPair authentication', () => {
|
it('with private key for keyPair authentication', () => {
|
||||||
const result = getConnectionOptions({
|
const result = getConnectionOptions({
|
||||||
...commonOptions,
|
...commonOptions,
|
||||||
|
username: 'test-username',
|
||||||
authentication: 'keyPair',
|
authentication: 'keyPair',
|
||||||
privateKey: 'test-private-key',
|
privateKey: 'test-private-key',
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
...commonOptions,
|
...commonOptions,
|
||||||
|
username: 'test-username',
|
||||||
|
authenticator: 'SNOWFLAKE_JWT',
|
||||||
|
privateKey: 'test-private-key',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with private key for keyPair authentication and passphrase', () => {
|
||||||
|
const createPrivateKeySpy = jest.spyOn(crypto, 'createPrivateKey').mockImplementation(
|
||||||
|
() =>
|
||||||
|
({
|
||||||
|
export: () => 'test-private-key',
|
||||||
|
}) as unknown as crypto.KeyObject,
|
||||||
|
);
|
||||||
|
const result = getConnectionOptions({
|
||||||
|
...commonOptions,
|
||||||
|
username: 'test-username',
|
||||||
|
authentication: 'keyPair',
|
||||||
|
privateKey: 'encrypted-private-key',
|
||||||
|
passphrase: 'test-passphrase',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(createPrivateKeySpy).toHaveBeenCalledWith({
|
||||||
|
key: 'encrypted-private-key',
|
||||||
|
format: 'pem',
|
||||||
|
passphrase: 'test-passphrase',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
...commonOptions,
|
||||||
|
username: 'test-username',
|
||||||
authenticator: 'SNOWFLAKE_JWT',
|
authenticator: 'SNOWFLAKE_JWT',
|
||||||
privateKey: 'test-private-key',
|
privateKey: 'test-private-key',
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user