Пример #1
0
    def test_body(conn_cfg):
        delete_temporary_credential(
            host=conn_cfg["host"], user=conn_cfg["user"], cred_type=MFA_TOKEN
        )

        # first connection, no mfa token cache
        con = snowflake.connector.connect(**conn_cfg)
        assert con._rest.token == "TOKEN"
        assert con._rest.master_token == "MASTER_TOKEN"
        assert con._rest.mfa_token == "MFA_TOKEN"
        con.close()

        # second connection that uses the mfa token issued for first connection to login
        con = snowflake.connector.connect(**conn_cfg)
        assert con._rest.token == "NEW_TOKEN"
        assert con._rest.master_token == "NEW_MASTER_TOKEN"
        assert con._rest.mfa_token == "NEW_MFA_TOKEN"
        con.close()

        # third connection which is expected to login with new mfa token
        con = snowflake.connector.connect(**conn_cfg)
        assert con._rest.mfa_token is None
        con.close()

        with pytest.raises(DatabaseError):
            # A failed login will be forced by a mocked response for this connection
            # Under authentication failed exception, mfa cache is expected to be cleaned up
            con = snowflake.connector.connect(**conn_cfg)

        # no mfa cache token should be sent at this connection
        con = snowflake.connector.connect(**conn_cfg)
        con.close()
Пример #2
0
    def test_body():
        account = 'testaccount'
        user = '******'
        authenticator = 'externalbrowser'
        host = 'testaccount.snowflakecomputing.com'

        delete_temporary_credential(host=host,
                                    user=user,
                                    store_temporary_credential=True)

        # first connection
        con = snowflake.connector.connect(
            account=account,
            user=user,
            host=host,
            authenticator=authenticator,
            database='TESTDB',
            warehouse='TESTWH',
            client_store_temporary_credential=True,
        )
        assert con._rest.token == 'TOKEN'
        assert con._rest.master_token == 'MASTER_TOKEN'
        assert con._rest.id_token == 'ID_TOKEN'

        # second connection that uses the id token to get the session token
        con = snowflake.connector.connect(
            account=account,
            user=user,
            host=host,
            authenticator=authenticator,
            database='TESTDB_NEW',  # override the database
            warehouse='TESTWH_NEW',  # override the warehouse
            client_store_temporary_credential=True,
        )

        assert con._rest.token == 'NEW_TOKEN'
        assert con._rest.master_token == 'NEW_MASTER_TOKEN'
        assert con._rest.id_token is None
        assert con.database == 'TESTDB_NEW'
        assert con.warehouse == 'TESTWH_NEW'
Пример #3
0
    def test_body():
        account = "testaccount"
        user = "******"
        authenticator = "externalbrowser"
        host = "testaccount.snowflakecomputing.com"

        delete_temporary_credential(host=host, user=user, cred_type=ID_TOKEN)

        # first connection
        con = snowflake.connector.connect(
            account=account,
            user=user,
            host=host,
            authenticator=authenticator,
            database="TESTDB",
            warehouse="TESTWH",
            client_store_temporary_credential=True,
        )
        assert con._rest.token == "TOKEN"
        assert con._rest.master_token == "MASTER_TOKEN"
        assert con._rest.id_token == "ID_TOKEN"

        # second connection that uses the id token to get the session token
        con = snowflake.connector.connect(
            account=account,
            user=user,
            host=host,
            authenticator=authenticator,
            database="TESTDB_NEW",  # override the database
            warehouse="TESTWH_NEW",  # override the warehouse
            client_store_temporary_credential=True,
        )

        assert con._rest.token == "NEW_TOKEN"
        assert con._rest.master_token == "NEW_MASTER_TOKEN"
        assert con._rest.id_token is None
        assert con.database == "TESTDB_NEW"
        assert con.warehouse == "TESTWH_NEW"
