Skip to content

Commit b7cee4c

Browse files
authored
[Auth] Unified validation functions (#9158)
### 📝 Description Follow-up to #9154. Refactors secret token validation by removing the standalone `validate_secret_tokens` function and unifying validation logic into `extract_and_validate_tokens_info`. --- ### 🛠️ Changes Made - Removed redundant `validate_secret_tokens` function from `mlrun/auth/utils.py` - Unified token validation into `extract_and_validate_tokens_info` with a new `filter_by_authenticated_id` parameter - Updated `load_and_prepare_secret_tokens` to use the unified validation function - Updated tests to reflect the refactored validation logic --- ### ✅ Checklist - [ ] I updated the documentation (if applicable) - [x] I have tested the changes in this PR - [ ] I confirmed whether my changes are covered by system tests - [ ] If yes, I ran all relevant system tests and ensured they passed before submitting this PR - [ ] I updated existing system tests and/or added new ones if needed to cover my changes - [ ] If I introduced a deprecation: - [ ] I followed the [Deprecation Guidelines](./DEPRECATION.md) - [ ] I updated the relevant Jira ticket for documentation --- ### 🧪 Testing - Unit tests updated to cover the refactored validation logic - Tests verify token filtering by authenticated user ID with the new `filter_by_authenticated_id` parameter --- ### 🔗 References - Ticket link: N/A - Related PR: #9154 --- ### 🚨 Breaking Changes? - [ ] Yes (explain below) - [x] No --- ### 🔍️ Additional Notes This is a code cleanup PR that consolidates duplicate validation logic introduced in #9154.
1 parent a474e38 commit b7cee4c

File tree

2 files changed

+152
-125
lines changed

2 files changed

+152
-125
lines changed

mlrun/auth/utils.py

Lines changed: 14 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -234,73 +234,23 @@ def load_and_prepare_secret_tokens(
234234
:rtype: list[mlrun.common.schemas.SecretToken]
235235
"""
236236
tokens_list = load_secret_tokens_from_file(raise_on_error=raise_on_error)
237-
validated_tokens = validate_secret_tokens(
238-
tokens_list, auth_user_id=auth_user_id, raise_on_error=raise_on_error
237+
validated_tokens = extract_and_validate_tokens_info(
238+
secret_tokens=[
239+
mlrun.common.schemas.SecretToken(
240+
name=token["name"],
241+
token=token["token"],
242+
)
243+
for token in tokens_list
244+
],
245+
authenticated_id=auth_user_id,
246+
filter_by_authenticated_id=True,
239247
)
240248
secret_tokens = translate_secret_tokens(
241249
validated_tokens, raise_on_error=raise_on_error
242250
)
243251
return secret_tokens
244252

245253

246-
def validate_secret_tokens(
247-
tokens_list: list[dict[str, typing.Any]],
248-
auth_user_id: str | None,
249-
raise_on_error: bool = True,
250-
) -> list[dict[str, typing.Any]]:
251-
"""
252-
Validate a list of token dictionaries.
253-
254-
Checks performed:
255-
- Each token has a non-empty 'name' and 'token'.
256-
If raise_on_error=False, invalid entries are ignored.
257-
- No duplicate token names.
258-
If raise_on_error=False, duplicates are ignored.
259-
260-
:param tokens_list: List of token dictionaries to validate.
261-
:param raise_on_error: Whether to raise exceptions on invalid entries.
262-
:return: List of validated token dictionaries.
263-
:rtype: list[dict[str, Any]]
264-
"""
265-
valid_tokens = []
266-
seen = set()
267-
268-
token_file = os.path.expanduser(mlconf.auth_with_oauth_token.token_file)
269-
for token in tokens_list:
270-
name = token.get("name")
271-
token_value = token.get("token")
272-
273-
if not name or not isinstance(token_value, str) or not token_value.strip():
274-
# Invalid entry
275-
mlrun.utils.helpers.raise_or_log_error(
276-
f"Invalid token entry in {token_file}: missing or empty 'name' or 'token'",
277-
raise_on_error,
278-
)
279-
continue
280-
281-
if name in seen:
282-
# Duplicate entry
283-
mlrun.utils.helpers.raise_or_log_error(
284-
f"Duplicate token name '{name}' found in {token_file}",
285-
raise_on_error,
286-
)
287-
continue
288-
289-
seen.add(name)
290-
valid_tokens.append(token)
291-
292-
# filter out token with "sub" claim not matching the authenticated user
293-
if auth_user_id:
294-
matching_tokens = []
295-
for token in valid_tokens:
296-
name, value = token["name"], token["token"]
297-
if _decode_offline_token(value).get("sub") == auth_user_id:
298-
matching_tokens.append(token)
299-
return matching_tokens
300-
301-
return valid_tokens
302-
303-
304254
def translate_secret_tokens(
305255
tokens_list: list[dict[str, typing.Any]], raise_on_error: bool = True
306256
) -> list[mlrun.common.schemas.SecretToken]:
@@ -332,6 +282,7 @@ def translate_secret_tokens(
332282
def extract_and_validate_tokens_info(
333283
secret_tokens: list[mlrun.common.schemas.SecretToken],
334284
authenticated_id: str,
285+
filter_by_authenticated_id: bool = False,
335286
) -> dict[str, dict[str, typing.Any]]:
336287
"""
337288
Extract and validate tokens info from a list of SecretToken objects.
@@ -362,6 +313,9 @@ def extract_and_validate_tokens_info(
362313
# Validate token belongs to the authenticated user
363314
token_sub = decoded_token.get("sub")
364315
if token_sub != authenticated_id:
316+
# just ignore the token as it doesn't belong to the authenticated user
317+
if filter_by_authenticated_id:
318+
continue
365319
mlrun.utils.logger.warning(
366320
"Offline token subject does not match the authenticated user",
367321
token_name=token_name,

0 commit comments

Comments
 (0)