Skip to content

Commit

Permalink
Refactor kubeconfig token replace logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Anna Blendermann committed Jul 13, 2023
1 parent 81f30cd commit 28eb62b
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 128 deletions.
76 changes: 39 additions & 37 deletions rancher2/resource_rancher2_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -528,9 +528,9 @@ func clusterStateRefreshFunc(client *managementClient.Client, clusterID string)
// The IsForbidden check is used in the case the user performing the action does not have the
// right to retrieve the full list of clusters. If the user tries to retrieve the cluster that
// just got deleted, instead of getting a 404 not found response it will get a 403 forbidden
// eventhough it had the right to access the cluster before it was deleted. If we reach this
// even though it had the right to access the cluster before it was deleted. If we reach this
// code path, it means that the user had the right to access the cluster, delete it, hence
// meaning that the delete was successful.
// meaning that delete was successful.
if IsNotFound(err) || IsForbidden(err) {
return obj, "removed", nil
}
Expand Down Expand Up @@ -636,7 +636,7 @@ func isKubeConfigValid(c *Config, config string) (string, bool, error) {
}
kubeconfig, err := clientcmd.RESTConfigFromKubeConfig([]byte(config))
if err != nil {
return "", false, fmt.Errorf("Checking Kubeconfig: %v", err)
return "", false, fmt.Errorf("checking Kubeconfig: %v", err)
}
_, err = kubernetes.NewForConfig(kubeconfig)
if err != nil {
Expand All @@ -649,72 +649,74 @@ func isKubeConfigValid(c *Config, config string) (string, bool, error) {
func isKubeConfigTokenValid(c *Config, config string) (string, bool, error) {
token, err := getTokenFromKubeConfig(config)
if err != nil {
return "", false, fmt.Errorf("Getting Kubeconfig token: %v", err)
return "", false, fmt.Errorf("getting Kubeconfig token: %v", err)
}
isValid, err := isTokenValid(c, splitTokenID(token))
if err != nil {
return "", false, fmt.Errorf("Checking Kubeconfig token: %v", err)
return "", false, fmt.Errorf("checking Kubeconfig token: %v", err)
}
return token, isValid, nil
}

func replaceKubeConfigToken(c *Config, config, token string) (string, error) {
if len(token) == 0 {
return config, nil
}
func replaceKubeConfigToken(c *Config, config string) (string, error) {
kubeconfig, err := getObjFromKubeConfig(config)
if err != nil {
return "", fmt.Errorf("Getting K8s config object: %v", err)
return "", fmt.Errorf("getting K8s config object: %v", err)
}
if kubeconfig == nil || kubeconfig.AuthInfos == nil || len(kubeconfig.AuthInfos) == 0 {
return config, nil
}

client, err := c.ManagementClient()
if err != nil {
return "", fmt.Errorf("Replacing cluster Kubeconfig token: %v", err)
return "", fmt.Errorf("replacing cluster Kubeconfig token: %v", err)
}
removeToken, err := client.Token.ByID(splitTokenID(kubeconfig.AuthInfos[0].AuthInfo.Token))
if err != nil {

// if cached token is corrupt, ByID will fail and the token can't be
// retrieved or cleaned up
currentToken, err := client.Token.ByID(splitTokenID(kubeconfig.AuthInfos[0].AuthInfo.Token))
if err != nil || currentToken.Expired {
if !IsNotFound(err) && !IsForbidden(err) {
return "", err
}
// client can't find the token or token has expired, so create
// a new one
currentToken, err = client.Token.Create(currentToken)
if err != nil {
return "", fmt.Errorf("error creating Token: %s", err)
}
}

err = client.Token.Delete(removeToken)
if err != nil {
return "", fmt.Errorf("Error removing Token: %s", err)
}
kubeconfig.AuthInfos[0].AuthInfo.Token = token
kubeconfig.AuthInfos[0].AuthInfo.Token = currentToken.Token
return getKubeConfigFromObj(kubeconfig)
}

func getClusterKubeconfig(c *Config, id, origconfig string) (*managementClient.GenerateKubeConfigOutput, error) {
action := "generateKubeconfig"
cluster := &Cluster{}

token, kubeValid, err := isKubeConfigValid(c, origconfig)
if err != nil {
return nil, fmt.Errorf("Getting cluster Kubeconfig: %v", err)
}
// kubeconfig is not valid due to an invalid token. Use the cached kubeconfig
// and replace the token
if !kubeValid && len(token) == 0 {
newConfig, err := replaceKubeConfigToken(c, origconfig, token)
// kubeconfig already exists in the cache
if len(origconfig) > 0 {
token, kubeValid, err := isKubeConfigValid(c, origconfig)
if err != nil {
return nil, err
return nil, fmt.Errorf("getting cluster Kubeconfig: %v", err)
}
if kubeValid {
return &managementClient.GenerateKubeConfigOutput{Config: origconfig}, nil
} else if len(token) == 0 {
// if token is zero length, token is not valid or expired so replace it
// in the cached kubeconfig
newConfig, err := replaceKubeConfigToken(c, origconfig)
if err != nil {
return nil, err
}
return &managementClient.GenerateKubeConfigOutput{Config: newConfig}, nil
}
origconfig = newConfig
kubeValid = true
}
if kubeValid {
return &managementClient.GenerateKubeConfigOutput{Config: origconfig}, nil
}

// kubeconfig is not valid for other reasons, download a new one
// kubeconfig is not cached or invalid for other reasons, download a new one
client, err := c.ManagementClient()
if err != nil {
return nil, fmt.Errorf("Getting cluster Kubeconfig: %v", err)
return nil, fmt.Errorf("getting cluster Kubeconfig: %v", err)
}

ctx, cancel := context.WithTimeout(context.Background(), c.Timeout)
Expand All @@ -723,7 +725,7 @@ func getClusterKubeconfig(c *Config, id, origconfig string) (*managementClient.G
err = client.APIBaseClient.ByID(managementClient.ClusterType, id, cluster)
if err != nil {
if !IsNotFound(err) && !IsForbidden(err) && !IsServiceUnavailableError(err) {
return nil, fmt.Errorf("Getting cluster Kubeconfig: %v", err)
return nil, fmt.Errorf("getting cluster Kubeconfig: %v", err)
}
} else if len(cluster.Actions[action]) > 0 {
isRancher26, err := c.IsRancherVersionGreaterThanOrEqual("2.6.0")
Expand All @@ -749,7 +751,7 @@ func getClusterKubeconfig(c *Config, id, origconfig string) (*managementClient.G
}
if err != nil {
if !IsNotFound(err) && !IsForbidden(err) && !IsServiceUnavailableError(err) {
return nil, fmt.Errorf("Getting cluster Kubeconfig: %w", err)
return nil, fmt.Errorf("getting cluster Kubeconfig: %w", err)
}
}
}
Expand Down
91 changes: 0 additions & 91 deletions rancher2/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"math/rand"
"net/http"
"net/url"
"os"
"reflect"
"sort"
"strings"
Expand All @@ -34,13 +33,6 @@ const (
maxHTTPRedirect = 5
)

func getMax(a, b int) int {
if a > b {
return a
}
return b
}

func AreEqual(o, n interface{}) bool {
return reflect.DeepEqual(o, n)
}
Expand All @@ -63,11 +55,6 @@ func Base64Decode(s string) (string, error) {
return string(data), err
}

func IsBase64(s string) bool {
_, err := base64.StdEncoding.DecodeString(s)
return err == nil
}

func getKubeConfigFromObj(kubeconfig *kubeconfig.Config) (string, error) {
if kubeconfig == nil {
return "", nil
Expand Down Expand Up @@ -116,34 +103,6 @@ func getTokenFromKubeConfig(config string) (string, error) {
return kubeconfig.AuthInfos[0].AuthInfo.Token, nil
}

func getTokenIDFromKubeConfig(config string) (string, error) {
token, err := getTokenFromKubeConfig(config)
if err != nil {
return "", err
}
return splitTokenID(token), nil

}

func updateKubeConfigToken(config, token string) (string, error) {
if len(token) == 0 {
return config, nil
}
if len(config) == 0 {
return "", nil
}
kubeconfig := &kubeconfig.Config{}
err := jsonToInterface(config, kubeconfig)
if err != nil {
return "", err
}
if kubeconfig == nil || kubeconfig.AuthInfos == nil || len(kubeconfig.AuthInfos) == 0 {
return "", nil
}

return kubeconfig.AuthInfos[0].AuthInfo.Token, nil
}

func TrimSpace(val interface{}) string {
return strings.TrimSpace(val.(string))
}
Expand Down Expand Up @@ -571,19 +530,6 @@ func toMapString(in map[string]interface{}) map[string]string {
return out
}

func toMapByte(in map[string]interface{}) map[string][]byte {
out := make(map[string][]byte)
for i, v := range in {
if v == nil {
out[i] = []byte{}
continue
}
value := v.(string)
out[i] = []byte(value)
}
return out
}

func toMapInterface(in map[string]string) map[string]interface{} {
out := make(map[string]interface{})
for i, v := range in {
Expand Down Expand Up @@ -711,43 +657,6 @@ func interfaceToGhodssyaml(in interface{}) (string, error) {
return string(out), err
}

func YAMLToJSON(in string) (string, error) {
if len(in) == 0 {
return "", nil
}
out, err := ghodssyaml.YAMLToJSON([]byte(in))
if err != nil {
return "", err
}
return string(out), nil
}

func JSONToYAML(in string) (string, error) {
if len(in) == 0 {
return "", nil
}
out, err := ghodssyaml.JSONToYAML([]byte(in))
if err != nil {
return "", err
}
return string(out), nil
}

func FileExist(path string) (bool, error) {
if path == "" {
return false, nil
}
_, err := os.Stat(path)

if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
return true, nil
}

func newString(value string) *string {
return &value
}
Expand Down

0 comments on commit 28eb62b

Please sign in to comment.