Skip to content

Commit

Permalink
add tests for keypair auth
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-akolodziejczyk committed Dec 2, 2024
1 parent 8a3db08 commit 4a39875
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 165 deletions.
Binary file modified .github/workflows/parameters_aws_auth_tests.json.gpg
Binary file not shown.
Binary file not shown.
Binary file added .github/workflows/rsa_keys/rsa_key.p8.gpg
Binary file not shown.
Binary file added .github/workflows/rsa_keys/rsa_key_invalid.p8.gpg
Binary file not shown.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ wss-*-agent.config
wss-unified-agent.jar
whitesource/
.nyc_output
rsa_*.p8
4 changes: 4 additions & 0 deletions ci/container/test_authentication.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ set -o pipefail
AUTH_PARAMETER_FILE=./.github/workflows/parameters_aws_auth_tests.json
eval $(jq -r '.authtestparams | to_entries | map("export \(.key)=\(.value|tostring)")|.[]' $AUTH_PARAMETER_FILE)

export SNOWFLAKE_AUTH_TEST_PRIVATE_KEY_PATH=./.github/workflows/rsa_keys/rsa_key.p8
export SNOWFLAKE_AUTH_TEST_ENCRYPTED_PRIVATE_KEY_PATH=./.github/workflows/rsa_keys/rsa_encrypted_key.p8
export SNOWFLAKE_AUTH_TEST_INVALID_PRIVATE_KEY_PATH=./.github/workflows/rsa_keys/rsa_key_invalid.p8

npm run test:authentication
3 changes: 3 additions & 0 deletions ci/test_authentication.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
export WORKSPACE=${WORKSPACE:-/tmp}

gpg --quiet --batch --yes --decrypt --passphrase="$PARAMETERS_SECRET" --output $THIS_DIR/../.github/workflows/parameters_aws_auth_tests.json "$THIS_DIR/../.github/workflows/parameters_aws_auth_tests.json.gpg"
gpg --quiet --batch --yes --decrypt --passphrase="$PARAMETERS_SECRET" --output $THIS_DIR/../.github/workflows/rsa_keys/rsa_encrypted_key.p8 "$THIS_DIR/../.github/workflows/rsa_keys/rsa_encrypted_key.p8.gpg"
gpg --quiet --batch --yes --decrypt --passphrase="$PARAMETERS_SECRET" --output $THIS_DIR/../.github/workflows/rsa_keys/rsa_key.p8 "$THIS_DIR/../.github/workflows/rsa_keys/rsa_key.p8.gpg"
gpg --quiet --batch --yes --decrypt --passphrase="$PARAMETERS_SECRET" --output $THIS_DIR/../.github/workflows/rsa_keys/rsa_key_invalid.p8 "$THIS_DIR/../.github/workflows/rsa_keys/rsa_key_invalid.p8.gpg"

docker run \
-v $(cd $THIS_DIR/.. && pwd):/mnt/host \
Expand Down
34 changes: 34 additions & 0 deletions test/authentication/connectionParameters.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const path = require('path');

Check failure on line 1 in test/authentication/connectionParameters.js

View workflow job for this annotation

GitHub Actions / Run lint

'path' is assigned a value but never used
const snowflakeAuthTestProtocol = process.env.SNOWFLAKE_AUTH_TEST_PROTOCOL;
const snowflakeAuthTestHost = process.env.SNOWFLAKE_AUTH_TEST_HOST;
const snowflakeAuthTestPort = process.env.SNOWFLAKE_AUTH_TEST_PORT;
Expand All @@ -13,6 +14,10 @@ const snowflakeAuthTestOauthClientSecret = process.env.SNOWFLAKE_AUTH_TEST_OAUTH
const snowflakeAuthTestDatabase = process.env.SNOWFLAKE_AUTH_TEST_DATABASE;
const snowflakeAuthTestWarehouse = process.env.SNOWFLAKE_AUTH_TEST_WAREHOUSE;
const snowflakeAuthTestSchema = process.env.SNOWFLAKE_AUTH_TEST_SCHEMA;
const snowflakeAuthTestPrivateKeyPath = process.env.SNOWFLAKE_AUTH_TEST_PRIVATE_KEY_PATH;
const snowflakeAuthTestInvalidPrivateKeyPath = process.env.SNOWFLAKE_AUTH_TEST_INVALID_PRIVATE_KEY_PATH;
const snowflakeAuthTestPrivateKeyPassword = process.env.SNOWFLAKE_AUTH_TEST_PRIVATE_KEY_PASSWORD;
const snowflakeAuthTestEncryptedPrivateKeyPath = process.env.SNOWFLAKE_AUTH_TEST_ENCRYPTED_PRIVATE_KEY_PATH;

