Skip to content

Commit ed73aef

Browse files
feat(parameters): Configure max_age and decrypt parameters via environment variables (#2088)
* feat(parameters) - environment default variables * feat(parameters) - environment default variables - maxage * feat(parameters) - environment default variables - refactor maxage code * feat(parameters) - addressing Ruben's feedback
1 parent 066fd82 commit ed73aef

File tree

10 files changed

+190
-38
lines changed

10 files changed

+190
-38
lines changed

aws_lambda_powertools/shared/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222

2323
IDEMPOTENCY_DISABLED_ENV: str = "POWERTOOLS_IDEMPOTENCY_DISABLED"
2424

25+
PARAMETERS_SSM_DECRYPT_ENV: str = "POWERTOOLS_PARAMETERS_SSM_DECRYPT"
26+
PARAMETERS_MAX_AGE_ENV: str = "POWERTOOLS_PARAMETERS_MAX_AGE"
27+
2528
LOGGER_LAMBDA_CONTEXT_KEYS = [
2629
"function_arn",
2730
"function_memory_size",

aws_lambda_powertools/shared/functions.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ def resolve_truthy_env_var_choice(env: str, choice: Optional[bool] = None) -> bo
5151
return choice if choice is not None else strtobool(env)
5252

5353

54+
def resolve_max_age(env: str, choice: Optional[int]) -> int:
55+
"""Resolve max age value"""
56+
return choice if choice is not None else int(env)
57+
58+
5459
@overload
5560
def resolve_env_var_choice(env: Optional[str], choice: float) -> float:
5661
...

aws_lambda_powertools/utilities/parameters/appconfig.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@
1414
if TYPE_CHECKING:
1515
from mypy_boto3_appconfigdata import AppConfigDataClient
1616

17-
from ...shared import constants
18-
from ...shared.functions import resolve_env_var_choice
17+
from aws_lambda_powertools.shared import constants
18+
from aws_lambda_powertools.shared.functions import (
19+
resolve_env_var_choice,
20+
resolve_max_age,
21+
)
22+
1923
from .base import DEFAULT_MAX_AGE_SECS, DEFAULT_PROVIDERS, BaseProvider
2024

2125

@@ -136,7 +140,7 @@ def get_app_config(
136140
application: Optional[str] = None,
137141
transform: TransformOptions = None,
138142
force_fetch: bool = False,
139-
max_age: int = DEFAULT_MAX_AGE_SECS,
143+
max_age: Optional[int] = None,
140144
**sdk_options
141145
) -> Union[str, list, dict, bytes]:
142146
"""
@@ -154,7 +158,7 @@ def get_app_config(
154158
Transforms the content from a JSON object ('json') or base64 binary string ('binary')
155159
force_fetch: bool, optional
156160
Force update even before a cached item has expired, defaults to False
157-
max_age: int
161+
max_age: int, optional
158162
Maximum age of the cached value
159163
sdk_options: dict, optional
160164
SDK options to propagate to `start_configuration_session` API call
@@ -187,6 +191,8 @@ def get_app_config(
187191
>>> print(value)
188192
My configuration's JSON value
189193
"""
194+
# If max_age is not set, resolve it from the environment variable, defaulting to DEFAULT_MAX_AGE_SECS
195+
max_age = resolve_max_age(env=os.getenv(constants.PARAMETERS_MAX_AGE_ENV, DEFAULT_MAX_AGE_SECS), choice=max_age)
190196

191197
# Only create the provider if this function is called at least once
192198
if "appconfig" not in DEFAULT_PROVIDERS:

aws_lambda_powertools/utilities/parameters/base.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import base64
77
import json
8+
import os
89
from abc import ABC, abstractmethod
910
from datetime import datetime, timedelta
1011
from typing import (
@@ -24,6 +25,8 @@
2425
import boto3
2526
from botocore.config import Config
2627

28+
from aws_lambda_powertools.shared import constants
29+
from aws_lambda_powertools.shared.functions import resolve_max_age
2730
from aws_lambda_powertools.utilities.parameters.types import TransformOptions
2831

2932
from .exceptions import GetParameterError, TransformParameterError
@@ -35,7 +38,8 @@
3538
from mypy_boto3_ssm import SSMClient
3639

3740

38-
DEFAULT_MAX_AGE_SECS = 5
41+
DEFAULT_MAX_AGE_SECS = "5"
42+
3943
# These providers will be dynamically initialized on first use of the helper functions
4044
DEFAULT_PROVIDERS: Dict[str, Any] = {}
4145
TRANSFORM_METHOD_JSON = "json"
@@ -77,7 +81,7 @@ def has_not_expired_in_cache(self, key: Tuple[str, TransformOptions]) -> bool:
7781
def get(
7882
self,
7983
name: str,
80-
max_age: int = DEFAULT_MAX_AGE_SECS,
84+
max_age: Optional[int] = None,
8185
transform: TransformOptions = None,
8286
force_fetch: bool = False,
8387
**sdk_options,
@@ -121,6 +125,9 @@ def get(
121125
value: Optional[Union[str, bytes, dict]] = None
122126
key = (name, transform)
123127

128+
# If max_age is not set, resolve it from the environment variable, defaulting to DEFAULT_MAX_AGE_SECS
129+
max_age = resolve_max_age(env=os.getenv(constants.PARAMETERS_MAX_AGE_ENV, DEFAULT_MAX_AGE_SECS), choice=max_age)
130+
124131
if not force_fetch and self.has_not_expired_in_cache(key):
125132
return self.store[key].value
126133

@@ -149,7 +156,7 @@ def _get(self, name: str, **sdk_options) -> Union[str, bytes]:
149156
def get_multiple(
150157
self,
151158
path: str,
152-
max_age: int = DEFAULT_MAX_AGE_SECS,
159+
max_age: Optional[int] = None,
153160
transform: TransformOptions = None,
154161
raise_on_transform_error: bool = False,
155162
force_fetch: bool = False,
@@ -186,6 +193,9 @@ def get_multiple(
186193
"""
187194
key = (path, transform)
188195

196+
# If max_age is not set, resolve it from the environment variable, defaulting to DEFAULT_MAX_AGE_SECS
197+
max_age = resolve_max_age(env=os.getenv(constants.PARAMETERS_MAX_AGE_ENV, DEFAULT_MAX_AGE_SECS), choice=max_age)
198+
189199
if not force_fetch and self.has_not_expired_in_cache(key):
190200
return self.store[key].value # type: ignore # need to revisit entire typing here
191201

aws_lambda_powertools/utilities/parameters/secrets.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44

55

6+
import os
67
from typing import TYPE_CHECKING, Any, Dict, Optional, Union
78

89
import boto3
@@ -11,6 +12,9 @@
1112
if TYPE_CHECKING:
1213
from mypy_boto3_secretsmanager import SecretsManagerClient
1314

15+
from aws_lambda_powertools.shared import constants
16+
from aws_lambda_powertools.shared.functions import resolve_max_age
17+
1418
from .base import DEFAULT_MAX_AGE_SECS, DEFAULT_PROVIDERS, BaseProvider
1519

1620

@@ -111,11 +115,7 @@ def _get_multiple(self, path: str, **sdk_options) -> Dict[str, str]:
111115

112116

113117
def get_secret(
114-
name: str,
115-
transform: Optional[str] = None,
116-
force_fetch: bool = False,
117-
max_age: int = DEFAULT_MAX_AGE_SECS,
118-
**sdk_options
118+
name: str, transform: Optional[str] = None, force_fetch: bool = False, max_age: Optional[int] = None, **sdk_options
119119
) -> Union[str, dict, bytes]:
120120
"""
121121
Retrieve a parameter value from AWS Secrets Manager
@@ -128,7 +128,7 @@ def get_secret(
128128
Transforms the content from a JSON object ('json') or base64 binary string ('binary')
129129
force_fetch: bool, optional
130130
Force update even before a cached item has expired, defaults to False
131-
max_age: int
131+
max_age: int, optional
132132
Maximum age of the cached value
133133
sdk_options: dict, optional
134134
Dictionary of options that will be passed to the get_secret_value call
@@ -162,6 +162,9 @@ def get_secret(
162162
>>> get_secret("my-secret", VersionId="f658cac0-98a5-41d9-b993-8a76a7799194")
163163
"""
164164

165+
# If max_age is not set, resolve it from the environment variable, defaulting to DEFAULT_MAX_AGE_SECS
166+
max_age = resolve_max_age(env=os.getenv(constants.PARAMETERS_MAX_AGE_ENV, DEFAULT_MAX_AGE_SECS), choice=max_age)
167+
165168
# Only create the provider if this function is called at least once
166169
if "secrets" not in DEFAULT_PROVIDERS:
167170
DEFAULT_PROVIDERS["secrets"] = SecretsProvider()

0 commit comments

Comments
 (0)