Пример #4
0
def test_connect_externalbrowser(token_validity_test_values):
    """SSO Id Token Cache tests. This test should only be ran if keyring optional dependency is installed.

    In order to run this test, remove the above pytest.mark.skip annotation and run it. It will popup a windows once
    but the rest connections should not create popups.
    """
    delete_temporary_credential(
        host=CONNECTION_PARAMETERS_SSO['host'],
        user=CONNECTION_PARAMETERS_SSO['user'],
        cred_type=ID_TOKEN)  # delete existing temporary credential
    CONNECTION_PARAMETERS_SSO['client_store_temporary_credential'] = True

    # change database and schema to non-default one
    print(
        "[INFO] 1st connection gets id token and stores in the local cache (keychain/credential manager/cache file). "
        "This popup a browser to SSO login")
    cnx = snowflake.connector.connect(**CONNECTION_PARAMETERS_SSO)
    assert cnx.database == 'TESTDB'
    assert cnx.schema == 'PUBLIC'
    assert cnx.role == 'SYSADMIN'
    assert cnx.warehouse == 'REGRESS'
    ret = cnx.cursor().execute(
        "select current_database(), current_schema(), "
        "current_role(), current_warehouse()").fetchall()
    assert ret[0][0] == 'TESTDB'
    assert ret[0][1] == 'PUBLIC'
    assert ret[0][2] == 'SYSADMIN'
    assert ret[0][3] == 'REGRESS'
    cnx.close()

    print("[INFO] 2nd connection reads the local cache and uses the id token. "
          "This should not popups a browser.")
    CONNECTION_PARAMETERS_SSO['database'] = 'testdb'
    CONNECTION_PARAMETERS_SSO['schema'] = 'testschema'
    cnx = snowflake.connector.connect(**CONNECTION_PARAMETERS_SSO)
    print("[INFO] Running a 10 seconds query. If the session expires in 10 "
          "seconds, the query should renew the token in the middle, "
          "and the current objects should be refreshed.")
    cnx.cursor().execute("select seq8() from table(generator(timelimit=>10))")
    assert cnx.database == 'TESTDB'
    assert cnx.schema == 'TESTSCHEMA'
    assert cnx.role == 'SYSADMIN'
    assert cnx.warehouse == 'REGRESS'

    print("[INFO] Running a 1 second query. ")
    cnx.cursor().execute("select seq8() from table(generator(timelimit=>1))")
    assert cnx.database == 'TESTDB'
    assert cnx.schema == 'TESTSCHEMA'
    assert cnx.role == 'SYSADMIN'
    assert cnx.warehouse == 'REGRESS'

    print("[INFO] Running a 90 seconds query. This pops up a browser in the "
          "middle of the query.")
    cnx.cursor().execute("select seq8() from table(generator(timelimit=>90))")
    assert cnx.database == 'TESTDB'
    assert cnx.schema == 'TESTSCHEMA'
    assert cnx.role == 'SYSADMIN'
    assert cnx.warehouse == 'REGRESS'

    cnx.close()

    # change database and schema again to ensure they are overridden
    CONNECTION_PARAMETERS_SSO['database'] = 'testdb'
    CONNECTION_PARAMETERS_SSO['schema'] = 'testschema'
    cnx = snowflake.connector.connect(**CONNECTION_PARAMETERS_SSO)
    assert cnx.database == 'TESTDB'
    assert cnx.schema == 'TESTSCHEMA'
    assert cnx.role == 'SYSADMIN'
    assert cnx.warehouse == 'REGRESS'
    cnx.close()

    with snowflake.connector.connect(
            **CONNECTION_PARAMETERS_ADMIN) as cnx_admin:
        # cnx_admin.cursor().execute("alter account testaccount set ALLOW_UNPROTECTED_ID_TOKEN=false;")
        cnx_admin.cursor().execute(
            "alter account testaccount set ALLOW_ID_TOKEN=false;")
        cnx_admin.cursor().execute(
            "alter account testaccount set ID_TOKEN_FEATURE_ENABLED=false;")
    print(
        "[INFO] Login again with ALLOW_UNPROTECTED_ID_TOKEN unset. Please make sure this pops up the browser"
    )
    cnx = snowflake.connector.connect(**CONNECTION_PARAMETERS_SSO)
    cnx.close()
