mirror of
https://github.com/kubevela/kubevela.git
synced 2026-02-14 18:10:21 +00:00
Feat: support token retrieval via AuthInfo.Exec command (#6721)
Signed-off-by: co_gwre <co@guidewire.com> Co-authored-by: co_gwre <co@guidewire.com>
This commit is contained in:
committed by
GitHub
parent
c48ded1994
commit
d9fcebb9e8
@@ -19,7 +19,10 @@ package multicluster
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -125,10 +128,20 @@ func (clusterConfig *KubeClusterConfig) createOrUpdateClusterSecret(ctx context.
|
||||
data["ca.crt"] = clusterConfig.Cluster.CertificateAuthorityData
|
||||
}
|
||||
}
|
||||
if len(clusterConfig.AuthInfo.Token) > 0 {
|
||||
switch {
|
||||
case len(clusterConfig.AuthInfo.Token) > 0:
|
||||
credentialType = clusterv1alpha1.CredentialTypeServiceAccountToken
|
||||
data["token"] = []byte(clusterConfig.AuthInfo.Token)
|
||||
} else {
|
||||
|
||||
case clusterConfig.AuthInfo.Exec != nil:
|
||||
token, err := getTokenFromExec(clusterConfig.AuthInfo.Exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
credentialType = clusterv1alpha1.CredentialTypeServiceAccountToken
|
||||
data["token"] = []byte(token)
|
||||
|
||||
default:
|
||||
credentialType = clusterv1alpha1.CredentialTypeX509Certificate
|
||||
data["tls.crt"] = clusterConfig.AuthInfo.ClientCertificateData
|
||||
data["tls.key"] = clusterConfig.AuthInfo.ClientKeyData
|
||||
@@ -598,3 +611,54 @@ func getMutableClusterSecret(ctx context.Context, c client.Client, clusterName s
|
||||
}
|
||||
return clusterSecret, nil
|
||||
}
|
||||
|
||||
func getTokenFromExec(execConfig *clientcmdapi.ExecConfig) (string, error) {
|
||||
// #nosec G204 -- This is intentionally running an exec command with user-provided input
|
||||
// The execConfig comes from the kubeconfig which should be trusted in this context
|
||||
|
||||
cmdPath := execConfig.Command
|
||||
if strings.Contains(cmdPath, "..") {
|
||||
return "", fmt.Errorf("command path must not contain '..'")
|
||||
}
|
||||
|
||||
if strings.ContainsAny(cmdPath, "$;&|<>\"'\\") {
|
||||
return "", fmt.Errorf("command must not contain shell metacharacters")
|
||||
}
|
||||
|
||||
for _, arg := range execConfig.Args {
|
||||
if strings.ContainsAny(arg, "$;&|<>\\") {
|
||||
return "", fmt.Errorf("arguments must not contain shell metacharacters")
|
||||
}
|
||||
}
|
||||
|
||||
cmd := exec.Command(cmdPath, execConfig.Args...) // #nosec G204
|
||||
|
||||
env := os.Environ()
|
||||
for _, e := range execConfig.Env {
|
||||
if strings.ContainsAny(e.Name, "=$;\n") || strings.ContainsAny(e.Value, "\n") {
|
||||
return "", fmt.Errorf("environment variable names and values must not contain control characters")
|
||||
}
|
||||
env = append(env, fmt.Sprintf("%s=%s", e.Name, e.Value))
|
||||
}
|
||||
cmd.Env = env
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to execute auth command: %w", err)
|
||||
}
|
||||
|
||||
var execCredential struct {
|
||||
Status struct {
|
||||
Token string `json:"token"`
|
||||
} `json:"status"`
|
||||
}
|
||||
if err := json.Unmarshal(output, &execCredential); err != nil {
|
||||
return "", fmt.Errorf("failed to parse exec command output: %w", err)
|
||||
}
|
||||
|
||||
if execCredential.Status.Token == "" {
|
||||
return "", fmt.Errorf("token not found in exec command output")
|
||||
}
|
||||
|
||||
return execCredential.Status.Token, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user