const accessUrlAuthTests = snowflakeAuthTestProtocol + '://' + snowflakeAuthTestHost + ':' +
snowflakeAuthTestPort;
Expand Down Expand Up @@ -50,13 +55,42 @@ const oauth =
authenticator: 'OAUTH'
};

const keypairPrivateKey =
{
...baseParameters,
username: snowflakeAuthTestOktaUser,
authenticator: 'SNOWFLAKE_JWT'
};

const keypairPrivateKeyPath =
{
...baseParameters,
username: snowflakeAuthTestOktaUser,
privateKeyPath: snowflakeAuthTestPrivateKeyPath,
authenticator: 'SNOWFLAKE_JWT'
};

const keypairEncryptedPrivateKeyPath =
{
...baseParameters,
username: snowflakeAuthTestOktaUser,
privateKeyPass: snowflakeAuthTestPrivateKeyPassword,
privateKeyPath: snowflakeAuthTestEncryptedPrivateKeyPath,
authenticator: 'SNOWFLAKE_JWT'
};

exports.externalBrowser = externalBrowser;
exports.okta = okta;
exports.oauth = oauth;
exports.keypairPrivateKey = keypairPrivateKey;
exports.keypairPrivateKeyPath = keypairPrivateKeyPath;
exports.keypairEncryptedPrivateKeyPath = keypairEncryptedPrivateKeyPath;
exports.snowflakeTestBrowserUser = snowflakeAuthTestBrowserUser;
exports.snowflakeAuthTestOktaUser = snowflakeAuthTestOktaUser;
exports.snowflakeAuthTestOktaPass = snowflakeAuthTestOktaPass;
exports.snowflakeAuthTestRole = snowflakeAuthTestRole;
exports.snowflakeAuthTestOauthClientId = snowflakeAuthTestOauthClientId;
exports.snowflakeAuthTestOauthClientSecret = snowflakeAuthTestOauthClientSecret;
exports.snowflakeAuthTestOauthUrl = snowflakeAuthTestOauthUrl;
exports.snowflakeAuthTestPrivateKeyPath = snowflakeAuthTestPrivateKeyPath;
exports.snowflakeAuthTestInvalidPrivateKeyPath = snowflakeAuthTestInvalidPrivateKeyPath;
93 changes: 93 additions & 0 deletions test/authentication/testKeyPair.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
const AuthTest = require('./authTestsBaseClass');
const connParameters = require('./connectionParameters');
const snowflake = require('../../lib/snowflake');
const path = require('path');
const assert = require('node:assert');
const fs = require('fs').promises;


