Skip to content

Commit

Permalink
refactor: use regular access keys for all vClusters
Browse files Browse the repository at this point in the history
  • Loading branch information
FabianKramm committed Sep 27, 2024
1 parent dcfb601 commit e870345
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 201 deletions.
47 changes: 6 additions & 41 deletions cmd/vclusterctl/cmd/platform/access_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ var (
type AccessKeyCmd struct {
*flags.GlobalFlags

Project string
VirtualCluster string
// deprecated: all of these flags are deprecated
Project string
// deprecated: all of these flags are deprecated
VirtualCluster string
// deprecated: all of these flags are deprecated
DirectClusterEndpoint bool

log log.Logger
Expand Down Expand Up @@ -73,14 +76,7 @@ func (cmd *AccessKeyCmd) Run(ctx context.Context) error {
return err
}

tokenFunc := getToken

if cmd.Project != "" && cmd.VirtualCluster != "" {
cmd.log.Debug("project and virtual cluster set, attempting fetch virtual cluster certificate data")
tokenFunc = getCertificate
}

return tokenFunc(cmd, platformClient)
return getToken(cmd, platformClient)
}

func getToken(_ *AccessKeyCmd, platformClient platform.Client) error {
Expand Down Expand Up @@ -118,34 +114,3 @@ func printToken(token string) error {
_, err = os.Stdout.Write(bytes)
return err
}

func getCertificate(cmd *AccessKeyCmd, platformClient platform.Client) error {
certificateData, keyData, err := platform.VirtualClusterAccessPointCertificate(platformClient, cmd.Project, cmd.VirtualCluster, false)
if err != nil {
return err
}

return printCertificate(certificateData, keyData)
}

func printCertificate(certificateData, keyData string) error {
// Print certificate-based exec credential to stdout
response := &v1beta1.ExecCredential{
TypeMeta: metav1.TypeMeta{
Kind: "ExecCredential",
APIVersion: v1beta1.SchemeGroupVersion.String(),
},
Status: &v1beta1.ExecCredentialStatus{
ClientCertificateData: certificateData,
ClientKeyData: keyData,
},
}

bytes, err := json.Marshal(response)
if err != nil {
return fmt.Errorf("json marshal: %w", err)
}

_, err = os.Stdout.Write(bytes)
return err
}
1 change: 0 additions & 1 deletion pkg/cli/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ func New() *CLI {
Kind: "Config",
APIVersion: "storage.loft.sh/v1",
},
VirtualClusterAccessPointCertificates: make(map[string]VirtualClusterCertificatesEntry),
},
}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/connect_platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func (cmd *connectPlatform) getVClusterKubeConfig(ctx context.Context, platformC
}

