webhook

package
v1.9.33 Latest Latest
Warning

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

Go to latest
Published: Oct 19, 2023 License: Apache-2.0 Imports: 40 Imported by: 0

Documentation

Overview

The PodMutator is a controller-runtime webhook that intercepts Pod Creation events and mutates them. Currently, there is only one registered Mutator, that's the SecretsMutator. It works as follows:

  • The Webhook only works on Pods. If propeller/plugins launch a resource outside of K8s (or in a separate k8s cluster), it's the responsibility of the plugin to correctly pass secret injection information.
  • When a k8s-plugin builds a resource, propeller's PluginManager will automatically inject a label `inject-flyte -secrets: true` and serialize the secret injection information into the annotations.
  • If a plugin does not use the K8sPlugin interface, it's its responsibility to pass secret injection information.
  • If a k8s plugin creates a CRD that launches other Pods (e.g. Spark/PyTorch... etc.), it's its responsibility to make sure the labels/annotations set on the CRD by PluginManager are propagated to those launched Pods. This ensures secret injection happens no matter how many levels of indirections there are.
  • The Webhook expects 'inject-flyte-secrets: true' as a label on the Pod. Otherwise it won't listen/observe that pod.
  • Once it intercepts the admission request, it goes over all registered Mutators and invoke them in the order they are registered as. If a Mutator fails and it's marked as `required`, the operation will fail and the admission will be rejected.
  • The SecretsMutator will attempt to lookup the requested secret from the process environment. If the secret is already mounted, it'll inject it as plain-text into the Pod Spec (Less secure).
  • If it's not found in the environment it'll, instead, fallback to the enabled Secrets Injector (K8s, Confidant, Vault... etc.).
  • Each SecretsInjector will mutate the Pod differently depending on how its backend secrets system injects the secrets for example:
  • For K8s secrets, it'll either add EnvFromSecret or VolumeMountSource (depending on the MountRequirement stated in the flyteIdl.Secret object) into the Pod. There is no validation that the secret exist and is available to the Pod at this point. If the secret is not accessible, the Pod will fail with ContainerCreationConfigError and will be retried.
  • For Vault secrets, it'll inject the right annotations to trigger Vault's own sidecar/webhook to mount the secret.

Index

Constants

View Source
const (
	// AWSSecretArnEnvVar defines the environment variable name to use to specify to the sidecar container which secret
	// to pull.
	AWSSecretArnEnvVar = "SECRET_ARN"

	// AWSSecretFilenameEnvVar defines the environment variable name to use to specify to the sidecar container where
	// to store the secret.
	AWSSecretFilenameEnvVar = "SECRET_FILENAME"

	// AWSSecretsVolumeName defines the static name of the volume used for mounting/sharing secrets between init-container
	// sidecar and the rest of the containers in the pod.
	AWSSecretsVolumeName = "aws-secret-vol" // #nosec

	// AWS SideCar Docker Container expects the mount to always be under /tmp
	AWSInitContainerMountPath = "/tmp"
)
View Source
const (
	PodNameEnvVar      = "POD_NAME"
	PodNamespaceEnvVar = "POD_NAMESPACE"
)
View Source
const (
	CaCertKey            = "ca.crt"
	ServerCertKey        = "tls.crt"
	ServerCertPrivateKey = "tls.key"
)
View Source
const (
	K8sDefaultEnvVarPrefix  = "_FSEC_"
	EnvVarGroupKeySeparator = "_"
)
View Source
const (
	SecretPathDefaultDirEnvVar = "FLYTE_SECRETS_DEFAULT_DIR" // #nosec
	SecretPathFilePrefixEnvVar = "FLYTE_SECRETS_FILE_PREFIX" // #nosec
	SecretEnvVarPrefix         = "FLYTE_SECRETS_ENV_PREFIX"  // #nosec
)
View Source
const (
	// GCPSecretsVolumeName defines the static name of the volume used for mounting/sharing secrets between init-container
	// sidecar and the rest of the containers in the pod.
	GCPSecretsVolumeName = "gcp-secret-vol" // #nosec
)

Variables

View Source
var (
	// AWSSecretMountPathPrefix defines the default mount path for secrets
	AWSSecretMountPathPrefix = []string{string(os.PathSeparator), "etc", "flyte", "secrets"}
)
View Source
var (
	// GCPSecretMountPath defines the default mount path for secrets
	GCPSecretMountPath = filepath.Join(string(os.PathSeparator), "etc", "flyte", "secrets")
)
View Source
var (
	K8sSecretPathPrefix = []string{string(os.PathSeparator), "etc", "flyte", "secrets"}
)
View Source
var (
	VaultSecretPathPrefix = []string{string(os.PathSeparator), "etc", "flyte", "secrets"}
)

