Skip to content

Commit 159ef14

Browse files
authored
Expose GCP Secret Manager case sensitive option (#626)
1 parent e9f7994 commit 159ef14

File tree

2 files changed

+26
-8
lines changed

2 files changed

+26
-8
lines changed

pydantic_settings/sources/providers/gcp.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,26 +37,34 @@ class GoogleSecretManagerMapping(Mapping[str, Optional[str]]):
3737
_loaded_secrets: dict[str, str | None]
3838
_secret_client: SecretManagerServiceClient
3939

40-
def __init__(self, secret_client: SecretManagerServiceClient, project_id: str) -> None:
40+
def __init__(self, secret_client: SecretManagerServiceClient, project_id: str, case_sensitive: bool) -> None:
4141
self._loaded_secrets = {}
4242
self._secret_client = secret_client
4343
self._project_id = project_id
44+
self._case_sensitive = case_sensitive
4445

4546
@property
4647
def _gcp_project_path(self) -> str:
4748
return self._secret_client.common_project_path(self._project_id)
4849

4950
@cached_property
5051
def _secret_names(self) -> list[str]:
51-
return [
52-
self._secret_client.parse_secret_path(secret.name).get('secret', '')
53-
for secret in self._secret_client.list_secrets(parent=self._gcp_project_path)
54-
]
52+
rv: list[str] = []
53+
54+
secrets = self._secret_client.list_secrets(parent=self._gcp_project_path)
55+
for secret in secrets:
56+
name = self._secret_client.parse_secret_path(secret.name).get('secret', '')
57+
if not self._case_sensitive:
58+
name = name.lower()
59+
rv.append(name)
60+
return rv
5561

5662
def _secret_version_path(self, key: str, version: str = 'latest') -> str:
5763
return self._secret_client.secret_version_path(self._project_id, key, version)
5864

5965
def __getitem__(self, key: str) -> str | None:
66+
if not self._case_sensitive:
67+
key = key.lower()
6068
if key not in self._loaded_secrets:
6169
# If we know the key isn't available in secret manager, raise a key error
6270
if key not in self._secret_names:
@@ -92,6 +100,7 @@ def __init__(
92100
env_parse_none_str: str | None = None,
93101
env_parse_enums: bool | None = None,
94102
secret_client: SecretManagerServiceClient | None = None,
103+
case_sensitive: bool | None = True,
95104
) -> None:
96105
# Import Google Packages if they haven't already been imported
97106
if SecretManagerServiceClient is None or Credentials is None or google_auth_default is None:
@@ -124,15 +133,17 @@ def __init__(
124133

125134
super().__init__(
126135
settings_cls,
127-
case_sensitive=True,
136+
case_sensitive=case_sensitive,
128137
env_prefix=env_prefix,
129138
env_ignore_empty=False,
130139
env_parse_none_str=env_parse_none_str,
131140
env_parse_enums=env_parse_enums,
132141
)
133142

134143
def _load_env_vars(self) -> Mapping[str, Optional[str]]:
135-
return GoogleSecretManagerMapping(self._secret_client, project_id=self._project_id)
144+
return GoogleSecretManagerMapping(
145+
self._secret_client, project_id=self._project_id, case_sensitive=self.case_sensitive
146+
)
136147

137148
def __repr__(self) -> str:
138149
return f'{self.__class__.__name__}(project_id={self._project_id!r}, env_nested_delimiter={self.env_nested_delimiter!r})'

tests/test_source_gcp_secret_manager.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def mock_access_secret_version(name: str):
5757

5858
@pytest.fixture
5959
def secret_manager_mapping(mock_secret_client):
60-
return GoogleSecretManagerMapping(mock_secret_client, 'test-project')
60+
return GoogleSecretManagerMapping(mock_secret_client, project_id='test-project', case_sensitive=True)
6161

6262

6363
@pytest.fixture
@@ -96,6 +96,13 @@ def test_secret_manager_mapping_getitem_success(self, secret_manager_mapping):
9696
value = secret_manager_mapping['test-secret']
9797
assert value == 'test-value'
9898

99+
def test_secret_manager_mapping_getitem_case_insensitive_success(self, mock_secret_client):
100+
case_insensitive_mapping = GoogleSecretManagerMapping(
101+
mock_secret_client, project_id='test-project', case_sensitive=False
102+
)
103+
value = case_insensitive_mapping['TEST-SECRET']
104+
assert value == 'test-value'
105+
99106
def test_secret_manager_mapping_getitem_nonexistent_key(self, secret_manager_mapping):
100107
with pytest.raises(KeyError):
101108
_ = secret_manager_mapping['nonexistent-secret']

0 commit comments

Comments
 (0)