mirror of https://github.com/k3s-io/k3s
refactor kubeadm join command generation
parent
6775a3252d
commit
c09d875c6c
|
@ -38,6 +38,7 @@ import (
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||||
|
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
||||||
|
@ -46,7 +47,6 @@ import (
|
||||||
clusterinfophase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo"
|
clusterinfophase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo"
|
||||||
nodebootstraptokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
|
nodebootstraptokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
|
||||||
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil"
|
|
||||||
controlplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane"
|
controlplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane"
|
||||||
etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
|
etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
|
||||||
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||||
|
@ -61,7 +61,6 @@ import (
|
||||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||||
dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun"
|
dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun"
|
||||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/pubkeypin"
|
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
utilsexec "k8s.io/utils/exec"
|
utilsexec "k8s.io/utils/exec"
|
||||||
)
|
)
|
||||||
|
@ -83,7 +82,7 @@ var (
|
||||||
You can now join any number of machines by running the following on each node
|
You can now join any number of machines by running the following on each node
|
||||||
as root:
|
as root:
|
||||||
|
|
||||||
kubeadm join --token {{.Token}} {{.MasterHostPort}} --discovery-token-ca-cert-hash {{.CAPubKeyPin}}
|
{{.joinCommand}}
|
||||||
|
|
||||||
`)))
|
`)))
|
||||||
|
|
||||||
|
@ -468,26 +467,15 @@ func (i *Init) Run(out io.Writer) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the CA certificate from so we can pin its public key
|
// Gets the join command
|
||||||
caCert, err := pkiutil.TryLoadCertFromDisk(i.cfg.CertificatesDir, kubeadmconstants.CACertAndKeyBaseName)
|
joinCommand, err := cmdutil.GetJoinCommand(kubeadmconstants.GetAdminKubeConfigPath(), i.cfg.Token, i.skipTokenPrint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error loading ca cert from disk: %v", err)
|
return fmt.Errorf("failed to get join command: %v", err)
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the Master host/port pair used by initDoneTempl
|
|
||||||
masterHostPort, err := kubeadmutil.GetMasterHostPort(i.cfg)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error getting master host port: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := map[string]string{
|
ctx := map[string]string{
|
||||||
"KubeConfigPath": adminKubeConfigPath,
|
"KubeConfigPath": adminKubeConfigPath,
|
||||||
"Token": i.cfg.Token,
|
"joinCommand": joinCommand,
|
||||||
"CAPubKeyPin": pubkeypin.Hash(caCert),
|
|
||||||
"MasterHostPort": masterHostPort,
|
|
||||||
}
|
|
||||||
if i.skipTokenPrint {
|
|
||||||
ctx["Token"] = "<value withheld>"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return initDoneTempl.Execute(out, ctx)
|
return initDoneTempl.Execute(out, ctx)
|
||||||
|
|
|
@ -34,11 +34,9 @@ import (
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo"
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil"
|
|
||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/pubkeypin"
|
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||||
)
|
)
|
||||||
|
@ -137,7 +135,7 @@ func NewSubCmdBootstrapTokenAll(kubeConfigFile *string) *cobra.Command {
|
||||||
kubeadmutil.CheckErr(err)
|
kubeadmutil.CheckErr(err)
|
||||||
|
|
||||||
// Creates the bootstap token
|
// Creates the bootstap token
|
||||||
err = createBootstrapToken(client, cfgPath, cfg, description, usages, extraGroups, skipTokenPrint)
|
err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, description, usages, extraGroups, skipTokenPrint)
|
||||||
kubeadmutil.CheckErr(err)
|
kubeadmutil.CheckErr(err)
|
||||||
|
|
||||||
// Create the cluster-info ConfigMap or update if it already exists
|
// Create the cluster-info ConfigMap or update if it already exists
|
||||||
|
@ -194,7 +192,7 @@ func NewSubCmdBootstrapToken(kubeConfigFile *string) *cobra.Command {
|
||||||
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
|
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
|
||||||
kubeadmutil.CheckErr(err)
|
kubeadmutil.CheckErr(err)
|
||||||
|
|
||||||
err = createBootstrapToken(client, cfgPath, cfg, description, usages, extraGroups, skipTokenPrint)
|
err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, description, usages, extraGroups, skipTokenPrint)
|
||||||
kubeadmutil.CheckErr(err)
|
kubeadmutil.CheckErr(err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -288,10 +286,6 @@ func addBootstrapTokenFlags(flagSet *pflag.FlagSet, cfg *kubeadmapiext.MasterCon
|
||||||
cfgPath, "config", *cfgPath,
|
cfgPath, "config", *cfgPath,
|
||||||
"Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)",
|
"Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)",
|
||||||
)
|
)
|
||||||
flagSet.StringVar(
|
|
||||||
&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir,
|
|
||||||
"The path where certificates are stored",
|
|
||||||
)
|
|
||||||
flagSet.StringVar(
|
flagSet.StringVar(
|
||||||
&cfg.Token, "token", cfg.Token,
|
&cfg.Token, "token", cfg.Token,
|
||||||
"The token to use for establishing bidirectional trust between nodes and masters",
|
"The token to use for establishing bidirectional trust between nodes and masters",
|
||||||
|
@ -318,7 +312,7 @@ func addBootstrapTokenFlags(flagSet *pflag.FlagSet, cfg *kubeadmapiext.MasterCon
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createBootstrapToken(client clientset.Interface, cfgPath string, cfg *kubeadmapiext.MasterConfiguration, description string, usages, extraGroups []string, skipTokenPrint bool) error {
|
func createBootstrapToken(kubeConfigFile string, client clientset.Interface, cfgPath string, cfg *kubeadmapiext.MasterConfiguration, description string, usages, extraGroups []string, skipTokenPrint bool) error {
|
||||||
// adding groups only makes sense for authentication
|
// adding groups only makes sense for authentication
|
||||||
usagesSet := sets.NewString(usages...)
|
usagesSet := sets.NewString(usages...)
|
||||||
usageAuthentication := strings.TrimPrefix(bootstrapapi.BootstrapTokenUsageAuthentication, bootstrapapi.BootstrapTokenUsagePrefix)
|
usageAuthentication := strings.TrimPrefix(bootstrapapi.BootstrapTokenUsageAuthentication, bootstrapapi.BootstrapTokenUsagePrefix)
|
||||||
|
@ -337,23 +331,19 @@ func createBootstrapToken(client clientset.Interface, cfgPath string, cfg *kubea
|
||||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
|
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
|
||||||
kubeadmutil.CheckErr(err)
|
kubeadmutil.CheckErr(err)
|
||||||
|
|
||||||
// Load the CA certificate from so we can pin its public key
|
|
||||||
caCert, err := pkiutil.TryLoadCertFromDisk(internalcfg.CertificatesDir, kubeadmconstants.CACertAndKeyBaseName)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error loading ca cert from disk: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates or updates the token
|
// Creates or updates the token
|
||||||
if err := node.UpdateOrCreateToken(client, internalcfg.Token, false, internalcfg.TokenTTL.Duration, usages, extraGroups, description); err != nil {
|
if err := node.UpdateOrCreateToken(client, internalcfg.Token, false, internalcfg.TokenTTL.Duration, usages, extraGroups, description); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("[bootstraptoken] Bootstrap token Created")
|
fmt.Println("[bootstraptoken] Bootstrap token Created")
|
||||||
if skipTokenPrint {
|
|
||||||
internalcfg.Token = "{token}"
|
|
||||||
}
|
|
||||||
fmt.Println("[bootstraptoken] You can now join any number of machines by running:")
|
fmt.Println("[bootstraptoken] You can now join any number of machines by running:")
|
||||||
fmt.Printf("[bootstraptoken] kubeadm join {master} --token %s --discovery-token-ca-cert-hash %s \n", internalcfg.Token, pubkeypin.Hash(caCert))
|
|
||||||
|
joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, internalcfg.Token, skipTokenPrint)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get join command: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Println(joinCommand)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,15 +17,12 @@ limitations under the License.
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/x509"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"text/template"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/renstrom/dedent"
|
"github.com/renstrom/dedent"
|
||||||
|
@ -38,8 +35,6 @@ import (
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
|
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
|
||||||
bootstraputil "k8s.io/client-go/tools/bootstrap/token/util"
|
bootstraputil "k8s.io/client-go/tools/bootstrap/token/util"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
|
||||||
clientcertutil "k8s.io/client-go/util/cert"
|
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
|
@ -47,16 +42,11 @@ import (
|
||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/pubkeypin"
|
|
||||||
tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token"
|
tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token"
|
||||||
api "k8s.io/kubernetes/pkg/apis/core"
|
api "k8s.io/kubernetes/pkg/apis/core"
|
||||||
"k8s.io/kubernetes/pkg/printers"
|
"k8s.io/kubernetes/pkg/printers"
|
||||||
)
|
)
|
||||||
|
|
||||||
var joinCommandTemplate = template.Must(template.New("join").Parse(`` +
|
|
||||||
`kubeadm join --token {{.Token}} {{.MasterHostPort}}{{range $h := .CAPubKeyPins}} --discovery-token-ca-cert-hash {{$h}}{{end}}`,
|
|
||||||
))
|
|
||||||
|
|
||||||
// NewCmdToken returns cobra.Command for token management
|
// NewCmdToken returns cobra.Command for token management
|
||||||
func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command {
|
func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command {
|
||||||
var kubeConfigFile string
|
var kubeConfigFile string
|
||||||
|
@ -247,7 +237,7 @@ func RunCreateToken(out io.Writer, client clientset.Interface, token string, tok
|
||||||
// if --print-join-command was specified, print the full `kubeadm join` command
|
// if --print-join-command was specified, print the full `kubeadm join` command
|
||||||
// otherwise, just print the token
|
// otherwise, just print the token
|
||||||
if printJoinCommand {
|
if printJoinCommand {
|
||||||
joinCommand, err := getJoinCommand(token, kubeConfigFile)
|
joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, token, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get join command: %v", err)
|
return fmt.Errorf("failed to get join command: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -395,52 +385,3 @@ func getClientset(file string, dryRun bool) (clientset.Interface, error) {
|
||||||
}
|
}
|
||||||
return kubeconfigutil.ClientSetFromFile(file)
|
return kubeconfigutil.ClientSetFromFile(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getJoinCommand(token string, kubeConfigFile string) (string, error) {
|
|
||||||
// load the kubeconfig file to get the CA certificate and endpoint
|
|
||||||
config, err := clientcmd.LoadFromFile(kubeConfigFile)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to load kubeconfig: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// load the default cluster config
|
|
||||||
clusterConfig := kubeconfigutil.GetClusterFromKubeConfig(config)
|
|
||||||
if clusterConfig == nil {
|
|
||||||
return "", fmt.Errorf("failed to get default cluster config")
|
|
||||||
}
|
|
||||||
|
|
||||||
// load CA certificates from the kubeconfig (either from PEM data or by file path)
|
|
||||||
var caCerts []*x509.Certificate
|
|
||||||
if clusterConfig.CertificateAuthorityData != nil {
|
|
||||||
caCerts, err = clientcertutil.ParseCertsPEM(clusterConfig.CertificateAuthorityData)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to parse CA certificate from kubeconfig: %v", err)
|
|
||||||
}
|
|
||||||
} else if clusterConfig.CertificateAuthority != "" {
|
|
||||||
caCerts, err = clientcertutil.CertsFromFile(clusterConfig.CertificateAuthority)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to load CA certificate referenced by kubeconfig: %v", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return "", fmt.Errorf("no CA certificates found in kubeconfig")
|
|
||||||
}
|
|
||||||
|
|
||||||
// hash all the CA certs and include their public key pins as trusted values
|
|
||||||
publicKeyPins := make([]string, 0, len(caCerts))
|
|
||||||
for _, caCert := range caCerts {
|
|
||||||
publicKeyPins = append(publicKeyPins, pubkeypin.Hash(caCert))
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := map[string]interface{}{
|
|
||||||
"Token": token,
|
|
||||||
"CAPubKeyPins": publicKeyPins,
|
|
||||||
"MasterHostPort": strings.Replace(clusterConfig.Server, "https://", "", -1),
|
|
||||||
}
|
|
||||||
|
|
||||||
var out bytes.Buffer
|
|
||||||
err = joinCommandTemplate.Execute(&out, ctx)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to render join command template: %v", err)
|
|
||||||
}
|
|
||||||
return out.String(), nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/x509"
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
|
clientcertutil "k8s.io/client-go/util/cert"
|
||||||
|
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/util/pubkeypin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var joinCommandTemplate = template.Must(template.New("join").Parse(`` +
|
||||||
|
`kubeadm join {{.MasterHostPort}} --token {{.Token}}{{range $h := .CAPubKeyPins}} --discovery-token-ca-cert-hash {{$h}}{{end}}`,
|
||||||
|
))
|
||||||
|
|
||||||
|
// GetJoinCommand returns the kubeadm join command for a given token and
|
||||||
|
// and kubernetes cluster (the current cluster in the kubeconfig file)
|
||||||
|
func GetJoinCommand(kubeConfigFile string, token string, skipTokenPrint bool) (string, error) {
|
||||||
|
// load the kubeconfig file to get the CA certificate and endpoint
|
||||||
|
config, err := clientcmd.LoadFromFile(kubeConfigFile)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to load kubeconfig: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// load the default cluster config
|
||||||
|
clusterConfig := kubeconfigutil.GetClusterFromKubeConfig(config)
|
||||||
|
if clusterConfig == nil {
|
||||||
|
return "", fmt.Errorf("failed to get default cluster config")
|
||||||
|
}
|
||||||
|
|
||||||
|
// load CA certificates from the kubeconfig (either from PEM data or by file path)
|
||||||
|
var caCerts []*x509.Certificate
|
||||||
|
if clusterConfig.CertificateAuthorityData != nil {
|
||||||
|
caCerts, err = clientcertutil.ParseCertsPEM(clusterConfig.CertificateAuthorityData)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to parse CA certificate from kubeconfig: %v", err)
|
||||||
|
}
|
||||||
|
} else if clusterConfig.CertificateAuthority != "" {
|
||||||
|
caCerts, err = clientcertutil.CertsFromFile(clusterConfig.CertificateAuthority)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to load CA certificate referenced by kubeconfig: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "", fmt.Errorf("no CA certificates found in kubeconfig")
|
||||||
|
}
|
||||||
|
|
||||||
|
// hash all the CA certs and include their public key pins as trusted values
|
||||||
|
publicKeyPins := make([]string, 0, len(caCerts))
|
||||||
|
for _, caCert := range caCerts {
|
||||||
|
publicKeyPins = append(publicKeyPins, pubkeypin.Hash(caCert))
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := map[string]interface{}{
|
||||||
|
"Token": token,
|
||||||
|
"CAPubKeyPins": publicKeyPins,
|
||||||
|
"MasterHostPort": strings.Replace(clusterConfig.Server, "https://", "", -1),
|
||||||
|
}
|
||||||
|
|
||||||
|
if skipTokenPrint {
|
||||||
|
ctx["Token"] = template.HTML("<value withheld>")
|
||||||
|
}
|
||||||
|
|
||||||
|
var out bytes.Buffer
|
||||||
|
err = joinCommandTemplate.Execute(&out, ctx)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to render join command template: %v", err)
|
||||||
|
}
|
||||||
|
return out.String(), nil
|
||||||
|
}
|
Loading…
Reference in New Issue