Skip to content

Commit

Permalink
Refactor util files
Browse files Browse the repository at this point in the history
  • Loading branch information
anusha94 committed Jun 10, 2022
1 parent 46412e6 commit 4b8e45c
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 71 deletions.
79 changes: 79 additions & 0 deletions common/bootstraptoken/token.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package bootstraptoken

import (
"fmt"
"time"

v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
restclient "k8s.io/client-go/rest"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
bootstraputil "k8s.io/cluster-bootstrap/token/util"
)

func GetTokenIDSecretFromBootstrapTokenStr(tokenStr string) (string, string, error) {
substrs := bootstraputil.BootstrapTokenRegexp.FindStringSubmatch(tokenStr)
if len(substrs) != 3 { // nolint: gomnd
return "", "", fmt.Errorf("the bootstrap token %q was not of the form %q", tokenStr, bootstrapapi.BootstrapTokenPattern)
}
tokenID := substrs[1]
tokenSecret := substrs[2]

return tokenID, tokenSecret, nil
}

func GenerateSecretFromBootstrapTokenStr(tokenStr string, ttl time.Duration) (*v1.Secret, error) {
tokenID, tokenSecret, err := GetTokenIDSecretFromBootstrapTokenStr(tokenStr)
if err != nil {
return nil, err
}
secretData := map[string][]byte{
bootstrapapi.BootstrapTokenIDKey: []byte(tokenID),
bootstrapapi.BootstrapTokenSecretKey: []byte(tokenSecret),
bootstrapapi.BootstrapTokenExpirationKey: []byte(time.Now().UTC().Add(ttl).Format(time.RFC3339)),
bootstrapapi.BootstrapTokenDescriptionKey: []byte("jsdj"),
bootstrapapi.BootstrapTokenExtraGroupsKey: []byte("system:bootstrappers:byoh"),
bootstrapapi.BootstrapTokenUsageSigningKey: []byte("true"),
bootstrapapi.BootstrapTokenUsageAuthentication: []byte("true"),
}

bootstrapSecret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: bootstraputil.BootstrapTokenSecretName(tokenID),
Namespace: metav1.NamespaceSystem,
},
Type: bootstrapapi.SecretTypeBootstrapToken,
Data: secretData,
}
return bootstrapSecret, nil
}

func GenerateBootstrapKubeconfigFromBootstrapToken(clientConfig *restclient.Config, tokenStr string) (*clientcmdapi.Config, error) {
tokenID, tokenSecret, err := GetTokenIDSecretFromBootstrapTokenStr(tokenStr)
if err != nil {
return nil, err
}
// Build resulting kubeconfig.
kubeconfigData := clientcmdapi.Config{
// Define a cluster stanza based on the bootstrap kubeconfig.
Clusters: map[string]*clientcmdapi.Cluster{"default-cluster": {
Server: clientConfig.Host,
InsecureSkipTLSVerify: clientConfig.Insecure,
CertificateAuthorityData: clientConfig.CAData,
}},
// Define auth based on the obtained client cert.
AuthInfos: map[string]*clientcmdapi.AuthInfo{"default-auth": {
Token: fmt.Sprintf(tokenID + "." + tokenSecret),
}},
// Define a context that connects the auth info and cluster, and set it as the default
Contexts: map[string]*clientcmdapi.Context{"default-context": {
Cluster: "default-cluster",
AuthInfo: "default-auth",
Namespace: "default",
}},
CurrentContext: "default-context",
}

return &kubeconfigData, nil
}
14 changes: 14 additions & 0 deletions common/encoder/decoder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2022 VMware, Inc. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package encoder

import (
"encoding/base64"
"encoding/json"
"strings"
)

func DecodeFromBase64(v interface{}, enc string) error {
return json.NewDecoder(base64.NewDecoder(base64.StdEncoding, strings.NewReader(enc))).Decode(v)
}
21 changes: 21 additions & 0 deletions common/encoder/encoder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2022 VMware, Inc. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package encoder

import (
"bytes"
"encoding/base64"
"encoding/json"
)

func EncodeToBase64(v interface{}) (string, error) {
var buf bytes.Buffer
encoder := base64.NewEncoder(base64.StdEncoding, &buf)
err := json.NewEncoder(encoder).Encode(v)
if err != nil {
return "", err
}
encoder.Close()
return buf.String(), nil
}
18 changes: 0 additions & 18 deletions common/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,9 @@ package common
import (
"bytes"
"compress/gzip"
"encoding/base64"
"encoding/json"
"io"
"os"
"path/filepath"
"strings"

"github.com/pkg/errors"
)
Expand Down Expand Up @@ -69,18 +66,3 @@ func RemoveGlob(path string) error {
}
return nil
}

func EncodeToBase64(v interface{}) (string, error) {
var buf bytes.Buffer
encoder := base64.NewEncoder(base64.StdEncoding, &buf)
err := json.NewEncoder(encoder).Encode(v)
if err != nil {
return "", err
}
encoder.Close()
return buf.String(), nil
}

