mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 18:53:35 +00:00
Fresh dep ensure
This commit is contained in:
4
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/BUILD
generated
vendored
4
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/BUILD
generated
vendored
@ -12,11 +12,13 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/discovery",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
|
||||
"//cmd/kubeadm/app/discovery/file:go_default_library",
|
||||
"//cmd/kubeadm/app/discovery/https:go_default_library",
|
||||
"//cmd/kubeadm/app/discovery/token:go_default_library",
|
||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
"//vendor/github.com/pkg/errors:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
39
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/discovery.go
generated
vendored
39
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/discovery.go
generated
vendored
@ -17,11 +17,13 @@ limitations under the License.
|
||||
package discovery
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/discovery/file"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/discovery/https"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/discovery/token"
|
||||
@ -31,37 +33,42 @@ import (
|
||||
// TokenUser defines token user
|
||||
const TokenUser = "tls-bootstrap-token-user"
|
||||
|
||||
// For returns a KubeConfig object that can be used for doing the TLS Bootstrap with the right credentials
|
||||
// For returns a kubeconfig object that can be used for doing the TLS Bootstrap with the right credentials
|
||||
// Also, before returning anything, it makes sure it can trust the API Server
|
||||
func For(cfg *kubeadmapi.NodeConfiguration) (*clientcmdapi.Config, error) {
|
||||
func For(cfg *kubeadmapi.JoinConfiguration) (*clientcmdapi.Config, error) {
|
||||
// TODO: Print summary info about the CA certificate, along with the checksum signature
|
||||
// we also need an ability for the user to configure the client to validate received CA cert against a checksum
|
||||
clusterinfo, err := GetValidatedClusterInfoObject(cfg)
|
||||
config, err := DiscoverValidatedKubeConfig(cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't validate the identity of the API Server: %v", err)
|
||||
return nil, errors.Wrap(err, "couldn't validate the identity of the API Server")
|
||||
}
|
||||
|
||||
if len(cfg.Discovery.TLSBootstrapToken) == 0 {
|
||||
return config, nil
|
||||
}
|
||||
clusterinfo := kubeconfigutil.GetClusterFromKubeConfig(config)
|
||||
return kubeconfigutil.CreateWithToken(
|
||||
clusterinfo.Server,
|
||||
cfg.ClusterName,
|
||||
kubeadmapiv1beta1.DefaultClusterName,
|
||||
TokenUser,
|
||||
clusterinfo.CertificateAuthorityData,
|
||||
cfg.TLSBootstrapToken,
|
||||
cfg.Discovery.TLSBootstrapToken,
|
||||
), nil
|
||||
}
|
||||
|
||||
// GetValidatedClusterInfoObject returns a validated Cluster object that specifies where the cluster is and the CA cert to trust
|
||||
func GetValidatedClusterInfoObject(cfg *kubeadmapi.NodeConfiguration) (*clientcmdapi.Cluster, error) {
|
||||
// DiscoverValidatedKubeConfig returns a validated Config object that specifies where the cluster is and the CA cert to trust
|
||||
func DiscoverValidatedKubeConfig(cfg *kubeadmapi.JoinConfiguration) (*clientcmdapi.Config, error) {
|
||||
switch {
|
||||
case len(cfg.DiscoveryFile) != 0:
|
||||
if isHTTPSURL(cfg.DiscoveryFile) {
|
||||
return https.RetrieveValidatedClusterInfo(cfg.DiscoveryFile, cfg.ClusterName)
|
||||
case cfg.Discovery.File != nil:
|
||||
kubeConfigPath := cfg.Discovery.File.KubeConfigPath
|
||||
if isHTTPSURL(kubeConfigPath) {
|
||||
return https.RetrieveValidatedConfigInfo(kubeConfigPath, kubeadmapiv1beta1.DefaultClusterName)
|
||||
}
|
||||
return file.RetrieveValidatedClusterInfo(cfg.DiscoveryFile, cfg.ClusterName)
|
||||
case len(cfg.DiscoveryToken) != 0:
|
||||
return token.RetrieveValidatedClusterInfo(cfg)
|
||||
return file.RetrieveValidatedConfigInfo(kubeConfigPath, kubeadmapiv1beta1.DefaultClusterName)
|
||||
case cfg.Discovery.BootstrapToken != nil:
|
||||
return token.RetrieveValidatedConfigInfo(cfg)
|
||||
default:
|
||||
return nil, fmt.Errorf("couldn't find a valid discovery configuration")
|
||||
return nil, errors.New("couldn't find a valid discovery configuration")
|
||||
}
|
||||
}
|
||||
|
||||
|
34
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/discovery_test.go
generated
vendored
34
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/discovery_test.go
generated
vendored
@ -24,31 +24,37 @@ import (
|
||||
|
||||
func TestFor(t *testing.T) {
|
||||
tests := []struct {
|
||||
d kubeadm.NodeConfiguration
|
||||
d kubeadm.JoinConfiguration
|
||||
expect bool
|
||||
}{
|
||||
{d: kubeadm.NodeConfiguration{}, expect: false},
|
||||
{d: kubeadm.JoinConfiguration{}, expect: false},
|
||||
{
|
||||
d: kubeadm.NodeConfiguration{
|
||||
DiscoveryFile: "notnil",
|
||||
d: kubeadm.JoinConfiguration{
|
||||
Discovery: kubeadm.Discovery{
|
||||
File: &kubeadm.FileDiscovery{
|
||||
KubeConfigPath: "notnil",
|
||||
},
|
||||
},
|
||||
},
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
d: kubeadm.NodeConfiguration{
|
||||
DiscoveryFile: "https://localhost",
|
||||
d: kubeadm.JoinConfiguration{
|
||||
Discovery: kubeadm.Discovery{
|
||||
File: &kubeadm.FileDiscovery{
|
||||
KubeConfigPath: "https://localhost",
|
||||
},
|
||||
},
|
||||
},
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
d: kubeadm.NodeConfiguration{
|
||||
DiscoveryFile: "notnil",
|
||||
},
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
d: kubeadm.NodeConfiguration{
|
||||
DiscoveryToken: "foo.bar@foobar",
|
||||
d: kubeadm.JoinConfiguration{
|
||||
Discovery: kubeadm.Discovery{
|
||||
BootstrapToken: &kubeadm.BootstrapTokenDiscovery{
|
||||
Token: "foo.bar@foobar",
|
||||
},
|
||||
},
|
||||
},
|
||||
expect: false,
|
||||
},
|
||||
|
15
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/file/BUILD
generated
vendored
15
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/file/BUILD
generated
vendored
@ -12,13 +12,14 @@ go_library(
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
|
||||
"//vendor/github.com/pkg/errors:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
86
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/file/file.go
generated
vendored
86
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/file/file.go
generated
vendored
@ -18,51 +18,87 @@ package file
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
)
|
||||
|
||||
// RetrieveValidatedClusterInfo connects to the API Server and makes sure it can talk
|
||||
// RetrieveValidatedConfigInfo connects to the API Server and makes sure it can talk
|
||||
// securely to the API Server using the provided CA cert and
|
||||
// optionally refreshes the cluster-info information from the cluster-info ConfigMap
|
||||
func RetrieveValidatedClusterInfo(filepath, clustername string) (*clientcmdapi.Cluster, error) {
|
||||
clusterinfo, err := clientcmd.LoadFromFile(filepath)
|
||||
func RetrieveValidatedConfigInfo(filepath, clustername string) (*clientcmdapi.Config, error) {
|
||||
config, err := clientcmd.LoadFromFile(filepath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ValidateClusterInfo(clusterinfo, clustername)
|
||||
return ValidateConfigInfo(config, clustername)
|
||||
}
|
||||
|
||||
// ValidateClusterInfo connects to the API Server and makes sure it can talk
|
||||
// securely to the API Server using the provided CA cert and
|
||||
// ValidateConfigInfo connects to the API Server and makes sure it can talk
|
||||
// securely to the API Server using the provided CA cert/client certificates and
|
||||
// optionally refreshes the cluster-info information from the cluster-info ConfigMap
|
||||
func ValidateClusterInfo(clusterinfo *clientcmdapi.Config, clustername string) (*clientcmdapi.Cluster, error) {
|
||||
err := validateClusterInfoKubeConfig(clusterinfo)
|
||||
func ValidateConfigInfo(config *clientcmdapi.Config, clustername string) (*clientcmdapi.Config, error) {
|
||||
err := validateKubeConfig(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// This is the cluster object we've got from the cluster-info KubeConfig file
|
||||
defaultCluster := kubeconfigutil.GetClusterFromKubeConfig(clusterinfo)
|
||||
// This is the cluster object we've got from the cluster-info kubeconfig file
|
||||
defaultCluster := kubeconfigutil.GetClusterFromKubeConfig(config)
|
||||
|
||||
// Create a new kubeconfig object from the given, just copy over the server and the CA cert
|
||||
// We do this in order to not pick up other possible misconfigurations in the clusterinfo file
|
||||
configFromClusterInfo := kubeconfigutil.CreateBasic(
|
||||
kubeconfig := kubeconfigutil.CreateBasic(
|
||||
defaultCluster.Server,
|
||||
clustername,
|
||||
"", // no user provided
|
||||
defaultCluster.CertificateAuthorityData,
|
||||
)
|
||||
// load pre-existing client certificates
|
||||
if config.Contexts[config.CurrentContext] != nil && len(config.AuthInfos) > 0 {
|
||||
user := config.Contexts[config.CurrentContext].AuthInfo
|
||||
authInfo, ok := config.AuthInfos[user]
|
||||
if !ok || authInfo == nil {
|
||||
return nil, errors.Errorf("empty settings for user %q", user)
|
||||
}
|
||||
if len(authInfo.ClientCertificateData) == 0 && len(authInfo.ClientCertificate) != 0 {
|
||||
clientCert, err := ioutil.ReadFile(authInfo.ClientCertificate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authInfo.ClientCertificateData = clientCert
|
||||
}
|
||||
if len(authInfo.ClientKeyData) == 0 && len(authInfo.ClientKey) != 0 {
|
||||
clientKey, err := ioutil.ReadFile(authInfo.ClientKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authInfo.ClientKeyData = clientKey
|
||||
}
|
||||
|
||||
client, err := kubeconfigutil.ToClientSet(configFromClusterInfo)
|
||||
if len(authInfo.ClientCertificateData) == 0 || len(authInfo.ClientKeyData) == 0 {
|
||||
return nil, errors.New("couldn't read authentication info from the given kubeconfig file")
|
||||
}
|
||||
kubeconfig = kubeconfigutil.CreateWithCerts(
|
||||
defaultCluster.Server,
|
||||
clustername,
|
||||
"", // no user provided
|
||||
defaultCluster.CertificateAuthorityData,
|
||||
authInfo.ClientKeyData,
|
||||
authInfo.ClientCertificateData,
|
||||
)
|
||||
}
|
||||
|
||||
client, err := kubeconfigutil.ToClientSet(kubeconfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -88,42 +124,42 @@ func ValidateClusterInfo(clusterinfo *clientcmdapi.Config, clustername string) (
|
||||
|
||||
// If we couldn't fetch the cluster-info ConfigMap, just return the cluster-info object the user provided
|
||||
if clusterinfoCM == nil {
|
||||
return defaultCluster, nil
|
||||
return kubeconfig, nil
|
||||
}
|
||||
|
||||
// We somehow got hold of the ConfigMap, try to read some data from it. If we can't, fallback on the user-provided file
|
||||
refreshedBaseKubeConfig, err := tryParseClusterInfoFromConfigMap(clusterinfoCM)
|
||||
if err != nil {
|
||||
fmt.Printf("[discovery] The %s ConfigMap isn't set up properly (%v), but the TLS cert is valid so proceeding...\n", bootstrapapi.ConfigMapClusterInfo, err)
|
||||
return defaultCluster, nil
|
||||
return kubeconfig, nil
|
||||
}
|
||||
|
||||
fmt.Println("[discovery] Synced cluster-info information from the API Server so we have got the latest information")
|
||||
// In an HA world in the future, this will make more sense, because now we've got new information, possibly about new API Servers to talk to
|
||||
return kubeconfigutil.GetClusterFromKubeConfig(refreshedBaseKubeConfig), nil
|
||||
return refreshedBaseKubeConfig, nil
|
||||
}
|
||||
|
||||
// tryParseClusterInfoFromConfigMap tries to parse a kubeconfig file from a ConfigMap key
|
||||
func tryParseClusterInfoFromConfigMap(cm *v1.ConfigMap) (*clientcmdapi.Config, error) {
|
||||
kubeConfigString, ok := cm.Data[bootstrapapi.KubeConfigKey]
|
||||
if !ok || len(kubeConfigString) == 0 {
|
||||
return nil, fmt.Errorf("no %s key in ConfigMap", bootstrapapi.KubeConfigKey)
|
||||
return nil, errors.Errorf("no %s key in ConfigMap", bootstrapapi.KubeConfigKey)
|
||||
}
|
||||
parsedKubeConfig, err := clientcmd.Load([]byte(kubeConfigString))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't parse the kubeconfig file in the %s ConfigMap: %v", bootstrapapi.ConfigMapClusterInfo, err)
|
||||
return nil, errors.Wrapf(err, "couldn't parse the kubeconfig file in the %s ConfigMap", bootstrapapi.ConfigMapClusterInfo)
|
||||
}
|
||||
return parsedKubeConfig, nil
|
||||
}
|
||||
|
||||
// validateClusterInfoKubeConfig makes sure the user-provided cluster-info KubeConfig file is valid
|
||||
func validateClusterInfoKubeConfig(clusterinfo *clientcmdapi.Config) error {
|
||||
if len(clusterinfo.Clusters) < 1 {
|
||||
return fmt.Errorf("the provided cluster-info KubeConfig file must have at least one Cluster defined")
|
||||
// validateKubeConfig makes sure the user-provided kubeconfig file is valid
|
||||
func validateKubeConfig(config *clientcmdapi.Config) error {
|
||||
if len(config.Clusters) < 1 {
|
||||
return errors.New("the provided cluster-info kubeconfig file must have at least one Cluster defined")
|
||||
}
|
||||
defaultCluster := kubeconfigutil.GetClusterFromKubeConfig(clusterinfo)
|
||||
defaultCluster := kubeconfigutil.GetClusterFromKubeConfig(config)
|
||||
if defaultCluster == nil {
|
||||
return fmt.Errorf("the provided cluster-info KubeConfig file must have an unnamed Cluster or a CurrentContext that specifies a non-nil Cluster")
|
||||
return errors.New("the provided cluster-info kubeconfig file must have an unnamed Cluster or a CurrentContext that specifies a non-nil Cluster")
|
||||
}
|
||||
return nil
|
||||
return clientcmd.Validate(*config)
|
||||
}
|
||||
|
6
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/https/BUILD
generated
vendored
6
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/https/BUILD
generated
vendored
@ -11,9 +11,9 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/discovery/https",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/discovery/file:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
8
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/https/https.go
generated
vendored
8
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/https/https.go
generated
vendored
@ -26,10 +26,10 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/discovery/file"
|
||||
)
|
||||
|
||||
// RetrieveValidatedClusterInfo connects to the API Server and makes sure it can talk
|
||||
// RetrieveValidatedConfigInfo connects to the API Server and makes sure it can talk
|
||||
// securely to the API Server using the provided CA cert and
|
||||
// optionally refreshes the cluster-info information from the cluster-info ConfigMap
|
||||
func RetrieveValidatedClusterInfo(httpsURL, clustername string) (*clientcmdapi.Cluster, error) {
|
||||
func RetrieveValidatedConfigInfo(httpsURL, clustername string) (*clientcmdapi.Config, error) {
|
||||
client := &http.Client{Transport: netutil.SetOldTransportDefaults(&http.Transport{})}
|
||||
response, err := client.Get(httpsURL)
|
||||
if err != nil {
|
||||
@ -42,9 +42,9 @@ func RetrieveValidatedClusterInfo(httpsURL, clustername string) (*clientcmdapi.C
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clusterinfo, err := clientcmd.Load(kubeconfig)
|
||||
config, err := clientcmd.Load(kubeconfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return file.ValidateClusterInfo(clusterinfo, clustername)
|
||||
return file.ValidateConfigInfo(config, clustername)
|
||||
}
|
||||
|
19
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/BUILD
generated
vendored
19
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/BUILD
generated
vendored
@ -12,16 +12,18 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/discovery/token",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||
"//cmd/kubeadm/app/util/pubkeypin:go_default_library",
|
||||
"//pkg/controller/bootstrap:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
|
||||
"//vendor/github.com/pkg/errors:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -42,8 +44,5 @@ go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["token_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
],
|
||||
deps = ["//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library"],
|
||||
)
|
||||
|
94
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token.go
generated
vendored
94
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token.go
generated
vendored
@ -24,13 +24,16 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/pubkeypin"
|
||||
@ -40,27 +43,27 @@ import (
|
||||
// BootstrapUser defines bootstrap user name
|
||||
const BootstrapUser = "token-bootstrap-client"
|
||||
|
||||
// RetrieveValidatedClusterInfo connects to the API Server and tries to fetch the cluster-info ConfigMap
|
||||
// RetrieveValidatedConfigInfo connects to the API Server and tries to fetch the cluster-info ConfigMap
|
||||
// It then makes sure it can trust the API Server by looking at the JWS-signed tokens and (if cfg.DiscoveryTokenCACertHashes is not empty)
|
||||
// validating the cluster CA against a set of pinned public keys
|
||||
func RetrieveValidatedClusterInfo(cfg *kubeadmapi.NodeConfiguration) (*clientcmdapi.Cluster, error) {
|
||||
token, err := kubeadmapi.NewBootstrapTokenString(cfg.DiscoveryToken)
|
||||
func RetrieveValidatedConfigInfo(cfg *kubeadmapi.JoinConfiguration) (*clientcmdapi.Config, error) {
|
||||
token, err := kubeadmapi.NewBootstrapTokenString(cfg.Discovery.BootstrapToken.Token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Load the cfg.DiscoveryTokenCACertHashes into a pubkeypin.Set
|
||||
pubKeyPins := pubkeypin.NewSet()
|
||||
err = pubKeyPins.Allow(cfg.DiscoveryTokenCACertHashes...)
|
||||
err = pubKeyPins.Allow(cfg.Discovery.BootstrapToken.CACertHashes...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// The function below runs for every endpoint, and all endpoints races with each other.
|
||||
// The endpoint that wins the race and completes the task first gets its kubeconfig returned below
|
||||
baseKubeConfig, err := runForEndpointsAndReturnFirst(cfg.DiscoveryTokenAPIServers, cfg.DiscoveryTimeout.Duration, func(endpoint string) (*clientcmdapi.Config, error) {
|
||||
baseKubeConfig, err := fetchKubeConfigWithTimeout(cfg.Discovery.BootstrapToken.APIServerEndpoint, cfg.Discovery.Timeout.Duration, func(endpoint string) (*clientcmdapi.Config, error) {
|
||||
|
||||
insecureBootstrapConfig := buildInsecureBootstrapKubeConfig(endpoint, cfg.ClusterName)
|
||||
insecureBootstrapConfig := buildInsecureBootstrapKubeConfig(endpoint, kubeadmapiv1beta1.DefaultClusterName)
|
||||
clusterName := insecureBootstrapConfig.Contexts[insecureBootstrapConfig.CurrentContext].Cluster
|
||||
|
||||
insecureClient, err := kubeconfigutil.ToClientSet(insecureBootstrapConfig)
|
||||
@ -85,19 +88,20 @@ func RetrieveValidatedClusterInfo(cfg *kubeadmapi.NodeConfiguration) (*clientcmd
|
||||
// Validate the MAC on the kubeconfig from the ConfigMap and load it
|
||||
insecureKubeconfigString, ok := insecureClusterInfo.Data[bootstrapapi.KubeConfigKey]
|
||||
if !ok || len(insecureKubeconfigString) == 0 {
|
||||
return nil, fmt.Errorf("there is no %s key in the %s ConfigMap. This API Server isn't set up for token bootstrapping, can't connect", bootstrapapi.KubeConfigKey, bootstrapapi.ConfigMapClusterInfo)
|
||||
return nil, errors.Errorf("there is no %s key in the %s ConfigMap. This API Server isn't set up for token bootstrapping, can't connect",
|
||||
bootstrapapi.KubeConfigKey, bootstrapapi.ConfigMapClusterInfo)
|
||||
}
|
||||
detachedJWSToken, ok := insecureClusterInfo.Data[bootstrapapi.JWSSignatureKeyPrefix+token.ID]
|
||||
if !ok || len(detachedJWSToken) == 0 {
|
||||
return nil, fmt.Errorf("token id %q is invalid for this cluster or it has expired. Use \"kubeadm token create\" on the master node to creating a new valid token", token.ID)
|
||||
return nil, errors.Errorf("token id %q is invalid for this cluster or it has expired. Use \"kubeadm token create\" on the master node to creating a new valid token", token.ID)
|
||||
}
|
||||
if !bootstrap.DetachedTokenIsValid(detachedJWSToken, insecureKubeconfigString, token.ID, token.Secret) {
|
||||
return nil, fmt.Errorf("failed to verify JWS signature of received cluster info object, can't trust this API Server")
|
||||
return nil, errors.New("failed to verify JWS signature of received cluster info object, can't trust this API Server")
|
||||
}
|
||||
insecureKubeconfigBytes := []byte(insecureKubeconfigString)
|
||||
insecureConfig, err := clientcmd.Load(insecureKubeconfigBytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't parse the kubeconfig file in the %s configmap: %v", bootstrapapi.ConfigMapClusterInfo, err)
|
||||
return nil, errors.Wrapf(err, "couldn't parse the kubeconfig file in the %s configmap", bootstrapapi.ConfigMapClusterInfo)
|
||||
}
|
||||
|
||||
// If no TLS root CA pinning was specified, we're done
|
||||
@ -108,7 +112,7 @@ func RetrieveValidatedClusterInfo(cfg *kubeadmapi.NodeConfiguration) (*clientcmd
|
||||
|
||||
// Load the cluster CA from the Config
|
||||
if len(insecureConfig.Clusters) != 1 {
|
||||
return nil, fmt.Errorf("expected the kubeconfig file in the %s configmap to have a single cluster, but it had %d", bootstrapapi.ConfigMapClusterInfo, len(insecureConfig.Clusters))
|
||||
return nil, errors.Errorf("expected the kubeconfig file in the %s configmap to have a single cluster, but it had %d", bootstrapapi.ConfigMapClusterInfo, len(insecureConfig.Clusters))
|
||||
}
|
||||
var clusterCABytes []byte
|
||||
for _, cluster := range insecureConfig.Clusters {
|
||||
@ -116,14 +120,14 @@ func RetrieveValidatedClusterInfo(cfg *kubeadmapi.NodeConfiguration) (*clientcmd
|
||||
}
|
||||
clusterCA, err := parsePEMCert(clusterCABytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse cluster CA from the %s configmap: %v", bootstrapapi.ConfigMapClusterInfo, err)
|
||||
return nil, errors.Wrapf(err, "failed to parse cluster CA from the %s configmap", bootstrapapi.ConfigMapClusterInfo)
|
||||
|
||||
}
|
||||
|
||||
// Validate the cluster CA public key against the pinned set
|
||||
err = pubKeyPins.Check(clusterCA)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cluster CA found in %s configmap is invalid: %v", bootstrapapi.ConfigMapClusterInfo, err)
|
||||
return nil, errors.Wrapf(err, "cluster CA found in %s configmap is invalid", bootstrapapi.ConfigMapClusterInfo)
|
||||
}
|
||||
|
||||
// Now that we know the proported cluster CA, connect back a second time validating with that CA
|
||||
@ -148,12 +152,12 @@ func RetrieveValidatedClusterInfo(cfg *kubeadmapi.NodeConfiguration) (*clientcmd
|
||||
// Pull the kubeconfig from the securely-obtained ConfigMap and validate that it's the same as what we found the first time
|
||||
secureKubeconfigBytes := []byte(secureClusterInfo.Data[bootstrapapi.KubeConfigKey])
|
||||
if !bytes.Equal(secureKubeconfigBytes, insecureKubeconfigBytes) {
|
||||
return nil, fmt.Errorf("the second kubeconfig from the %s configmap (using validated TLS) was different from the first", bootstrapapi.ConfigMapClusterInfo)
|
||||
return nil, errors.Errorf("the second kubeconfig from the %s configmap (using validated TLS) was different from the first", bootstrapapi.ConfigMapClusterInfo)
|
||||
}
|
||||
|
||||
secureKubeconfig, err := clientcmd.Load(secureKubeconfigBytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't parse the kubeconfig file in the %s configmap: %v", bootstrapapi.ConfigMapClusterInfo, err)
|
||||
return nil, errors.Wrapf(err, "couldn't parse the kubeconfig file in the %s configmap", bootstrapapi.ConfigMapClusterInfo)
|
||||
}
|
||||
|
||||
fmt.Printf("[discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server %q\n", endpoint)
|
||||
@ -163,10 +167,10 @@ func RetrieveValidatedClusterInfo(cfg *kubeadmapi.NodeConfiguration) (*clientcmd
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return kubeconfigutil.GetClusterFromKubeConfig(baseKubeConfig), nil
|
||||
return baseKubeConfig, nil
|
||||
}
|
||||
|
||||
// buildInsecureBootstrapKubeConfig makes a KubeConfig object that connects insecurely to the API Server for bootstrapping purposes
|
||||
// buildInsecureBootstrapKubeConfig makes a kubeconfig object that connects insecurely to the API Server for bootstrapping purposes
|
||||
func buildInsecureBootstrapKubeConfig(endpoint, clustername string) *clientcmdapi.Config {
|
||||
masterEndpoint := fmt.Sprintf("https://%s", endpoint)
|
||||
bootstrapConfig := kubeconfigutil.CreateBasic(masterEndpoint, clustername, BootstrapUser, []byte{})
|
||||
@ -174,44 +178,44 @@ func buildInsecureBootstrapKubeConfig(endpoint, clustername string) *clientcmdap
|
||||
return bootstrapConfig
|
||||
}
|
||||
|
||||
// buildSecureBootstrapKubeConfig makes a KubeConfig object that connects securely to the API Server for bootstrapping purposes (validating with the specified CA)
|
||||
// buildSecureBootstrapKubeConfig makes a kubeconfig object that connects securely to the API Server for bootstrapping purposes (validating with the specified CA)
|
||||
func buildSecureBootstrapKubeConfig(endpoint string, caCert []byte, clustername string) *clientcmdapi.Config {
|
||||
masterEndpoint := fmt.Sprintf("https://%s", endpoint)
|
||||
bootstrapConfig := kubeconfigutil.CreateBasic(masterEndpoint, clustername, BootstrapUser, caCert)
|
||||
return bootstrapConfig
|
||||
}
|
||||
|
||||
// runForEndpointsAndReturnFirst loops the endpoints slice and let's the endpoints race for connecting to the master
|
||||
func runForEndpointsAndReturnFirst(endpoints []string, discoveryTimeout time.Duration, fetchKubeConfigFunc func(string) (*clientcmdapi.Config, error)) (*clientcmdapi.Config, error) {
|
||||
// fetchKubeConfigWithTimeout tries to run fetchKubeConfigFunc on every DiscoveryRetryInterval, but until discoveryTimeout is reached
|
||||
func fetchKubeConfigWithTimeout(apiEndpoint string, discoveryTimeout time.Duration, fetchKubeConfigFunc func(string) (*clientcmdapi.Config, error)) (*clientcmdapi.Config, error) {
|
||||
stopChan := make(chan struct{})
|
||||
var resultingKubeConfig *clientcmdapi.Config
|
||||
var once sync.Once
|
||||
var wg sync.WaitGroup
|
||||
for _, endpoint := range endpoints {
|
||||
wg.Add(1)
|
||||
go func(apiEndpoint string) {
|
||||
defer wg.Done()
|
||||
wait.Until(func() {
|
||||
fmt.Printf("[discovery] Trying to connect to API Server %q\n", apiEndpoint)
|
||||
cfg, err := fetchKubeConfigFunc(apiEndpoint)
|
||||
if err != nil {
|
||||
fmt.Printf("[discovery] Failed to connect to API Server %q: %v\n", apiEndpoint, err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("[discovery] Successfully established connection with API Server %q\n", apiEndpoint)
|
||||
|
||||
// connection established, stop all wait threads
|
||||
once.Do(func() {
|
||||
close(stopChan)
|
||||
resultingKubeConfig = cfg
|
||||
})
|
||||
}, constants.DiscoveryRetryInterval, stopChan)
|
||||
}(endpoint)
|
||||
}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
wait.Until(func() {
|
||||
fmt.Printf("[discovery] Trying to connect to API Server %q\n", apiEndpoint)
|
||||
cfg, err := fetchKubeConfigFunc(apiEndpoint)
|
||||
if err != nil {
|
||||
fmt.Printf("[discovery] Failed to connect to API Server %q: %v\n", apiEndpoint, err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("[discovery] Successfully established connection with API Server %q\n", apiEndpoint)
|
||||
once.Do(func() {
|
||||
resultingKubeConfig = cfg
|
||||
close(stopChan)
|
||||
})
|
||||
}, constants.DiscoveryRetryInterval, stopChan)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-time.After(discoveryTimeout):
|
||||
close(stopChan)
|
||||
err := fmt.Errorf("abort connecting to API servers after timeout of %v", discoveryTimeout)
|
||||
once.Do(func() {
|
||||
close(stopChan)
|
||||
})
|
||||
err := errors.Errorf("abort connecting to API servers after timeout of %v", discoveryTimeout)
|
||||
fmt.Printf("[discovery] %v\n", err)
|
||||
wg.Wait()
|
||||
return nil, err
|
||||
@ -225,10 +229,10 @@ func runForEndpointsAndReturnFirst(endpoints []string, discoveryTimeout time.Dur
|
||||
func parsePEMCert(certData []byte) (*x509.Certificate, error) {
|
||||
pemBlock, trailingData := pem.Decode(certData)
|
||||
if pemBlock == nil {
|
||||
return nil, fmt.Errorf("invalid PEM data")
|
||||
return nil, errors.New("invalid PEM data")
|
||||
}
|
||||
if len(trailingData) != 0 {
|
||||
return nil, fmt.Errorf("trailing data after first PEM block")
|
||||
return nil, errors.New("trailing data after first PEM block")
|
||||
}
|
||||
return x509.ParseCertificate(pemBlock.Bytes)
|
||||
}
|
||||
|
65
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token_test.go
generated
vendored
65
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token_test.go
generated
vendored
@ -17,12 +17,11 @@ limitations under the License.
|
||||
package token
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
)
|
||||
|
||||
// testCertPEM is a simple self-signed test certificate issued with the openssl CLI:
|
||||
@ -49,41 +48,49 @@ c1vuFqTnJBPcb7W//R/GI2Paicm1cmns9NLnPR35exHxFTy+D1yxmGokpoPMdife
|
||||
aH+sfuxT8xeTPb3kjzF9eJTlnEquUDLM
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
func TestRunForEndpointsAndReturnFirst(t *testing.T) {
|
||||
func TestFetchKubeConfigWithTimeout(t *testing.T) {
|
||||
const testAPIEndpoint = "sample-endpoint:1234"
|
||||
tests := []struct {
|
||||
endpoints []string
|
||||
expectedEndpoint string
|
||||
name string
|
||||
discoveryTimeout time.Duration
|
||||
shouldFail bool
|
||||
}{
|
||||
{
|
||||
endpoints: []string{"1", "2", "3"},
|
||||
expectedEndpoint: "1",
|
||||
name: "Timeout if value is not returned on time",
|
||||
discoveryTimeout: 1 * time.Second,
|
||||
shouldFail: true,
|
||||
},
|
||||
{
|
||||
endpoints: []string{"6", "5"},
|
||||
expectedEndpoint: "5",
|
||||
},
|
||||
{
|
||||
endpoints: []string{"10", "4"},
|
||||
expectedEndpoint: "4",
|
||||
name: "Don't timeout if value is returned on time",
|
||||
discoveryTimeout: 5 * time.Second,
|
||||
shouldFail: false,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
returnKubeConfig, err := runForEndpointsAndReturnFirst(rt.endpoints, 5*time.Minute, func(endpoint string) (*clientcmdapi.Config, error) {
|
||||
timeout, _ := strconv.Atoi(endpoint)
|
||||
time.Sleep(time.Second * time.Duration(timeout))
|
||||
return kubeconfigutil.CreateBasic(endpoint, "foo", "foo", []byte{}), nil
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
cfg, err := fetchKubeConfigWithTimeout(testAPIEndpoint, test.discoveryTimeout, func(apiEndpoint string) (*clientcmdapi.Config, error) {
|
||||
if apiEndpoint != testAPIEndpoint {
|
||||
return nil, fmt.Errorf("unexpected API server endpoint:\n\texpected: %q\n\tgot: %q", testAPIEndpoint, apiEndpoint)
|
||||
}
|
||||
|
||||
time.Sleep(3 * time.Second)
|
||||
return &clientcmdapi.Config{}, nil
|
||||
})
|
||||
|
||||
if test.shouldFail {
|
||||
if err == nil {
|
||||
t.Fatal("unexpected success")
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected failure: %v", err)
|
||||
}
|
||||
if cfg == nil {
|
||||
t.Fatal("cfg is nil")
|
||||
}
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v for endpoint %s", err, rt.expectedEndpoint)
|
||||
}
|
||||
endpoint := returnKubeConfig.Clusters[returnKubeConfig.Contexts[returnKubeConfig.CurrentContext].Cluster].Server
|
||||
if endpoint != rt.expectedEndpoint {
|
||||
t.Errorf(
|
||||
"failed TestRunForEndpointsAndReturnFirst:\n\texpected: %s\n\t actual: %s",
|
||||
endpoint,
|
||||
rt.expectedEndpoint,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user