Skip to content

Commit c7e169f

Browse files
authored
Merge pull request #11 from phasehq/fix--secret-reference-1
Fix: Local Path Secret Referencing
2 parents b71f3cb + 2653097 commit c7e169f

File tree

6 files changed

+61
-45
lines changed

6 files changed

+61
-45
lines changed

helm-repo/index.yaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ apiVersion: v1
22
entries:
33
phase-kubernetes-operator:
44
- apiVersion: v2
5-
appVersion: 1.2.0
6-
created: "2024-03-01T11:48:42.57136212+05:30"
5+
appVersion: 1.2.1
6+
created: "2024-07-29T18:55:33.848979547+05:30"
77
description: A Helm chart for deploying the Phase Kubernetes Operator
8-
digest: 1304ec0454da2e1fb6830d451fc34f39e56b91ec6a165d00db29ddc8c906824f
8+
digest: dc708b49b17107c0bf6efd354777f2ddaf4e080c18f7ab0541968338dfe808c5
99
home: https://github.com/phasehq/kubernetes-secrets-operator
1010
icon: https://phase.dev/apple-touch-icon.png
1111
keywords:
@@ -21,6 +21,6 @@ entries:
2121
- https://github.com/phasehq/kubernetes-secrets-operator
2222
type: application
2323
urls:
24-
- phase-kubernetes-operator-1.2.0.tgz
25-
version: 1.2.0
26-
generated: "2024-03-01T11:48:42.570910076+05:30"
24+
- https://helm.phase.dev/phase-kubernetes-operator-1.2.1.tgz
25+
version: 1.2.1
26+
generated: "2024-07-29T18:55:33.848176069+05:30"
-2.92 KB
Binary file not shown.
2.92 KB
Binary file not shown.

phase-kubernetes-operator/Chart.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ description: A Helm chart for deploying the Phase Kubernetes Operator
55
type: application
66

77
# Version of the chart
8-
version: 1.2.0
8+
version: 1.2.1
99

1010
# Version of the application (operator) that is being deployed
11-
appVersion: "1.2.0"
11+
appVersion: "1.2.1"
1212

1313
# Keywords, maintainers, and source URLs can also be added here
1414
keywords:

src/utils/const.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import os
22
import re
3-
__version__ = "1.2.0"
3+
__version__ = "1.2.1"
44
__ph_version__ = "v1"
55

66
description = "Securely manage application secrets and environment variables with Phase."