func DecodeFromBase64(v interface{}, enc string) error {
return json.NewDecoder(base64.NewDecoder(base64.StdEncoding, strings.NewReader(enc))).Decode(v)
}
65 changes: 14 additions & 51 deletions controllers/infrastructure/bootstrapkubeconfig_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@ package controllers

import (
"context"
"fmt"
"time"

infrastructurev1beta1 "github.com/vmware-tanzu/cluster-api-provider-bringyourownhost/apis/infrastructure/v1beta1"
"github.com/vmware-tanzu/cluster-api-provider-bringyourownhost/common"
v1 "k8s.io/api/core/v1"
"github.com/vmware-tanzu/cluster-api-provider-bringyourownhost/common/bootstraptoken"
"github.com/vmware-tanzu/cluster-api-provider-bringyourownhost/common/encoder"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/rest"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
bootstraputil "k8s.io/cluster-bootstrap/token/util"
"sigs.k8s.io/cluster-api/util/patch"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -57,63 +54,29 @@ func (r *BootstrapKubeconfigReconciler) Reconcile(ctx context.Context, req ctrl.
if err != nil {
return ctrl.Result{}, nil
}
substrs := bootstraputil.BootstrapTokenRegexp.FindStringSubmatch(tokenStr)
tokenID := substrs[1]
tokenSecret := substrs[2]

data := map[string][]byte{
bootstrapapi.BootstrapTokenIDKey: []byte(tokenID),
bootstrapapi.BootstrapTokenSecretKey: []byte(tokenSecret),
bootstrapKubeconfigSecret, err := bootstraptoken.GenerateSecretFromBootstrapTokenStr(tokenStr, time.Minute*30)
if err != nil {
return ctrl.Result{}, nil
}
description := "BYOH controller generated bootstrap token"
data["Description"] = []byte(description)
// for _, usage := range token.Usages {
// data[bootstrapapi.BootstrapTokenUsagePrefix+usage] = []byte("true")
// }
data[bootstrapapi.BootstrapTokenExtraGroupsKey] = []byte("system:bootstrappers:byoh")

bootstrapSecret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: bootstraputil.BootstrapTokenSecretName(tokenID),
Namespace: metav1.NamespaceSystem,
},
Type: bootstrapapi.SecretTypeBootstrapToken,
Data: data,
// create secret
err = r.Client.Create(ctx, bootstrapKubeconfigSecret)
if err != nil {
return ctrl.Result{}, nil
}

// TODO: check if secret with name already exists
// if exists, maybe update the secret?
err = r.Client.Create(ctx, bootstrapSecret)
bootstrapKubeconfigData, err := bootstraptoken.GenerateBootstrapKubeconfigFromBootstrapToken(r.Config, tokenStr)
if err != nil {
return ctrl.Result{}, err
return ctrl.Result{}, nil
}

// Build resulting kubeconfig.
kubeconfigData := clientcmdapi.Config{
// Define a cluster stanza based on the bootstrap kubeconfig.
Clusters: map[string]*clientcmdapi.Cluster{"default-cluster": {
Server: r.Config.Host,
InsecureSkipTLSVerify: r.Config.Insecure,
CertificateAuthorityData: r.Config.CAData,
}},
// Define auth based on the obtained client cert.
AuthInfos: map[string]*clientcmdapi.AuthInfo{"default-auth": {
Token: fmt.Sprintf(tokenID + "." + tokenSecret),
}},
// Define a context that connects the auth info and cluster, and set it as the default
Contexts: map[string]*clientcmdapi.Context{"default-context": {
Cluster: "default-cluster",
AuthInfo: "default-auth",
Namespace: "default",
}},
CurrentContext: "default-context",
}
encodedKubeConfig, err := common.EncodeToBase64(kubeconfigData)
encodedBootstrapKubeConfig, err := encoder.EncodeToBase64(bootstrapKubeconfigData)
helper, err := patch.NewHelper(bootstrapKubeconfig, r.Client)
if err != nil {
return ctrl.Result{}, err
}
bootstrapKubeconfig.Status.BootstrapKubeconfigData = encodedKubeConfig
bootstrapKubeconfig.Status.BootstrapKubeconfigData = encodedBootstrapKubeConfig

return ctrl.Result{}, helper.Patch(ctx, bootstrapKubeconfig)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
infrav1 "github.com/vmware-tanzu/cluster-api-provider-bringyourownhost/apis/infrastructure/v1beta1"
"github.com/vmware-tanzu/cluster-api-provider-bringyourownhost/common"
"github.com/vmware-tanzu/cluster-api-provider-bringyourownhost/common/encoder"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/scheme"
Expand Down Expand Up @@ -68,7 +68,7 @@ var _ = Describe("Controllers/BoottrapKubeconfigController", func() {
var config *clientcmdapi.Config

// should be able to decode into a Config struct
err = common.DecodeFromBase64(&config, createdBootstrapKubeconfig.Status.BootstrapKubeconfigData)
err = encoder.DecodeFromBase64(&config, createdBootstrapKubeconfig.Status.BootstrapKubeconfigData)
Expect(err).ToNot(HaveOccurred())

})
Expand Down

0 comments on commit 4b8e45c

Please sign in to comment.