Skip to content

Commit

Permalink
Merge pull request #136 from FabianKramm/main
Browse files Browse the repository at this point in the history
service account tokens api
  • Loading branch information
FabianKramm authored Sep 22, 2021
2 parents 858455f + d26395a commit d5ec175
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 22 deletions.
2 changes: 1 addition & 1 deletion cmd/vcluster/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import (
translatepods "github.com/loft-sh/vcluster/pkg/controllers/resources/pods/translate"
"github.com/loft-sh/vcluster/pkg/leaderelection"
"github.com/loft-sh/vcluster/pkg/util/kubeconfig"
"github.com/loft-sh/vcluster/pkg/util/log"
"io/ioutil"
"k8s.io/client-go/discovery"
"os"
"time"

"github.com/loft-sh/kiosk/pkg/manager/blockingcacheclient"
"github.com/loft-sh/kiosk/pkg/util/log"
"github.com/loft-sh/vcluster/cmd/vcluster/context"
"github.com/loft-sh/vcluster/pkg/controllers"
"github.com/loft-sh/vcluster/pkg/controllers/resources/endpoints"
Expand Down
8 changes: 4 additions & 4 deletions cmd/vclusterctl/cmd/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func (cmd *ConnectCmd) Connect(vclusterName string) error {
out, err = exec.Command("kubectl", args...).CombinedOutput()
if err != nil {
if !printedWaiting {
cmd.log.Infof("Waiting for vCluster to come up...")
cmd.log.Infof("Waiting for vcluster to come up...")
printedWaiting = true
}

Expand All @@ -136,7 +136,7 @@ func (cmd *ConnectCmd) Connect(vclusterName string) error {
return true, nil
})
if err != nil {
return errors.Wrap(err, "wait for vCluster")
return errors.Wrap(err, "wait for vcluster")
}

kubeConfig, err := clientcmd.Load(out)
Expand Down Expand Up @@ -178,7 +178,7 @@ func (cmd *ConnectCmd) Connect(vclusterName string) error {

if len(service.Status.LoadBalancer.Ingress) == 0 {
if !printedWaiting {
cmd.log.Infof("Waiting for vCluster LoadBalancer ip...")
cmd.log.Infof("Waiting for vcluster LoadBalancer ip...")
printedWaiting = true
}

Expand All @@ -199,7 +199,7 @@ func (cmd *ConnectCmd) Connect(vclusterName string) error {
return true, nil
})
if err != nil {
return errors.Wrap(err, "wait for vCluster")
return errors.Wrap(err, "wait for vcluster")
}
}

Expand Down
1 change: 0 additions & 1 deletion devspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ images:
rebuildStrategy: ignoreContextChanges
build:
buildKit:
skipPush: true
options:
target: builder
deployments:
Expand Down
3 changes: 2 additions & 1 deletion devspace_start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ ${COLOR_RESET}
Welcome to your development container!
This is how you can work with it:
- Run \`${COLOR_CYAN}go run -mod vendor cmd/vcluster/main.go${COLOR_RESET}\` to start vcluster
- Run \`devspace enter -n vcluster --pod ${HOSTNAME} -c syncer\` to create another shell into this container
- Run \`${COLOR_CYAN}devspace enter -n vcluster --pod ${HOSTNAME} -c syncer${COLOR_RESET}\` to create another shell into this container
- Run \`${COLOR_CYAN}kubectl ...${COLOR_RESET}\` from within the container to access the vcluster if its started
- ${COLOR_CYAN}Files will be synchronized${COLOR_RESET} between your local machine and this container
"

Expand Down
2 changes: 1 addition & 1 deletion hack/build-cli.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
# This script will build vCluster and calculate hash for each
# This script will build vcluster and calculate hash for each
# (VCLUSTER_BUILD_PLATFORMS, VCLUSTER_BUILD_ARCHS) pair.
# VCLUSTER_BUILD_PLATFORMS="linux" VCLUSTER_BUILD_ARCHS="amd64" ./hack/build-all.bash
# can be called to build only for linux-amd64
Expand Down
33 changes: 25 additions & 8 deletions pkg/controllers/resources/pods/translate/translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ import (
"github.com/loft-sh/vcluster/pkg/util/translate"
"github.com/pkg/errors"
appsv1 "k8s.io/api/apps/v1"
authenticationv1 "k8s.io/api/authentication/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/util/keyutil"
"k8s.io/utils/pointer"
"regexp"
Expand Down Expand Up @@ -63,6 +65,7 @@ func NewTranslator(ctx *context2.ControllerContext) (Translator, error) {
}

return &translator{
vClientConfig: ctx.VirtualManager.GetConfig(),
vClient: ctx.VirtualManager.GetClient(),
imageTranslator: imageTranslator,
tokenGenerator: tokenGenerator,
Expand All @@ -77,6 +80,7 @@ func NewTranslator(ctx *context2.ControllerContext) (Translator, error) {
}

type translator struct {
vClientConfig *rest.Config
vClient client.Client
tokenGenerator serviceaccount.TokenGenerator
imageTranslator ImageTranslator
Expand Down Expand Up @@ -478,21 +482,34 @@ func (t *translator) translateProjectedVolume(projectedVolume *corev1.ProjectedV
serviceAccountName = vPod.Spec.DeprecatedServiceAccount
}

serviceAccount := corev1.ServiceAccount{}
err := t.vClient.Get(context.Background(), types.NamespacedName{Namespace: vPod.Namespace, Name: serviceAccountName}, &serviceAccount)
// create new client
vClient, err := kubernetes.NewForConfig(t.vClientConfig)
if err != nil {
return errors.Wrapf(err, "get service account "+serviceAccountName)
return errors.Wrap(err, "create client")
}

audience := "https://kubernetes.default.svc." + t.clusterDomain
if projectedVolume.Sources[i].ServiceAccountToken.Audience != "" {
audience = projectedVolume.Sources[i].ServiceAccountToken.Audience
}

public, private := serviceaccount.Claims(serviceAccount, vPod, nil, 10*365*24*60*60, 0, []string{audience})
serviceAccountToken, err := t.tokenGenerator.GenerateToken(public, private)
expirationSeconds := int64(10 * 365 * 24 * 60 * 60)
token, err := vClient.CoreV1().ServiceAccounts(vPod.Namespace).CreateToken(context.Background(), serviceAccountName, &authenticationv1.TokenRequest{
Spec: authenticationv1.TokenRequestSpec{
Audiences: []string{audience},
BoundObjectRef: &authenticationv1.BoundObjectReference{
APIVersion: corev1.SchemeGroupVersion.String(),
Kind: "Pod",
Name: vPod.Name,
UID: vPod.UID,
},
ExpirationSeconds: &expirationSeconds,
},
}, metav1.CreateOptions{})
if err != nil {
return errors.Wrap(err, "generate token")
return errors.Wrap(err, "create token")
} else if token.Status.Token == "" {
return errors.New("received empty token")
}

// set the token as annotation
Expand All @@ -503,7 +520,7 @@ func (t *translator) translateProjectedVolume(projectedVolume *corev1.ProjectedV
for {
annotation = ServiceAccountTokenAnnotation + random.RandomString(8)
if pPod.Annotations[annotation] == "" {
pPod.Annotations[annotation] = serviceAccountToken
pPod.Annotations[annotation] = token.Status.Token
break
}
}
Expand Down
168 changes: 168 additions & 0 deletions pkg/util/log/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package log

import (
"fmt"
"github.com/go-logr/logr"
"k8s.io/klog"
"strings"
)

type WithDepth interface {
WithDepth(depth int) logr.Logger
}

func NewLog(level int) logr.Logger {
return &log{
level: level,
depth: 1,
}
}

type log struct {
current int
level int
prefixes []string
depth int
}

func (l *log) WithDepth(depth int) logr.Logger {
return &log{
level: l.level,
current: l.current,
prefixes: l.prefixes,
depth: depth,
}
}

// Info logs a non-error message with the given key/value pairs as context.
//
// The msg argument should be used to add some constant description to
// the log line. The key/value pairs can then be used to add additional
// variable information. The key/value pairs should alternate string
// keys and arbitrary values.
func (l *log) Info(msg string, keysAndValues ...interface{}) {
klog.InfoDepth(l.depth, l.formatMsg(msg, keysAndValues...))
}

// Enabled tests whether this InfoLogger is enabled. For example,
// commandline flags might be used to set the logging verbosity and disable
// some info logs.
func (l *log) Enabled() bool {
return true
}

// Error logs an error, with the given message and key/value pairs as context.
// It functions similarly to calling Info with the "error" named value, but may
// have unique behavior, and should be preferred for logging errors (see the
// package documentations for more information).
//
// The msg field should be used to add context to any underlying error,
// while the err field should be used to attach the actual error that
// triggered this log line, if present.
func (l *log) Error(err error, msg string, keysAndValues ...interface{}) {
newKeysAndValues := []interface{}{err}
newKeysAndValues = append(newKeysAndValues, keysAndValues...)
klog.ErrorDepth(l.depth, l.formatMsg(msg, newKeysAndValues...))
}

// V returns an InfoLogger value for a specific verbosity level. A higher
// verbosity level means a log message is less important. It's illegal to
// pass a log level less than zero.
func (l *log) V(level int) logr.Logger {
if level < l.level {
return &silent{}
}

prefixes := []string{}
prefixes = append(prefixes, l.prefixes...)
return &log{
level: l.level,
current: level,
prefixes: prefixes,
depth: l.depth,
}
}

// WithValues adds some key-value pairs of context to a logger.
// See Info for documentation on how key/value pairs work.
func (l *log) WithValues(keysAndValues ...interface{}) logr.Logger {
prefixes := []string{}
prefixes = append(prefixes, l.prefixes...)
prefixes = append(prefixes, formatKeysAndValues(keysAndValues...))

return &log{
level: l.level,
current: l.current,
prefixes: prefixes,
depth: l.depth,
}
}

// WithName adds a new element to the logger's name.
// Successive calls with WithName continue to append
// suffixes to the logger's name. It's strongly reccomended
// that name segments contain only letters, digits, and hyphens
// (see the package documentation for more information).
func (l *log) WithName(name string) logr.Logger {
if name == "" {
return &log{
level: l.level,
current: l.current,
prefixes: l.prefixes,
depth: l.depth,
}
}

prefixes := []string{}
prefixes = append(prefixes, l.prefixes...)
prefixes = append(prefixes, name)

return &log{
level: l.level,
current: l.current,
prefixes: prefixes,
depth: l.depth,
}
}

func (l *log) formatMsg(msg string, keysAndValues ...interface{}) string {
prefixes := strings.Join(l.prefixes, ": ")
addString := formatKeysAndValues(keysAndValues...)

retString := msg
if prefixes != "" {
retString = prefixes + ": " + retString
}
if addString != "" {
retString += " " + addString
}
// if l.current != 0 {
// retString = "(" + strconv.Itoa(l.current) + ") " + retString
// }
return retString
}

func formatKeysAndValues(keysAndValues ...interface{}) string {
args := []string{}
for _, kv := range keysAndValues {
switch t := kv.(type) {
case string:
args = append(args, t)
case error:
args = append(args, t.Error())
default:
args = append(args, fmt.Sprintf("%#v", kv))
}
}

return strings.Join(args, " ")
}

type silent struct{}

func (s *silent) Info(msg string, keysAndValues ...interface{}) {}
func (s *silent) Enabled() bool { return false }
func (s *silent) Error(err error, msg string, keysAndValues ...interface{}) {}
func (s *silent) V(level int) logr.Logger { return s }
func (s *silent) WithValues(keysAndValues ...interface{}) logr.Logger { return s }
func (s *silent) WithName(name string) logr.Logger { return s }
27 changes: 21 additions & 6 deletions pkg/util/loghelper/loghelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"github.com/go-logr/logr"
"github.com/loft-sh/vcluster/pkg/util/log"
ctrl "sigs.k8s.io/controller-runtime"
)

Expand All @@ -19,8 +20,14 @@ type logger struct {
}

func New(name string) Logger {
l := ctrl.Log.WithName(name)
withDepthLogger, ok := l.(log.WithDepth)
if ok {
l = withDepthLogger.WithDepth(2)
}

return &logger{
ctrl.Log.WithName(name),
l,
}
}

Expand All @@ -37,13 +44,21 @@ func (l *logger) Errorf(format string, a ...interface{}) {
}

func Infof(format string, a ...interface{}) {
(&logger{ctrl.Log}).Infof(format, a...)
}
l := ctrl.Log.WithName("")
withDepthLogger, ok := l.(log.WithDepth)
if ok {
l = withDepthLogger.WithDepth(2)
}

func Debugf(format string, a ...interface{}) {
(&logger{ctrl.Log}).Debugf(format, a...)
(&logger{l}).Infof(format, a...)
}

func Errorf(format string, a ...interface{}) {
(&logger{ctrl.Log}).Errorf(format, a...)
l := ctrl.Log.WithName("")
withDepthLogger, ok := l.(log.WithDepth)
if ok {
l = withDepthLogger.WithDepth(2)
}

(&logger{l}).Errorf(format, a...)
}

0 comments on commit d5ec175

Please sign in to comment.