github.com/SUSE/skuba@v1.4.17/pkg/skuba/actions/auth/login.go (about) 1 /* 2 * Copyright (c) 2019 SUSE LLC. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 package auth 19 20 import ( 21 "bufio" 22 "fmt" 23 "io/ioutil" 24 "net/url" 25 "os" 26 27 "github.com/pkg/errors" 28 clientcmdapi "k8s.io/client-go/tools/clientcmd/api" 29 clientcmdlatest "k8s.io/client-go/tools/clientcmd/api/latest" 30 ) 31 32 const ( 33 clientID = "oidc-cli" 34 clientSecret = "swac7qakes7AvucH8bRucucH" 35 36 authProviderID = "oidc" 37 ) 38 39 const ( 40 defaultScheme = "https" 41 42 defaultAPIServerPort = "6443" 43 ) 44 45 // LoginConfig represents the login configuration 46 type LoginConfig struct { 47 DexServer string 48 Username string 49 Password string 50 RootCAPath string 51 InsecureSkipVerify bool 52 AuthConnector string 53 ClusterName string 54 KubeConfigPath string 55 Debug bool 56 } 57 58 // Login do authentication login process 59 func Login(cfg LoginConfig) (*clientcmdapi.Config, error) { 60 var err error 61 var rootCAData []byte 62 63 if !cfg.InsecureSkipVerify && cfg.RootCAPath != "" { 64 rootCAData, err = ioutil.ReadFile(cfg.RootCAPath) 65 if err != nil { 66 return nil, errors.Wrap(err, "read CA failed") 67 } 68 } 69 70 url, err := url.Parse(cfg.DexServer) 71 if err != nil { 72 return nil, errors.Wrap(err, "parse url") 73 } 74 75 authResp, err := doAuth(request{ 76 clientID: clientID, 77 clientSecret: clientSecret, 78 IssuerURL: cfg.DexServer, 79 Username: cfg.Username, 80 Password: cfg.Password, 81 RootCAData: rootCAData, 82 InsecureSkipVerify: cfg.InsecureSkipVerify, 83 AuthConnector: cfg.AuthConnector, 84 Debug: cfg.Debug, 85 }) 86 if err != nil { 87 return nil, errors.Wrap(err, "auth failed") 88 } 89 90 // fill out clusters 91 kubeConfig := clientcmdapi.NewConfig() 92 kubeConfig.Clusters[cfg.ClusterName] = &clientcmdapi.Cluster{ 93 Server: fmt.Sprintf("%s://%s:%s", defaultScheme, url.Hostname(), defaultAPIServerPort), // Guess kube-apiserver on port 6443 94 InsecureSkipTLSVerify: cfg.InsecureSkipVerify, 95 CertificateAuthorityData: rootCAData, 96 } 97 98 // fill out contexts 99 kubeConfig.Contexts[cfg.ClusterName] = &clientcmdapi.Context{ 100 Cluster: cfg.ClusterName, 101 AuthInfo: cfg.Username, 102 } 103 kubeConfig.CurrentContext = cfg.ClusterName 104 105 // fill out auth infos 106 kubeConfig.AuthInfos[cfg.Username] = &clientcmdapi.AuthInfo{ 107 AuthProvider: &clientcmdapi.AuthProviderConfig{ 108 Name: authProviderID, 109 Config: map[string]string{ 110 "idp-issuer-url": cfg.DexServer, 111 "client-id": clientID, 112 "client-secret": clientSecret, 113 "id-token": authResp.IDToken, 114 "refresh-token": authResp.RefreshToken, 115 }, 116 }, 117 } 118 119 return kubeConfig, nil 120 } 121 122 // SaveKubeconfig saves kubeconfig to filename 123 func SaveKubeconfig(filename string, kubeConfig *clientcmdapi.Config) error { 124 f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) 125 if err != nil { 126 return errors.Wrap(err, "open file") 127 } 128 defer f.Close() 129 w := bufio.NewWriter(f) 130 131 err = clientcmdlatest.Codec.Encode(kubeConfig, w) 132 if err != nil { 133 return errors.Wrap(err, "encode kubeconfig") 134 } 135 136 w.Flush() 137 return nil 138 }