Functions

func AppendEnvVars

func AppendEnvVars(containers []corev1.Container, envVar corev1.EnvVar) []corev1.Container

func AppendVolume

func AppendVolume(volumes []corev1.Volume, volume corev1.Volume) []corev1.Volume

func AppendVolumeMounts

func AppendVolumeMounts(containers []corev1.Container, mount corev1.VolumeMount) []corev1.Container

func CreateEnvVarForSecret

func CreateEnvVarForSecret(secret *core.Secret) corev1.EnvVar

func CreateVaultAnnotationsForSecret

func CreateVaultAnnotationsForSecret(secret *core.Secret, kvversion config.KVVersion) map[string]string

func CreateVolumeForSecret

func CreateVolumeForSecret(secret *core.Secret) corev1.Volume

func CreateVolumeMountForSecret

func CreateVolumeMountForSecret(volumeName string, secret *core.Secret) corev1.VolumeMount

func InitCerts

func InitCerts(ctx context.Context, propellerCfg *config.Config, cfg *webhookConfig.Config) error

func Run

func Run(ctx context.Context, propellerCfg *config.Config, cfg *config2.Config,
	defaultNamespace string, scope *promutils.Scope, mgr *manager.Manager) error

Types

type AWSSecretManagerInjector

type AWSSecretManagerInjector struct {
	// contains filtered or unexported fields
}

AWSSecretManagerInjector allows injecting of secrets from AWS Secret Manager as files. It uses AWS-provided SideCar as an init-container to download the secret and save it to a local volume shared with all other containers in the pod. It supports multiple secrets to be mounted but that will result into adding an init container for each secret. The role/serviceaccount used to run the Pod must have permissions to pull the secret from AWS Secret Manager. Otherwise, the Pod will fail with an init-error. Files will be mounted on /etc/flyte/secrets/<SecretGroup>/<SecretKey>

func NewAWSSecretManagerInjector

func NewAWSSecretManagerInjector(cfg config.AWSSecretManagerConfig) AWSSecretManagerInjector

NewAWSSecretManagerInjector creates a SecretInjector that's able to mount secrets from AWS Secret Manager.

func (AWSSecretManagerInjector) Inject

func (i AWSSecretManagerInjector) Inject(ctx context.Context, secret *core.Secret, p *corev1.Pod) (newP *corev1.Pod, injected bool, err error)

func (AWSSecretManagerInjector) Type

type GCPSecretManagerInjector

type GCPSecretManagerInjector struct {
	// contains filtered or unexported fields
}

GCPSecretManagerInjector allows injecting of secrets from GCP Secret Manager as files. It uses a Google Cloud SDK SideCar as an init-container to download the secret and save it to a local volume shared with all other containers in the pod. It supports multiple secrets to be mounted but that will result into adding an init container for each secret. The Google serviceaccount (GSA) associated with the Pod, either via Workload Identity (recommended) or the underlying node's serviceacccount, must have permissions to pull the secret from GCP Secret Manager. Currently, the secret must also exist in the same project. Otherwise, the Pod will fail with an init-error. Files will be mounted on /etc/flyte/secrets/<SecretGroup>/<SecretGroupVersion>

func NewGCPSecretManagerInjector

func NewGCPSecretManagerInjector(cfg config.GCPSecretManagerConfig) GCPSecretManagerInjector

NewGCPSecretManagerInjector creates a SecretInjector that's able to mount secrets from GCP Secret Manager.

func (GCPSecretManagerInjector) Inject

func (i GCPSecretManagerInjector) Inject(ctx context.Context, secret *core.Secret, p *corev1.Pod) (newP *corev1.Pod, injected bool, err error)

func (GCPSecretManagerInjector) Type

type GlobalSecretProvider

type GlobalSecretProvider interface {
	GetForSecret(ctx context.Context, secret *coreIdl.Secret) (string, error)
}

type GlobalSecrets

type GlobalSecrets struct {
	// contains filtered or unexported fields
}

GlobalSecrets allows the injection of secrets from the process memory space (env vars) or mounted files into pods intercepted through this admission webhook. Secrets injected through this type will be mounted as environment variables. If a secret has a mounting requirement that does not allow Env Vars, it'll fail to inject the secret.

func NewGlobalSecrets

func NewGlobalSecrets(provider GlobalSecretProvider) GlobalSecrets

func (GlobalSecrets) Inject

