Skip to content

Commit 43b1299

Browse files
committed
Add support for AWS Secrets Manager
1 parent 65929cd commit 43b1299

File tree

3 files changed

+53
-0
lines changed

3 files changed

+53
-0
lines changed

pydantic_settings/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from .main import BaseSettings, CliApp, SettingsConfigDict
22
from .sources import (
33
CLI_SUPPRESS,
4+
AWSSecretsManagerSettingsSource,
45
AzureKeyVaultSettingsSource,
56
CliExplicitFlag,
67
CliImplicitFlag,
@@ -50,6 +51,7 @@
5051
'TomlConfigSettingsSource',
5152
'YamlConfigSettingsSource',
5253
'AzureKeyVaultSettingsSource',
54+
'AWSSecretsManagerSettingsSource',
5355
'get_subcommand',
5456
'__version__',
5557
)

pydantic_settings/sources.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,19 @@ def import_azure_key_vault() -> None:
108108
) from e
109109

110110

111+
def import_aws_secrets_manager() -> None:
112+
global boto3_client
113+
global SecretsManagerClient
114+
115+
try:
116+
from boto3 import client as boto3_client
117+
from mypy_boto3_secretsmanager.client import SecretsManagerClient
118+
except ImportError as e:
119+
raise ImportError(
120+
'AWS Secrets Manager dependencies are not installed, run `pip install pydantic-settings[aws-secrets-manager]`'
121+
) from e
122+
123+
111124
DotenvType = Union[Path, str, Sequence[Union[Path, str]]]
112125
PathType = Union[Path, str, Sequence[Union[Path, str]]]
113126
DEFAULT_PATH: PathType = Path('')
@@ -2237,6 +2250,43 @@ def __repr__(self) -> str:
22372250
return f'{self.__class__.__name__}(url={self._url!r}, ' f'env_nested_delimiter={self.env_nested_delimiter!r})'
22382251

22392252

2253+
class AWSSecretsManagerSettingsSource(EnvSettingsSource):
2254+
_secret_id: str
2255+
_secretsmanager_client: SecretsManagerClient # type: ignore
2256+
2257+
def __init__(
2258+
self,
2259+
settings_cls: type[BaseSettings],
2260+
secret_id: str,
2261+
env_prefix: str | None = None,
2262+
env_parse_none_str: str | None = None,
2263+
env_parse_enums: bool | None = None,
2264+
) -> None:
2265+
import_aws_secrets_manager()
2266+
self._secretsmanager_client = boto3_client('secretsmanager') # type: ignore
2267+
self._secret_id = secret_id
2268+
super().__init__(
2269+
settings_cls,
2270+
case_sensitive=True,
2271+
env_prefix=env_prefix,
2272+
env_nested_delimiter='--',
2273+
env_ignore_empty=False,
2274+
env_parse_none_str=env_parse_none_str,
2275+
env_parse_enums=env_parse_enums,
2276+
)
2277+
2278+
def _load_env_vars(self) -> Mapping[str, Optional[str]]:
2279+
response = self._secretsmanager_client.get_secret_value(SecretId=self._secret_id)
2280+
2281+
return json.loads(response['SecretString'])
2282+
2283+
def __repr__(self) -> str:
2284+
return (
2285+
f'{self.__class__.__name__}(secret_id={self._secret_id!r}, '
2286+
f'env_nested_delimiter={self.env_nested_delimiter!r})'
2287+
)
2288+
2289+
22402290
def _get_env_var_key(key: str, case_sensitive: bool = False) -> str:
22412291
return key if case_sensitive else key.lower()
22422292

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ dynamic = ['version']
5050
yaml = ["pyyaml>=6.0.1"]
5151
toml = ["tomli>=2.0.1"]
5252
azure-key-vault = ["azure-keyvault-secrets>=4.8.0", "azure-identity>=1.16.0"]
53+
aws-secrets-manager = ["boto3>=1.35.0", "boto3-stubs[secretsmanager]"]
5354

5455
[project.urls]
5556
Homepage = 'https://github.com/pydantic/pydantic-settings'

0 commit comments

Comments
 (0)