kubeexec

package
v0.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 12, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package kubeexec runs a kubeconfig's exec credential plugin on the developer's own machine and reads back the credential it prints, the way kubectl does (Task 20416).

Managed clusters authenticate people through exec credential plugins: kubelogin on AKS with Entra ID, `aws eks get-token` on EKS, gke-gcloud-auth-plugin on GKE. The hub refuses such a kubeconfig, because running the plugin there would execute code named in an uploaded file on the control-plane host (pkg/executor/kubernetes.ParseKubeconfig). So the plugin is run here instead, by `cloop remote kube share` on the developer's machine, against the developer's own kubeconfig, as the developer — which is exactly where kubectl would have run it.

Nothing the hub runs may import this package. tests/security asserts that: the guarantee "the hub never runs a credential plugin" is structural, not a promise that a code path is never taken.

The protocol is client.authentication.k8s.io's ExecCredential, versions v1 and v1beta1 (v1alpha1 was removed from Kubernetes in 1.24 and is refused with that said). The behaviour mirrors client-go's exec authenticator:

  • KUBERNETES_EXEC_INFO carries an ExecCredential whose spec says whether the plugin may interact with the user and, with provideClusterInfo, which cluster it is authenticating to;
  • interactiveMode decides whether the plugin gets this process's stdin: Never, IfAvailable (when stdin is a terminal) or Always (and fail when it is not); v1 requires the field, v1beta1 defaults it to IfAvailable;
  • the plugin's stderr is the user's, so a device-code prompt reaches them;
  • its stdout is the credential: a bearer token or a client certificate and key, with an optional expirationTimestamp.

A plugin's output is a credential. It is read under a size cap, never echoed into an error, and Credential's String method redacts it.

Index

Constants

View Source
const (
	APIVersionV1      = "client.authentication.k8s.io/v1"
	APIVersionV1beta1 = "client.authentication.k8s.io/v1beta1"
)

The ExecCredential API versions.

View Source
const (

	// DefaultTimeout bounds a plugin that may not interact with anyone.
	DefaultTimeout = 2 * time.Minute
	// DefaultInteractiveTimeout bounds one that may: a device-code sign-in
	// waits for a person to type a code into a browser.
	DefaultInteractiveTimeout = 10 * time.Minute
)

Limits.

View Source
const ClusterExtensionName = "client.authentication.k8s.io/exec"

ClusterExtensionName is the name of the cluster extension whose content is handed to a plugin with provideClusterInfo, as spec.cluster.config.

Variables

View Source
var (
	// ErrNotFound is a plugin command that does not exist. Its message carries
	// the exec block's installHint, which is the one thing a person seeing it
	// needs.
	ErrNotFound = errors.New("exec credential plugin not found")
	// ErrMalformed is a plugin whose output is not a usable ExecCredential.
	ErrMalformed = errors.New("exec credential plugin printed no usable credential")
	// ErrExpired is a plugin that answered with a credential already past its
	// expiry.
	ErrExpired = errors.New("exec credential plugin returned an expired credential")
	// ErrInteractive is a plugin that needs a terminal this process has not got.
	ErrInteractive = errors.New("exec credential plugin needs an interactive terminal")
)

Errors a caller may want to tell apart.

Functions

func DefaultPaths

func DefaultPaths() []string

DefaultPaths returns the files kubectl would read: $KUBECONFIG's list when it is set, otherwise ~/.kube/config.

Types

type Cluster

type Cluster struct {
	Server                   string
	TLSServerName            string
	InsecureSkipTLSVerify    bool
	CertificateAuthorityData []byte
	ProxyURL                 string
	DisableCompression       bool
	// Config is the cluster's client.authentication.k8s.io/exec extension, as
	// JSON. Nil when the cluster has none.
	Config json.RawMessage
}

Cluster is what a plugin with provideClusterInfo is told about the cluster it is authenticating to.

type Config

type Config struct {
	APIVersion         string
	Command            string
	Args               []string
	Env                []EnvVar
	InstallHint        string
	ProvideClusterInfo bool
	InteractiveMode    InteractiveMode
	// Dir is the directory a relative command path resolves against: the
	// directory of the kubeconfig file the block came from, as kubectl does.
	// A bare name ("kubelogin") is looked up on PATH instead.
	Dir string
}

