Skip to content

Conversation

@elbamit
Copy link
Contributor

@elbamit elbamit commented Dec 14, 2025

📝 Description

Add secret token mounting for RemoteRuntime functions.
Save auth as part of the function's spec. Use it to mount the secret into the runtime during function config compilation.


🛠️ Changes Made

  • Added auth as part of NuclioSpec, ApplicationSpec and ServingSpec
  • Enrich auth token name on the function during deployment, then mount secret to runtime during function config compilation.
  • Refactor mount_secret_token_to_runtime to remove existing auth secret volumes/mounts
  • Refactor _enrich_and_validate_auth_token_name to enrich_and_validate_auth_token_name_on_object to support both runObject and remoteRuntime

✅ Checklist

  • I updated the documentation (if applicable)
  • 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:

🧪 Testing

Unit tests + manual tests of deployment of nuclio/application/serving


🔗 References


🚨 Breaking Changes?

  • Yes (explain below)
  • No

🔍️ Additional Notes

As part of https://iguazio.atlassian.net/browse/ML-11599, need to handle redeployment of a function with a different auth token name.

@elbamit elbamit marked this pull request as ready for review December 14, 2025 18:27
@elbamit elbamit requested review from a team, TomerShor and adamdelman as code owners December 14, 2025 18:27
Copy link
Member

@liranbg liranbg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some suggestions and renamings, overall very well. I suggest to run some nuclio system tests to see how it plays and no regressions were made.

