The functions _lifecycle_hook_from_deco, _error_msg_capture_hook_templates, and _heartbeat_daemon_template
|
def _lifecycle_hook_from_deco(self, deco): |
|
def _error_msg_capture_hook_templates(self): |
|
def _heartbeat_daemon_template(self): |
all include the same pattern of copying the start step's @kubernetes attributes
|
# We want to grab the base image used by the start step, as this is known to be pullable from within the cluster, |
|
# and it might contain the required libraries, allowing us to start up faster. |
|
resources = dict( |
|
[deco for deco in start_step.decorators if deco.name == "kubernetes"][ |
|
0 |
|
].attributes |
|
) |
and then use this resources dict to fill in attributes such as the image and secrets of the container. However, it does not copy over the security context defined from the original @kubernetes decorator, which can result in, for instance, the resulting pod being labeled as insecure or even rejected.
To resolve this issue, I think it should be sufficient to specify the security_context in the generated container using the same security context from resources (resources["security_container"]).
Reproducing
I used the following flow and ran the comment python flow.py argo-workflows create --only-json (note: datastore required).
from metaflow import FlowSpec, kubernetes, step
_SECURITY_CONTEXT = {"allow_privilege_escalation": False}
class TestFlow(FlowSpec):
"""
Minimal example to show error-msg-capture-hook does not inherit
the same security context as all the steps
"""
@kubernetes(security_context=_SECURITY_CONTEXT)
@step
def start(self):
print("Start")
self.next(self.end)
@kubernetes(security_context=_SECURITY_CONTEXT)
@step
def end(self):
print("End")
if __name__ == '__main__':
TestFlow()
This will produce a start, an end, and an error-msg-capture-hook. The start and end steps have the following security context:
"securityContext": {
"allowPrivilegeEscalation": false,
"appArmorProfile": null,
"capabilities": null,
"privileged": null,
"procMount": null,
"readOnlyRootFilesystem": null,
"runAsGroup": null,
"runAsNonRoot": null,
"runAsUser": null,
"seLinuxOptions": null,
"seccompProfile": null,
"windowsOptions": null
},
meanwhile the error hook has "securityContext": null.
The functions
_lifecycle_hook_from_deco,_error_msg_capture_hook_templates, and_heartbeat_daemon_templatemetaflow/metaflow/plugins/argo/argo_workflows.py
Line 3041 in d2dd7f9
metaflow/metaflow/plugins/argo/argo_workflows.py
Line 3188 in d2dd7f9
metaflow/metaflow/plugins/argo/argo_workflows.py
Line 3650 in d2dd7f9
all include the same pattern of copying the start step's
@kubernetesattributesmetaflow/metaflow/plugins/argo/argo_workflows.py
Lines 3192 to 3198 in d2dd7f9
and then use this
resourcesdict to fill in attributes such as the image and secrets of the container. However, it does not copy over the security context defined from the original@kubernetesdecorator, which can result in, for instance, the resulting pod being labeled as insecure or even rejected.To resolve this issue, I think it should be sufficient to specify the
security_contextin the generated container using the same security context from resources (resources["security_container"]).Reproducing
I used the following flow and ran the comment
python flow.py argo-workflows create --only-json(note: datastore required).This will produce a
start, anend, and anerror-msg-capture-hook. Thestartandendsteps have the following security context:meanwhile the error hook has
"securityContext": null.