Skip to content

Commit

Permalink
Adds user impersonation
Browse files Browse the repository at this point in the history
  • Loading branch information
dagan committed Jul 23, 2023
1 parent c2b594e commit a291d66
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 11 deletions.
4 changes: 0 additions & 4 deletions config/crd/bases/konfirm.goraft.tech_testsuites.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,8 @@ spec:
helm:
description: TestSuiteHelmSetUp describes a Secret-embedded
properties:
chartKey:
type: string
secret:
type: string
valuesKey:
type: string
type: object
type: object
template:
Expand Down
31 changes: 29 additions & 2 deletions controllers/testsuite_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ func (r *TestSuiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
logger.Debug("added finalizer")
}

// Handle errors


// Handle changes to scheduling
if sched := testSuite.Spec.When.Schedule; sched != "" {
if sched != testSuite.Annotations[TestSuiteScheduleAnnotation] {
Expand Down Expand Up @@ -705,8 +708,32 @@ func (r *TestSuiteReconciler) isRunning(ctx context.Context, testSuite *konfirm.

// doSetUp performs any required setup and returns true when all set up
// is complete. An error is returned if set up cannot be performed.
func (r *TestSuiteReconciler) doSetUp(ctx context.Context, testSuite *konfirm.TestSuite) (ok bool) {
ok = true
func (r *TestSuiteReconciler) doSetUp(ctx context.Context, testSuite *konfirm.TestSuite) bool {

// Return early if no set up
if testSuite.Spec.SetUp.Helm.SecretName == "" {
return true
}

logger := logging.FromContextWithName(ctx, testSuiteControllerLoggerName)
var err error

// Get impersonator
var user client.Client
logger.Trace("initiating impersonation")
if user, err = r.Impersonate(ctx, testSuite.Namespace, testSuite.Spec.RunAs); err != nil {
logger.Error(err, "error initializing impersonation")
return false
}
logger.Debug("impersonation initialized")

// Get the Helm secret
if name := testSuite.Spec.SetUp.Helm.SecretName; name != "" {
secret := v1.Secret{}
if err :=
} else {
return true
}
return
}

Expand Down
3 changes: 0 additions & 3 deletions internal/helm/types.go

This file was deleted.

4 changes: 2 additions & 2 deletions internal/impersonate/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,12 @@ func (ic impersonatingClient) Impersonate(ctx context.Context, namespace string,
}

// Copy the rest.Config and add impersonation
config := *ic.config // Dereference original config to avoid reconfiguring other clients
config := rest.CopyConfig(ic.config)
if user := userRef.Spec.UserName; user != "" {
config.Impersonate.UserName = user
}

c, err := client.New(&config, ic.options)
c, err := client.New(config, ic.options)
if err != nil {
return nil, err
}
Expand Down
144 changes: 144 additions & 0 deletions internal/setup/helm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package setup

import (
"context"
"fmt"
"github.com/raft-tech/konfirm/logging"
helm "helm.sh/helm/v3/pkg/action"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/discovery"
"k8s.io/client-go/discovery/cached/memory"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)

type HelmInstallInput struct {
types.NamespacedName
ChartUrl string
Username string
Password string
Values map[string]interface{}
}

type HelmRelease struct{}

type HelmClient interface {
Install(ctx context.Context, config HelmInstallInput) (*HelmRelease, error)
Uninstall(ctx context.Context, release *HelmRelease) error
}

func NewHelmClient(namespace string, cfg *rest.Config, mapper meta.RESTMapper, logger logging.Logger) (HelmClient, error) {
debugLogger := logger.DebugLogger().WithName("helm").WithCallDepth(1)
debugFunc := func(format string, v ...interface{}) {
if debugLogger.Enabled() {
debugLogger.Info(fmt.Sprintf(format, v...))
}
}
config := &helm.Configuration{}
if err := config.Init(&restClientGetter{config: cfg, restMapper: mapper}, namespace, "", debugFunc); err != nil {
return nil, err
}

return &helmClient{config: config}, nil
}

type helmClient struct {
config *helm.Configuration
}

func (h helmClient) Install(ctx context.Context, config HelmInstallInput) (*HelmRelease, error) {
//TODO implement me
panic("implement me")
}

func (h helmClient) Uninstall(ctx context.Context, release *HelmRelease) error {
//TODO implement me
panic("implement me")
}

type restClientGetter struct {
config *rest.Config
restMapper meta.RESTMapper
}

func (r restClientGetter) ToRESTConfig() (*rest.Config, error) {
return r.config, nil
}

func (r restClientGetter) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) {
if dc, err := discovery.NewDiscoveryClientForConfig(r.config); err == nil {
return memory.NewMemCacheClient(dc), nil
} else {
return nil, err
}
}

func (r restClientGetter) ToRESTMapper() (meta.RESTMapper, error) {
return r.restMapper, nil
}

func (r restClientGetter) ToRawKubeConfigLoader() clientcmd.ClientConfig {

// This is based on the behavior of genericclioptions.ConfigFlags.ToRawKubeConfigLoader

loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
loadingRules.DefaultClientConfig = &clientcmd.DefaultClientConfig

overrides := &clientcmd.ConfigOverrides{ClusterDefaults: clientcmd.ClusterDefaults}

if v := r.config.CertFile; v != "" {
overrides.AuthInfo.ClientCertificate = v
}

if v := r.config.KeyFile; v != "" {
overrides.AuthInfo.ClientKey = v
}

if v := r.config.BearerTokenFile; v != "" {
overrides.AuthInfo.TokenFile = v
} else if v = r.config.BearerToken; v != "" {
overrides.AuthInfo.Token = v
}

if v := r.config.Impersonate.UserName; v != "" {
overrides.AuthInfo.Impersonate = v
}

if v := r.config.Impersonate.UID; v != "" {
overrides.AuthInfo.ImpersonateUID = v
}

if v := r.config.Impersonate.Groups; v != nil {
overrides.AuthInfo.ImpersonateGroups = make([]string, len(v))
copy(overrides.AuthInfo.ImpersonateGroups, v)
}

if v := r.config.Username; v != "" {
overrides.AuthInfo.Username = v
}

if v := r.config.Password; v != "" {
overrides.AuthInfo.Password = v
}

if v := r.config.Host; v != "" {
overrides.ClusterInfo.Server = v
if v = r.config.APIPath; v != "" {
overrides.ClusterInfo.Server += v
}
}

if v := r.config.ServerName; v != "" {
overrides.ClusterInfo.TLSServerName = v
}

if v := r.config.CAFile; v != "" {
overrides.ClusterInfo.CertificateAuthority = v
}

overrides.ClusterInfo.InsecureSkipTLSVerify = r.config.Insecure
overrides.Timeout = r.config.Timeout.String()

return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, overrides)
}
4 changes: 4 additions & 0 deletions logging/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ func NewLogger(from logr.Logger) *Logger {
}
}

func (l *Logger) DebugLogger() logr.Logger {
return l.debug
}

func (l *Logger) Debug(msg string, keysAndValues ...interface{}) {
l.debug.Info(msg, keysAndValues...)
}
Expand Down

0 comments on commit a291d66

Please sign in to comment.