describe('Key-pair authentication', function () {
let authTest;

beforeEach(async () => {
authTest = new AuthTest();
});

afterEach(async () => {
await authTest.destroyConnection();
});

describe('Private key', function () {
it('Successful connection', async function () {
const privateKey = await getFileContent(connParameters.snowflakeAuthTestPrivateKeyPath);
const connectionOption = { ... connParameters.keypairPrivateKey, privateKey: privateKey };
authTest.createConnection(connectionOption);
await authTest.connectAsync();
authTest.verifyNoErrorWasThrown();
await authTest.verifyConnectionIsUp();
});

it('Invalid private key format', async function () {
const invalidPrivateKeyFormat = 'invalidKey';
const connectionOption = { ... connParameters.keypairPrivateKey, privateKey: invalidPrivateKeyFormat };
try {
snowflake.createConnection(connectionOption);
assert.fail('Expected error was not thrown');
} catch (err) {
assert.strictEqual(err.message, 'Invalid private key. The specified value must be a string in pem format of type pkcs8');
}
});

it('Invalid private key', async function () {
const privateKey = await getFileContent(connParameters.snowflakeAuthTestInvalidPrivateKeyPath);
const connectionOption = { ... connParameters.keypairPrivateKey, privateKey: privateKey };
authTest.createConnection(connectionOption);
await authTest.connectAsync();
assert.match(authTest.error?.message, /JWT token is invalid./);
await authTest.verifyConnectionIsNotUp('Unable to perform operation using terminated connection.');
});
});

describe('Private key path', function () {
it('Successful connection', async function () {
const connectionOption = connParameters.keypairPrivateKeyPath;
authTest.createConnection(connectionOption);
await authTest.connectAsync();
authTest.verifyNoErrorWasThrown();
await authTest.verifyConnectionIsUp();
});

it('Invalid private key', async function () {
const connectionOption = { ...connParameters.keypairPrivateKeyPath, privateKeyPath: connParameters.snowflakeAuthTestInvalidPrivateKeyPath };
authTest.createConnection(connectionOption);
await authTest.connectAsync();
assert.match(authTest.error?.message, /JWT token is invalid./);
await authTest.verifyConnectionIsNotUp('Unable to perform operation using terminated connection.');
});

it('Successful connection using encrypted private key', async function () {
const connectionOption = connParameters.keypairEncryptedPrivateKeyPath;
authTest.createConnection(connectionOption);
await authTest.connectAsync();
authTest.verifyNoErrorWasThrown();
await authTest.verifyConnectionIsUp();
});

it('Invalid private key password', async function () {
const connectionOption = { ...connParameters.keypairEncryptedPrivateKeyPath, privateKeyPass: 'invalid' };
authTest.createConnection(connectionOption);
await authTest.connectAsync();
assert.match(authTest.error?.message, /bad decrypt/);
await authTest.verifyConnectionIsNotUp();
});
});
});

async function getFileContent(filePath) {
try {
const absolutePath = path.resolve(filePath);
return await fs.readFile(absolutePath, 'utf8');
} catch (err) {
throw new Error(`Error reading file: ${err.message}`);
}
}
58 changes: 0 additions & 58 deletions test/integration/connectionOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ const snowflakeTestRole = process.env.SNOWFLAKE_TEST_ROLE;
const snowflakeTestPassword = process.env.SNOWFLAKE_TEST_PASSWORD;
const snowflakeTestAdminUser = process.env.SNOWFLAKE_TEST_ADMIN_USER;
const snowflakeTestAdminPassword = process.env.SNOWFLAKE_TEST_ADMIN_PASSWORD;
const snowflakeTestPrivateKeyUser = process.env.SNOWFLAKE_JWT_TEST_USER;
const snowflakeTestPrivateKey = process.env.SNOWFLAKE_TEST_PRIVATE_KEY;
const snowflakeTestPrivateKeyPath = process.env.SNOWFLAKE_TEST_PRIVATE_KEY_PATH;
const snowflakeTestPrivateKeyPass = process.env.SNOWFLAKE_TEST_PRIVATE_KEY_PASS;
const snowflakeTestPrivateKeyPathUnencrypted = process.env.SNOWFLAKE_TEST_PRIVATE_KEY_PATH_UNENCRYPTED;
const snowflakeTestPasscode = process.env.SNOWFLAKE_TEST_PASSCODE;

if (snowflakeTestProtocol === undefined) {
Expand Down Expand Up @@ -83,55 +78,6 @@ const wrongPwd =
account: snowflakeTestAccount
};

const keypairPrivateKey =
{
accessUrl: accessUrl,
username: snowflakeTestPrivateKeyUser,
account: snowflakeTestAccount,
warehouse: snowflakeTestWarehouse,
database: snowflakeTestDatabase,
schema: snowflakeTestSchema,
role: snowflakeTestRole,
privateKey: snowflakeTestPrivateKey,
authenticator: 'SNOWFLAKE_JWT'
};

