Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ COPY gen/go gen/go
COPY actions actions
COPY events events
COPY runs runs
COPY secret secret

COPY go.mod go.sum ./
RUN go mod download
Expand Down
2 changes: 2 additions & 0 deletions charts/flyte-binary/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ Get the Flyte API paths for ingress.
- /flyteidl2.actions.ActionsService/*
- /flyteidl2.dataproxy.DataProxyService
- /flyteidl2.dataproxy.DataProxyService/*
- /flyteidl2.secret.SecretService
- /flyteidl2.secret.SecretService/*
{{- end -}}
{{/*
Expand Down
9 changes: 9 additions & 0 deletions charts/flyte-binary/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ flyte-core-components:
download:
maxExpiresIn: 1h

secret:
kubernetes:
namespace: "flyte"
clusterName: "flyte-sandbox"
kubeconfig: ""
qps: 100
burst: 200
timeout: "30s"

# configuration Specify configuration for Flyte
configuration:
# database Specify configuration for Flyte's database connection
Expand Down
5 changes: 5 additions & 0 deletions charts/flyte-sandbox/templates/proxy/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ data:
route:
cluster: flyte
timeout: 0s
- match:
prefix: "/flyteidl2.secret.SecretService"
route:
cluster: flyte
timeout: 0s
{{- end }}
{{- if index .Values "kubernetes-dashboard" "enabled" }}
- match:
Expand Down
19 changes: 16 additions & 3 deletions docker/sandbox-bundled/manifests/complete.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,14 @@ data:
port: 8090
storagePrefix: s3://flyte-data
watchBufferSize: 100
secret:
kubernetes:
burst: 200
clusterName: flyte-sandbox
kubeconfig: ""
namespace: flyte
qps: 100
timeout: 30s
001-plugins.yaml: |
tasks:
task-plugins:
Expand Down Expand Up @@ -919,6 +927,11 @@ data:
route:
cluster: flyte
timeout: 0s
- match:
prefix: "/flyteidl2.secret.SecretService"
route:
cluster: flyte
timeout: 0s
- match:
path: "/kubernetes-dashboard"
redirect:
Expand Down Expand Up @@ -1031,7 +1044,7 @@ type: Opaque
---
apiVersion: v1
data:
haSharedSecret: Rkk2Y1ZETzk4SnV2V3JZUA==
haSharedSecret: Z1Q5TnVpb1Z5NnFzUUtXRg==
proxyPassword: ""
proxyUsername: ""
kind: Secret
Expand Down Expand Up @@ -1402,7 +1415,7 @@ spec:
template:
metadata:
annotations:
checksum/configuration: 6604a6d84082df7341941081eccb62a8c12d4472cf84b319cccc7f5c1684c63c
checksum/configuration: d2d832fb02faa1b1a6c7ad361090cbef8ba1af501bcd0864bf089ced0cdb19a5
checksum/configuration-secret: 588da2ac84d45dd5285521c58bc6c9969924887acb9674d75802055c3a97d9bb
labels:
app.kubernetes.io/component: flyte-binary
Expand Down Expand Up @@ -1557,7 +1570,7 @@ spec:
metadata:
annotations:
checksum/config: 8f50e768255a87f078ba8b9879a0c174c3e045ffb46ac8723d2eedbe293c8d81
checksum/secret: 89994f7cdb81c298a0f3073a45e5fd8afd4cf154b99d3983ed597946794e2d2a
checksum/secret: 79f592556b0140443fc9e525c7750bb5327cf1d5b76b1db91f34ac5dac7a0028
labels:
app: docker-registry
release: flyte-sandbox
Expand Down
9 changes: 7 additions & 2 deletions docker/sandbox-bundled/manifests/dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,11 @@ data:
route:
cluster: flyte
timeout: 0s
- match:
prefix: "/flyteidl2.secret.SecretService"
route:
cluster: flyte
timeout: 0s
- match:
path: "/kubernetes-dashboard"
redirect:
Expand Down Expand Up @@ -753,7 +758,7 @@ metadata:
---
apiVersion: v1
data:
haSharedSecret: U0VJZnFNeGFTWE9peDFlMw==
haSharedSecret: TGVTSmZkaTNQY2k1ZUNreg==
proxyPassword: ""
proxyUsername: ""
kind: Secret
Expand Down Expand Up @@ -1176,7 +1181,7 @@ spec:
metadata:
annotations:
checksum/config: 8f50e768255a87f078ba8b9879a0c174c3e045ffb46ac8723d2eedbe293c8d81
checksum/secret: 770936f6bf0e6bc5cd48fc176eee8831648fb3c4204aa706e08f88ad9b96441b
checksum/secret: de90444b7b2337b4e0217af715490f080c41a20ae4a800a563bb2d1e221bc981
labels:
app: docker-registry
release: flyte-sandbox
Expand Down
15 changes: 11 additions & 4 deletions executor/pkg/webhook/init_cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"encoding/pem"
"fmt"
"math/big"
"net/url"
"os"
"path"
"time"
Expand Down Expand Up @@ -47,7 +48,13 @@ func InitCerts(ctx context.Context, kubeClient kubernetes.Interface, cfg *webhoo
}

logger.Infof(ctx, "Issuing certs")
certs, err := createCerts(cfg.ServiceName, podNamespace)
var extraDNSNames []string
if cfg.WebhookURL != "" {
if u, err := url.Parse(cfg.WebhookURL); err == nil && u.Hostname() != "" {
extraDNSNames = append(extraDNSNames, u.Hostname())
}
}
certs, err := createCerts(cfg.ServiceName, podNamespace, extraDNSNames)
if err != nil {
return err
}
Expand Down Expand Up @@ -114,7 +121,7 @@ func createWebhookSecret(ctx context.Context, namespace string, cfg *webhookConf
return err
}

func createCerts(serviceName string, serviceNamespace string) (certs webhookCerts, err error) {
func createCerts(serviceName string, serviceNamespace string, extraDNSNames []string) (certs webhookCerts, err error) {
caRequest := &x509.Certificate{
SerialNumber: big.NewInt(2021),
Subject: pkix.Name{Organization: []string{"flyte.org"}},
Expand All @@ -141,11 +148,11 @@ func createCerts(serviceName string, serviceNamespace string) (certs webhookCert
return webhookCerts{}, err
}

dnsNames := []string{
dnsNames := append([]string{
serviceName,
serviceName + "." + serviceNamespace,
serviceName + "." + serviceNamespace + ".svc",
}
}, extraDNSNames...)
commonName := serviceName + "." + serviceNamespace + ".svc"

certRequest := &x509.Certificate{
Expand Down
31 changes: 21 additions & 10 deletions executor/pkg/webhook/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,25 @@ func generateMutatePath(gvk schema.GroupVersionKind) string {
gvk.Version + "-" + strings.ToLower(gvk.Kind)
}

func (pm PodMutator) buildWebhookClientConfig(caBytes []byte, namespace, path string) admissionregistrationv1.WebhookClientConfig {
if pm.cfg.WebhookURL != "" {
url := pm.cfg.WebhookURL + path
return admissionregistrationv1.WebhookClientConfig{
CABundle: caBytes,
URL: &url,
}
}
return admissionregistrationv1.WebhookClientConfig{
CABundle: caBytes,
Service: &admissionregistrationv1.ServiceReference{
Name: pm.cfg.ServiceName,
Namespace: namespace,
Path: &path,
Port: &pm.cfg.ServicePort,
},
}
}

func (pm PodMutator) CreateMutationWebhookConfiguration(namespace string) (*admissionregistrationv1.MutatingWebhookConfiguration, error) {
caBytes, err := os.ReadFile(filepath.Join(pm.cfg.ExpandCertDir(), "ca.crt"))
if err != nil {
Expand All @@ -102,16 +121,8 @@ func (pm PodMutator) CreateMutationWebhookConfiguration(namespace string) (*admi
},
Webhooks: []admissionregistrationv1.MutatingWebhook{
{
Name: webhookName,
ClientConfig: admissionregistrationv1.WebhookClientConfig{
CABundle: caBytes,
Service: &admissionregistrationv1.ServiceReference{
Name: pm.cfg.ServiceName,
Namespace: namespace,
Path: &path,
Port: &pm.cfg.ServicePort,
},
},
Name: webhookName,
ClientConfig: pm.buildWebhookClientConfig(caBytes, namespace, path),
Rules: []admissionregistrationv1.RuleWithOperations{
{
Operations: []admissionregistrationv1.OperationType{
Expand Down
4 changes: 4 additions & 0 deletions flyteplugins/go/tasks/pluginmachinery/secret/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ type Config struct {
ImageBuilderConfig ImageBuilderConfig `json:"imageBuilderConfig,omitempty" pflag:"-,"`
WebhookTimeout int32 `json:"webhookTimeout" pflag:",Timeout for webhook calls in seconds. Defaults to 30 seconds."`
DisableCreateMutatingWebhookConfig bool `json:"disableCreateMutatingWebhookConfig"`
// WebhookURL, if set, uses a URL-based webhook client config instead of a k8s Service reference.
// Useful for local development where the webhook server runs outside the cluster
// (e.g. "https://host.docker.internal:9443").
WebhookURL string `json:"webhookURL" pflag:",If set, use this base URL instead of the k8s Service reference for the MutatingWebhookConfiguration (e.g. https://host.docker.internal:9443)"`
KubeClientConfig KubeClientConfig `json:"kubeClientConfig" pflag:",Configuration to control the Kubernetes client used by the webhook"`
SecretEnvVarPrefix string `json:"secretEnvVarPrefix" pflag:",The prefix for secret environment variables. Used by K8s, Global, and Embedded secret managers. Defaults to _UNION_"`
}
Expand Down
4 changes: 4 additions & 0 deletions manager/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
managerconfig "github.com/flyteorg/flyte/v2/manager/config"
"github.com/flyteorg/flyte/v2/runs"
runsconfig "github.com/flyteorg/flyte/v2/runs/config"
"github.com/flyteorg/flyte/v2/secret"
)

func main() {
Expand Down Expand Up @@ -91,6 +92,9 @@ func setup(ctx context.Context, sc *app.SetupContext) error {
if err := executor.Setup(ctx, sc); err != nil {
return err
}
if err := secret.Setup(ctx, sc); err != nil {
return err
}

return nil
}
Expand Down
2 changes: 2 additions & 0 deletions manager/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ manager:
# localCert: true writes the generated TLS cert to disk so the webhook server can read it.
webhook:
localCert: true
certDir: /tmp/flyte/webhook/certs
webhookURL: "https://host.docker.internal:9443"

# Executor configuration
executor:
Expand Down
41 changes: 41 additions & 0 deletions secret/cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package main

import (
"context"
"fmt"
"os"

"github.com/flyteorg/flyte/v2/app"
"github.com/flyteorg/flyte/v2/secret"
secretconfig "github.com/flyteorg/flyte/v2/secret/config"
)

func main() {
a := &app.App{
Name: "secret-service",
Short: "Secret Service for Flyte",
Setup: func(ctx context.Context, sc *app.SetupContext) error {
cfg := secretconfig.GetConfig()
sc.Host = cfg.Server.Host
sc.Port = cfg.Server.Port

k8sClient, _, err := app.InitKubernetesClient(ctx, app.K8sConfig{
KubeConfig: cfg.Kubernetes.KubeConfig,
Namespace: cfg.Kubernetes.Namespace,
QPS: cfg.Kubernetes.QPS,
Burst: cfg.Kubernetes.Burst,
Timeout: cfg.Kubernetes.Timeout,
}, nil)
if err != nil {
return fmt.Errorf("failed to initialize Kubernetes client: %w", err)
}
sc.K8sClient = k8sClient
sc.Namespace = cfg.Kubernetes.Namespace

return secret.Setup(ctx, sc)
},
}
if err := a.Run(); err != nil {
os.Exit(1)
}
}
66 changes: 66 additions & 0 deletions secret/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package config

import (
"github.com/flyteorg/flyte/v2/flytestdlib/config"
)

const configSectionKey = "secret"

//go:generate pflags Config --default-var=defaultConfig

var defaultConfig = &Config{
Server: ServerConfig{
Port: 8093,
Host: "0.0.0.0",
},
Kubernetes: KubernetesConfig{
Namespace: "flyte",
ClusterName: "flyte-sandbox",
QPS: 100,
Burst: 200,
Timeout: "30s",
},
}

var configSection = config.MustRegisterSection(configSectionKey, defaultConfig)

// Config holds the configuration for the Secret service
type Config struct {
// HTTP server configuration
Server ServerConfig `json:"server"`

// Kubernetes configuration
Kubernetes KubernetesConfig `json:"kubernetes"`
}

// ServerConfig holds HTTP server configuration
type ServerConfig struct {
Port int `json:"port" pflag:",Port to bind the HTTP server"`
Host string `json:"host" pflag:",Host to bind the HTTP server"`
}

// KubernetesConfig holds Kubernetes client configuration
type KubernetesConfig struct {
// Namespace where secrets are managed
Namespace string `json:"namespace" pflag:",Kubernetes namespace for secret operations"`

// ClusterName is the logical name of this cluster, used in secret status reporting
ClusterName string `json:"clusterName" pflag:",Logical name of the cluster for secret status reporting"`

// KubeConfig path (optional - if empty, uses in-cluster config)
KubeConfig string `json:"kubeconfig" pflag:",Path to kubeconfig file (optional)"`

// QPS is the maximum number of queries per second to the API server
QPS int `json:"qps" pflag:",Maximum queries per second to the Kubernetes API server"`

// Burst is the maximum burst above QPS allowed when talking to the API server
Burst int `json:"burst" pflag:",Maximum burst above QPS for Kubernetes API server requests"`

// Timeout is the request timeout for Kubernetes API server calls (e.g. "30s")
Timeout string `json:"timeout" pflag:",Request timeout for Kubernetes API server calls"`
}

// GetConfig returns the parsed secret service configuration
func GetConfig() *Config {
return configSection.GetConfig().(*Config)
}
Loading
Loading