src/utils/secret_referencing.py

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
2222
2. Cross-Environment Reference (Root Path):
2323
Syntax: `${staging.DEBUG}`
24-
- Environment: Different environment (e.g., `dev`).
24+
- Environment: Different environment (e.g., `staging`).
2525
- Path: Root path (`/`) of the specified environment.
2626
- Secret Key: `DEBUG`
2727
- Description: References a secret named `DEBUG` in the root path of the `staging` environment.
@@ -45,6 +45,31 @@
4545
"""
4646

4747

48+
def split_path_and_key(ref: str) -> tuple:
49+
"""
50+
Splits a reference string into path and key components.
51+
52+
Args:
53+
ref (str): The reference string to split.
54+
55+
Returns:
56+
tuple: A tuple containing the path and key.
57+
"""
58+
last_slash_index = ref.rfind("/")
59+
if last_slash_index != -1:
60+
path = ref[:last_slash_index]
61+
key_name = ref[last_slash_index + 1:]
62+
else:
63+
path = "/"
64+
key_name = ref
65+
66+
# Ensure path starts with a slash
67+
if not path.startswith("/"):
68+
path = "/" + path
69+
70+
return path, key_name
71+
72+
4873
def resolve_secret_reference(ref: str, secrets_dict: Dict[str, Dict[str, Dict[str, str]]], phase: 'Phase', current_application_name: str, current_env_name: str) -> str:
4974
"""
5075
Resolves a single secret reference to its actual value by fetching it from the specified environment.
@@ -55,50 +80,42 @@ def resolve_secret_reference(ref: str, secrets_dict: Dict[str, Dict[str, Dict[st
5580
5681
Args:
5782
ref (str): The secret reference string, which could be a local or cross-environment reference.
58-
current_env_name (str): The current environment name, used for resolving local references.
83+
secrets_dict (Dict[str, Dict[str, Dict[str, str]]]): A dictionary containing known secrets.
5984
phase ('Phase'): An instance of the Phase class to fetch secrets.
85+
current_application_name (str): The name of the current application.
86+
current_env_name (str): The current environment name, used for resolving local references.
6087
6188
Returns:
62-
str: The resolved secret value.
63-
64-
Raises:
65-
ValueError: If the current environment name is not provided, or the secret is not found.
89+
str: The resolved secret value or the original reference if not resolved.
6690
"""
67-
6891
env_name = current_env_name
69-
path = "/" # Default root path
92+
path = "/" # Default root path
7093
key_name = ref
7194

7295
# 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.
96+
if "." in ref: # Cross-environment references
7497
parts = ref.split(".", 1)
7598
env_name, rest = parts[0], parts[1]
76-
last_slash_index = rest.rfind("/")
77-
if last_slash_index != -1:
78-
path = rest[:last_slash_index]
79-
key_name = rest[last_slash_index + 1:]
80-
else:
81-
key_name = rest
82-
elif "/" in ref: # Local reference with specified path
83-
last_slash_index = ref.rfind("/")
84-
path = ref[:last_slash_index]
85-
key_name = ref[last_slash_index + 1:]
86-
87-
# Adjust for leading slash in path if not present
88-
if not path.startswith("/"):
89-
path = "/" + path
99+
path, key_name = split_path_and_key(rest)
100+
else: # Local reference
101+
path, key_name = split_path_and_key(ref)
90102

91103
try:
92104
# 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]
95-
else:
96-
# Handle fallback for cross-environment or missing secrets
97-
if env_name != current_env_name:
98-
fetched_secrets = phase.get(env_name=env_name, app_name=current_application_name, keys=[key_name], path=path)
99-
for secret in fetched_secrets:
100-
if secret["key"] == key_name:
101-
return secret["value"]
105+
if env_name in secrets_dict:
106+
# Try to find the secret in the exact path
107+
if path in secrets_dict[env_name] and key_name in secrets_dict[env_name][path]:
108+
return secrets_dict[env_name][path][key_name]
109+
110+
# For local references, try to find the secret in the root path only if the original path was root
111+
if env_name == current_env_name and path == "/" and '/' in secrets_dict[env_name] and key_name in secrets_dict[env_name]['/']:
112+
return secrets_dict[env_name]['/'][key_name]
113+
114+
# If the secret is not found in secrets_dict, try to fetch it from Phase
115+
fetched_secrets = phase.get(env_name=env_name, app_name=current_application_name, keys=[key_name], path=path)
116+
for secret in fetched_secrets:
117+
if secret["key"] == key_name:
118+
return secret["value"]
102119
except EnvironmentNotFoundException:
103120
pass
104121

@@ -116,14 +133,13 @@ def resolve_all_secrets(value: str, all_secrets: List[Dict[str, str]], phase: 'P
116133
117134
Args:
118135
value (str): The input string containing one or more secret references.
119-
current_env_name (str): The current environment name for resolving local references.
136+
all_secrets (List[Dict[str, str]]): A list of all known secrets.
120137
phase ('Phase'): An instance of the Phase class to fetch secrets.
138+
current_application_name (str): The name of the current application.
139+
current_env_name (str): The current environment name for resolving local references.
121140
122141
Returns:
123142
str: The input string with all secret references resolved to their actual values.
124-
125-
Raises:
126-
ValueError: If the current environment name is not provided.
127143
"""
128144

129145
secrets_dict = {}

0 commit comments

Comments
 (0)