Пример #5
0
def test_mfa_no_local_secure_storage(mockSnowflakeRestfulPostRequest):
    """Test whether username_password_mfa authenticator can work when no local secure storage is available."""
    global mock_post_req_cnt
    mock_post_req_cnt = 0

    # This test requires Mac/Win and no keyring lib is installed
    assert not installed_keyring

    def mock_post_request(url, headers, json_body, **kwargs):
        global mock_post_req_cnt
        ret = None
        body = json.loads(json_body)
        if mock_post_req_cnt == 0:
            # issue MFA token for a succeeded login
            assert (body["data"]["SESSION_PARAMETERS"].get(
                "CLIENT_REQUEST_MFA_TOKEN") is True)
            ret = {
                "success": True,
                "message": None,
                "data": {
                    "token": "TOKEN",
                    "masterToken": "MASTER_TOKEN",
                    "mfaToken": "MFA_TOKEN",
                },
            }
        elif mock_post_req_cnt == 2:
            # No local secure storage available, so no mfa cache token should be provided
            assert (body["data"]["SESSION_PARAMETERS"].get(
                "CLIENT_REQUEST_MFA_TOKEN") is True)
            assert "TOKEN" not in body["data"]
            ret = {
                "success": True,
                "message": None,
                "data": {
                    "token": "NEW_TOKEN",
                    "masterToken": "NEW_MASTER_TOKEN",
                },
            }
        elif mock_post_req_cnt in [1, 3]:
            # connection.close()
            ret = {"success": True}
        mock_post_req_cnt += 1
        return ret

    # POST requests mock
    mockSnowflakeRestfulPostRequest.side_effect = mock_post_request

    conn_cfg = {
        "account": "testaccount",
        "user": "******",
        "password": "******",
        "authenticator": "username_password_mfa",
        "host": "testaccount.snowflakecomputing.com",
    }

    delete_temporary_credential(host=conn_cfg["host"],
                                user=conn_cfg["user"],
                                cred_type=MFA_TOKEN)

    # first connection, no mfa token cache
    con = snowflake.connector.connect(**conn_cfg)
    assert con._rest.token == "TOKEN"
    assert con._rest.master_token == "MASTER_TOKEN"
    assert con._rest.mfa_token == "MFA_TOKEN"
    con.close()

    # second connection, no mfa token should be issued as well since no available local secure storage
    con = snowflake.connector.connect(**conn_cfg)
    assert con._rest.token == "NEW_TOKEN"
    assert con._rest.master_token == "NEW_MASTER_TOKEN"
    assert not con._rest.mfa_token
    con.close()
Пример #6
0
def test_mfa_no_local_secure_storage(mockSnowflakeRestfulPostRequest):
    """Test whether username_password_mfa authenticator can work when no local secure storage is available."""
    global mock_post_req_cnt
    mock_post_req_cnt = 0

    # This test requires Mac/Win and no keyring lib is installed
    assert not installed_keyring

    def mock_post_request(url, headers, json_body, **kwargs):
        global mock_post_req_cnt
        ret = None
        body = json.loads(json_body)
        if mock_post_req_cnt == 0:
            # issue MFA token for a succeeded login
            assert body['data']['SESSION_PARAMETERS'].get(
                'CLIENT_REQUEST_MFA_TOKEN') is True
            ret = {
                'success': True,
                'message': None,
                'data': {
                    'token': 'TOKEN',
                    'masterToken': 'MASTER_TOKEN',
                    'mfaToken': 'MFA_TOKEN',
                }
            }
        elif mock_post_req_cnt == 2:
            # No local secure storage available, so no mfa cache token should be provided
            assert body['data']['SESSION_PARAMETERS'].get(
                'CLIENT_REQUEST_MFA_TOKEN') is True
            assert 'TOKEN' not in body['data']
            ret = {
                'success': True,
                'message': None,
                'data': {
                    'token': 'NEW_TOKEN',
                    'masterToken': 'NEW_MASTER_TOKEN',
                }
            }
        elif mock_post_req_cnt in [1, 3]:
            # connection.close()
            ret = {'success': True}
        mock_post_req_cnt += 1
        return ret

    # POST requests mock
    mockSnowflakeRestfulPostRequest.side_effect = mock_post_request

    conn_cfg = {
        'account': 'testaccount',
        'user': '******',
        'password': '******',
        'authenticator': 'username_password_mfa',
        'host': 'testaccount.snowflakecomputing.com',
    }

    delete_temporary_credential(host=conn_cfg['host'],
                                user=conn_cfg['user'],
                                cred_type=MFA_TOKEN)

    # first connection, no mfa token cache
    con = snowflake.connector.connect(**conn_cfg)
    assert con._rest.token == 'TOKEN'
    assert con._rest.master_token == 'MASTER_TOKEN'
    assert con._rest.mfa_token == 'MFA_TOKEN'
    con.close()

    # second connection, no mfa token should be issued as well since no available local secure storage
    con = snowflake.connector.connect(**conn_cfg)
    assert con._rest.token == 'NEW_TOKEN'
    assert con._rest.master_token == 'NEW_MASTER_TOKEN'
    assert not con._rest.mfa_token
    con.close()