const keypairPathEncrypted =
{
accessUrl: accessUrl,
username: snowflakeTestPrivateKeyUser,
account: snowflakeTestAccount,
warehouse: snowflakeTestWarehouse,
database: snowflakeTestDatabase,
schema: snowflakeTestSchema,
role: snowflakeTestRole,
privateKeyPath: snowflakeTestPrivateKeyPath,
privateKeyPass: snowflakeTestPrivateKeyPass,
authenticator: 'SNOWFLAKE_JWT'
};

const keypairPathUnencrypted =
{
accessUrl: accessUrl,
username: snowflakeTestPrivateKeyUser,
account: snowflakeTestAccount,
warehouse: snowflakeTestWarehouse,
database: snowflakeTestDatabase,
schema: snowflakeTestSchema,
role: snowflakeTestRole,
privateKeyPath: snowflakeTestPrivateKeyPathUnencrypted,
authenticator: 'SNOWFLAKE_JWT'
};

const keypairWrongToken =
{
accessUrl: accessUrl,
username: 'node',
account: snowflakeTestAccount,
privateKey: snowflakeTestPrivateKey,
authenticator: 'SNOWFLAKE_JWT'
};

const MFA = {
...valid,
authenticator: 'USER_PWD_MFA_AUTHENTICATOR',
Expand Down Expand Up @@ -166,10 +112,6 @@ exports.wrongUserName = wrongUserName;
exports.wrongPwd = wrongPwd;
exports.accessUrl = accessUrl;
exports.account = snowflakeTestAccount;
exports.keypairPrivateKey = keypairPrivateKey;
exports.keypairPathEncrypted = keypairPathEncrypted;
exports.keypairPathUnencrypted = keypairPathUnencrypted;
exports.keypairWrongToken = keypairWrongToken;
exports.privatelink = privatelink;
exports.connectionWithProxy = connectionWithProxy;
exports.MFA = MFA;
107 changes: 0 additions & 107 deletions test/integration/testManualConnection.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,113 +101,6 @@ if (process.env.RUN_MANUAL_TESTS_ONLY === 'true') {
});
});
});

describe('Connection test - keypair', function () {
it('Simple Connect - specify private key', function (done) {
const connection = snowflake.createConnection(
connOption.keypairPrivateKey
);

async.series([
function (callback) {
connection.connect(function (err) {
done(err);
assert.ok(!err, JSON.stringify(err));
callback();
});
},
function (callback) {
assert.ok(connection.isUp(), 'not active');
callback();
},
function (callback) {
connection.destroy(function (err) {
assert.ok(!err, JSON.stringify(err));
callback();
});
},
function (callback) {
assert.ok(!connection.isUp(), 'still active');
callback();
},
]);
});

it('Simple Connect - specify encrypted private key path and passphrase', function (done) {
const connection = snowflake.createConnection(
connOption.keypairPathEncrypted
);

async.series([
function (callback) {
connection.connect(function (err) {
done(err);
assert.ok(!err, JSON.stringify(err));
callback();
});
},
function (callback) {
assert.ok(connection.isUp(), 'not active');
callback();
},
function (callback) {
connection.destroy(function (err) {
assert.ok(!err, JSON.stringify(err));
callback();
});
},
function (callback) {
assert.ok(!connection.isUp(), 'still active');
callback();
},
]);
});

it('Simple Connect - specify unencrypted private key path without passphrase', function (done) {
const connection = snowflake.createConnection(
connOption.keypairPathEncrypted
);

async.series([
function (callback) {
connection.connect(function (err) {
done(err);
assert.ok(!err, JSON.stringify(err));
callback();
});
},
function (callback) {
assert.ok(connection.isUp(), 'not active');
callback();
},
function (callback) {
connection.destroy(function (err) {
assert.ok(!err, JSON.stringify(err));
callback();
});
},
function (callback) {
assert.ok(!connection.isUp(), 'still active');
callback();
},
]);
});

it('Wrong JWT token', function (done) {
const connection = snowflake.createConnection(
connOption.keypairWrongToken
);
connection.connect(function (err) {
try {
assert.ok(err, 'Incorrect JWT token is passed.');
assert.equal('JWT token is invalid.', err['message']);
done();
} catch (err) {
done(err);
}
});
});
});
});

describe('keepAlive test', function () {
Expand Down

0 comments on commit 4a39875

Please sign in to comment.