From 3c7b690cd7ed0489383975454a66da05ba0e90e1 Mon Sep 17 00:00:00 2001 From: corvofeng Date: Sat, 18 May 2024 11:29:59 +0800 Subject: [PATCH] Add support for load kubeconfig. Signed-off-by: corvofeng --- go.mod | 13 ++++ go.sum | 15 +++++ lib/cloud_provider/common.go | 9 ++- lib/cloud_provider/km_aws/eks.go | 29 +++++++++ lib/cloud_provider/km_aws/eks_auth.go | 87 +++++++++++++++++++++++++++ 5 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 lib/cloud_provider/km_aws/eks_auth.go diff --git a/go.mod b/go.mod index aa29979..4e4cd90 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.22.0 toolchain go1.22.2 require ( + github.com/Masterminds/semver v1.5.0 github.com/aws/aws-sdk-go v1.52.5 github.com/jedib0t/go-pretty v4.3.0+incompatible github.com/schollz/progressbar/v3 v3.14.2 @@ -23,7 +24,10 @@ require ( github.com/go-openapi/errors v0.22.0 // indirect github.com/go-openapi/strfmt v0.23.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/gofuzz v1.2.0 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/imdario/mergo v0.3.6 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -37,11 +41,20 @@ require ( github.com/rivo/uniseg v0.4.7 // indirect github.com/spf13/pflag v1.0.5 // indirect go.mongodb.org/mongo-driver v1.14.0 // indirect + golang.org/x/net v0.23.0 // indirect + golang.org/x/oauth2 v0.10.0 // indirect golang.org/x/sys v0.18.0 // indirect golang.org/x/term v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.3.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apimachinery v0.30.0 // indirect k8s.io/klog/v2 v2.120.1 // indirect + k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index e4b9f96..7287be3 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.52.5 h1:m2lty5v9sHm1J3lhA43hJql+yKZudF09qzab0Ag9chM= @@ -22,6 +24,7 @@ github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/ github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= @@ -34,6 +37,8 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= +github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PHJzaeDodcfvRAbIo= @@ -103,11 +108,14 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= +golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -123,9 +131,12 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -134,6 +145,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -148,6 +161,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/api v0.30.0 h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA= +k8s.io/api v0.30.0/go.mod h1:OPlaYhoHs8EQ1ql0R/TsUgaRPhpKNxIMrKQfWUp8QSE= k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA= k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ= diff --git a/lib/cloud_provider/common.go b/lib/cloud_provider/common.go index c6f697a..02a5498 100644 --- a/lib/cloud_provider/common.go +++ b/lib/cloud_provider/common.go @@ -44,8 +44,9 @@ type Cluster struct { Endpoint string CertificateAuthorityData string Status string - GenerateClusterConfig func(cls *Cluster) *clientcmdapi.Cluster - GenerateAuthInfo func(cls *Cluster) *clientcmdapi.AuthInfo + + GenerateClusterConfig func(cls *Cluster) *clientcmdapi.Cluster + GenerateAuthInfo func(cls *Cluster) *clientcmdapi.AuthInfo } func NewCluster() *Cluster { @@ -60,3 +61,7 @@ func defaultGenerateClusterConfig(cls *Cluster) *clientcmdapi.Cluster { cluster.CertificateAuthorityData = []byte(cls.CertificateAuthorityData) return cluster } + +// func (cls *Cluster) GetConfigAuthInfo() *clientcmdapi.AuthInfo { +// return cls.GenerateAuthInfo(cls) +// } diff --git a/lib/cloud_provider/km_aws/eks.go b/lib/cloud_provider/km_aws/eks.go index 56b56b4..690d5cf 100644 --- a/lib/cloud_provider/km_aws/eks.go +++ b/lib/cloud_provider/km_aws/eks.go @@ -19,6 +19,8 @@ import ( "github.com/aws/aws-sdk-go/service/eks/eksiface" log "github.com/sirupsen/logrus" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" ) type AWSProvider struct { @@ -201,5 +203,32 @@ func (c *AWSProvider) ListClusters(regions []string, setProgress func(int)) ([]* setProgress(progress) } } + fmt.Println(allClusters[0]) + c.GenerteClusterConfig(allClusters[0]) return allClusters, nil } +func getConfigContext(ctxName string) *clientcmdapi.Context { + ctx := clientcmdapi.NewContext() + ctx.Cluster = ctxName + ctx.AuthInfo = ctxName + return ctx +} + +func (provider *AWSProvider) GenerteClusterConfig(c *cluster.Cluster) { + + cfg := c.GenerateClusterConfig(c) + + config := clientcmdapi.NewConfig() + config.Clusters["example-cluster"] = cfg + // config.AuthInfos["example-user"] = c.GenerateAuthInfo(c) + config.Contexts["example-context"] = getConfigContext("test") + config.CurrentContext = "example-context" + + err := clientcmd.WriteToFile(*config, "/tmp/kubeconfig") + + if err != nil { + fmt.Println(err) + } + fmt.Println() + +} diff --git a/lib/cloud_provider/km_aws/eks_auth.go b/lib/cloud_provider/km_aws/eks_auth.go new file mode 100644 index 0000000..e3b7901 --- /dev/null +++ b/lib/cloud_provider/km_aws/eks_auth.go @@ -0,0 +1,87 @@ +package km_aws + +import ( + cluster "kubemux/lib/cloud_provider" + "os/exec" + "regexp" + + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + + "github.com/Masterminds/semver" + log "github.com/sirupsen/logrus" +) + +type AuthType int + +const ( + useAWSCLI AuthType = iota + useIAMAuthenticator +) +const ( + commandAWScli = "aws" + commandIAMAuthenticator = "aws-iam-authenticator" +) + +var ( + commands = map[AuthType]string{ + useAWSCLI: commandAWScli, + useIAMAuthenticator: commandIAMAuthenticator, + } + + awsCLIVersionCommand = []string{"aws", "--version"} +) + +func getAuthType() AuthType { + // According to the docs the first version that supports this is 1.18.17 + // See: https://docs.aws.amazon.com/eks/latest/userguide/create-kubeconfig.html + // but looking at the source code the get token is present from 1.16.266 + // See: https://github.com/aws/aws-cli/commits/develop/awscli/customizations/eks/get_token.py + pivotVersion, _ := semver.NewVersion("1.16.266") + currentVersion := getAWSCLIversion(awsCLIVersionCommand) + if currentVersion.LessThan(pivotVersion) { + return useIAMAuthenticator + } + return useAWSCLI +} + +func getAWSCLIversion(cmd []string) *semver.Version { + v, _ := semver.NewVersion("0.0.0") + command := exec.Command(cmd[0], cmd[1:]...) //nolint:gosec + out, err := command.Output() + if err != nil { + log.Warn("Can't get aws cli tool version") + return v + } + r := regexp.MustCompile(`aws-cli\/(?P[0-9]+\.[0-9]+\.[0-9]+)`) + if match := r.FindStringSubmatch(string(out)); len(match) != 0 { + v, _ = semver.NewVersion(match[1]) + log.WithFields(log.Fields{ + "version": v, + }).Info("Found AWS CLI version") + } + return v +} + +const ( + clientAPIVersion = "client.authentication.k8s.io/v1beta1" +) + +var ( + options = map[AuthType][]string{ + useAWSCLI: {"eks", "get-token", "--cluster-name"}, + useIAMAuthenticator: {"token", "-i"}, + } +) + +func getConfigAuthInfo(cls *cluster.Cluster, authType AuthType) *clientcmdapi.AuthInfo { + authInfo := clientcmdapi.NewAuthInfo() + args := make([]string, len(options[authType])) + copy(args, options[authType]) + args = append(args, cls.Name, "--region", cls.Region) + + authInfo.Exec = &clientcmdapi.ExecConfig{ + Command: commands[authType], + Args: args, + APIVersion: clientAPIVersion} + return authInfo +}