Skip to content

Commit 8dabf6a

Browse files
authored
fix: Add support to manage token based auth (#527)
## What type of PR is this? /kind refactor ## What this PR does / why we need it: If uploading a token based kubeconfig, error reported as invalid kubeconfig. In fact, token based kubeconfig is general usage in many cases. ref: https://kb.leaseweb.com/products/kubernetes/users-roles-and-permissions-on-kubernetes-rbac/create-a-token-based-kubeconfig
1 parent 916cd76 commit 8dabf6a

File tree

6 files changed

+79
-14
lines changed

6 files changed

+79
-14
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ endif
3434
.PHONY: test
3535
test: ## Run the tests
3636
@PKG_LIST=$${TARGET_PKG:-$(GOSOURCE_PATHS)}; \
37-
go test -gcflags=all=-l -timeout=10m `go list $${PKG_LIST} | grep -vE "internalimport|generated|handler"` ${TEST_FLAGS}
37+
go test -gcflags=all=-l -timeout=10m `go list -e $${PKG_LIST} | grep -vE "internalimport|generated|handler"` ${TEST_FLAGS}
3838

3939

4040
# cover: Generates a coverage report for the specified TARGET_PKG or default GOSOURCE_PATHS.

pkg/core/handler/cluster/cluster.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ func ValidateKubeConfig(clusterMgr *cluster.ClusterManager) http.HandlerFunc {
365365
// Decode the request body into the payload.
366366
payload := &ValidatePayload{}
367367
if err := payload.Decode(r); err != nil {
368+
log.Error(err, "failed to decode kubeconfig")
368369
render.Render(w, r, handler.FailureResponse(ctx, err))
369370
return
370371
}
@@ -378,6 +379,8 @@ func ValidateKubeConfig(clusterMgr *cluster.ClusterManager) http.HandlerFunc {
378379
if info, err := clusterMgr.ValidateKubeConfigWithYAML(ctx, payload.KubeConfig); err == nil {
379380
render.JSON(w, r, handler.SuccessResponse(ctx, info))
380381
} else {
382+
log.Error(err, "failed to validate kubeconfig")
383+
w.WriteHeader(http.StatusBadRequest)
381384
render.Render(w, r, handler.FailureResponse(ctx, err))
382385
}
383386
}

pkg/core/manager/cluster/manager.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -418,13 +418,20 @@ func (c *ClusterManager) ValidateKubeConfigFor(
418418
if cluster.Server == "" {
419419
return "", ErrMissingClusterServer
420420
}
421-
if cluster.CertificateAuthorityData == "" {
421+
422+
if cluster.Insecure && len(cluster.CertificateAuthorityData) > 0 {
423+
return "", ErrBothInsecureAndCertificateAuthority
424+
}
425+
426+
if !cluster.Insecure && len(cluster.CertificateAuthorityData) <= 0 {
427+
// when insecure is false, CA is required.
422428
return "", ErrMissingCertificateAuthority
423429
}
424-
if _, err := base64.StdEncoding.DecodeString(cluster.CertificateAuthorityData); err != nil {
425-
return "", ErrInvalidCertificateAuthority
430+
if len(cluster.CertificateAuthorityData) > 0 {
431+
if _, err := base64.StdEncoding.DecodeString(cluster.CertificateAuthorityData); err != nil {
432+
return "", ErrInvalidCertificateAuthority
433+
}
426434
}
427-
428435
// Check cluster server address connectivity
429436
if err := checkEndpointConnectivity(cluster.Server); err != nil {
430437
return "", ErrClusterServerConnectivity

pkg/core/manager/cluster/manager_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,29 @@ users:
542542
- name: test-user
543543
user:
544544
token: 6b26************************99af
545+
`,
546+
expectedErr: false,
547+
},
548+
{
549+
name: "Sanitize token based kubeconfig",
550+
plainKubeConfig: newMockTokenAndInsecureKubeConfig(),
551+
expectedSanitizedKubeConfig: `apiVersion: v1
552+
kind: Config
553+
clusters:
554+
- name: cluster-local
555+
cluster:
556+
insecure-skip-tls-verify: true
557+
server: https://127.0.0.1:30383/k8s/cluster/cluster-local
558+
contexts:
559+
- name: cluster-local-admin@cluster-local
560+
context:
561+
cluster: cluster-local
562+
user: cluster-local-admin
563+
current-context: cluster-local-admin@cluster-local
564+
users:
565+
- name: cluster-local-admin
566+
user:
567+
token: 3ac4************************ddd5
545568
`,
546569
expectedErr: false,
547570
},
@@ -660,6 +683,29 @@ current-context: test-context
660683
`, base64.StdEncoding.EncodeToString([]byte("sensitive-certificate-data")))
661684
}
662685

686+
// newMockTokenAndInsecureKubeConfig generates a mock token-based kubeconfig with sensitive information
687+
// included.
688+
func newMockTokenAndInsecureKubeConfig() string {
689+
return fmt.Sprintf(`apiVersion: v1
690+
kind: Config
691+
clusters:
692+
- name: cluster-local
693+
cluster:
694+
insecure-skip-tls-verify: true
695+
server: https://127.0.0.1:30383/k8s/cluster/cluster-local
696+
contexts:
697+
- context:
698+
cluster: cluster-local
699+
user: cluster-local-admin
700+
name: cluster-local-admin@cluster-local
701+
current-context: cluster-local-admin@cluster-local
702+
users:
703+
- name: cluster-local-admin
704+
user:
705+
token: %s
706+
`, base64.StdEncoding.EncodeToString([]byte("sensitive-token-data")))
707+
}
708+
663709
// newMockCluster is a helper function that creates a mock cluster unstructured
664710
// object.
665711
func newMockCluster(name string) *unstructured.Unstructured {

pkg/core/manager/cluster/types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ var (
2323
ErrMissingUserEntry = errors.New("at least one user entry is required")
2424
ErrMissingClusterName = errors.New("cluster name is required")
2525
ErrMissingClusterServer = errors.New("cluster server is required")
26+
ErrBothInsecureAndCertificateAuthority = errors.New("certificate-authority-data and insecure-skip-tls-verify couldn't both be set")
2627
ErrMissingCertificateAuthority = errors.New("certificate-authority-data is required")
2728
ErrInvalidCertificateAuthority = errors.New("certificate-authority-data is invalid")
2829
ErrClusterServerConnectivity = errors.New("cannot connect to the cluster server")
@@ -70,6 +71,7 @@ type ClusterEntry struct {
7071
//
7172
//nolint:tagliatelle
7273
type Cluster struct {
74+
Insecure bool `yaml:"insecure-skip-tls-verify,omitempty"`
7375
Server string `yaml:"server"`
7476
CertificateAuthorityData string `yaml:"certificate-authority-data,omitempty"`
7577
}

pkg/core/manager/cluster/util.go

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,26 +74,33 @@ func checkEndpointConnectivity(endpoint string) error {
7474
func buildClientConfigFromKubeConfig(config *KubeConfig) (*rest.Config, error) {
7575
// Create an initial rest.Config object.
7676
clientConfig := &rest.Config{}
77-
7877
// Set the API server and authentication details.
7978
if len(config.Clusters) > 0 {
8079
cluster := config.Clusters[0].Cluster
8180
clientConfig.Host = cluster.Server
82-
if plain, err := base64.StdEncoding.DecodeString(cluster.CertificateAuthorityData); err != nil {
83-
return nil, errors.Wrapf(
84-
err,
85-
"invalid certificate-authority-data for cluster %s",
86-
config.Clusters[0].Name,
87-
)
88-
} else {
89-
clientConfig.CAData = plain
81+
clientConfig.Insecure = cluster.Insecure // allow insecure connection
82+
if len(cluster.CertificateAuthorityData) > 0 {
83+
if plain, err := base64.StdEncoding.DecodeString(cluster.CertificateAuthorityData); err != nil {
84+
return nil, errors.Wrapf(
85+
err,
86+
"invalid certificate-authority-data for cluster %s",
87+
config.Clusters[0].Name,
88+
)
89+
} else {
90+
clientConfig.CAData = plain
91+
}
9092
}
9193
}
9294

9395
if len(config.Users) > 0 {
9496
user := config.Users[0].User
9597
clientConfig.Username = user.Username
9698
clientConfig.Password = user.Password
99+
clientConfig.BearerToken = user.Token
100+
if len(user.Token) > 0 || (len(user.Password) > 0 && len(user.Username) > 0) {
101+
// prefer token or username/password
102+
return clientConfig, nil
103+
}
97104
if plain, err := base64.StdEncoding.DecodeString(user.ClientCertificateData); err != nil {
98105
return nil, fmt.Errorf(
99106
"invalid client-certificate-data for user %s: %v",

0 commit comments

Comments
 (0)