func (g GlobalSecrets) Inject(ctx context.Context, secret *coreIdl.Secret, p *corev1.Pod) (newP *corev1.Pod, injected bool, err error)

func (GlobalSecrets) Type

type K8sSecretInjector

type K8sSecretInjector struct {
}

K8sSecretInjector allows injecting of secrets into pods by specifying either EnvVarSource or SecretVolumeSource in the Pod Spec. It'll, by default, mount secrets as files into pods. The current version does not allow mounting an entire secret object (with all keys inside it). It only supports mounting a single key from the referenced secret object. The secret.Group will be used to reference the k8s secret object, the Secret.Key will be used to reference a key inside and the secret.Version will be ignored. Environment variables will be named _FSEC_<SecretGroup>_<SecretKey>. Files will be mounted on /etc/flyte/secrets/<SecretGroup>/<SecretKey>

func NewK8sSecretsInjector

func NewK8sSecretsInjector() K8sSecretInjector

func (K8sSecretInjector) Inject

func (i K8sSecretInjector) Inject(ctx context.Context, secret *core.Secret, p *corev1.Pod) (newP *corev1.Pod, injected bool, err error)

func (K8sSecretInjector) Type

type Mutator

type Mutator interface {
	ID() string
	Mutate(ctx context.Context, p *corev1.Pod) (newP *corev1.Pod, changed bool, err error)
}

type MutatorConfig

type MutatorConfig struct {
	Mutator  Mutator
	Required bool
}

type PodMutator

type PodMutator struct {
	Mutators []MutatorConfig
	// contains filtered or unexported fields
}

PodMutator implements controller-runtime WebHook interface.

func NewPodMutator

func NewPodMutator(cfg *config.Config, scope promutils.Scope) *PodMutator

func (PodMutator) CreateMutationWebhookConfiguration

func (pm PodMutator) CreateMutationWebhookConfiguration(namespace string) (*admissionregistrationv1.MutatingWebhookConfiguration, error)

func (PodMutator) GetMutatePath

func (pm PodMutator) GetMutatePath() string

func (*PodMutator) Handle

func (pm *PodMutator) Handle(ctx context.Context, request admission.Request) admission.Response

func (*PodMutator) InjectClient

func (pm *PodMutator) InjectClient(_ client.Client) error

func (*PodMutator) InjectDecoder

func (pm *PodMutator) InjectDecoder(d *admission.Decoder) error

InjectDecoder injects the decoder into a mutatingHandler.

func (PodMutator) Mutate

func (pm PodMutator) Mutate(ctx context.Context, p *corev1.Pod) (newP *corev1.Pod, changed bool, err error)

func (*PodMutator) Register

func (pm *PodMutator) Register(ctx context.Context, mgr manager.Manager) error

type SecretsInjector

type SecretsInjector interface {
	Type() config.SecretManagerType
	Inject(ctx context.Context, secrets *core.Secret, p *corev1.Pod) (newP *corev1.Pod, injected bool, err error)
}

type SecretsMutator

type SecretsMutator struct {
	// contains filtered or unexported fields
}

func NewSecretsMutator

func NewSecretsMutator(cfg *config.Config, _ promutils.Scope) *SecretsMutator

NewSecretsMutator creates a new SecretsMutator with all available plugins. Depending on the selected plugins in the config, only the global plugin and one other plugin can be enabled.

func (SecretsMutator) ID

func (s SecretsMutator) ID() string

func (*SecretsMutator) Mutate

func (s *SecretsMutator) Mutate(ctx context.Context, p *corev1.Pod) (newP *corev1.Pod, injected bool, err error)

type VaultSecretManagerInjector

type VaultSecretManagerInjector struct {
	// contains filtered or unexported fields
}

VaultSecretManagerInjector allows injecting of secrets into pods by leveraging an existing deployment of Vault Agent Vault Agent functions as an additional webhook that is triggered through annotations and then retrieves and mounts the requested secrets from Vault. This injector parses a secret Request into vault annotations, interpreting the secret Group as the vault secret path and the secret Key as the key for which to extract a value from a Vault secret. It supports adding multiple secrets. (The common annotations will simply be overwritten if added several times) Note that you need to configure the Vault role that this injector will try to use and add Vault policies for the service account and namespaces that your workflows run under. Files will be mounted at /etc/flyte/secrets/<SecretGroup>/<SecretKey>

func (VaultSecretManagerInjector) Inject

func (i VaultSecretManagerInjector) Inject(ctx context.Context, secret *coreIdl.Secret, p *corev1.Pod) (newP *corev1.Pod, injected bool, err error)

func (VaultSecretManagerInjector) Type

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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