kubeconfig.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*
  2. Copyright 2017 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package kubeconfig
  14. import (
  15. "fmt"
  16. "io/ioutil"
  17. clientset "k8s.io/client-go/kubernetes"
  18. "k8s.io/client-go/tools/clientcmd"
  19. clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
  20. "github.com/pkg/errors"
  21. )
  22. // CreateBasic creates a basic, general KubeConfig object that then can be extended
  23. func CreateBasic(serverURL, clusterName, userName string, caCert []byte) *clientcmdapi.Config {
  24. // Use the cluster and the username as the context name
  25. contextName := fmt.Sprintf("%s@%s", userName, clusterName)
  26. return &clientcmdapi.Config{
  27. Clusters: map[string]*clientcmdapi.Cluster{
  28. clusterName: {
  29. Server: serverURL,
  30. CertificateAuthorityData: caCert,
  31. },
  32. },
  33. Contexts: map[string]*clientcmdapi.Context{
  34. contextName: {
  35. Cluster: clusterName,
  36. AuthInfo: userName,
  37. },
  38. },
  39. AuthInfos: map[string]*clientcmdapi.AuthInfo{},
  40. CurrentContext: contextName,
  41. }
  42. }
  43. // CreateWithCerts creates a KubeConfig object with access to the API server with client certificates
  44. func CreateWithCerts(serverURL, clusterName, userName string, caCert []byte, clientKey []byte, clientCert []byte) *clientcmdapi.Config {
  45. config := CreateBasic(serverURL, clusterName, userName, caCert)
  46. config.AuthInfos[userName] = &clientcmdapi.AuthInfo{
  47. ClientKeyData: clientKey,
  48. ClientCertificateData: clientCert,
  49. }
  50. return config
  51. }
  52. // CreateWithToken creates a KubeConfig object with access to the API server with a token
  53. func CreateWithToken(serverURL, clusterName, userName string, caCert []byte, token string) *clientcmdapi.Config {
  54. config := CreateBasic(serverURL, clusterName, userName, caCert)
  55. config.AuthInfos[userName] = &clientcmdapi.AuthInfo{
  56. Token: token,
  57. }
  58. return config
  59. }
  60. // ClientSetFromFile returns a ready-to-use client from a kubeconfig file
  61. func ClientSetFromFile(path string) (*clientset.Clientset, error) {
  62. config, err := clientcmd.LoadFromFile(path)
  63. if err != nil {
  64. return nil, errors.Wrap(err, "failed to load admin kubeconfig")
  65. }
  66. return ToClientSet(config)
  67. }
  68. // ToClientSet converts a KubeConfig object to a client
  69. func ToClientSet(config *clientcmdapi.Config) (*clientset.Clientset, error) {
  70. clientConfig, err := clientcmd.NewDefaultClientConfig(*config, &clientcmd.ConfigOverrides{}).ClientConfig()
  71. if err != nil {
  72. return nil, errors.Wrap(err, "failed to create API client configuration from kubeconfig")
  73. }
  74. client, err := clientset.NewForConfig(clientConfig)
  75. if err != nil {
  76. return nil, errors.Wrap(err, "failed to create API client")
  77. }
  78. return client, nil
  79. }
  80. // WriteToDisk writes a KubeConfig object down to disk with mode 0600
  81. func WriteToDisk(filename string, kubeconfig *clientcmdapi.Config) error {
  82. err := clientcmd.WriteToFile(*kubeconfig, filename)
  83. if err != nil {
  84. return err
  85. }
  86. return nil
  87. }
  88. // GetClusterFromKubeConfig returns the default Cluster of the specified KubeConfig
  89. func GetClusterFromKubeConfig(config *clientcmdapi.Config) *clientcmdapi.Cluster {
  90. // If there is an unnamed cluster object, use it
  91. if config.Clusters[""] != nil {
  92. return config.Clusters[""]
  93. }
  94. if config.Contexts[config.CurrentContext] != nil {
  95. return config.Clusters[config.Contexts[config.CurrentContext].Cluster]
  96. }
  97. return nil
  98. }
  99. // HasAuthenticationCredentials returns true if the current user has valid authentication credentials for
  100. // token authentication, basic authentication or X509 authentication
  101. func HasAuthenticationCredentials(config *clientcmdapi.Config) bool {
  102. authInfo := getCurrentAuthInfo(config)
  103. if authInfo == nil {
  104. return false
  105. }
  106. // token authentication
  107. if len(authInfo.Token) != 0 {
  108. return true
  109. }
  110. // basic authentication
  111. if len(authInfo.Username) != 0 && len(authInfo.Password) != 0 {
  112. return true
  113. }
  114. // X509 authentication
  115. if (len(authInfo.ClientCertificate) != 0 || len(authInfo.ClientCertificateData) != 0) &&
  116. (len(authInfo.ClientKey) != 0 || len(authInfo.ClientKeyData) != 0) {
  117. return true
  118. }
  119. return false
  120. }
  121. // EnsureAuthenticationInfoAreEmbedded check if some authentication info are provided as external key/certificate
  122. // files, and eventually embeds such files into the kubeconfig file
  123. func EnsureAuthenticationInfoAreEmbedded(config *clientcmdapi.Config) error {
  124. authInfo := getCurrentAuthInfo(config)
  125. if authInfo == nil {
  126. return errors.New("invalid kubeconfig file. AuthInfo is not defined for the current user")
  127. }
  128. if len(authInfo.ClientCertificateData) == 0 && len(authInfo.ClientCertificate) != 0 {
  129. clientCert, err := ioutil.ReadFile(authInfo.ClientCertificate)
  130. if err != nil {
  131. return err
  132. }
  133. authInfo.ClientCertificateData = clientCert
  134. authInfo.ClientCertificate = ""
  135. }
  136. if len(authInfo.ClientKeyData) == 0 && len(authInfo.ClientKey) != 0 {
  137. clientKey, err := ioutil.ReadFile(authInfo.ClientKey)
  138. if err != nil {
  139. return err
  140. }
  141. authInfo.ClientKeyData = clientKey
  142. authInfo.ClientKey = ""
  143. }
  144. return nil
  145. }
  146. // getCurrentAuthInfo returns current authInfo, if defined
  147. func getCurrentAuthInfo(config *clientcmdapi.Config) *clientcmdapi.AuthInfo {
  148. if config == nil || config.CurrentContext == "" ||
  149. len(config.Contexts) == 0 || config.Contexts[config.CurrentContext] == nil {
  150. return nil
  151. }
  152. user := config.Contexts[config.CurrentContext].AuthInfo
  153. if user == "" || len(config.AuthInfos) == 0 || config.AuthInfos[user] == nil {
  154. return nil
  155. }
  156. return config.AuthInfos[user]
  157. }