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

Fixes secret marshaling for kube play. Merge stringData with data for secrets. #16631

Merged

Conversation

ancosma
Copy link
Contributor

@ancosma ancosma commented Nov 26, 2022

Fixes secret (un)marshaling for kube play.

Merges stringData into data for secrets as in k8s.
Fixes e2e tests, remove '\n' from base64 encoded data.
Correct test to check that data in secret mounted file is decoded.

Closes #16269
Closes #16625

Signed-off-by: Andrei Natanael Cosma andrei@intersect.ro

Does this PR introduce a user-facing change?

NO

Fixes secret unmarshaling for kube play.

@ancosma ancosma force-pushed the fix-secret-unmarshal branch 4 times, most recently from d60bec5 to c6dc1fe Compare November 26, 2022 23:02
@ancosma ancosma changed the title Fixes secret unmarshaling for kube play. Fixes secret marshaling for kube play. Merge stringData with data for secrets. Nov 26, 2022
@ancosma ancosma force-pushed the fix-secret-unmarshal branch 5 times, most recently from ca0f876 to 8530bc9 Compare November 27, 2022 02:26
Copy link
Member

@vrothberg vrothberg left a comment

Choose a reason for hiding this comment

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

Thanks for contributing!

Changes LGTM
@cdoern PTAL

@rhatdan
Copy link
Member

rhatdan commented Nov 28, 2022

@odra PTAL

@rhatdan
Copy link
Member

rhatdan commented Nov 28, 2022

@ygalblum PTAL

@rhatdan
Copy link
Member

rhatdan commented Nov 28, 2022

@ashley-cui @umohnani8 PTAL

@ygalblum
Copy link
Collaborator

This change mixes data and stringData together. But, according to the spec for Secret, the field data is base64 encoded while stringData isn't. Furthermore, in K8S stringData is used to create a secret, but its content is merged into data after the values are base64 encoded. In addition, when mounted as a volume, all values are decoded back. So, the application can read them as is.

I can see that you changed the test so that it looks for the decoded value, but I don't understand what made it work now

@odra
Copy link
Contributor

odra commented Nov 28, 2022

I tried to run the pr locally but I got the following error:

$ ./bin/podman play kube --replace pod.yaml 
Error: failed to create volume "mysecret": invalid character 'a' looking for beginning of value

secret.yaml:

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  foo: YmFy

pod.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: app
      image: fedora
      command: ["/usr/bin/sleep", "infinity"]
      volumeMounts:
        - name: mysecret
          mountPath: "/etc/mysecret"
          readOnly: true
            # envFrom:
            # - secretRef:
            # name: mysecret
            # env:
            #   - name: FOO
            #     valueFrom:
            #       secretKeyRef:
            #         name: mysecret
            #         key: foo
  volumes:
    - name: mysecret
      secret:
        secretName: mysecret
        optional: false

@ancosma
Copy link
Contributor Author

ancosma commented Nov 28, 2022

This change mixes data and stringData together. But, according to the spec for Secret, the field data is base64 encoded while stringData isn't. Furthermore, in K8S stringData is used to create a secret, but its content is merged into data after the values are base64 encoded. In addition, when mounted as a volume, all values are decoded back. So, the application can read them as is.

I can see that you changed the test so that it looks for the decoded value, but I don't understand what made it work now

The base64 decoding happens on unmarshaling.
https://github.com/containers/podman/blob/main/pkg/domain/infra/abi/play.go#L268

The problem was that the entire secret object was serialized and stored in the (podman) secret while only the data of it was expected to be loaded when using it to fill env vars or volumes - hence the error. Also K8s states that content of secrets in volumes and environment variables should be decoded and also that stringData will be put on top of data (which was no the case previously).
Since decoding on base64 data happens during unmarshaling, adding stringData on top doesn't have to be base64 encoded before adding it. We only store podman secret as storage medium for values of K8s secret (data and stringData) - we could store the entire secret yaml, but then the code has to be changed since it mixed storing the yaml and loading json (data).

@ancosma
Copy link
Contributor Author