// make sure access key is set
if contextOptions.Token == "" && len(contextOptions.ClientCertificateData) == 0 && len(contextOptions.ClientKeyData) == 0 {
if contextOptions.Token == "" {
contextOptions.Token = platformClient.Config().Platform.AccessKey
}

Expand Down
4 changes: 1 addition & 3 deletions pkg/platform/clihelper/clihelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,8 @@ func GetProKubeConfig(options kubeconfig.ContextOptions) (*clientcmdapi.Config,
cluster.InsecureSkipTLSVerify = options.InsecureSkipTLSVerify

authInfo := clientcmdapi.NewAuthInfo()
if options.Token != "" || options.ClientCertificateData != nil || options.ClientKeyData != nil {
if options.Token != "" {
authInfo.Token = options.Token
authInfo.ClientKeyData = options.ClientKeyData
authInfo.ClientCertificateData = options.ClientCertificateData
}

config := clientcmdapi.NewConfig()
Expand Down
131 changes: 6 additions & 125 deletions pkg/platform/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,19 @@ import (
"github.com/loft-sh/api/v4/pkg/clientset/versioned/scheme"
"github.com/loft-sh/log"
"github.com/loft-sh/log/survey"
"github.com/loft-sh/vcluster/pkg/cli/config"
"github.com/loft-sh/vcluster/pkg/platform/clihelper"
"github.com/loft-sh/vcluster/pkg/platform/kube"
"github.com/loft-sh/vcluster/pkg/platform/kubeconfig"
"github.com/loft-sh/vcluster/pkg/platform/sleepmode"
"github.com/loft-sh/vcluster/pkg/projectutil"
"github.com/loft-sh/vcluster/pkg/util"
perrors "github.com/pkg/errors"
"gopkg.in/yaml.v2"
authorizationv1 "k8s.io/api/authorization/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/kubectl/pkg/util/term"
"k8s.io/utils/ptr"
crclient "sigs.k8s.io/controller-runtime/pkg/client"
)

Expand Down Expand Up @@ -690,44 +686,14 @@ func CreateVirtualClusterInstanceOptions(ctx context.Context, client Client, con
ConfigPath: config,
SetActive: setActive,
}
if virtualClusterInstance.Status.VirtualCluster != nil && virtualClusterInstance.Status.VirtualCluster.AccessPoint.Ingress.Enabled {
kubeConfig, err := getVirtualClusterInstanceAccessConfig(ctx, client, virtualClusterInstance)
if err != nil {
return kubeconfig.ContextOptions{}, fmt.Errorf("retrieve kube config %w", err)
}

// get server
for _, val := range kubeConfig.Clusters {
if val != nil {
contextOptions.Server = val.Server
}
}

if len(kubeConfig.AuthInfos) == 0 {
return kubeconfig.ContextOptions{}, errors.New("ingress access is configured but no credentials were present in the kubeconfig")
}
// find the first user and fill cert data with it
for _, v := range kubeConfig.AuthInfos {
contextOptions.ClientCertificateData = v.ClientCertificateData
contextOptions.ClientKeyData = v.ClientKeyData
break
}
if contextOptions.Server == "" {
return kubeconfig.ContextOptions{}, errors.New("could not determine server url")
}

contextOptions.InsecureSkipTLSVerify = true
contextOptions.VirtualClusterAccessPointEnabled = true
} else {
contextOptions.Server = client.Config().Platform.Host + "/kubernetes/project/" + projectName + "/virtualcluster/" + virtualClusterInstance.Name
contextOptions.InsecureSkipTLSVerify = client.Config().Platform.Insecure
contextOptions.Server = client.Config().Platform.Host + "/kubernetes/project/" + projectName + "/virtualcluster/" + virtualClusterInstance.Name
contextOptions.InsecureSkipTLSVerify = client.Config().Platform.Insecure

data, err := RetrieveCaData(cluster)
if err != nil {
return kubeconfig.ContextOptions{}, err
}
contextOptions.CaData = data
data, err := RetrieveCaData(cluster)
if err != nil {
return kubeconfig.ContextOptions{}, err
}
contextOptions.CaData = data
return contextOptions, nil
}

Expand All @@ -754,59 +720,6 @@ func CreateSpaceInstanceOptions(ctx context.Context, client Client, config strin
return contextOptions, nil
}

func VirtualClusterAccessPointCertificate(client Client, project, virtualCluster string, forceRefresh bool) (string, string, error) {
contextName := kubeconfig.VirtualClusterInstanceContextName(project, virtualCluster)

// see if we have stored cert data for this vci
now := metav1.Now()
cachedVirtualClusterAccessPointCertificate, ok := client.Config().Platform.VirtualClusterAccessPointCertificates[contextName]
if !forceRefresh && ok && cachedVirtualClusterAccessPointCertificate.LastRequested.Add(RefreshToken).After(now.Time) && cachedVirtualClusterAccessPointCertificate.ExpirationTime.After(now.Time) {
return cachedVirtualClusterAccessPointCertificate.CertificateData, cachedVirtualClusterAccessPointCertificate.KeyData, nil
}

// refresh token
managementClient, err := client.Management()
if err != nil {
return "", "", err
}

kubeConfigResponse, err := managementClient.Loft().ManagementV1().VirtualClusterInstances(projectutil.ProjectNamespace(project)).GetKubeConfig(
context.Background(),
virtualCluster,
&managementv1.VirtualClusterInstanceKubeConfig{
Spec: managementv1.VirtualClusterInstanceKubeConfigSpec{
CertificateTTL: ptr.To[int32](86_400),
},
},
metav1.CreateOptions{},
)
if err != nil {
return "", "", perrors.Wrap(err, "fetch certificate data")
}

certificateData, keyData, err := getCertificateAndKeyDataFromKubeConfig(kubeConfigResponse.Status.KubeConfig)
if err != nil {
return "", "", err
}

if client.Config().Platform.VirtualClusterAccessPointCertificates == nil {
client.Config().Platform.VirtualClusterAccessPointCertificates = make(map[string]config.VirtualClusterCertificatesEntry)
}
client.Config().Platform.VirtualClusterAccessPointCertificates[contextName] = config.VirtualClusterCertificatesEntry{
CertificateData: certificateData,
KeyData: keyData,
LastRequested: now,
ExpirationTime: now.Add(86_400 * time.Second),
}

err = client.Save()
if err != nil {
return "", "", perrors.Wrap(err, "save config")
}

return certificateData, keyData, nil
}

func ResolveVirtualClusterTemplate(
ctx context.Context,
client Client,
Expand Down Expand Up @@ -1279,38 +1192,6 @@ func getCertificateAndKeyDataFromKubeConfig(config string) (string, string, erro
return string(authInfo.ClientCertificateData), string(authInfo.ClientKeyData), nil
}

func getVirtualClusterInstanceAccessConfig(ctx context.Context, client Client, virtualClusterInstance *managementv1.VirtualClusterInstance) (clientcmdapi.Config, error) {
managementClient, err := client.Management()
if err != nil {
return clientcmdapi.Config{}, err
}

kubeConfig, err := managementClient.Loft().ManagementV1().VirtualClusterInstances(virtualClusterInstance.Namespace).GetKubeConfig(
ctx,
virtualClusterInstance.Name,
&managementv1.VirtualClusterInstanceKubeConfig{
Spec: managementv1.VirtualClusterInstanceKubeConfigSpec{},
},
metav1.CreateOptions{},
)
if err != nil {
return clientcmdapi.Config{}, err
}

// parse kube config string
clientCfg, err := clientcmd.NewClientConfigFromBytes([]byte(kubeConfig.Status.KubeConfig))
if err != nil {
return clientcmdapi.Config{}, err
}

apiCfg, err := clientCfg.RawConfig()
if err != nil {
return clientcmdapi.Config{}, err
}

return apiCfg, nil
}

func findProjectCluster(ctx context.Context, client Client, projectName, clusterName string) (*managementv1.Cluster, error) {
managementClient, err := client.Management()
if err != nil {
Expand Down
42 changes: 12 additions & 30 deletions pkg/platform/kubeconfig/kubeconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,13 @@ import (
)

type ContextOptions struct {
Name string
Server string
CaData []byte
ConfigPath string
InsecureSkipTLSVerify bool
DirectClusterEndpointEnabled bool
VirtualClusterAccessPointEnabled bool

Token string
ClientKeyData []byte
ClientCertificateData []byte
Name string
Server string
CaData []byte
ConfigPath string
InsecureSkipTLSVerify bool

Token string

CurrentNamespace string
SetActive bool
Expand Down Expand Up @@ -237,10 +233,8 @@ func createContext(options ContextOptions) (string, *api.Cluster, *api.AuthInfo,
cluster.InsecureSkipTLSVerify = options.InsecureSkipTLSVerify

authInfo := api.NewAuthInfo()
if options.Token != "" || options.ClientCertificateData != nil || options.ClientKeyData != nil {
if options.Token != "" {
authInfo.Token = options.Token
authInfo.ClientKeyData = options.ClientKeyData
authInfo.ClientCertificateData = options.ClientCertificateData
} else {
command, err := os.Executable()
if err != nil {
Expand All @@ -252,22 +246,10 @@ func createContext(options ContextOptions) (string, *api.Cluster, *api.AuthInfo,
return "", nil, nil, err
}

if options.VirtualClusterAccessPointEnabled {
projectName, virtualClusterName := virtualClusterInstanceProjectAndNameFromContextName(contextName)
authInfo.Exec = &api.ExecConfig{
APIVersion: v1beta1.SchemeGroupVersion.String(),
Command: command,
Args: []string{"platform", "token", "--silent", "--project", projectName, "--virtual-cluster", virtualClusterName},
}
} else {
authInfo.Exec = &api.ExecConfig{
APIVersion: v1beta1.SchemeGroupVersion.String(),
Command: command,
Args: []string{"platform", "token", "--silent", "--config", absConfigPath},
}
if options.DirectClusterEndpointEnabled {
authInfo.Exec.Args = append(authInfo.Exec.Args, "--direct-cluster-endpoint")
}
authInfo.Exec = &api.ExecConfig{
APIVersion: v1beta1.SchemeGroupVersion.String(),
Command: command,
Args: []string{"platform", "token", "--silent", "--config", absConfigPath},
}
}

Expand Down

0 comments on commit e870345

Please sign in to comment.