Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

loozhengyuan
Copy link
Contributor

@loozhengyuan loozhengyuan commented Nov 1, 2020

What type of PR is this?

/kind feature

What this PR does / why we need it:

As elaborated in #87840, the existing implementation of kubectl diff exposes base64-encoded data in secrets. While this is somewhat helpful for comparison, the exposure of these secrets renders the command unsafe for use in shared environments, e.g. running as part of CI/CD workflows.

This PR resolves this issue by masking sensitive values in the Secret object when generating the diffs. If a secret value has been changed, an additional (before)/(after) suffix is added so that they can still be compared.

View examples

Which issue(s) this PR fixes:

Fixes #87840

Special notes for your reviewer:

cc: @apelisse

Does this PR introduce a user-facing change?:

Secret values are now masked by default in kubectl diff output.

/area kubectl
/sig cli

@k8s-ci-robot k8s-ci-robot added kind/feature Categorizes issue or PR as related to a new feature. area/kubectl size/L Denotes a PR that changes 100-499 lines, ignoring generated files. sig/cli Categorizes an issue or PR as relevant to SIG CLI. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. release-note Denotes a PR that will be considered when it comes time to generate release notes. needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. labels Nov 1, 2020
@k8s-ci-robot
Copy link
Contributor

@loozhengyuan: This issue is currently awaiting triage.

If a SIG or subproject determines this is a relevant issue, they will accept it by applying the triage/accepted label and provide further guidance.

The triage/accepted label can be added by org members by writing /triage accepted in a comment.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@k8s-ci-robot k8s-ci-robot added the needs-priority Indicates a PR lacks a `priority/foo` label and requires one. label Nov 1, 2020
@k8s-ci-robot
Copy link
Contributor

Welcome @loozhengyuan!

It looks like this is your first PR to kubernetes/kubernetes 🎉. Please refer to our pull request process documentation to help your PR have a smooth ride to approval.

You will be prompted by a bot to use commands during the review process. Do not be afraid to follow the prompts! It is okay to experiment. Here is the bot commands documentation.

You can also check if kubernetes/kubernetes has its own contribution guidelines.

You may want to refer to our testing guide if you run into trouble with your tests not passing.

If you are having difficulty getting your pull request seen, please follow the recommended escalation practices. Also, for tips and tricks in the contribution process you may want to read the Kubernetes contributor cheat sheet. We want to make sure your contribution gets all the attention it needs!

Thank you, and welcome to Kubernetes. 😃

@k8s-ci-robot
Copy link
Contributor

Hi @loozhengyuan. Thanks for your PR.

I'm waiting for a kubernetes member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@k8s-ci-robot k8s-ci-robot added needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Nov 1, 2020
@loozhengyuan
Copy link
Contributor Author

I've added a draft implementation for the PR. I still have a few failing test cases which I have yet to resolve, will be working on those.

Some things to note:

  1. I've opted to mask using a fixed-length string of asterisks since it probably isn't helpful to compare the asterisks per se.
  2. For now, this only works if the object is a V1Secret. I'm not sure if there are any other objects containing sensitive values, do let me know if there are others we should consider.
  3. This is expected to be the new default behaviour but i'm unsure if there are use cases where we would like to know the exact diffs of the secrets. I think this is quite unlikely because (1) comparing the base64-encoded values are not that helpful and (2) we could use kubectl get or kubectl describe if we really need to compare the values for debugging.

@apelisse
Copy link
Member

apelisse commented Nov 2, 2020

  1. I've opted to mask using a fixed-length string of asterisks since it probably isn't helpful to compare the asterisks per se.

Let me see that, because we do want diff(1) to generate a diff between old and new, so the strings need to be different somehow. I'll comment directly on the PR.

EDIT: OK I just saw, that's quite good. I'm not sure if we can improve the wording to clarify what's going on here, I can see how it could be confusing but I'm not sure yet how we could improve that phrasing.

  1. For now, this only works if the object is a V1Secret. I'm not sure if there are any other objects containing sensitive values, do let me know if there are others we should consider.

I think that's fine.

  1. This is expected to be the new default behaviour but i'm unsure if there are use cases where we would like to know the exact diffs of the secrets. I think this is quite unlikely because (1) comparing the base64-encoded values are not that helpful and (2) we could use kubectl get or kubectl describe if we really need to compare the values for debugging.

I think that's fine too

Thanks for working on this!

@loozhengyuan
Copy link
Contributor Author

Just to provide visibility on how this PR will change the representation of diffs for V1Secret, I’ve generated a comparison of three common scenarios using the current and new implementation of kubectl diff.

Added Secret Value

OldNew
$ kubectl diff -f secret.yaml
...
@@ -1,6 +1,7 @@
 apiVersion: v1
 data:
   password: c2VjcmV0
+  username: YmFyCg==
 kind: Secret
 metadata:
   annotations:
$ kubectl diff -f secret.yaml
...
@@ -1,6 +1,7 @@
 apiVersion: v1
 data:
   password: '***'
+  username: '***'
 kind: Secret
 metadata:
   annotations:

Changed Secret Value

OldNew
$ kubectl diff -f secret.yaml
...
@@ -1,6 +1,6 @@
 apiVersion: v1
 data:
-  password: c2VjcmV0
+  password: MTIzCg==
   username: YmFyCg==
 kind: Secret
 metadata:
$ kubectl diff -f secret.yaml
...
@@ -1,6 +1,6 @@
 apiVersion: v1
 data:
-  password: '*** (before)'
+  password: '*** (after)'
   username: '***'
 kind: Secret
 metadata:

Removed Secret Value

OldNew
$ kubectl diff -f secret.yaml
...
@@ -1,6 +1,5 @@
 apiVersion: v1
 data:
-  password: c2VjcmV0
   username: YmFyCg==
 kind: Secret
 metadata:
$ kubectl diff -f secret.yaml
...
@@ -1,6 +1,5 @@
 apiVersion: v1
 data:
-  password: '***'
   username: '***'
 kind: Secret
 metadata:

@loozhengyuan loozhengyuan changed the title [WIP] feat: masked secrets in kubectl diff output feat: masked secrets in kubectl diff output Nov 2, 2020
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Nov 2, 2020
@loozhengyuan
Copy link
Contributor Author

I've resolved all the remaining test cases so this should be ready for review and testing.

@apelisse
Copy link
Member

apelisse commented Nov 2, 2020

I'll take a look at the code, the behavior looks good to me.
/ok-to-test

@k8s-ci-robot k8s-ci-robot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Nov 2, 2020
@loozhengyuan
Copy link
Contributor Author

/retest

@apelisse
Copy link
Member

apelisse commented Nov 2, 2020

I think you'll have to refactor this a little bit. I would change the "(DIffer) Diff" function so that you can do something like this:

func (d *Differ) Diff(obj Object, printer Printer) error {
        fromObject, err := d.From.Get(obj) // This Get function doesn't exist yet
        if err != nil {
          return err
        }
        toObject, err := d.To.Get(obj) // This Get function doesn't exist yet
        if err != nil {
          return err
        }

        // XXX: Mask the data here somehow

        // you might not need to have "to" and "from" to have different printers.
	if err := d.From.Print(fromObject, printer); err != nil {
		return err
	}
	if err := d.To.Print(toObject, printer); err != nil {
		return err
	}
	return nil
}

@loozhengyuan
Copy link
Contributor Author

Yeah I think that looks better, i'll work on refactoring into Differ.Diff.

@william-salt-cko
Copy link

@loozhengyuan any update on this?

@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 1, 2021
@loozhengyuan loozhengyuan force-pushed the kubectl-diff-with-masked-secrets branch from 5372458 to af9001c Compare May 2, 2021 00:25
@loozhengyuan
Copy link
Contributor Author

/test pull-kubernetes-e2e-kind

@loozhengyuan
Copy link
Contributor Author

loozhengyuan commented May 2, 2021

@apelisse and @rikatz, I've rebased the PR and made the necessary changes, ready for another review.

@loozhengyuan loozhengyuan requested review from apelisse and rikatz May 2, 2021 02:15
@apelisse
Copy link
Member

apelisse commented May 4, 2021

Thanks
/lgtm
/approve

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label May 4, 2021
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: apelisse, loozhengyuan

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

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label May 4, 2021
@apelisse
Copy link
Member

apelisse commented May 4, 2021

/hold

Would you mind squashing these commits? Thanks.

@k8s-ci-robot k8s-ci-robot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label May 4, 2021
@rikatz
Copy link
Member

rikatz commented May 4, 2021

/label tide/merge-method-squash
@apelisse tide can do this for us :D
/retest

@k8s-ci-robot k8s-ci-robot added the tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges. label May 4, 2021
@apelisse
Copy link
Member

apelisse commented May 5, 2021

/hold cancel

@k8s-ci-robot k8s-ci-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label May 5, 2021
@loozhengyuan
Copy link
Contributor Author

/retest

@k8s-ci-robot k8s-ci-robot merged commit 0cbf00a into kubernetes:master May 6, 2021
@k8s-ci-robot k8s-ci-robot added this to the v1.22 milestone May 6, 2021
@loozhengyuan loozhengyuan deleted the kubectl-diff-with-masked-secrets branch May 6, 2021 07:42
@lindhe
Copy link

lindhe commented Apr 14, 2022

How can I disable this feature? Sorry if I've missed it, but I checked the docs and I tried to read through this thread...

It's great that the default is secure, but I need to be able to see the diff if I want to.

@loozhengyuan
Copy link
Contributor Author

loozhengyuan commented Apr 14, 2022

@lindhe The short answer is that there is no way to disable this feature AFAIK, but you may be able to use kubectl get or kubectl describe to achieve your purpose.

This is expected to be the new default behaviour but i'm unsure if there are use cases where we would like to know the exact diffs of the secrets. I think this is quite unlikely because (1) comparing the base64-encoded values are not that helpful and (2) we could use kubectl get or kubectl describe if we really need to compare the values for debugging.

@lindhe
Copy link

lindhe commented Apr 14, 2022

Thanks for the response!

Yeah, I'm certainly able to use kubectl to inspect the values and inspect them manually. But when it's part of a larger deployment, that's pretty tedious and when everything else works so well with diff it's kind of annoying to have a separate work flow just for Secrets.

I think comparing the base64-encoded values is plenty helpful! Mostly because it indicates to me that I'm applying the correct value (templating and automation, or high complexity in general may make it hard to know on beforehand). And I often know what the base64 encoded value is, or at least what it should start with, so it's really helpful.

I want to emphasize again that I think it's 100% the right decision to not reveal secret values by default. But I do think there's a lot to be gained by making that optional.

And there's other tooling I think we can get inspiration from:

  • In helm diff, there's a --show-secrets flag that can be used instead of the default --suppress-secrets. I've had to use that many times when debugging things.
  • In terraform, secret values are redacted by default in the plan printout, but using the -json flag it's revealed.
  • In kubectl the secret value is redacted when running kubectl describe secret foo (with the very helpful additional information which size each field has), while the secret value is revealed using kubectl get secrets foo -o yaml.

@apelisse
Copy link
Member

Thanks @lindhe for the feedback, I think it's fair to add an option for that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. area/kubectl cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/feature Categorizes issue or PR as related to a new feature. lgtm "Looks good to me", indicates that a PR is ready to be merged. needs-priority Indicates a PR lacks a `priority/foo` label and requires one. needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/cli Categorizes an issue or PR as relevant to SIG CLI. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Mask secrets in kubectl diff output
7 participants