/
kubeconfig.go
132 lines (108 loc) · 3.91 KB
/
kubeconfig.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2017 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 auth
import (
"errors"
authApi "github.com/kubernetes/dashboard/src/app/backend/auth/api"
yaml "gopkg.in/yaml.v2"
"k8s.io/client-go/tools/clientcmd/api"
)
// Below structures represent structure of kubeconfig file. They only contain fields required to gather data needed
// to log in user. It should support same auth options as defined in auth/api/types.go file. Currently: basic, token.
type contextInfo struct {
User string `yaml:"user"`
}
type contextEntry struct {
Name string `yaml:"name"`
Context contextInfo `yaml:"context"`
}
type userEntry struct {
Name string `yaml:"name"`
User userInfo `yaml:"user"`
}
type userInfo struct {
Token string `yaml:"token"`
Username string `yaml:"username"`
Password string `yaml:"password"`
}
type kubeConfig struct {
Contexts []contextEntry `yaml:"contexts"`
CurrentContext string `yaml:"current-context"`
Users []userEntry `yaml:"users"`
}
// Implements Authenticator interface.
type kubeConfigAuthenticator struct {
fileContent []byte
authModes authApi.AuthenticationModes
}
// GetAuthInfo implements Authenticator interface. See Authenticator for more information.
func (self *kubeConfigAuthenticator) GetAuthInfo() (api.AuthInfo, error) {
kubeConfig, err := self.parseKubeConfig(self.fileContent)
if err != nil {
return api.AuthInfo{}, err
}
info, err := self.getCurrentUserInfo(*kubeConfig)
if err != nil {
return api.AuthInfo{}, err
}
return self.getAuthInfo(info)
}
// Parses kubeconfig file and returns kubeConfig object.
func (self *kubeConfigAuthenticator) parseKubeConfig(bytes []byte) (*kubeConfig, error) {
kubeConfig := new(kubeConfig)
if err := yaml.Unmarshal(bytes, kubeConfig); err != nil {
return nil, err
}
return kubeConfig, nil
}
// Returns user info based on defined current context. In case it is not found error is returned.
func (self *kubeConfigAuthenticator) getCurrentUserInfo(config kubeConfig) (userInfo, error) {
userName := ""
for _, context := range config.Contexts {
if context.Name == config.CurrentContext {
userName = context.Context.User
}
}
if len(userName) == 0 {
return userInfo{}, errors.New("Context matching current context not found. Check if your config file is valid.")
}
for _, user := range config.Users {
if user.Name == userName {
return user.User, nil
}
}
return userInfo{}, errors.New("User matching current context user not found. Check if your config file is valid.")
}
// Returns auth info structure based on provided user info or error in case not enough data has been provided.
func (self *kubeConfigAuthenticator) getAuthInfo(info userInfo) (api.AuthInfo, error) {
if len(info.Token) == 0 && (len(info.Password) == 0 || len(info.Username) == 0) {
return api.AuthInfo{}, errors.New("Not enough data to create auth info structure.")
}
result := api.AuthInfo{}
if self.authModes.IsEnabled(authApi.Token) {
result.Token = info.Token
}
if self.authModes.IsEnabled(authApi.Basic) {
result.Username = info.Username
result.Password = info.Password
}
return result, nil
}
// NewBasicAuthenticator returns Authenticator based on LoginSpec.
func NewKubeConfigAuthenticator(spec *authApi.LoginSpec, authModes authApi.AuthenticationModes) authApi.Authenticator {
return &kubeConfigAuthenticator{
fileContent: []byte(spec.KubeConfig),
authModes: authModes,
}
}