From e6f30aa5242661aa0e0e6e01c252d38ea68e4fcd Mon Sep 17 00:00:00 2001 From: Przemyslaw Motacki Date: Wed, 4 Dec 2024 08:01:53 +0100 Subject: [PATCH 1/2] Added point about types to PR checklist (#920) --- .github/PULL_REQUEST_TEMPLATE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index b7d430c57..766856111 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -5,5 +5,6 @@ Please explain the changes you made here. - [ ] Format code according to the existing code style (run `npm run lint:check -- CHANGED_FILES` and fix problems in changed code) - [ ] Create tests which fail without the change (if possible) - [ ] Make all tests (unit and integration) pass (`npm run test:unit` and `npm run test:integration`) +- [ ] Extend the types in index.d.ts file (if necessary) - [ ] Extend the README / documentation and ensure is properly displayed (if necessary) - [ ] Provide JIRA issue id (if possible) or GitHub issue id in commit message From f6d50ea937e9c87a275ecba20a50dbc66c22bf9d Mon Sep 17 00:00:00 2001 From: Adam Kolodziejczyk Date: Wed, 4 Dec 2024 10:22:58 +0100 Subject: [PATCH 2/2] SNOW-1739611 add automated tests for okta, oauth and keypair (#976) --- .../parameters_aws_auth_tests.json.gpg | Bin 386 -> 550 bytes .../rsa_keys/rsa_encrypted_key.p8.gpg | Bin 0 -> 1511 bytes .github/workflows/rsa_keys/rsa_key.p8.gpg | Bin 0 -> 1401 bytes .../workflows/rsa_keys/rsa_key_invalid.p8.gpg | Bin 0 -> 1409 bytes .gitignore | 1 + ci/container/test_authentication.sh | 4 + ci/test_authentication.sh | 5 +- test/authentication/authTestsBaseClass.js | 69 +++++++ test/authentication/connectionParameters.js | 93 +++++++-- test/authentication/testExternalBrowser.js | 124 ++++-------- test/authentication/testKeyPair.js | 94 +++++++++ test/authentication/testOauth.js | 67 +++++++ test/authentication/testOkta.js | 39 ++++ test/integration/connectionOptions.js | 101 ---------- test/integration/testManualConnection.js | 189 ------------------ 15 files changed, 396 insertions(+), 390 deletions(-) create mode 100644 .github/workflows/rsa_keys/rsa_encrypted_key.p8.gpg create mode 100644 .github/workflows/rsa_keys/rsa_key.p8.gpg create mode 100644 .github/workflows/rsa_keys/rsa_key_invalid.p8.gpg create mode 100644 test/authentication/authTestsBaseClass.js create mode 100644 test/authentication/testKeyPair.js create mode 100644 test/authentication/testOauth.js create mode 100644 test/authentication/testOkta.js diff --git a/.github/workflows/parameters_aws_auth_tests.json.gpg b/.github/workflows/parameters_aws_auth_tests.json.gpg index 6143d3b24450aa2939b2d861f086afdd13dde001..bea557c1340e79134e2fef7d057b0a4b5367351a 100644 GIT binary patch literal 550 zcmV+>0@?kH4Fm}T2-FugK{~32dH>Ss0b<`~^&DSip?`>%SG9?1!L0F6kN1 z1H(=yjN#Jcj%jjXe7rfzTZFwPJqWmp*qI5X)Wgv`-d`hhNAO*&z|GapXV!+t zL|fp@LZ-!r4BnA8i%`3Sc4Y=W)iU_fkFGJ8a#`P1$!%jom$X*pILH?B4fHk*>=7=#r2C$b3G}%VOrukil0Q- zw9J>$9+(182dZSa5Df=^_IQ35Xq$9*Wmd2{{A*&y(si z&;_vnF>5&C8kN?uZumObRZZz#8`>m!+c*zlaGs|(8zH+(`)YcT; zDvefsX#EBtNvBp{M%68a(T`h;k@Ruw4(WKeFWu5C9J?^MP7%PP6oG1lu*7gWYZ;Dy zu`u?J?Tg+!Ft%oJ>vVJm|UYVz%q9 z;BSn@FH@3?`jW>W<8`LhPGP@p>W*wq|J&hoN2Sc}@p_GxE%Q{KmXeg=r|h*I^*mGS z0j33mPGb49<7#5Z&sl6`qCX5dhaI`=yuDWENYkM_d6<(5q{g5QL|ba_f*5l}_diNr z-+7+m`TBLz9-nPrryFZb%bDm{cD}xz;s!l>S=M4+IoTvK#*1Ue)n!8zpItJqfg!38 z9PrdGuJpVFq8l<<$9emZFaDw#NGEl{E@=A9Z#J{TYJI}0GZ)d`Ne*H>6?eizUvl}T gGyPrtXT$a~!~X3--MO;^Z$=8~)S3MK=;U4yjH2txg8%>k diff --git a/.github/workflows/rsa_keys/rsa_encrypted_key.p8.gpg b/.github/workflows/rsa_keys/rsa_encrypted_key.p8.gpg new file mode 100644 index 0000000000000000000000000000000000000000..3643cdb1ffc804a1ad85fc245cdb7b2c40a208a3 GIT binary patch literal 1511 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 HBt6`SeZ8+W literal 0 HcmV?d00001 diff --git a/.github/workflows/rsa_keys/rsa_key_invalid.p8.gpg b/.github/workflows/rsa_keys/rsa_key_invalid.p8.gpg new file mode 100644 index 0000000000000000000000000000000000000000..3d2442a7c8c319f53ac8d6af8b12bcff78a364da GIT binary patch literal 1409 zcmV-{1%CRB4Fm}T2oOE^p^$#mNB`350dCH$DrP24&;&c@7=1}8SgJ`t2Jhbld~Tl6 z0G^#)CvI%Mkv<0lD%2OXL2~H0fW4z>z(2$S(~kytf&DxtVS*9dICkcS+ffG~Z})uY zB`zl9fytg}f2tY#aS$7$`dU!eSG^#6UQrisepTgBF1~k(CjXE)AYQUTzEc--YbK}u zfsLh_J)DoV(9go0v$9Lt*l~ZQa4WUnT`63VpmmGnc8nyJjA-hQ*mB*#+OG1a7ASWB ze9Raxfi?A`6~)p!PMM?gM{9IagV-L({Z#oVi}JuWJi|)kx!>=yOrS9Gq5B-*7@l)) z{1{^`_X~Fv&Doaj))DjJ-L^W*9SS1i*gV(ca; zCE#)|nKO-5uH?~G%8AdGged-2(o6$lg?(fJ4+X01x(E6BVUjyzwz#mG9;gAgohtx= z+&#TCKz~*>R9}QeY_}#N+573zc^{U_Y4gN;>sP>M4jpt_~jH>I~>|f z@HAD^fpJJ@X(hwEc(W@+EO*05}n$URL!)yDLn$0&x z^Y^TAlbtX(ef+HM*}-W=_w*kkq{JQnh7gX=9dA%?Uj;erdH&Br>=oUw^F_@8# zLANF=N8ti7r*?em#%jnoCdOAhX5?oaWg<8t>FGIOrHxIeM@3$j&RnDKL$ZO^m($@tnS=DJfQX8u0o%kqgA|Ez(3Xdev20sf`K49<(%)+s=$Lqn7cLK zcYr+C2QO{oaBUN&oPOqMtoXcn*^>5AfVW*-OjbrWWwCs<;gyMKQ_0~e9`Pd2^zd>R zPX&|_DioP6LIMMh`;dZ*njth+Ku%Gg29O|p4;>}oQFCY>4qILxtFqk;)Bc%ZF3f)+`?qFwQwiKph#32+tK`; z=hK)V8LHpTW2$|D8@l``@kxvrP5`g*-?MM*%hfFnknxU z8cM#TPhCW@difY~FYFCSv86g8s5|^8##L%J7Ja|v+O~qJJ-y}x5Zh}k_BaO;v=2G` z+ny&dA%H9;I6Ct#0(NHo*n(D4L>KHT*TeodHh;rXV#}gki)mI%l-}(jmh@%C=yj&+ zS&Cj=Jp0|>K~z)V(Z4UOueoNTy4huPrFV~!yPZp;MUU5kNFE>N@{W&7(!v#LnSkIr zRv~<=iZTb7zF~)46dwn2zL%K#j?aMpW8ffUfnkv<{;fKOMqmyh5>jTxsWit;I&THD zL{Eh#W~~%SQQ8F3URzklBVsset&u0^faeR4!Z66t3mnorN#pDIQGk~3E%IowD9NC0 Plk!d)KNyEuj^Ur;bOOha literal 0 HcmV?d00001 diff --git a/.gitignore b/.gitignore index 785a1a3c7..5c1e6c21c 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ wss-*-agent.config wss-unified-agent.jar whitesource/ .nyc_output +rsa_*.p8 diff --git a/ci/container/test_authentication.sh b/ci/container/test_authentication.sh index cffe7336e..31e18dde5 100755 --- a/ci/container/test_authentication.sh +++ b/ci/container/test_authentication.sh @@ -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 diff --git a/ci/test_authentication.sh b/ci/test_authentication.sh index 725520798..49ab3ae26 100755 --- a/ci/test_authentication.sh +++ b/ci/test_authentication.sh @@ -5,10 +5,13 @@ 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 \ -v $WORKSPACE:/mnt/workspace \ --rm \ - nexus.int.snowflakecomputing.com:8086/docker/snowdrivers-test-external-browser:2 \ + nexus.int.snowflakecomputing.com:8086/docker/snowdrivers-test-external-browser:3 \ "/mnt/host/ci/container/test_authentication.sh" diff --git a/test/authentication/authTestsBaseClass.js b/test/authentication/authTestsBaseClass.js new file mode 100644 index 000000000..74308399a --- /dev/null +++ b/test/authentication/authTestsBaseClass.js @@ -0,0 +1,69 @@ +const assert = require('assert'); +const testUtil = require('../integration/testUtil'); +const snowflake = require('../../lib/snowflake'); + +class AuthTest { + constructor() { + this.connection = null; + this.error = null; + this.callbackCompleted = false; + } + + connectAsyncCallback() { + return (err) => { + this.error = err; + this.callbackCompleted = true; + }; + } + + async waitForCallbackCompletion() { + const timeout = Date.now() + 5000; + while (Date.now() < timeout) { + await new Promise(resolve => setTimeout(resolve, 100)); + if (this.callbackCompleted) { + return; + } + } + throw new Error('Connection callback did not complete'); + } + + async createConnection(connectionOption) { + this.connection = snowflake.createConnection(connectionOption); + } + + async connectAsync() { + await this.connection.connectAsync(this.connectAsyncCallback()); + await this.waitForCallbackCompletion(); + } + + async verifyConnectionIsUp() { + assert.ok(await this.connection.isValidAsync(), 'Connection is not valid'); + await testUtil.executeCmdAsync(this.connection, 'Select 1'); + } + + async verifyConnectionIsNotUp(message = 'Unable to perform operation because a connection was never established.') { + assert.ok(!(this.connection.isUp()), 'Connection should not be up'); + try { + await testUtil.executeCmdAsync(this.connection, 'Select 1'); + assert.fail('Expected error was not thrown'); + } catch (error) { + assert.strictEqual(error.message, message); + } + } + + async destroyConnection() { + if (this.connection !== undefined && this.connection !== null && this.connection.isUp()) { + await testUtil.destroyConnectionAsync(this.connection); + } + } + + verifyNoErrorWasThrown() { + assert.equal(this.error, null); + } + + verifyErrorWasThrown(message) { + assert.strictEqual(this.error?.message, message); + } +} + +module.exports = AuthTest; diff --git a/test/authentication/connectionParameters.js b/test/authentication/connectionParameters.js index 620285674..7d9d10745 100644 --- a/test/authentication/connectionParameters.js +++ b/test/authentication/connectionParameters.js @@ -3,28 +3,93 @@ const snowflakeAuthTestHost = process.env.SNOWFLAKE_AUTH_TEST_HOST; const snowflakeAuthTestPort = process.env.SNOWFLAKE_AUTH_TEST_PORT; const snowflakeAuthTestAccount = process.env.SNOWFLAKE_AUTH_TEST_ACCOUNT; const snowflakeAuthTestRole = process.env.SNOWFLAKE_AUTH_TEST_ROLE; -const snowflakeTestBrowserUser = process.env.SNOWFLAKE_AUTH_TEST_BROWSER_USER; +const snowflakeAuthTestBrowserUser = process.env.SNOWFLAKE_AUTH_TEST_BROWSER_USER; +const snowflakeAuthTestOktaAuth = process.env.SNOWFLAKE_AUTH_TEST_OKTA_AUTH; +const snowflakeAuthTestOktaUser = process.env.SNOWFLAKE_AUTH_TEST_OKTA_USER; const snowflakeAuthTestOktaPass = process.env.SNOWFLAKE_AUTH_TEST_OKTA_PASS; +const snowflakeAuthTestOauthUrl = process.env.SNOWFLAKE_AUTH_TEST_OAUTH_URL; +const snowflakeAuthTestOauthClientId = process.env.SNOWFLAKE_AUTH_TEST_OAUTH_CLIENT_ID; +const snowflakeAuthTestOauthClientSecret = process.env.SNOWFLAKE_AUTH_TEST_OAUTH_CLIENT_SECRET; 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; + snowflakeAuthTestPort; + +const baseParameters = + { + accessUrl: accessUrlAuthTests, + account: snowflakeAuthTestAccount, + role: snowflakeAuthTestRole, + host: snowflakeAuthTestHost, + warehouse: snowflakeAuthTestWarehouse, + database: snowflakeAuthTestDatabase, + schema: snowflakeAuthTestSchema, + }; const externalBrowser = - { - accessUrl: accessUrlAuthTests, - username: snowflakeTestBrowserUser, - account: snowflakeAuthTestAccount, - role: snowflakeAuthTestRole, - host: snowflakeAuthTestHost, - warehouse: snowflakeAuthTestWarehouse, - database: snowflakeAuthTestDatabase, - schema: snowflakeAuthTestSchema, - authenticator: 'EXTERNALBROWSER' - }; + { + ...baseParameters, + username: snowflakeAuthTestBrowserUser, + authenticator: 'EXTERNALBROWSER' + }; + +const okta = + { + ...baseParameters, + username: snowflakeAuthTestOktaUser, + password: snowflakeAuthTestOktaPass, + authenticator: snowflakeAuthTestOktaAuth + }; + +const oauth = + { + ...baseParameters, + username: snowflakeAuthTestOktaUser, + 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.snowflakeTestBrowserUser = snowflakeTestBrowserUser; +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; diff --git a/test/authentication/testExternalBrowser.js b/test/authentication/testExternalBrowser.js index 3ab3ef75b..ade0f03ce 100644 --- a/test/authentication/testExternalBrowser.js +++ b/test/authentication/testExternalBrowser.js @@ -1,66 +1,64 @@ -const snowflake = require('../../lib/snowflake'); const assert = require('assert'); -const testUtil = require('../integration/testUtil'); const connParameters = require('./connectionParameters'); const { spawn } = require('child_process'); const Util = require('../../lib/util'); const JsonCredentialManager = require('../../lib/authentication/secure_storage/json_credential_manager'); +const AuthTest = require('./authTestsBaseClass.js'); describe('External browser authentication tests', function () { + const runAuthTestsManually = process.env.RUN_AUTH_TESTS_MANUALLY === 'true'; const cleanBrowserProcessesPath = '/externalbrowser/cleanBrowserProcesses.js'; const provideBrowserCredentialsPath = '/externalbrowser/provideBrowserCredentials.js'; const login = connParameters.snowflakeTestBrowserUser; const password = connParameters.snowflakeAuthTestOktaPass; - let connection, error, callbackCompleted; + let authTest; - before(async () => { + beforeEach(async () => { + authTest = new AuthTest(); await cleanBrowserProcesses(); }); afterEach(async () => { - await cleanBrowserProcesses(); - await destroyConnection(connection); - callbackCompleted = false; - error = undefined; + await authTest.destroyConnection(); }); describe('External browser tests', async () => { it('Successful connection', async () => { const connectionOption = { ...connParameters.externalBrowser, clientStoreTemporaryCredential: false }; - connection = await snowflake.createConnection(connectionOption); + authTest.createConnection(connectionOption); const provideCredentialsPromise = execWithTimeout('node', [provideBrowserCredentialsPath, 'success', login, password], 15000); - await connectAndProvideCredentials(connection, provideCredentialsPromise); - verifyNoErrorWasThrown(); - await verifyConnectionIsUp(connection); + await connectAndProvideCredentials(provideCredentialsPromise); + authTest.verifyNoErrorWasThrown(); + await authTest.verifyConnectionIsUp(); }); it('Mismatched Username', async () => { const connectionOption = { ...connParameters.externalBrowser, username: 'differentUsername', clientStoreTemporaryCredential: false }; - connection = await snowflake.createConnection(connectionOption); + authTest.createConnection(connectionOption); const provideCredentialsPromise = execWithTimeout('node', [provideBrowserCredentialsPath, 'success', login, password], 15000); - await connectAndProvideCredentials(connection, provideCredentialsPromise); - assert.strictEqual(error?.message, 'The user you were trying to authenticate as differs from the user currently logged in at the IDP.'); - await verifyConnectionIsNotUp(connection, 'Unable to perform operation using terminated connection.'); + await connectAndProvideCredentials(provideCredentialsPromise); + authTest.verifyErrorWasThrown('The user you were trying to authenticate as differs from the user currently logged in at the IDP.'); + await authTest.verifyConnectionIsNotUp('Unable to perform operation using terminated connection.'); }); it('Wrong credentials', async () => { const login = 'itsnotanaccount.com'; const password = 'fakepassword'; const connectionOption = { ...connParameters.externalBrowser, browserActionTimeout: 10000, clientStoreTemporaryCredential: false }; - connection = await snowflake.createConnection(connectionOption); + authTest.createConnection(connectionOption); const provideCredentialsPromise = execWithTimeout('node', [provideBrowserCredentialsPath, 'fail', login, password]); - await connectAndProvideCredentials(connection, provideCredentialsPromise); - assert.strictEqual(error?.message, 'Error while getting SAML token: Browser action timed out after 10000 ms.'); - await verifyConnectionIsNotUp(connection); + await connectAndProvideCredentials(provideCredentialsPromise); + authTest.verifyErrorWasThrown('Error while getting SAML token: Browser action timed out after 10000 ms.'); + await authTest.verifyConnectionIsNotUp(); }); it('External browser timeout', async () => { const connectionOption = { ...connParameters.externalBrowser, browserActionTimeout: 100, clientStoreTemporaryCredential: false }; - connection = await snowflake.createConnection(connectionOption); + authTest.createConnection(connectionOption); const connectToBrowserPromise = execWithTimeout('node', [provideBrowserCredentialsPath, 'timeout']); - await connectAndProvideCredentials(connection, connectToBrowserPromise); - assert.strictEqual(error?.message, 'Error while getting SAML token: Browser action timed out after 100 ms.'); - await verifyConnectionIsNotUp(connection); + await connectAndProvideCredentials(connectToBrowserPromise); + authTest.verifyErrorWasThrown('Error while getting SAML token: Browser action timed out after 100 ms.'); + await authTest.verifyConnectionIsNotUp(); }); }); @@ -75,11 +73,11 @@ describe('External browser authentication tests', function () { }); it('obtains the id token from the server and saves it on the local storage', async function () { - connection = snowflake.createConnection(connectionOption); + authTest.createConnection(connectionOption); const provideCredentialsPromise = execWithTimeout('node', [provideBrowserCredentialsPath, 'success', login, password], 15000); - await connectAndProvideCredentials(connection, provideCredentialsPromise); - verifyNoErrorWasThrown(); - await verifyConnectionIsUp(connection); + await connectAndProvideCredentials(provideCredentialsPromise); + authTest.verifyNoErrorWasThrown(); + await authTest.verifyConnectionIsUp(); }); it('the token is saved in the credential manager', async function () { @@ -88,19 +86,19 @@ describe('External browser authentication tests', function () { }); it('authenticates by token, browser credentials not needed', async function () { - connection = snowflake.createConnection(connectionOption); - await connection.connectAsync(connectAsyncCallback()); - verifyNoErrorWasThrown(); - await verifyConnectionIsUp(connection); + authTest.createConnection(connectionOption); + await authTest.connectAsync(); + authTest.verifyNoErrorWasThrown(); + await authTest.verifyConnectionIsUp(); }); it('opens browser okta authentication again when token is incorrect', async function () { await defaultCredentialManager.write(key, '1234'); - connection = snowflake.createConnection(connectionOption); + authTest.createConnection(connectionOption); const provideCredentialsPromise = execWithTimeout('node', [provideBrowserCredentialsPath, 'success', login, password], 15000); - await connectAndProvideCredentials(connection, provideCredentialsPromise); - verifyNoErrorWasThrown(); - await verifyConnectionIsUp(connection); + await connectAndProvideCredentials(provideCredentialsPromise); + authTest.verifyNoErrorWasThrown(); + await authTest.verifyConnectionIsUp(); }); it('refreshes the token for credential cache key', async function () { @@ -109,65 +107,21 @@ describe('External browser authentication tests', function () { }); }); - function connectAsyncCallback() { - return function (err) { - error = err; - callbackCompleted = true; - }; - } - - function verifyNoErrorWasThrown() { - assert.equal(error, null); - } - async function cleanBrowserProcesses() { - if (process.env.RUN_AUTH_TESTS_MANUALLY !== 'true') { + if (!runAuthTestsManually) { await execWithTimeout('node', [cleanBrowserProcessesPath], 15000); } } - async function connectAndProvideCredentials(connection, provideCredentialsPromise) { - if (process.env.RUN_AUTH_TESTS_MANUALLY === 'true') { - await connection.connectAsync(connectAsyncCallback()); + async function connectAndProvideCredentials(provideCredentialsPromise) { + if (runAuthTestsManually) { + await authTest.connectAsync(); } else { - await Promise.allSettled([connection.connectAsync(connectAsyncCallback()), provideCredentialsPromise]); - } - await waitForCallbackCompletion(); - } - - async function waitForCallbackCompletion() { - const timeout = Date.now() + 5000; - while (Date.now() < timeout) { - await new Promise(resolve => setTimeout(resolve, 100)); - if (callbackCompleted) { - return; - } + await Promise.allSettled([authTest.connectAsync(), provideCredentialsPromise]); } - throw new Error('Connection callback did not complete'); } }); -async function verifyConnectionIsUp(connection) { - assert.ok(await connection.isValidAsync(), 'Connection is not valid'); - await testUtil.executeCmdAsync(connection, 'Select 1'); -} - -async function verifyConnectionIsNotUp(connection, message = 'Unable to perform operation because a connection was never established.') { - assert.ok(!(connection.isUp()), 'Connection should not be up'); - try { - await testUtil.executeCmdAsync(connection, 'Select 1'); - assert.fail('Expected error was not thrown'); - } catch (error) { - assert.strictEqual(error.message, message); - } -} - -async function destroyConnection(connection) { - if (connection !== undefined && connection.isUp()) { - await testUtil.destroyConnectionAsync(connection); - } -} - function execWithTimeout(command, args, timeout = 5000) { return new Promise((resolve, reject) => { const child = spawn(command, args, { shell: true }); diff --git a/test/authentication/testKeyPair.js b/test/authentication/testKeyPair.js new file mode 100644 index 000000000..60b48df28 --- /dev/null +++ b/test/authentication/testKeyPair.js @@ -0,0 +1,94 @@ +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(); + }); + + //todo SNOW-1844747 improve error message + 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}`); + } +} diff --git a/test/authentication/testOauth.js b/test/authentication/testOauth.js new file mode 100644 index 000000000..5f1148626 --- /dev/null +++ b/test/authentication/testOauth.js @@ -0,0 +1,67 @@ +const assert = require('assert'); +const connParameters = require('./connectionParameters'); +const axios = require('axios'); +const { snowflakeAuthTestOktaUser, snowflakeAuthTestOktaPass, snowflakeAuthTestRole, snowflakeAuthTestOauthClientId, + snowflakeAuthTestOauthClientSecret, snowflakeAuthTestOauthUrl +} = require('./connectionParameters'); +const AuthTest = require('./authTestsBaseClass'); + + +describe('Oauth authentication', function () { + let authTest; + + beforeEach(async () => { + authTest = new AuthTest(); + }); + + afterEach(async () => { + await authTest.destroyConnection(); + }); + + it('Successful connection', async function () { + const token = await getToken(); + const connectionOption = { ...connParameters.oauth, token: token }; + authTest.createConnection(connectionOption); + await authTest.connectAsync(); + authTest.verifyNoErrorWasThrown(); + await authTest.verifyConnectionIsUp(); + }); + + it('Invalid token', async function () { + const connectionOption = { ...connParameters.oauth, token: 'invalidToken' }; + authTest.createConnection(connectionOption); + await authTest.connectAsync(); + authTest.verifyErrorWasThrown('Invalid OAuth access token. '); + await authTest.verifyConnectionIsNotUp('Unable to perform operation using terminated connection.'); + }); + + it('Mismatched username', async function () { + const token = await getToken(); + const connectionOption = { ...connParameters.oauth, username: 'itsnotanaccount.com', token: token }; + authTest.createConnection(connectionOption); + await authTest.connectAsync(); + authTest.verifyErrorWasThrown('The user you were trying to authenticate as differs from the user tied to the access token.'); + await authTest.verifyConnectionIsNotUp('Unable to perform operation using terminated connection.'); + }); +}); + +async function getToken() { + const response = await axios.post(snowflakeAuthTestOauthUrl, data, { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' + }, + auth: { + username: snowflakeAuthTestOauthClientId, + password: snowflakeAuthTestOauthClientSecret + } + }); + assert.strictEqual(response.status, 200, 'Failed to get access token'); + return response.data.access_token; +} + +const data = [ + `username=${snowflakeAuthTestOktaUser}`, + `password=${snowflakeAuthTestOktaPass}`, + 'grant_type=password', + `scope=session:role:${snowflakeAuthTestRole.toLowerCase()}` +].join('&'); diff --git a/test/authentication/testOkta.js b/test/authentication/testOkta.js new file mode 100644 index 000000000..1230bb0db --- /dev/null +++ b/test/authentication/testOkta.js @@ -0,0 +1,39 @@ +const connParameters = require('./connectionParameters'); +const AuthTest = require('./authTestsBaseClass'); + +describe('Okta authentication', function () { + let authTest; + + beforeEach(async () => { + authTest = new AuthTest(); + }); + + afterEach(async () => { + await authTest.destroyConnection(); + }); + + it('Successful connection', async function () { + const connectionOption = connParameters.okta; + authTest.createConnection(connectionOption); + await authTest.connectAsync(); + authTest.verifyNoErrorWasThrown(); + await authTest.verifyConnectionIsUp(); + }); + + it('Wrong credentials', async function () { + const connectionOption = { ...connParameters.okta, username: 'itsnotanaccount.com', password: 'fakepassword' }; + authTest.createConnection(connectionOption); + await authTest.connectAsync(); + authTest.verifyErrorWasThrown('Request failed with status code 401'); + await authTest.verifyConnectionIsNotUp(); + }); + + //todo SNOW-1844747 improve error message + it('Wrong okta url', async function () { + const connectionOption = { ...connParameters.okta, authenticator: 'https://testinvalidaccoount.com' }; + authTest.createConnection(connectionOption); + await authTest.connectAsync(); + authTest.verifyErrorWasThrown('Cannot read properties of null (reading \'ssoUrl\')'); + await authTest.verifyConnectionIsNotUp(); + }); +}); diff --git a/test/integration/connectionOptions.js b/test/integration/connectionOptions.js index 28185ff2e..88c56e344 100644 --- a/test/integration/connectionOptions.js +++ b/test/integration/connectionOptions.js @@ -16,16 +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 snowflakeTestOauthUser = process.env.SNOWFLAKE_TEST_OAUTH_USER; -const snowflakeTestToken = process.env.SNOWFLAKE_TEST_OAUTH_TOKEN; -const snowflakeTestOktaUser = process.env.SNOWFLAKE_TEST_OKTA_USER; -const snowflakeTestOktaPass = process.env.SNOWFLAKE_TEST_OKTA_PASS; -const snowflakeTestOktaAuth = process.env.SNOWFLAKE_TEST_OKTA_AUTH; const snowflakeTestPasscode = process.env.SNOWFLAKE_TEST_PASSCODE; if (snowflakeTestProtocol === undefined) { @@ -88,96 +78,12 @@ 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', passcode: snowflakeTestPasscode, }; -const oauth = -{ - accessUrl: accessUrl, - username: snowflakeTestOauthUser, - account: snowflakeTestAccount, - warehouse: snowflakeTestWarehouse, - database: snowflakeTestDatabase, - schema: snowflakeTestSchema, - role: snowflakeTestRole, - token: snowflakeTestToken, - authenticator: 'OAUTH' -}; - -const oauthMismatchUser = -{ - accessUrl: accessUrl, - username: 'node', - account: snowflakeTestAccount, - token: snowflakeTestToken, - authenticator: 'OAUTH' -}; - -const okta = -{ - accessUrl: accessUrl, - username: snowflakeTestOktaUser, - password: snowflakeTestOktaPass, - account: snowflakeTestAccount, - warehouse: snowflakeTestWarehouse, - database: snowflakeTestDatabase, - schema: snowflakeTestSchema, - role: snowflakeTestRole, - authenticator: snowflakeTestOktaAuth -}; - const privatelink = { accessUrl: accessUrl, @@ -206,13 +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.oauth = oauth; -exports.oauthMismatchUser = oauthMismatchUser; -exports.okta = okta; exports.privatelink = privatelink; exports.connectionWithProxy = connectionWithProxy; exports.MFA = MFA; diff --git a/test/integration/testManualConnection.js b/test/integration/testManualConnection.js index 57f148412..9fe3ad78d 100644 --- a/test/integration/testManualConnection.js +++ b/test/integration/testManualConnection.js @@ -3,7 +3,6 @@ */ const snowflake = require('./../../lib/snowflake'); -const async = require('async'); const assert = require('assert'); const connOption = require('./connectionOptions'); const testUtil = require('./testUtil'); @@ -13,87 +12,6 @@ const JsonCredentialManager = require('../../lib/authentication/secure_storage/j if (process.env.RUN_MANUAL_TESTS_ONLY === 'true') { describe('Run manual tests', function () { - describe('Connection test - oauth', function () { - it('Simple Connect', function (done) { - const connection = snowflake.createConnection(connOption.oauth); - - 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('Mismatched Username', function (done) { - const connection = snowflake.createConnection( - connOption.oauthMismatchUser - ); - connection.connect(function (err) { - try { - assert.ok( - err, - 'Logged in with different user than one on connection string' - ); - assert.equal( - 'The user you were trying to authenticate as differs from the user tied to the access token.', - err['message'] - ); - done(); - } catch (err) { - done(err); - } - }); - }); - }); - - describe('Connection test - okta', function () { - it('Simple Connect', function (done) { - const connection = snowflake.createConnection(connOption.okta); - - async.series([ - function (callback) { - connection.connectAsync(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(); - }, - ]); - }); - }); - describe('Connection - MFA authenticator with DUO', function () { const connectionOption = connOption.MFA; @@ -182,113 +100,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 () {