Пример #7
0
def test_connect_externalbrowser(token_validity_test_values):
    """
    SSO Id Token Cache tests. This is disabled by default.
    In order to run this test, remove the above pytest.mark.skip annotation
    and run it. It will popup a windows once but the rest connections
    should not create popups.
    """

    delete_temporary_credential(host=CONNECTION_PARAMETERS_SSO['host'],
                                user=CONNECTION_PARAMETERS_SSO['user'],
                                store_temporary_credential=True
                                )  # delete existing temporary credential
    CONNECTION_PARAMETERS_SSO['client_store_temporary_credential'] = True

    # change database and schema to non-default one
    print("[INFO] 1st connection gets id token and stores in the cache file. "
          "This popup a browser to SSO login")
    cnx = snowflake.connector.connect(**CONNECTION_PARAMETERS_SSO)
    assert cnx.database == 'TESTDB'
    assert cnx.schema == 'PUBLIC'
    assert cnx.role == 'SYSADMIN'
    assert cnx.warehouse == 'REGRESS'
    ret = cnx.cursor().execute(
        "select current_database(), current_schema(), "
        "current_role(), current_warehouse()").fetchall()
    assert ret[0][0] == 'TESTDB'
    assert ret[0][1] == 'PUBLIC'
    assert ret[0][2] == 'SYSADMIN'
    assert ret[0][3] == 'REGRESS'
    cnx.close()

    print("[INFO] 2nd connection reads the cache file and uses the id token. "
          "This should not popups a browser.")
    CONNECTION_PARAMETERS_SSO['database'] = 'testdb'
    CONNECTION_PARAMETERS_SSO['schema'] = 'testschema'
    cnx = snowflake.connector.connect(**CONNECTION_PARAMETERS_SSO)
    print("[INFO] Running a 10 seconds query. If the session expires in 10 "
          "seconds, the query should renew the token in the middle, "
          "and the current objects should be refreshed.")
    cnx.cursor().execute("select seq8() from table(generator(timelimit=>10))")
    assert cnx.database == 'TESTDB'
    assert cnx.schema == 'TESTSCHEMA'
    assert cnx.role == 'SYSADMIN'
    assert cnx.warehouse == 'REGRESS'

    print("[INFO] Running a 1 seconds query. ")
    cnx.cursor().execute("select seq8() from table(generator(timelimit=>1))")
    assert cnx.database == 'TESTDB'
    assert cnx.schema == 'TESTSCHEMA'
    assert cnx.role == 'SYSADMIN'
    assert cnx.warehouse == 'REGRESS'

    print("[INFO] Running a 90 seconds query. This pops up a browser in the "
          "middle of the query.")
    cnx.cursor().execute("select seq8() from table(generator(timelimit=>90))")
    assert cnx.database == 'TESTDB'
    assert cnx.schema == 'TESTSCHEMA'
    assert cnx.role == 'SYSADMIN'
    assert cnx.warehouse == 'REGRESS'

    # change database and schema again to ensure they are overridden
    CONNECTION_PARAMETERS_SSO['database'] = 'testdb'
    CONNECTION_PARAMETERS_SSO['schema'] = 'testschema'
    cnx = snowflake.connector.connect(**CONNECTION_PARAMETERS_SSO)
    assert cnx.database == 'TESTDB'
    assert cnx.schema == 'TESTSCHEMA'
    assert cnx.role == 'SYSADMIN'
    assert cnx.warehouse == 'REGRESS'
    cnx.close()