ancosma commented Nov 28, 2022

@odra
I've tried it and no issue. Please make sure that you run podman from the build and not local one (did same mistake while testing it previously).

podman on  fix-secret-unmarshal [?] via 🐹 v1.19.3 via 🐍 v3.10.8 via ⍱
❯ bin/podman kube play secret.yaml

podman on  fix-secret-unmarshal [?] via 🐹 v1.19.3 via 🐍 v3.10.8 via ⍱
❯ bin/podman kube play pod.yaml
Pod:
4dd786023d2a7c717b025d6cb97177f34c3bd1051566bfb88f660944d0ea3ef7
Container:
3f3e8a5033a595b91d611142773d4ee24f2ed8c9ad7ee261ec418dec13dc8396

podman on  fix-secret-unmarshal [?] via 🐹 v1.19.3 via 🐍 v3.10.8 via ⍱
❯ bin/podman exec -it mypod-app ls /etc/mysecret/
foo

podman on  fix-secret-unmarshal [?] via 🐹 v1.19.3 via 🐍 v3.10.8 via ⍱
❯ bin/podman exec -it mypod-app cat /etc/mysecret/foo
bar

@ancosma
Copy link
Contributor Author

ancosma commented Nov 28, 2022

Ran it with --replace and no issue.
podman on  fix-secret-unmarshal [?] via 🐹 v1.19.3 via 🐍 v3.10.8 via ⍱
❯ bin/podman kube play --replace pod.yaml
Pods stopped:
4dd786023d2a7c717b025d6cb97177f34c3bd1051566bfb88f660944d0ea3ef7
Pods removed:
4dd786023d2a7c717b025d6cb97177f34c3bd1051566bfb88f660944d0ea3ef7
Volumes removed:
Pod:
2ed36a9f4b51467e07fa60ef127808ed236256c43ce8150e62d83261446b8335
Container:
48114384883ca0d04442c9fa36055913d56b251b348211293c7aa2f81b03898a

@ygalblum
Copy link
Collaborator

Sorry for nagging, I'm just trying to understand why before the change the values in the container were encoded and now they are not.

Your change I understand. Instead of storing the entire K8S secret object as Podman secret, you store only its data by combining data and stringData into a single map and marshaling it into a json.

Furthermore, I now understand that the decoding is handled by the Unmarshal method and as a result when you merge data and stringData the values in both maps are decoded and hence there is no issue in combining them.

But, what I fail to understand is why before this change the values mounted into the container were encoded and now they are decoded. Now, don't get me wrong, I agree they should be decoded to align with K8S. I just don't understand how it happened.

Thanks in advance

@ancosma
Copy link
Contributor Author

ancosma commented Nov 28, 2022

I haven't really checked it but might come from the fact that play used "github.com/ghodss/yaml" for marshaling while volume used "gopkg.in/yaml.v3" for unmarshaling.

@ygalblum
Copy link
Collaborator

I haven't really checked it but might come from the fact that play used "github.com/ghodss/yaml" for marshaling while volume used "gopkg.in/yaml.v3" for unmarshaling.

OK, thanks

@ygalblum
Copy link
Collaborator

LGTM, but I guess @odra should first see what's not working for him

@ashley-cui
Copy link
Member

ashley-cui commented Nov 28, 2022

Will this break existing kube secrets? Since this changes the secret storage schema?

I don't remember if kube secrets persist across plays though, so this might not be a problem..

@ygalblum
Copy link
Collaborator

I think @ashley-cui is right. K8S secrets are stored into Podman secrets and hence persist. Since this change breaks the schema, podman will fail to load secrets that were created with an older version

@ancosma
Copy link
Contributor Author

ancosma commented Nov 28, 2022

Maybe that's the issue @odra is having.
I personally wouldn't care much about backward compatibility since the secrets were not usable in the last versions of podman. If needed I can modify it to store/load the entire K8s secret instead of only the data, not sure if make sense.

@odra
Copy link
Contributor

odra commented Nov 28, 2022

