Skip to content

Commit 47a08db

Browse files
committed
feat: added secret referencing support
1 parent 53b66ce commit 47a08db

File tree

2 files changed

+22
-12
lines changed

2 files changed

+22
-12
lines changed

src/phase/phase.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from .utils.crypto import CryptoUtils
1818
from .utils.const import __ph_version__, pss_user_pattern, pss_service_pattern
1919
from .utils.misc import phase_get_context, normalize_tag, tag_matches
20+
from .utils.secret_referencing import resolve_all_secrets
2021

2122

2223
@dataclass
@@ -176,6 +177,7 @@ def get(self, env_name: str, keys: List[str] = None, app_name: str = None, tag:
176177
secrets_data = secrets_response.json()
177178

178179
results = []
180+
all_secrets = [] # List to store all secrets for resolving references
179181
for secret in secrets_data:
180182
# Check if a tag filter is applied and if the secret has the correct tags.
181183
if tag and not tag_matches(secret.get("tags", []), tag):
@@ -209,6 +211,13 @@ def get(self, env_name: str, keys: List[str] = None, app_name: str = None, tag:
209211

210212
if not keys or decrypted_key in keys:
211213
results.append(secret_obj)
214+
215+
all_secrets.append(secret_obj)
216+
217+
# Resolve secret references
218+
for secret in results:
219+
resolved_value = resolve_all_secrets(secret.value, all_secrets, self, app_name, env_name)
220+
secret.value = resolved_value
212221

213222
return results
214223

src/phase/utils/secret_referencing.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ def resolve_secret_reference(ref: str, secrets_dict: Dict[str, Dict[str, Dict[st
6666
"""
6767

6868
env_name = current_env_name
69-
path = "/" # Default root path
69+
path = "/" # Default root path
7070
key_name = ref
7171

7272
# Parse the reference to identify environment, path, and secret key.
73-
if "." in ref: # Cross-environment references, split by the first dot to get environment and the rest.
73+
if "." in ref: # Cross-environment references
7474
parts = ref.split(".", 1)
7575
env_name, rest = parts[0], parts[1]
7676
last_slash_index = rest.rfind("/")
@@ -90,15 +90,17 @@ def resolve_secret_reference(ref: str, secrets_dict: Dict[str, Dict[str, Dict[st
9090

9191
try:
9292
# Lookup with environment, path, and key
93-
if env_name in secrets_dict and path in secrets_dict[env_name] and key_name in secrets_dict[env_name][path]:
94-
return secrets_dict[env_name][path][key_name]
93+
if env_name in secrets_dict and path in secrets_dict[env_name]:
94+
for secret in secrets_dict[env_name][path]:
95+
if secret.key == key_name:
96+
return secret.value
9597
else:
9698
# Handle fallback for cross-environment or missing secrets
9799
if env_name != current_env_name:
98100
fetched_secrets = phase.get(env_name=env_name, app_name=current_application_name, keys=[key_name], path=path)
99101
for secret in fetched_secrets:
100-
if secret["key"] == key_name:
101-
return secret["value"]
102+
if secret.key == key_name:
103+
return secret.value
102104
except EnvironmentNotFoundException:
103105
pass
104106

@@ -128,14 +130,13 @@ def resolve_all_secrets(value: str, all_secrets: List[Dict[str, str]], phase: 'P
128130

129131
secrets_dict = {}
130132
for secret in all_secrets:
131-
env_name = secret['environment']
132-
path = secret['path']
133-
key = secret['key']
133+
env_name = current_env_name # Assume current environment if not specified
134+
path = secret.path
134135
if env_name not in secrets_dict:
135136
secrets_dict[env_name] = {}
136137
if path not in secrets_dict[env_name]:
137-
secrets_dict[env_name][path] = {}
138-
secrets_dict[env_name][path][key] = secret['value']
138+
secrets_dict[env_name][path] = []
139+
secrets_dict[env_name][path].append(secret)
139140

140141
refs = SECRET_REF_REGEX.findall(value)
141142
resolved_value = value
@@ -144,4 +145,4 @@ def resolve_all_secrets(value: str, all_secrets: List[Dict[str, str]], phase: 'P
144145
resolved_secret_value = resolve_secret_reference(ref, secrets_dict, phase, current_application_name, current_env_name)
145146
resolved_value = resolved_value.replace(f"${{{ref}}}", resolved_secret_value)
146147

147-
return resolved_value
148+
return resolved_value

0 commit comments

Comments
 (0)