Config is a kubeconfig user's exec block.

func (Config) Validate

func (c Config) Validate() error

Validate reports the first problem with the exec block itself, before anything is run.

type Context

type Context struct {
	Name      string
	Namespace string
	Cluster   string
	User      string

	Server                string
	CAData                []byte
	TLSServerName         string
	InsecureSkipTLSVerify bool
	ProxyURL              string
	DisableCompression    bool
	// ExecExtension is the cluster's client.authentication.k8s.io/exec
	// extension as JSON, handed to a provideClusterInfo plugin.
	ExecExtension json.RawMessage
	// contains filtered or unexported fields
}

Context is one resolved context: where the cluster is, how it is trusted, and how its user authenticates.

func (*Context) Plugin

func (c *Context) Plugin() *Config

Plugin reports the exec plugin the context's user runs, or nil.

func (*Context) RESTConfig

func (c *Context) RESTConfig(ctx context.Context, opts Options) (*kubernetes.RESTConfig, *Credential, error)

RESTConfig returns a config for the context with a working credential: the token or certificate as written, or the one its exec plugin prints when run now, on this machine.

type Credential

type Credential struct {
	Token                 string
	ClientCertificateData []byte
	ClientKeyData         []byte
	// ExpiresAt is when the plugin said the credential stops working; zero
	// when it did not say.
	ExpiresAt time.Time
}

Credential is what a plugin printed.

func Run

func Run(ctx context.Context, cfg Config, cluster *Cluster, opts Options) (*Credential, error)

Run executes the plugin and returns the credential it printed.

cluster is required when the exec block sets provideClusterInfo, and ignored otherwise.

func (*Credential) GoString

func (c *Credential) GoString() string

GoString mirrors String.

func (*Credential) String

func (c *Credential) String() string

String redacts the credential, so a %v of one cannot log it.

type EnvVar

type EnvVar struct {
	Name  string `yaml:"name" json:"name"`
	Value string `yaml:"value" json:"value"`
}

EnvVar is one entry of the exec block's env list.

type InteractiveMode

type InteractiveMode string

InteractiveMode is the exec block's interactiveMode.

const (
	InteractiveNever       InteractiveMode = "Never"
	InteractiveIfAvailable InteractiveMode = "IfAvailable"
	InteractiveAlways      InteractiveMode = "Always"
)

The three interactive modes.

type Kubeconfig

type Kubeconfig struct {
	// CurrentContext is the merged current-context.
	CurrentContext string
	// Files are the files read, in order.
	Files []string
	// contains filtered or unexported fields
}

Kubeconfig is several workstation kubeconfig files, merged.

func Load

func Load(paths []string) (*Kubeconfig, error)

Load reads and merges paths. A file in a $KUBECONFIG list that does not exist is skipped, as kubectl skips it; when none exists the error says which were tried.

func (*Kubeconfig) Context

func (k *Kubeconfig) Context(name string) (*Context, error)

Context resolves name, or the current context when name is empty.

func (*Kubeconfig) ContextNames

func (k *Kubeconfig) ContextNames() []string

ContextNames lists the contexts, sorted.

type Options

type Options struct {
	// Stdin is handed to an interactive plugin. Default os.Stdin.
	Stdin io.Reader
	// Stderr receives the plugin's own stderr: its prompts and its errors.
	// Default os.Stderr.
	Stderr io.Writer
	// Terminal reports whether Stdin is a terminal, which decides
	// IfAvailable and Always.
	Terminal bool
	// Timeout bounds the plugin. Zero picks DefaultTimeout, or
	// DefaultInteractiveTimeout when it may interact.
	Timeout time.Duration
	// Environ is the environment the plugin inherits before its own env
	// entries. Nil means os.Environ().
	Environ []string
	// Now is the clock an expiry is judged against. Nil means time.Now.
	Now func() time.Time
	// LookPath resolves a bare command name. Nil means exec.LookPath.
	LookPath func(string) (string, error)
}

Options are the runtime knobs. The zero value runs the plugin the way kubectl would in this process.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL