diff --git a/pydantic_settings/sources/providers/aws.py b/pydantic_settings/sources/providers/aws.py index dc5c0cd0..c1004ec5 100644 --- a/pydantic_settings/sources/providers/aws.py +++ b/pydantic_settings/sources/providers/aws.py @@ -4,6 +4,7 @@ from collections.abc import Mapping from typing import TYPE_CHECKING, Optional +from ..utils import parse_env_vars from .env import EnvSettingsSource if TYPE_CHECKING: @@ -36,6 +37,7 @@ def __init__( settings_cls: type[BaseSettings], secret_id: str, region_name: str | None = None, + case_sensitive: bool | None = True, env_prefix: str | None = None, env_parse_none_str: str | None = None, env_parse_enums: bool | None = None, @@ -45,7 +47,7 @@ def __init__( self._secret_id = secret_id super().__init__( settings_cls, - case_sensitive=True, + case_sensitive=case_sensitive, env_prefix=env_prefix, env_nested_delimiter='--', env_ignore_empty=False, @@ -56,7 +58,12 @@ def __init__( def _load_env_vars(self) -> Mapping[str, Optional[str]]: response = self._secretsmanager_client.get_secret_value(SecretId=self._secret_id) # type: ignore - return json.loads(response['SecretString']) + return parse_env_vars( + json.loads(response['SecretString']), + self.case_sensitive, + self.env_ignore_empty, + self.env_parse_none_str, + ) def __repr__(self) -> str: return ( diff --git a/tests/test_source_aws_secrets_manager.py b/tests/test_source_aws_secrets_manager.py index 46160070..c68aa928 100644 --- a/tests/test_source_aws_secrets_manager.py +++ b/tests/test_source_aws_secrets_manager.py @@ -88,6 +88,43 @@ class AWSSecretsManagerSettings(BaseSettings): assert settings['SqlServerUser'] == 'test-user' assert settings['SqlServer']['Password'] == 'test-password' + @mock_aws + def test_secret_manager_case_insensitive_success(self) -> None: + """Test secret manager getitem case insensitive success.""" + + class SqlServer(BaseModel): + password: str = Field(..., alias='Password') + + class AWSSecretsManagerSettings(BaseSettings): + """AWSSecretsManager settings.""" + + sql_server_user: str + sql_server: SqlServer + + @classmethod + def settings_customise_sources( + cls, + settings_cls: type[BaseSettings], + init_settings: PydanticBaseSettingsSource, + env_settings: PydanticBaseSettingsSource, + dotenv_settings: PydanticBaseSettingsSource, + file_secret_settings: PydanticBaseSettingsSource, + ) -> tuple[PydanticBaseSettingsSource, ...]: + return (AWSSecretsManagerSettingsSource(settings_cls, 'test-secret', case_sensitive=False),) + + secret_data = { + 'SQL_SERVER_USER': 'test-user', + 'SQL_SERVER--PASSWORD': 'test-password', + } + + client = boto3.client('secretsmanager') + client.create_secret(Name='test-secret', SecretString=json.dumps(secret_data)) + + settings = AWSSecretsManagerSettings() # type: ignore + + assert settings.sql_server_user == 'test-user' + assert settings.sql_server.password == 'test-password' + @mock_aws def test_aws_secrets_manager_settings_source(self) -> None: """Test AWSSecretsManagerSettingsSource."""