Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions src/snowflake/cli/_app/snow_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
)
from snowflake.cli._app.telemetry import command_info
from snowflake.cli._plugins.auth.oidc.manager import OidcManager
from snowflake.cli.api.cli_global_context import get_cli_context
from snowflake.cli.api.config import (
get_connection_dict,
get_env_value,
Expand Down Expand Up @@ -247,10 +248,27 @@ def connect_to_snowflake(
contextlib.redirect_stdout(silent_stdout),
contextlib.redirect_stderr(silent_stderr),
):
return snowflake.connector.connect(
application=command_info(),
connect_kwargs = {
"application": command_info(),
**connection_parameters,
)
}
if get_cli_context().config_file_override is not None:
connect_kwargs["unsafe_skip_file_permissions_check"] = True
from snowflake.connector.config_manager import (
CONFIG_MANAGER,
ConfigSlice,
ConfigSliceOptions,
)

CONFIG_MANAGER._slices = [ # noqa: SLF001
ConfigSlice(
s.path, ConfigSliceOptions(check_permissions=False), s.section
)
for s in CONFIG_MANAGER._slices # noqa: SLF001
]

result = snowflake.connector.connect(**connect_kwargs)
return result
except ForbiddenError as err:
raise SnowflakeConnectionError(err)
except DatabaseError as err:
Expand Down
1 change: 1 addition & 0 deletions tests/api/test_connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ def test_connection_cache_caches(

mock_connect.assert_called_once_with(
application=mock_command_info.return_value,
unsafe_skip_file_permissions_check=True,
database="db_for_test",
schema="test_public",
role="test_role",
Expand Down
8 changes: 8 additions & 0 deletions tests/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,7 @@ def test_temporary_connection(mock_connector, mock_ctx, option, runner):
assert result.exit_code == 0
mock_connector.assert_called_once_with(
application="SNOWCLI.OBJECT.LIST",
unsafe_skip_file_permissions_check=True,
host="snowcli_test_host",
port=123456789,
account="test_account",
Expand Down Expand Up @@ -712,6 +713,7 @@ def test_key_pair_authentication(
assert result.exit_code == 0
mock_connector.assert_called_once_with(
application="SNOWCLI.OBJECT.LIST",
unsafe_skip_file_permissions_check=True,
private_key=private_key,
account="test_account",
user="snowcli_test",
Expand Down Expand Up @@ -759,6 +761,7 @@ def test_session_and_master_tokens(mock_connector, mock_ctx, runner):
assert result.exit_code == 0
mock_connector.assert_called_once_with(
application="SNOWCLI.OBJECT.LIST",
unsafe_skip_file_permissions_check=True,
session_token=session_token,
master_token=master_token,
account="test_account",
Expand Down Expand Up @@ -795,6 +798,7 @@ def test_token_file_path_tokens(mock_connector, mock_ctx, runner, temporary_dire
assert result.exit_code == 0
mock_connector.assert_called_once_with(
application="SNOWCLI.OBJECT.LIST",
unsafe_skip_file_permissions_check=True,
token_file_path=str(token_file),
application_name="snowcli",
using_session_keep_alive=True,
Expand Down Expand Up @@ -841,6 +845,7 @@ def test_key_pair_authentication_from_config(
mock_load_file.assert_called_once_with("~/sf_private_key.p8")
mock_connector.assert_called_once_with(
application="SNOWCLI.OBJECT.LIST",
unsafe_skip_file_permissions_check=True,
account="my_account",
user="jdoe",
authenticator="SNOWFLAKE_JWT",
Expand Down Expand Up @@ -979,6 +984,7 @@ def test_connection_details_are_resolved_using_environment_variables(
assert kwargs == {
"account": "some_account",
"application": "SNOWCLI.SQL",
"unsafe_skip_file_permissions_check": True,
"database": "test_database",
"warehouse": "large",
"schema": "my_schema",
Expand Down Expand Up @@ -1043,6 +1049,7 @@ def test_flags_take_precedence_before_environment_variables(
assert kwargs == {
"account": "account_from_flag",
"application": "SNOWCLI.SQL",
"unsafe_skip_file_permissions_check": True,
"database": "database_from_flag",
"warehouse": "large",
"schema": "schema_from_flag",
Expand Down Expand Up @@ -1085,6 +1092,7 @@ def test_source_precedence(mock_connect, runner):
"user": "python", # from config
"account": "account_from_flag",
"application": "SNOWCLI.SQL",
"unsafe_skip_file_permissions_check": True,
"database": "database_from_connection_env",
"role": "role_from_global_env",
"application_name": "snowcli",
Expand Down
1 change: 1 addition & 0 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ def test_custom_config_path(mock_conn, runner, mock_cursor):
password="dummy_password",
application_name="snowcli",
using_session_keep_alive=True,
unsafe_skip_file_permissions_check=True,
)


Expand Down
4 changes: 4 additions & 0 deletions tests/test_oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def test_oauth_from_parameters(mock_connect, runner):

mock_connect.assert_called_once_with(
application="SNOWCLI.SQL",
unsafe_skip_file_permissions_check=True,
application_name="snowcli",
authenticator="OAUTH_AUTHORIZATION_CODE",
oauth_client_id="client_id",
Expand Down Expand Up @@ -76,6 +77,7 @@ def test_oauth_from_config(mock_connect, runner, config_file):

mock_connect.assert_called_once_with(
application="SNOWCLI.SQL",
unsafe_skip_file_permissions_check=True,
application_name="snowcli",
authenticator="OAUTH_AUTHORIZATION_CODE",
oauth_client_id="client_id",
Expand Down Expand Up @@ -125,6 +127,7 @@ def test_oauth_from_env_variables(mock_connect, runner, config_file):

mock_connect.assert_called_once_with(
application="SNOWCLI.SQL",
unsafe_skip_file_permissions_check=True,
application_name="snowcli",
authenticator="OAUTH_AUTHORIZATION_CODE",
oauth_client_id="client_id",
Expand Down Expand Up @@ -164,6 +167,7 @@ def test_oauth_from_env_variables_and_temporary_connection(mock_connect, runner)

mock_connect.assert_called_once_with(
application="SNOWCLI.SQL",
unsafe_skip_file_permissions_check=True,
application_name="snowcli",
authenticator="OAUTH_AUTHORIZATION_CODE",
oauth_client_id="client_id",
Expand Down
31 changes: 31 additions & 0 deletions tests/test_snow_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def test_command_context_is_passed_to_snowflake_connection(

mock_connect.assert_called_once_with(
application=expected,
unsafe_skip_file_permissions_check=True,
database="db_for_test",
schema="test_public",
role="test_role",
Expand Down Expand Up @@ -177,6 +178,7 @@ def test_private_key_loading_and_aliases(
)
mock_connect.assert_called_once_with(
application=mock_command_info.return_value,
unsafe_skip_file_permissions_check=True,
authenticator="SNOWFLAKE_JWT",
application_name="snowcli",
using_session_keep_alive=True,
Expand Down Expand Up @@ -269,6 +271,7 @@ def test_internal_application_data_is_sent_if_feature_flag_is_set(
):
expected_kwargs = {
"application": "SNOWCLI.SQL",
"unsafe_skip_file_permissions_check": True,
"database": "db_for_test",
"schema": "test_public",
"role": "test_role",
Expand Down Expand Up @@ -641,3 +644,31 @@ def test_externalbrowser_authenticator_is_case_insensitive(

# For externalbrowser, stdout should mirror to stderr
assert stdout_stream._mirror is not None # noqa: SLF001


@mock.patch("snowflake.cli._app.snow_connector.command_info")
@mock.patch("snowflake.connector.connect")
def test_config_file_override_disables_connector_slice_permission_checks(
mock_connect, mock_command_info, test_snowcli_config
):
"""Test that when config_file_override is set, connector's config slices have permission checks disabled."""
from snowflake.cli._app.snow_connector import connect_to_snowflake
from snowflake.cli.api.config import config_init
from snowflake.connector.config_manager import CONFIG_MANAGER

config_init(test_snowcli_config)
mock_command_info.return_value = "SNOWCLI.TEST"

# The autouse fixture already sets config_file_override to test_snowcli_config
# so this test verifies that when config_file_override is set, slices are modified
connect_to_snowflake(connection_name="default")

# Verify that all slices have check_permissions=False
for slice_entry in CONFIG_MANAGER._slices: # noqa: SLF001
assert (
slice_entry.options.check_permissions is False
), f"Slice {slice_entry.path} should have check_permissions=False"

# Verify unsafe_skip_file_permissions_check is passed to connector
call_kwargs = mock_connect.call_args[1]
assert call_kwargs["unsafe_skip_file_permissions_check"] is True
2 changes: 2 additions & 0 deletions tests/test_workload_identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def test_workload_identity_provider_parameter(mock_connect, runner):

mock_connect.assert_called_once_with(
application="SNOWCLI.SQL",
unsafe_skip_file_permissions_check=True,
application_name="snowcli",
account="test_account",
user="test_user",
Expand Down Expand Up @@ -61,6 +62,7 @@ def test_workload_identity_provider_from_config(mock_connect, runner, config_fil

mock_connect.assert_called_once_with(
application="SNOWCLI.SQL",
unsafe_skip_file_permissions_check=True,
application_name="snowcli",
account="test_account",
user="test_user",
Expand Down
4 changes: 4 additions & 0 deletions tests_integration/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from textwrap import dedent
from unittest import mock

import pytest

from tests_common import IS_WINDOWS
from tests_integration.snowflake_connector import (
setup_test_database,
setup_test_schema,
Expand Down
Loading