diff --git a/gpustack_runtime/deployer/kubernetes.py b/gpustack_runtime/deployer/kubernetes.py index 69128c3..bb819d9 100644 --- a/gpustack_runtime/deployer/kubernetes.py +++ b/gpustack_runtime/deployer/kubernetes.py @@ -692,6 +692,21 @@ def _resolve_runtime_class_name( pod.spec.runtime_class_name = runtime_class_name +def _set_privilege_escalation(container: kubernetes.client.V1Container) -> None: + security = container.security_context or kubernetes.client.V1SecurityContext() + capabilities = security.capabilities + added_capabilities = { + capability.upper().removeprefix("CAP_") + for capability in (capabilities.add or []) + } if capabilities else set() + # Kubernetes cannot disable escalation for privileged containers, SYS_ADMIN, or ALL. + security.allow_privilege_escalation = bool( + security.privileged + or added_capabilities.intersection({"SYS_ADMIN", "ALL"}), + ) + container.security_context = security + + def _resolve_privileged(container: Container, kdp: bool) -> bool: """ Resolve whether a container runs privileged. @@ -1765,6 +1780,8 @@ def _create_pod( ), ) + _set_privilege_escalation(container) + # Append the container. if c.profile == ContainerProfileEnum.INIT: pod.spec.init_containers = pod.spec.init_containers or [] diff --git a/tests/gpustack_runtime/deployer/test_privilege_escalation.py b/tests/gpustack_runtime/deployer/test_privilege_escalation.py new file mode 100644 index 0000000..c4d0005 --- /dev/null +++ b/tests/gpustack_runtime/deployer/test_privilege_escalation.py @@ -0,0 +1,36 @@ +from __future__ import annotations as __future_annotations__ + +import kubernetes +import pytest + +from gpustack_runtime.deployer.kubernetes import _set_privilege_escalation + + +@pytest.mark.parametrize( + "security, expected", + [ + (None, False), + (kubernetes.client.V1SecurityContext(privileged=False), False), + (kubernetes.client.V1SecurityContext(privileged=True), True), + *[ + (kubernetes.client.V1SecurityContext( + capabilities=kubernetes.client.V1Capabilities(add=[value]), + ), True) + for value in ["SYS_ADMIN", "CAP_SYS_ADMIN", "sys_admin", "cap_sys_admin", "ALL", "CAP_ALL"] + ], + ( + kubernetes.client.V1SecurityContext( + capabilities=kubernetes.client.V1Capabilities(add=["IPC_LOCK"]), + run_as_user=1000, + ), + False, + ), + ], +) +def test_privilege_escalation_matches_final_security_context(security, expected): + container = kubernetes.client.V1Container(name="model", security_context=security) + _set_privilege_escalation(container) + assert container.security_context.allow_privilege_escalation is expected + if security is not None: + assert container.security_context is security + assert container.security_context.run_as_user == security.run_as_user