# TODO In ML-11600, implement token name resolution and validation + tests
def _enrich_and_validate_auth_token_name(self, run: mlrun.run.RunObject):
auth = run.spec.auth or {}
def enrich_and_validate_auth_token_name_on_object(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def enrich_and_validate_auth_token_name_on_object(
def enrich_and_validate_auth_token_name(

why renaming? also, function name should reflect what it does (enriches/validates the auth token) the added information is subjected to the argument - which can be omitted from the name for redundancy or (TMI)

else url.startswith("http")
)

def test_compile_function_config_iguazio_v4_mounts_auth_secret(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def test_compile_function_config_iguazio_v4_mounts_auth_secret(self):
def test_compile_function_config_with_auth_secret(self):

Comment on lines 1371 to 1372
runtime.spec.volumes = initial_volumes.copy()
runtime.spec.volume_mounts = initial_mounts.copy()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you need to copy them?

def enrich_and_validate_auth_token_name_on_object(
self, object: Union[mlrun.run.RunObject, mlrun.runtimes.RemoteRuntime]
):
# Ensure the auth dictionary exists
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Ensure the auth dictionary exists

code is self explanatory

Comment on lines 710 to 716
# Resolve token name
if provided_token_name:
token_name = provided_token_name
self._validate_token_name(token_name, raise_error_on_failure=True)
else:
token_name = "default"
self._validate_token_name(token_name, raise_error_on_failure=False)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is default token name a constant? I think it should be
also, comment on why you raise an exception?

Suggested change
# Resolve token name
if provided_token_name:
token_name = provided_token_name
self._validate_token_name(token_name, raise_error_on_failure=True)
else:
token_name = "default"
self._validate_token_name(token_name, raise_error_on_failure=False)
# explain me
raise_error_on_failure = bool(provided_token_name)
token_name = provided_token_name or "default"
self._validate_token_name(token_name, raise_error_on_failure=False)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@quaark I can use mlconf.auth_with_oauth_token.token_name, however if user sets this env var prior to importing mlrun, then runs/deploy a function, the token resolution logic will use that instead.
I assume we don't want that behavior right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok so we'll make it a constant not a config

Comment on lines 853 to 860
for vol in volumes:
if "secret" in vol:
secret = vol["secret"]
secret_name = secret.get("secretName", "")

# Pattern of auth secret volumes
if secret_name.startswith("mlrun-auth-secrets"):
volumes_to_remove.add(vol["name"])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for vol in volumes:
if "secret" in vol:
secret = vol["secret"]
secret_name = secret.get("secretName", "")
# Pattern of auth secret volumes
if secret_name.startswith("mlrun-auth-secrets"):
volumes_to_remove.add(vol["name"])
for volume in volumes:
if secret := volume.get("secret"):
secret_name = secret.get("secretName", "")
if secret_name.startswith("mlrun-auth-secrets"):
volumes_to_remove.add(volume["name"])

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shorter, with full name

Copy link
Contributor Author

@elbamit elbamit Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rokatyy's suggestion is more robust. Using her's instead

Comment on lines 863 to 865
runtime.spec.volumes = [
v for v in volumes if v["name"] not in volumes_to_remove
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
runtime.spec.volumes = [
v for v in volumes if v["name"] not in volumes_to_remove
]
runtime.spec.volumes = [
volume
for volume in volumes
if volume["name"] not in volumes_to_remove
]

use full name, makes it more readable


# Filter out matching mounts
runtime.spec.volume_mounts = [
m for m in mounts if m["name"] not in volumes_to_remove
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make it readable

)

# Remove any existing auth secret volumes/mounts
services.api.crud.secrets.Secrets._remove_auth_secret_volumes(runtime)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seeing these calls (static method) from within same class static method) shows me that the decision to put the logic under Secrets class that it was a bit wrong.
I think we need to change it and move logic under runtime/etc. then we could do

runtime.enrich_and_validate()
function.remove_auth_secret_volumes()

using self, etc

Comment on lines 253 to 257
function = services.api.crud.secrets.Secrets.mount_secret_token_to_runtime(
function,
token_name=function.spec.auth.get("token_name"),
username=auth_info.username,
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@rokatyy rokatyy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor suggestions

…umes' logic from outside the 'Secrets' class into the baseRuntime and the BaseRuntimeHandler. The '_mount_secret_token_to_runtime' is now used inside the 'add_k8s_secrets_to_spec' method which is called both from the runtime handler flow and the nuclio deployment flow. Tests have been updated respectively to match the new functions locations (however not refactored based on other PR comments)
… the mlrun.utils.get_in method, using constant for auth secret name prefix and using full name for variables. The used constant returns a trailing dot in the prefix name which allowed me to discover that the examples in the tests didn't perfectly match real life - so tests have been adjusted accordingly
…d changes. Refactor enrich_and_validate_auth_token_name to run on ig4 only, removed if/else condition and used constant name for default token name
Copy link
Member

@rokatyy rokatyy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

silent=True
).is_running_inside_kubernetes_cluster():
_add_secrets_config_to_function_spec(function)
token_name = mlrun.utils.get_in(function.spec, "auth.token_name", None)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want to skip if token is empty? Or will it be handled later in the flow?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Later in the flow it will try to list the secrets matching that token, but there won't be such, so we won't perform the mounting.

Copy link
Member

@liranbg liranbg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks much much better. minor suggestion to keep the coding better



def _resolve_env_vars(function, auth_info=None):
def _enrich_config_spec(function, username):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not passing auth_info entirely? a better practice as you might late on use its other fields

runtime: mlrun.runtimes.pod.KubeResource,
project_name: Optional[str] = None,
token_name: Optional[str] = None,
username: Optional[str] = None,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pass auth_info

project_name: Optional[str] = None,
encode_key_names: bool = True,
token_name: Optional[str] = None,
username: Optional[str] = None,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pass auth_info


@staticmethod
def _mount_secret_token_to_runtime(
runtime: mlrun.runtimes.base.BaseRuntime, token_name: str, username: str
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pass auth_info

runtime,
project_name=run.metadata.project,
token_name=(run.spec.auth or {}).get("token_name"),
username=auth_info.username,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

simply pass the auto info - it allows the function to extend and use the class capabilities later on when we want to identify user not just by username but even perhaps its group

…ow extension in the class capabilities in the future. Fixed tests accordingly.
@liranbg liranbg merged commit e779888 into mlrun:development Dec 17, 2025
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants