mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-31 15:25:57 +00:00
Update redacting functionality to redact all sensitive info in config when printing with view (#109189)
* Add RedactSecrets function * Move RedactSecrets method to existing RawBytesData case * Update TestRedactSecrets to use new pattern of os.CreateTemp()
This commit is contained in:
parent
34ca18d1d0
commit
e721272d10
@ -23,6 +23,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -81,21 +83,21 @@ func MinifyConfig(config *Config) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
redactedBytes []byte
|
|
||||||
dataOmittedBytes []byte
|
dataOmittedBytes []byte
|
||||||
|
redactedBytes []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
// Flatten redacts raw data entries from the config object for a human-readable view.
|
// ShortenConfig redacts raw data entries from the config object for a human-readable view.
|
||||||
func ShortenConfig(config *Config) {
|
func ShortenConfig(config *Config) {
|
||||||
// trick json encoder into printing a human readable string in the raw data
|
// trick json encoder into printing a human-readable string in the raw data
|
||||||
// by base64 decoding what we want to print. Relies on implementation of
|
// by base64 decoding what we want to print. Relies on implementation of
|
||||||
// http://golang.org/pkg/encoding/json/#Marshal using base64 to encode []byte
|
// http://golang.org/pkg/encoding/json/#Marshal using base64 to encode []byte
|
||||||
for key, authInfo := range config.AuthInfos {
|
for key, authInfo := range config.AuthInfos {
|
||||||
if len(authInfo.ClientKeyData) > 0 {
|
if len(authInfo.ClientKeyData) > 0 {
|
||||||
authInfo.ClientKeyData = redactedBytes
|
authInfo.ClientKeyData = dataOmittedBytes
|
||||||
}
|
}
|
||||||
if len(authInfo.ClientCertificateData) > 0 {
|
if len(authInfo.ClientCertificateData) > 0 {
|
||||||
authInfo.ClientCertificateData = redactedBytes
|
authInfo.ClientCertificateData = dataOmittedBytes
|
||||||
}
|
}
|
||||||
if len(authInfo.Token) > 0 {
|
if len(authInfo.Token) > 0 {
|
||||||
authInfo.Token = "REDACTED"
|
authInfo.Token = "REDACTED"
|
||||||
@ -110,7 +112,7 @@ func ShortenConfig(config *Config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flatten changes the config object into a self contained config (useful for making secrets)
|
// FlattenConfig changes the config object into a self-contained config (useful for making secrets)
|
||||||
func FlattenConfig(config *Config) error {
|
func FlattenConfig(config *Config) error {
|
||||||
for key, authInfo := range config.AuthInfos {
|
for key, authInfo := range config.AuthInfos {
|
||||||
baseDir, err := MakeAbs(path.Dir(authInfo.LocationOfOrigin), "")
|
baseDir, err := MakeAbs(path.Dir(authInfo.LocationOfOrigin), "")
|
||||||
@ -188,3 +190,77 @@ func MakeAbs(path, base string) (string, error) {
|
|||||||
}
|
}
|
||||||
return filepath.Join(base, path), nil
|
return filepath.Join(base, path), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RedactSecrets replaces any sensitive values with REDACTED
|
||||||
|
func RedactSecrets(config *Config) error {
|
||||||
|
return redactSecrets(reflect.ValueOf(config), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func redactSecrets(curr reflect.Value, redact bool) error {
|
||||||
|
redactedBytes = []byte("REDACTED")
|
||||||
|
if !curr.IsValid() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
actualCurrValue := curr
|
||||||
|
if curr.Kind() == reflect.Ptr {
|
||||||
|
actualCurrValue = curr.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch actualCurrValue.Kind() {
|
||||||
|
case reflect.Map:
|
||||||
|
for _, v := range actualCurrValue.MapKeys() {
|
||||||
|
err := redactSecrets(actualCurrValue.MapIndex(v), false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case reflect.String:
|
||||||
|
if redact {
|
||||||
|
if !actualCurrValue.IsZero() {
|
||||||
|
actualCurrValue.SetString("REDACTED")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case reflect.Slice:
|
||||||
|
if actualCurrValue.Type() == reflect.TypeOf([]byte{}) && redact {
|
||||||
|
if !actualCurrValue.IsNil() {
|
||||||
|
actualCurrValue.SetBytes(redactedBytes)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for i := 0; i < actualCurrValue.Len(); i++ {
|
||||||
|
err := redactSecrets(actualCurrValue.Index(i), false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case reflect.Struct:
|
||||||
|
for fieldIndex := 0; fieldIndex < actualCurrValue.NumField(); fieldIndex++ {
|
||||||
|
currFieldValue := actualCurrValue.Field(fieldIndex)
|
||||||
|
currFieldType := actualCurrValue.Type().Field(fieldIndex)
|
||||||
|
currYamlTag := currFieldType.Tag.Get("datapolicy")
|
||||||
|
currFieldTypeYamlName := strings.Split(currYamlTag, ",")[0]
|
||||||
|
if currFieldTypeYamlName != "" {
|
||||||
|
err := redactSecrets(currFieldValue, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := redactSecrets(currFieldValue, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -240,8 +241,8 @@ func Example_minifyAndShorten() {
|
|||||||
// users:
|
// users:
|
||||||
// red-user:
|
// red-user:
|
||||||
// LocationOfOrigin: ""
|
// LocationOfOrigin: ""
|
||||||
// client-certificate-data: REDACTED
|
// client-certificate-data: DATA+OMITTED
|
||||||
// client-key-data: REDACTED
|
// client-key-data: DATA+OMITTED
|
||||||
// token: REDACTED
|
// token: REDACTED
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,7 +275,6 @@ func TestShortenSuccess(t *testing.T) {
|
|||||||
t.Errorf("expected %v, got %v", startingConfig.Contexts, mutatingConfig.Contexts)
|
t.Errorf("expected %v, got %v", startingConfig.Contexts, mutatingConfig.Contexts)
|
||||||
}
|
}
|
||||||
|
|
||||||
redacted := string(redactedBytes)
|
|
||||||
dataOmitted := string(dataOmittedBytes)
|
dataOmitted := string(dataOmittedBytes)
|
||||||
if len(mutatingConfig.Clusters) != 2 {
|
if len(mutatingConfig.Clusters) != 2 {
|
||||||
t.Errorf("unexpected clusters: %v", mutatingConfig.Clusters)
|
t.Errorf("unexpected clusters: %v", mutatingConfig.Clusters)
|
||||||
@ -292,13 +292,65 @@ func TestShortenSuccess(t *testing.T) {
|
|||||||
if !reflect.DeepEqual(startingConfig.AuthInfos[unchangingAuthInfo], mutatingConfig.AuthInfos[unchangingAuthInfo]) {
|
if !reflect.DeepEqual(startingConfig.AuthInfos[unchangingAuthInfo], mutatingConfig.AuthInfos[unchangingAuthInfo]) {
|
||||||
t.Errorf("expected %v, got %v", startingConfig.AuthInfos[unchangingAuthInfo], mutatingConfig.AuthInfos[unchangingAuthInfo])
|
t.Errorf("expected %v, got %v", startingConfig.AuthInfos[unchangingAuthInfo], mutatingConfig.AuthInfos[unchangingAuthInfo])
|
||||||
}
|
}
|
||||||
if string(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificateData) != redacted {
|
if string(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificateData) != dataOmitted {
|
||||||
t.Errorf("expected %v, got %v", redacted, string(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificateData))
|
t.Errorf("expected %v, got %v", dataOmitted, string(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificateData))
|
||||||
}
|
}
|
||||||
if string(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData) != redacted {
|
if string(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData) != dataOmitted {
|
||||||
t.Errorf("expected %v, got %v", redacted, string(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData))
|
t.Errorf("expected %v, got %v", dataOmitted, string(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData))
|
||||||
|
}
|
||||||
|
if mutatingConfig.AuthInfos[changingAuthInfo].Token != "REDACTED" {
|
||||||
|
t.Errorf("expected REDACTED, got %q", mutatingConfig.AuthInfos[changingAuthInfo].Token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedactSecrets(t *testing.T) {
|
||||||
|
certFile, _ := os.CreateTemp("", "")
|
||||||
|
defer os.Remove(certFile.Name())
|
||||||
|
keyFile, _ := os.CreateTemp("", "")
|
||||||
|
defer os.Remove(keyFile.Name())
|
||||||
|
caFile, _ := os.CreateTemp("", "")
|
||||||
|
defer os.Remove(caFile.Name())
|
||||||
|
|
||||||
|
certData := "cert"
|
||||||
|
keyData := "key"
|
||||||
|
caData := "ca"
|
||||||
|
|
||||||
|
unchangingCluster := "chicken-cluster"
|
||||||
|
unchangingAuthInfo := "blue-user"
|
||||||
|
changingAuthInfo := "red-user"
|
||||||
|
|
||||||
|
startingConfig := newMergedConfig(certFile.Name(), certData, keyFile.Name(), keyData, caFile.Name(), caData, t)
|
||||||
|
mutatingConfig := startingConfig
|
||||||
|
|
||||||
|
err := RedactSecrets(&mutatingConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error redacting secrets:\n%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(mutatingConfig.Contexts) != 2 {
|
||||||
|
t.Errorf("unexpected contexts: %v", mutatingConfig.Contexts)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(startingConfig.Contexts, mutatingConfig.Contexts) {
|
||||||
|
t.Errorf("expected %v, got %v", startingConfig.Contexts, mutatingConfig.Contexts)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(mutatingConfig.Clusters) != 2 {
|
||||||
|
t.Errorf("unexpected clusters: %v", mutatingConfig.Clusters)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(startingConfig.Clusters[unchangingCluster], mutatingConfig.Clusters[unchangingCluster]) {
|
||||||
|
t.Errorf("expected %v, got %v", startingConfig.Clusters[unchangingCluster], mutatingConfig.Clusters[unchangingCluster])
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(mutatingConfig.AuthInfos) != 2 {
|
||||||
|
t.Errorf("unexpected users: %v", mutatingConfig.AuthInfos)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(startingConfig.AuthInfos[unchangingAuthInfo], mutatingConfig.AuthInfos[unchangingAuthInfo]) {
|
||||||
|
t.Errorf("expected %v, got %v", startingConfig.AuthInfos[unchangingAuthInfo], mutatingConfig.AuthInfos[unchangingAuthInfo])
|
||||||
}
|
}
|
||||||
if mutatingConfig.AuthInfos[changingAuthInfo].Token != "REDACTED" {
|
if mutatingConfig.AuthInfos[changingAuthInfo].Token != "REDACTED" {
|
||||||
t.Errorf("expected REDACTED, got %v", mutatingConfig.AuthInfos[changingAuthInfo].Token)
|
t.Errorf("expected REDACTED, got %v", mutatingConfig.AuthInfos[changingAuthInfo].Token)
|
||||||
}
|
}
|
||||||
|
if !bytes.Equal(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData, []byte("REDACTED")) {
|
||||||
|
t.Errorf("expected REDACTED, got %s", mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,7 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
"k8s.io/cli-runtime/pkg/printers"
|
"k8s.io/cli-runtime/pkg/printers"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
@ -60,7 +58,7 @@ var (
|
|||||||
# Show merged kubeconfig settings
|
# Show merged kubeconfig settings
|
||||||
kubectl config view
|
kubectl config view
|
||||||
|
|
||||||
# Show merged kubeconfig settings and raw certificate data
|
# Show merged kubeconfig settings and raw certificate data and exposed secrets
|
||||||
kubectl config view --raw
|
kubectl config view --raw
|
||||||
|
|
||||||
# Get the password for the e2e user
|
# Get the password for the e2e user
|
||||||
@ -93,7 +91,7 @@ func NewCmdConfigView(streams genericclioptions.IOStreams, ConfigAccess clientcm
|
|||||||
o.Merge.Default(true)
|
o.Merge.Default(true)
|
||||||
mergeFlag := cmd.Flags().VarPF(&o.Merge, "merge", "", "Merge the full hierarchy of kubeconfig files")
|
mergeFlag := cmd.Flags().VarPF(&o.Merge, "merge", "", "Merge the full hierarchy of kubeconfig files")
|
||||||
mergeFlag.NoOptDefVal = "true"
|
mergeFlag.NoOptDefVal = "true"
|
||||||
cmd.Flags().BoolVar(&o.RawByteData, "raw", o.RawByteData, "Display raw byte data")
|
cmd.Flags().BoolVar(&o.RawByteData, "raw", o.RawByteData, "Display raw byte data and sensitive data")
|
||||||
cmd.Flags().BoolVar(&o.Flatten, "flatten", o.Flatten, "Flatten the resulting kubeconfig file into self-contained output (useful for creating portable kubeconfig files)")
|
cmd.Flags().BoolVar(&o.Flatten, "flatten", o.Flatten, "Flatten the resulting kubeconfig file into self-contained output (useful for creating portable kubeconfig files)")
|
||||||
cmd.Flags().BoolVar(&o.Minify, "minify", o.Minify, "Remove all information not used by current-context from the output")
|
cmd.Flags().BoolVar(&o.Minify, "minify", o.Minify, "Remove all information not used by current-context from the output")
|
||||||
return cmd
|
return cmd
|
||||||
@ -150,6 +148,9 @@ func (o ViewOptions) Run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if !o.RawByteData {
|
} else if !o.RawByteData {
|
||||||
|
if err := clientcmdapi.RedactSecrets(config); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
clientcmdapi.ShortenConfig(config)
|
clientcmdapi.ShortenConfig(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,8 +47,18 @@ func TestViewCluster(t *testing.T) {
|
|||||||
},
|
},
|
||||||
CurrentContext: "minikube",
|
CurrentContext: "minikube",
|
||||||
AuthInfos: map[string]*clientcmdapi.AuthInfo{
|
AuthInfos: map[string]*clientcmdapi.AuthInfo{
|
||||||
"minikube": {Token: "REDACTED"},
|
"minikube": {
|
||||||
"mu-cluster": {Token: "REDACTED"},
|
ClientKeyData: []byte("notredacted"),
|
||||||
|
Token: "notredacted",
|
||||||
|
Username: "foo",
|
||||||
|
Password: "notredacted",
|
||||||
|
},
|
||||||
|
"mu-cluster": {
|
||||||
|
ClientKeyData: []byte("notredacted"),
|
||||||
|
Token: "notredacted",
|
||||||
|
Username: "bar",
|
||||||
|
Password: "notredacted",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,16 +88,113 @@ preferences: {}
|
|||||||
users:
|
users:
|
||||||
- name: minikube
|
- name: minikube
|
||||||
user:
|
user:
|
||||||
|
client-key-data: DATA+OMITTED
|
||||||
|
password: REDACTED
|
||||||
token: REDACTED
|
token: REDACTED
|
||||||
|
username: foo
|
||||||
- name: mu-cluster
|
- name: mu-cluster
|
||||||
user:
|
user:
|
||||||
token: REDACTED` + "\n",
|
client-key-data: DATA+OMITTED
|
||||||
|
password: REDACTED
|
||||||
|
token: REDACTED
|
||||||
|
username: bar` + "\n",
|
||||||
}
|
}
|
||||||
|
|
||||||
test.run(t)
|
test.run(t)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestViewClusterUnredacted(t *testing.T) {
|
||||||
|
conf := clientcmdapi.Config{
|
||||||
|
Kind: "Config",
|
||||||
|
APIVersion: "v1",
|
||||||
|
Clusters: map[string]*clientcmdapi.Cluster{
|
||||||
|
"minikube": {Server: "https://192.168.99.100:8443"},
|
||||||
|
"my-cluster": {Server: "https://192.168.0.1:3434"},
|
||||||
|
},
|
||||||
|
Contexts: map[string]*clientcmdapi.Context{
|
||||||
|
"minikube": {AuthInfo: "minikube", Cluster: "minikube"},
|
||||||
|
"my-cluster": {AuthInfo: "mu-cluster", Cluster: "my-cluster"},
|
||||||
|
},
|
||||||
|
CurrentContext: "minikube",
|
||||||
|
AuthInfos: map[string]*clientcmdapi.AuthInfo{
|
||||||
|
"minikube": {
|
||||||
|
ClientKeyData: []byte("notredacted"),
|
||||||
|
ClientCertificateData: []byte("plaintext"),
|
||||||
|
Token: "notredacted",
|
||||||
|
Username: "foo",
|
||||||
|
Password: "notredacted",
|
||||||
|
},
|
||||||
|
"mu-cluster": {
|
||||||
|
ClientKeyData: []byte("notredacted"),
|
||||||
|
ClientCertificateData: []byte("plaintext"),
|
||||||
|
Token: "notredacted",
|
||||||
|
Username: "bar",
|
||||||
|
Password: "notredacted",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
description string
|
||||||
|
config clientcmdapi.Config
|
||||||
|
flags []string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "Testing for kubectl config view --raw=true",
|
||||||
|
config: conf,
|
||||||
|
flags: []string{"--raw=true"},
|
||||||
|
expected: `apiVersion: v1
|
||||||
|
clusters:
|
||||||
|
- cluster:
|
||||||
|
server: https://192.168.99.100:8443
|
||||||
|
name: minikube
|
||||||
|
- cluster:
|
||||||
|
server: https://192.168.0.1:3434
|
||||||
|
name: my-cluster
|
||||||
|
contexts:
|
||||||
|
- context:
|
||||||
|
cluster: minikube
|
||||||
|
user: minikube
|
||||||
|
name: minikube
|
||||||
|
- context:
|
||||||
|
cluster: my-cluster
|
||||||
|
user: mu-cluster
|
||||||
|
name: my-cluster
|
||||||
|
current-context: minikube
|
||||||
|
kind: Config
|
||||||
|
preferences: {}
|
||||||
|
users:
|
||||||
|
- name: minikube
|
||||||
|
user:
|
||||||
|
client-certificate-data: cGxhaW50ZXh0
|
||||||
|
client-key-data: bm90cmVkYWN0ZWQ=
|
||||||
|
password: notredacted
|
||||||
|
token: notredacted
|
||||||
|
username: foo
|
||||||
|
- name: mu-cluster
|
||||||
|
user:
|
||||||
|
client-certificate-data: cGxhaW50ZXh0
|
||||||
|
client-key-data: bm90cmVkYWN0ZWQ=
|
||||||
|
password: notredacted
|
||||||
|
token: notredacted
|
||||||
|
username: bar` + "\n",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
cmdTest := viewClusterTest{
|
||||||
|
description: test.description,
|
||||||
|
config: test.config,
|
||||||
|
flags: test.flags,
|
||||||
|
expected: test.expected,
|
||||||
|
}
|
||||||
|
cmdTest.run(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestViewClusterMinify(t *testing.T) {
|
func TestViewClusterMinify(t *testing.T) {
|
||||||
conf := clientcmdapi.Config{
|
conf := clientcmdapi.Config{
|
||||||
Kind: "Config",
|
Kind: "Config",
|
||||||
@ -102,8 +209,18 @@ func TestViewClusterMinify(t *testing.T) {
|
|||||||
},
|
},
|
||||||
CurrentContext: "minikube",
|
CurrentContext: "minikube",
|
||||||
AuthInfos: map[string]*clientcmdapi.AuthInfo{
|
AuthInfos: map[string]*clientcmdapi.AuthInfo{
|
||||||
"minikube": {Token: "REDACTED"},
|
"minikube": {
|
||||||
"mu-cluster": {Token: "REDACTED"},
|
ClientKeyData: []byte("notredacted"),
|
||||||
|
Token: "notredacted",
|
||||||
|
Username: "foo",
|
||||||
|
Password: "notredacted",
|
||||||
|
},
|
||||||
|
"mu-cluster": {
|
||||||
|
ClientKeyData: []byte("notredacted"),
|
||||||
|
Token: "notredacted",
|
||||||
|
Username: "bar",
|
||||||
|
Password: "notredacted",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +250,10 @@ preferences: {}
|
|||||||
users:
|
users:
|
||||||
- name: minikube
|
- name: minikube
|
||||||
user:
|
user:
|
||||||
token: REDACTED` + "\n",
|
client-key-data: DATA+OMITTED
|
||||||
|
password: REDACTED
|
||||||
|
token: REDACTED
|
||||||
|
username: foo` + "\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Testing for kubectl config view --minify=true --context=my-cluster",
|
description: "Testing for kubectl config view --minify=true --context=my-cluster",
|
||||||
@ -155,7 +275,10 @@ preferences: {}
|
|||||||
users:
|
users:
|
||||||
- name: mu-cluster
|
- name: mu-cluster
|
||||||
user:
|
user:
|
||||||
token: REDACTED` + "\n",
|
client-key-data: DATA+OMITTED
|
||||||
|
password: REDACTED
|
||||||
|
token: REDACTED
|
||||||
|
username: bar` + "\n",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user