Skip to content

Commit

Permalink
Don't export admin user by default. Allow specifying existing user wh…
Browse files Browse the repository at this point in the history
…en exporting context
  • Loading branch information
Ole Markus With committed Jun 5, 2020
1 parent 5cc1b5a commit 1e3116c
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 60 deletions.
19 changes: 14 additions & 5 deletions cmd/kops/export_kubecfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ import (

var (
exportKubecfgLong = templates.LongDesc(i18n.T(`
Export a kubecfg file for a cluster from the state store. The configuration
will be saved into a users $HOME/.kube/config file.
To export the kubectl configuration to a specific file set the KUBECONFIG
environment variable.`))
Export a kubecfg file for a cluster from the state store. By default, the configuration
will be saved into a users $HOME/.kube/config file. Kops will respect KUBECONFIG environment variable
if --kubeconfig flag is not set.
`))

exportKubecfgExample = templates.Examples(i18n.T(`
# export a kubecfg file
Expand All @@ -50,6 +50,8 @@ var (
type ExportKubecfgOptions struct {
KubeConfigPath string
all bool
admin bool
user string
}

func NewCmdExportKubecfg(f *util.Factory, out io.Writer) *cobra.Command {
Expand All @@ -71,6 +73,8 @@ func NewCmdExportKubecfg(f *util.Factory, out io.Writer) *cobra.Command {

cmd.Flags().StringVar(&options.KubeConfigPath, "kubeconfig", options.KubeConfigPath, "The location of the kubeconfig file to create.")
cmd.Flags().BoolVar(&options.all, "all", options.all, "export all clusters from the kops state store")
cmd.Flags().BoolVar(&options.admin, "admin", options.admin, "also export the admin user")
cmd.Flags().StringVar(&options.user, "user", options.user, "existing user to add to the cluster context")

return cmd
}
Expand Down Expand Up @@ -116,7 +120,12 @@ func RunExportKubecfg(ctx context.Context, f *util.Factory, out io.Writer, optio
return err
}

conf, err := kubeconfig.BuildKubecfg(cluster, keyStore, secretStore, &commands.CloudDiscoveryStatusStore{}, buildPathOptions(options))
conf, err := kubeconfig.BuildKubecfg(cluster, keyStore, secretStore, &commands.CloudDiscoveryStatusStore{}, buildPathOptions(options), options.admin)
if options.admin {
conf.User = cluster.ObjectMeta.Name
} else {
conf.User = options.user
}
if err != nil {
return err
}
Expand Down
16 changes: 14 additions & 2 deletions cmd/kops/update_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ type UpdateClusterOptions struct {
OutDir string
SSHPublicKey string
RunTasksOptions fi.RunTasksOptions
CreateKubecfg bool

CreateKubecfg bool
admin bool
user string

Phase string

Expand Down Expand Up @@ -116,6 +119,8 @@ func NewCmdUpdateCluster(f *util.Factory, out io.Writer) *cobra.Command {
cmd.Flags().StringVar(&options.SSHPublicKey, "ssh-public-key", options.SSHPublicKey, "SSH public key to use (deprecated: use kops create secret instead)")
cmd.Flags().StringVar(&options.OutDir, "out", options.OutDir, "Path to write any local output")
cmd.Flags().BoolVar(&options.CreateKubecfg, "create-kube-config", options.CreateKubecfg, "Will control automatically creating the kube config file on your local filesystem")
cmd.Flags().BoolVar(&options.admin, "admin", options.admin, "also export the admin user")
cmd.Flags().StringVar(&options.user, "user", options.user, "existing user to add to the cluster context")
cmd.Flags().StringVar(&options.Phase, "phase", options.Phase, "Subset of tasks to run: "+strings.Join(cloudup.Phases.List(), ", "))
cmd.Flags().StringSliceVar(&options.LifecycleOverrides, "lifecycle-overrides", options.LifecycleOverrides, "comma separated list of phase overrides, example: SecurityGroups=Ignore,InternetGateway=ExistsAndWarnIfChanges")
viper.BindPFlag("lifecycle-overrides", cmd.Flags().Lookup("lifecycle-overrides"))
Expand Down Expand Up @@ -306,10 +311,17 @@ func RunUpdateCluster(ctx context.Context, f *util.Factory, clusterName string,
}
if kubecfgCert != nil {
klog.Infof("Exporting kubecfg for cluster")
conf, err := kubeconfig.BuildKubecfg(cluster, keyStore, secretStore, &commands.CloudDiscoveryStatusStore{}, clientcmd.NewDefaultPathOptions())
conf, err := kubeconfig.BuildKubecfg(cluster, keyStore, secretStore, &commands.CloudDiscoveryStatusStore{}, clientcmd.NewDefaultPathOptions(), c.admin)
if err != nil {
return nil, err
}

if c.admin {
conf.User = cluster.ObjectMeta.Name
} else {
conf.User = c.user
}

err = conf.WriteKubecfg()
if err != nil {
return nil, err
Expand Down
81 changes: 41 additions & 40 deletions pkg/kubeconfig/create_kubecfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
"k8s.io/kops/upup/pkg/fi"
)

func BuildKubecfg(cluster *kops.Cluster, keyStore fi.Keystore, secretStore fi.SecretStore, status kops.StatusStore, configAccess clientcmd.ConfigAccess) (*KubeconfigBuilder, error) {
func BuildKubecfg(cluster *kops.Cluster, keyStore fi.Keystore, secretStore fi.SecretStore, status kops.StatusStore, configAccess clientcmd.ConfigAccess, admin bool) (*KubeconfigBuilder, error) {
clusterName := cluster.ObjectMeta.Name

master := cluster.Spec.MasterPublicName
Expand Down Expand Up @@ -85,56 +85,57 @@ func BuildKubecfg(cluster *kops.Cluster, keyStore fi.Keystore, secretStore fi.Se
b := NewKubeconfigBuilder(configAccess)

b.Context = clusterName
b.Server = server

// add the CA Cert to the kubeconfig only if we didn't specify a SSL cert for the LB
if cluster.Spec.API == nil || cluster.Spec.API.LoadBalancer == nil || cluster.Spec.API.LoadBalancer.SSLCertificate == "" {
cert, _, _, err := keyStore.FindKeypair(fi.CertificateId_CA)
if err != nil {
return nil, fmt.Errorf("error fetching CA keypair: %v", err)
}
if cert != nil {
b.CACert, err = cert.AsBytes()
if admin {
// add the CA Cert to the kubeconfig only if we didn't specify a SSL cert for the LB
if cluster.Spec.API == nil || cluster.Spec.API.LoadBalancer == nil || cluster.Spec.API.LoadBalancer.SSLCertificate == "" {
cert, _, _, err := keyStore.FindKeypair(fi.CertificateId_CA)
if err != nil {
return nil, err
return nil, fmt.Errorf("error fetching CA keypair: %v", err)
}
if cert != nil {
b.CACert, err = cert.AsBytes()
if err != nil {
return nil, err
}
} else {
return nil, fmt.Errorf("cannot find CA certificate")
}
} else {
return nil, fmt.Errorf("cannot find CA certificate")
}
}

{
cert, key, _, err := keyStore.FindKeypair("kubecfg")
if err != nil {
return nil, fmt.Errorf("error fetching kubecfg keypair: %v", err)
}
if cert != nil {
b.ClientCert, err = cert.AsBytes()
{
cert, key, _, err := keyStore.FindKeypair("kubecfg")
if err != nil {
return nil, err
return nil, fmt.Errorf("error fetching kubecfg keypair: %v", err)
}
if cert != nil {
b.ClientCert, err = cert.AsBytes()
if err != nil {
return nil, err
}
} else {
return nil, fmt.Errorf("cannot find kubecfg certificate")
}
if key != nil {
b.ClientKey, err = key.AsBytes()
if err != nil {
return nil, err
}
} else {
return nil, fmt.Errorf("cannot find kubecfg key")
}
} else {
return nil, fmt.Errorf("cannot find kubecfg certificate")
}
if key != nil {
b.ClientKey, err = key.AsBytes()

if secretStore != nil {
secret, err := secretStore.FindSecret("kube")
if err != nil {
return nil, err
}
} else {
return nil, fmt.Errorf("cannot find kubecfg key")
}
}

b.Server = server

if secretStore != nil {
secret, err := secretStore.FindSecret("kube")
if err != nil {
return nil, err
}
if secret != nil {
b.KubeUser = "admin"
b.KubePassword = string(secret.Data)
if secret != nil {
b.KubeUser = "admin"
b.KubePassword = string(secret.Data)
}
}
}

Expand Down
23 changes: 10 additions & 13 deletions pkg/kubeconfig/kubecfg_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type KubeconfigBuilder struct {
Context string
Namespace string

User string
KubeBearerToken string
KubeUser string
KubePassword string
Expand Down Expand Up @@ -116,25 +117,15 @@ func (b *KubeconfigBuilder) WriteKubecfg() error {
cluster = clientcmdapi.NewCluster()
}
cluster.Server = b.Server

if b.CACert == nil {
// For now, we assume that the cluster has a "real" cert issued by a CA
cluster.InsecureSkipTLSVerify = false
cluster.CertificateAuthority = ""
cluster.CertificateAuthorityData = nil
} else {
cluster.InsecureSkipTLSVerify = false
cluster.CertificateAuthority = ""
cluster.CertificateAuthorityData = b.CACert
}
cluster.CertificateAuthorityData = b.CACert

if config.Clusters == nil {
config.Clusters = make(map[string]*clientcmdapi.Cluster)
}
config.Clusters[b.Context] = cluster
}

{
if b.KubeUser == "admin" {
authInfo := config.AuthInfos[b.Context]
if authInfo == nil {
authInfo = clientcmdapi.NewAuthInfo()
Expand All @@ -158,6 +149,10 @@ func (b *KubeconfigBuilder) WriteKubecfg() error {
config.AuthInfos = make(map[string]*clientcmdapi.AuthInfo)
}
config.AuthInfos[b.Context] = authInfo
} else if b.User != "" {
if config.AuthInfos[b.User] == nil {
return fmt.Errorf("could not find user %q", b.User)
}
}

// If we have a bearer token, also create a credential entry with basic auth
Expand Down Expand Up @@ -186,7 +181,9 @@ func (b *KubeconfigBuilder) WriteKubecfg() error {
}

context.Cluster = b.Context
context.AuthInfo = b.Context
if b.User != "" {
context.AuthInfo = b.User
}

if b.Namespace != "" {
context.Namespace = b.Namespace
Expand Down

0 comments on commit 1e3116c

Please sign in to comment.