Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

securityContext default override not as expected #11130

Open
2 of 3 tasks
rwong2888 opened this issue May 25, 2023 · 11 comments · May be fixed by #12476
Open
2 of 3 tasks

securityContext default override not as expected #11130

rwong2888 opened this issue May 25, 2023 · 11 comments · May be fixed by #12476
Assignees
Labels
area/spec Changes to the workflow specification. P3 Low priority type/bug type/security Security related

Comments

@rwong2888
Copy link
Contributor

rwong2888 commented May 25, 2023

Pre-requisites

  • I have double-checked my configuration
  • I can confirm the issues exists when I tested with :latest
  • I'd like to contribute the fix myself (see contributing guide)

What happened/what you expected to happen?

#11127

I have the below controller configmap on v3.4.7.

apiVersion: v1
kind: ConfigMap
metadata:
  name: workflow-controller-configmap
data:
  # https://blog.argoproj.io/practical-argo-workflows-hardening-dd8429acc1ce
  mainContainer: |
    securityContext:
      runAsNonRoot: true
      runAsUser: 8737
      runAsGroup: 8737
      privileged: false
      readOnlyRootFilesystem: true
      allowPrivilegeEscalation: false
      capabilities:
        drop:
          - ALL
  executor: |
    securityContext:
      runAsNonRoot: true
      runAsUser: 8737
      runAsGroup: 8737
      privileged: false
      allowPrivilegeEscalation: false
      capabilities:
        drop:
          - ALL
  workflowDefaults: |
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 8737
        runAsGroup: 8737

I am trying to remove securityContext.capabilities.drop from the main container in a containerset.

I've tried setting capabilities to null or {} on my main container.

I've tried setting drop to null or [] on my main container.

e.g.

            securityContext:
              runAsUser: 1000
              runAsGroup: 1000
              capabilities: null
            securityContext:
              runAsUser: 1000
              runAsGroup: 1000
              capabilities: {}

But when I check the yaml of my pod, the container's securityContext capabilities is still drop all.

Referencing @alexec's blog post

And helm's deleting a default key

@terrytangyuan

Seems like a bug. The logic here needs to be revisited: https://github.com/argoproj/argo-workflows/blob/master/workflow/controller/workflowpod.go#L607-L629

Version

v3.4.7

Paste a small workflow that reproduces the issue. We must be able to run the workflow; don't enter a workflows that uses private images.

n/a

Logs from the workflow controller

n/a

Logs from in your workflow's wait container

n/a
@rwong2888
Copy link
Contributor Author

rwong2888 commented May 25, 2023

I also tried @crenshaw-dev 's suggestion of podSpecPatch which did not work

      containerSet:
        podSpecPatch: '{"containers":[{"name":"main", "securityContext":{"capabilities":{}}}]}'
        containers:
      containerSet:
        podSpecPatch: '{"containers":[{"name":"main", "securityContext":{"capabilities":null}}]}'
        containers:

Referencing

@sarabala1979
Copy link
Member

@rohankmr414 it looks like a JSON merge issue. Please take a look at operator.go and workflowPod.go. These two places Json will merge to construct the securitycontext.

@sarabala1979 sarabala1979 added the P3 Low priority label Jun 1, 2023
@mslapek
Copy link

mslapek commented Jun 13, 2023

The merge logic is in createWorkflowPod from workflowpod.go:

if ctrDefaults := woc.controller.Config.MainContainer; ctrDefaults != nil {
// essentially merge the defaults, then the template, into the container
a, err := json.Marshal(ctrDefaults)
if err != nil {
return nil, err
}
b, err := json.Marshal(c)
if err != nil {
return nil, err
}
if err := json.Unmarshal(a, &c); err != nil {
return nil, err
}
if err = json.Unmarshal(b, &c); err != nil {
return nil, err
}
}
mainCtrs[i] = c

However, I'm afraid we cannot have the expected result with mainCtrs []apiv1.Container as an input – because we cannot differ between two kinds of null:

  1. Set by user explicitly in JSON – so we want to delete the key.
  2. Omitted by user in JSON – so we want to use a default value.

To solve the issue, we would need to take untyped JSON as an input mainCtrs []map[string]any - so json.Unmarshal would decode the intent properly.

Question Should we make big-change of mainCtrs to this new type? (looks like a big churn ☹️)

@stale

This comment was marked as resolved.

@stale stale bot added the problem/stale This has not had a response in some time label Sep 17, 2023
@rwong2888

This comment was marked as resolved.

@stale stale bot removed the problem/stale This has not had a response in some time label Sep 18, 2023
@agilgur5 agilgur5 added type/security Security related area/spec Changes to the workflow specification. labels Sep 18, 2023
@terrytangyuan
Copy link
Member

@jswxstw Are you interested in working on this?

@terrytangyuan
Copy link
Member

That sounds confusing though. Let's try reusing the current fields if possible

@terrytangyuan
Copy link
Member

@jswxstw Please do not delete comments unless necessary since others will lose the context.

@jswxstw
Copy link
Member

jswxstw commented Jan 5, 2024

That sounds confusing though. Let's try reusing the current fields if possible

ok, podSpecPatch seems like it can be used to solve this problem, I will try to check out why it did not work.

@jswxstw
Copy link
Member

jswxstw commented Jan 5, 2024

'{"containers":[{"name":"main", "securityContext":{"capabilities":{}}}]}'

The correct usage of podSpecPatch:

spec:
  entrypoint: whalesay
  templates:
  - name: whalesay
    podSpecPatch: '{"containers":[{"name":"main", "securityContext":{"capabilities":null}}]}'
    containerSet:

However, there is still a bug here: @terrytangyuan

// Apply the patch string from template
if woc.hasPodSpecPatch(tmpl) {
tmpl.PodSpecPatch, err = util.PodSpecPatchMerge(woc.wf, tmpl)
if err != nil {
return nil, errors.Wrap(err, "", "Failed to merge the workflow PodSpecPatch with the template PodSpecPatch due to invalid format")
}
// Final substitution for workflow level PodSpecPatch
localParams := make(map[string]string)
if tmpl.IsPodType() {
localParams[common.LocalVarPodName] = pod.Name
}
tmpl, err := common.ProcessArgs(tmpl, &wfv1.Arguments{}, woc.globalParams, localParams, false, woc.wf.Namespace, woc.controller.configMapInformer.GetIndexer())
if err != nil {
return nil, errors.Wrap(err, "", "Failed to substitute the PodSpecPatch variables")
}
patchedPodSpec, err := util.ApplyPodSpecPatch(pod.Spec, tmpl.PodSpecPatch)
if err != nil {
return nil, errors.Wrap(err, "", "Error applying PodSpecPatch")
}
pod.Spec = *patchedPodSpec
}

before PodSpecPatchMerge: '{"containers":[{"name":"main", "securityContext":{"capabilities":null}}]}'
after PodSpecPatchMerge: '{"containers":[{"name":"main", "securityContext":{"capabilities":{}}}]}'

jswxstw pushed a commit to jswxstw/argo-workflows that referenced this issue Jan 6, 2024
jswxstw pushed a commit to jswxstw/argo-workflows that referenced this issue Jan 6, 2024
jswxstw pushed a commit to jswxstw/argo-workflows that referenced this issue Jan 7, 2024
@terrytangyuan
Copy link
Member

Thanks. Could you take a look at my comment?

jswxstw pushed a commit to jswxstw/argo-workflows that referenced this issue May 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/spec Changes to the workflow specification. P3 Low priority type/bug type/security Security related
Projects
None yet
7 participants