Yeah, that's the issue I had, storing secrets with "play kube" works wihile storing a raw kubernetes secret with "podman secret create.." breaks it (altough that was working before this change) but creating it wth "play kube" works.

I thought that creating a k8s secret using "play kube" would store the raw yaml/json secret as podman secret but that doesn't seem to be the case right?

Using "play kube" to store kubernetes secrets sound a bit weird to me since there but I may not have the full context of a podman secret.

@rhatdan
Copy link
Member

rhatdan commented Nov 28, 2022

If the kube.yaml file includes a secret then the secret should be created for the run of the podman kube play command and removed when the command exits, which I believe follows the k8s standard.

@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Nov 28, 2022
@ashley-cui ashley-cui added the do-not-merge/needs-confirmation Waiting for feedback from stakeholder before merging label Dec 2, 2022
@vrothberg
Copy link
Member

I personally wouldn't care much about backward compatibility since the secrets were not usable in the last versions of podman. If needed I can modify it to store/load the entire K8s secret instead of only the data, not sure if make sense.

Yes, let's restore to the previous behavior. We must remain backwards compatible unless there's an urgent need not to (e.g., security fix). Thanks for pointing that out, @ashley-cui! (And sorry for not spotting that in my earlier review)

@ancosma
Copy link
Contributor Author

ancosma commented Dec 6, 2022

@vrothberg Previous behavior restored for backward compatibility.

@vrothberg
Copy link
Member

Thanks, @andrei-n-cosma! The tests seem unhappy.

@ancosma
Copy link
Contributor Author

ancosma commented Dec 7, 2022

@vrothberg Fixed the read of k8s secret from podman secret to support both JSON and YAML. Should pass now.

Copy link
Member

@vrothberg vrothberg left a comment

Choose a reason for hiding this comment

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

Thanks!

@ashley-cui PTAL

@ashley-cui
Copy link
Member

LGTM, thanks @andrei-n-cosma!

Fixes e2e tests, remove '\n' from base64 encoded data.
Correct test to check that data in secret mounted file is decoded.

Closes containers#16269
Closes containers#16625

Signed-off-by: Andrei Natanael Cosma <andrei@intersect.ro>
Copy link
Member

@vrothberg vrothberg left a comment

Choose a reason for hiding this comment

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

/lgtm
/hold

I restarted the flaked job.

@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Dec 8, 2022
@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Dec 8, 2022
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Dec 8, 2022

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: andrei-n-cosma, vrothberg

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Dec 8, 2022
@vrothberg
Copy link
Member

/hold cancel

@openshift-ci openshift-ci bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Dec 8, 2022
@rhatdan rhatdan removed the do-not-merge/needs-confirmation Waiting for feedback from stakeholder before merging label Dec 9, 2022
@openshift-merge-robot openshift-merge-robot merged commit 7d2a19c into containers:main Dec 9, 2022
@MartinX3
Copy link

MartinX3 commented Dec 9, 2022

will there be a v4.3.2 bugfix release?
I sadly don't see a podman roadmap or a milestone anywhere.

@vrothberg
Copy link
Member

There are no plans to cut a v4.3.2. But 4.4 is scheduled early next year.

@MartinX3
Copy link

MartinX3 commented Dec 9, 2022

Thank you for the info
But also it's sad to hear, that bug fixes don't get backported to patch releases until the next feature release comes :(

@vrothberg
Copy link
Member

Thank you for the info But also it's sad to hear, that bug fixes don't get backported to patch releases until the next feature release comes :(

They do get backported. v4.3 had two bug-fix releases already. We didn't plan for another patch-release in this specific case as we're close to the end of the year; many folks are on vacation or shortly going to be.

@ancosma ancosma deleted the fix-secret-unmarshal branch December 9, 2022 22:56
@github-actions github-actions bot added the locked - please file new issue/PR Assist humans wanting to comment on an old issue or PR with locked comments. label Sep 18, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged. locked - please file new issue/PR Assist humans wanting to comment on an old issue or PR with locked comments. release-note
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Kubernetes secret and base64 data play kube: invalid character 'a' looking for beginning of value
8 participants