Merge pull request #7007 from jlowdermilk/kubeconfig-verbose

Add a --short flag to kubectl config view
This commit is contained in:
Satnam Singh
2015-04-23 14:51:13 -07:00
33 changed files with 167 additions and 30 deletions

View File

@@ -17,6 +17,7 @@ limitations under the License.
package api
import (
"encoding/base64"
"errors"
"fmt"
"io/ioutil"
@@ -25,6 +26,11 @@ import (
"path/filepath"
)
func init() {
sDec, _ := base64.StdEncoding.DecodeString("REDACTED+")
redactedBytes = []byte(string(sDec))
}
// MinifyConfig read the current context and uses that to keep only the relevant pieces of config
// This is useful for making secrets based on kubeconfig files
func MinifyConfig(config *Config) error {
@@ -65,6 +71,30 @@ func MinifyConfig(config *Config) error {
return nil
}
var redactedBytes []byte
// Flatten redacts raw data entries from the config object for a human-readable view.
func ShortenConfig(config *Config) {
// 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
// http://golang.org/pkg/encoding/json/#Marshal using base64 to encode []byte
for key, authInfo := range config.AuthInfos {
if len(authInfo.ClientKeyData) > 0 {
authInfo.ClientKeyData = redactedBytes
}
if len(authInfo.ClientCertificateData) > 0 {
authInfo.ClientCertificateData = redactedBytes
}
config.AuthInfos[key] = authInfo
}
for key, cluster := range config.Clusters {
if len(cluster.CertificateAuthorityData) > 0 {
cluster.CertificateAuthorityData = redactedBytes
}
config.Clusters[key] = cluster
}
}
// Flatten changes the config object into a self contained config (useful for making secrets)
// AuthPath is not handled.
func FlattenConfig(config *Config) error {

View File

@@ -17,10 +17,13 @@ limitations under the License.
package api
import (
"fmt"
"io/ioutil"
"os"
"reflect"
"testing"
"github.com/ghodss/yaml"
)
func newMergedConfig(certFile, certContent, keyFile, keyContent, caFile, caContent string, t *testing.T) Config {
@@ -36,10 +39,10 @@ func newMergedConfig(certFile, certContent, keyFile, keyContent, caFile, caConte
return Config{
AuthInfos: map[string]AuthInfo{
"red-user": {Token: "red-token"},
"red-user": {Token: "red-token", ClientCertificateData: []byte(certContent), ClientKeyData: []byte(keyContent)},
"blue-user": {Token: "blue-token", ClientCertificate: certFile, ClientKey: keyFile}},
Clusters: map[string]Cluster{
"cow-cluster": {Server: "http://cow.org:8080"},
"cow-cluster": {Server: "http://cow.org:8080", CertificateAuthorityData: []byte(caContent)},
"chicken-cluster": {Server: "http://chicken.org:8080", CertificateAuthority: caFile}},
Contexts: map[string]Context{
"federal-context": {AuthInfo: "red-user", Cluster: "cow-cluster"},
@@ -202,3 +205,97 @@ func TestFlattenSuccess(t *testing.T) {
}
}
func ExampleMinifyAndShorten() {
certFile, _ := ioutil.TempFile("", "")
defer os.Remove(certFile.Name())
keyFile, _ := ioutil.TempFile("", "")
defer os.Remove(keyFile.Name())
caFile, _ := ioutil.TempFile("", "")
defer os.Remove(caFile.Name())
certData := "cert"
keyData := "key"
caData := "ca"
config := newMergedConfig(certFile.Name(), certData, keyFile.Name(), keyData, caFile.Name(), caData, nil)
MinifyConfig(&config)
ShortenConfig(&config)
output, _ := yaml.Marshal(config)
fmt.Printf("%s", string(output))
// Output:
// clusters:
// cow-cluster:
// LocationOfOrigin: ""
// certificate-authority-data: REDACTED
// server: http://cow.org:8080
// contexts:
// federal-context:
// LocationOfOrigin: ""
// cluster: cow-cluster
// user: red-user
// current-context: federal-context
// preferences: {}
// users:
// red-user:
// LocationOfOrigin: ""
// client-certificate-data: REDACTED
// client-key-data: REDACTED
// token: red-token
}
func TestShortenSuccess(t *testing.T) {
certFile, _ := ioutil.TempFile("", "")
defer os.Remove(certFile.Name())
keyFile, _ := ioutil.TempFile("", "")
defer os.Remove(keyFile.Name())
caFile, _ := ioutil.TempFile("", "")
defer os.Remove(caFile.Name())
certData := "cert"
keyData := "key"
caData := "ca"
unchangingCluster := "chicken-cluster"
unchangingAuthInfo := "blue-user"
changingCluster := "cow-cluster"
changingAuthInfo := "red-user"
startingConfig := newMergedConfig(certFile.Name(), certData, keyFile.Name(), keyData, caFile.Name(), caData, t)
mutatingConfig := startingConfig
ShortenConfig(&mutatingConfig)
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)
}
redacted := string(redactedBytes)
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 string(mutatingConfig.Clusters[changingCluster].CertificateAuthorityData) != redacted {
t.Errorf("expected %v, got %v", redacted, string(mutatingConfig.Clusters[changingCluster].CertificateAuthorityData))
}
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 string(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificateData) != redacted {
t.Errorf("expected %v, got %v", redacted, string(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificateData))
}
if string(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData) != redacted {
t.Errorf("expected %v, got %v", redacted, string(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData))
}
}