1
0
Fork 0
mirror of https://github.com/external-secrets/external-secrets.git synced 2024-12-14 11:57:59 +00:00

WIP: implementing separate deployments

Signed-off-by: Gustavo Carvalho <gustavo.carvalho@container-solutions.com>
This commit is contained in:
Gustavo Carvalho 2022-02-13 09:14:41 -03:00
parent ab03bcdcc7
commit e776f6d843
21 changed files with 760 additions and 88 deletions

View file

@ -103,6 +103,14 @@ build-%: generate ## Build binary for the specified arch
@CGO_ENABLED=0 GOOS=linux GOARCH=$* \
go build -o '$(OUTPUT_DIR)/external-secrets-linux-$*' main.go
@$(OK) go build $*
@$(INFO) go build $*
@CGO_ENABLED=0 GOOS=linux GOARCH=$* \
go build -o 'webhook/$(OUTPUT_DIR)/external-secrets-webhook-linux-$*' webhook/main.go
@$(OK) go build $*
@$(INFO) go build $*
@CGO_ENABLED=0 GOOS=linux GOARCH=$* \
go build -o 'webhook/certcontroller$(OUTPUT_DIR)/external-secrets-cert-controller-linux-$*' webhook/certcontroller/main.go
@$(OK) go build $*
lint.check: ## Check install of golanci-lint
@if ! golangci-lint --version > /dev/null 2>&1; then \

View file

@ -42,6 +42,24 @@ app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{- define "external-secrets-webhook.labels" -}}
helm.sh/chart: {{ include "external-secrets.chart" . }}
{{ include "external-secrets-webhook.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{- define "external-secrets-cert-controller.labels" -}}
helm.sh/chart: {{ include "external-secrets.chart" . }}
{{ include "external-secrets-cert-controller.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
@ -49,7 +67,14 @@ Selector labels
app.kubernetes.io/name: {{ include "external-secrets.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- define "external-secrets-webhook.selectorLabels" -}}
app.kubernetes.io/name: {{ include "external-secrets.name" . }}-webhook
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- define "external-secrets-cert-controller.selectorLabels" -}}
app.kubernetes.io/name: {{ include "external-secrets.name" . }}-cert-controller
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
@ -60,3 +85,26 @@ Create the name of the service account to use
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "external-secrets-webhook.serviceAccountName" -}}
{{- if .Values.webhook.serviceAccount.create }}
{{- default "external-secrets-webhook" .Values.webhook.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.webhook.serviceAccount.name }}
{{- end }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "external-secrets-cert-controller.serviceAccountName" -}}
{{- if .Values.certController.serviceAccount.create }}
{{- default "external-secrets-cert-controller" .Values.certController.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.certController.serviceAccount.name }}
{{- end }}
{{- end }}

View file

@ -0,0 +1,79 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "external-secrets.fullname" . }}-cert-controller
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "external-secrets-cert-controller.labels" . | nindent 4 }}
{{- with .Values.certController.deploymentAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
replicas: {{ .Values.certController.replicaCount }}
selector:
matchLabels:
{{- include "external-secrets-cert-controller.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.certController.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "external-secrets-cert-controller.selectorLabels" . | nindent 8 }}
{{- with .Values.certController.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.certController.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "external-secrets-cert-controller.serviceAccountName" . }}
{{- with .Values.certController.podSecurityContext }}
securityContext:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: cert-controller
{{- with .Values.certController.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
image: "{{ .Values.certController.image.repository }}:{{ .Values.certController.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.certController.image.pullPolicy }}
{{- range $key, $value := .Values.certController.extraArgs }}
{{- if $value }}
- --{{ $key }}={{ $value }}
{{- else }}
- --{{ $key }}
{{- end }}
{{- end }}
ports:
- containerPort: {{ .Values.certController.prometheus.service.port }}
protocol: TCP
name: metrics
{{- with .Values.certController.extraEnv }}
env:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.certController.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.webhook.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.webhook.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.webhook.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- if .Values.webhook.priorityClassName }}
priorityClassName: {{ .Values.webhook.priorityClassName }}
{{- end }}

View file

@ -0,0 +1,52 @@
{{- if .Values.certController.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "external-secrets.fullname" . }}-cert-controller
labels:
{{- include "external-secrets-cert-controller.labels" . | nindent 4 }}
rules:
- apiGroups:
- "apiextensions.k8s.io"
resources:
- "customresourcedefinitions"
verbs:
- "get"
- "list"
- "watch"
- "update"
- "patch"
- apiGroups:
- ""
resources:
- "services"
verbs:
- "get"
- "list"
- "watch"
- apiGroups:
- ""
resources:
- "secrets"
verbs:
- "get"
- "list"
- "watch"
- "update"
- "patch"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "external-secrets.fullname" . }}-cert-controller
labels:
{{- include "external-secrets-cert-controller.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "external-secrets.fullname" . }}-cert-controller
subjects:
- name: {{ include "external-secrets-cert-controller.serviceAccountName" . }}
namespace: {{ .Release.Namespace | quote }}
kind: ServiceAccount
{{- end }}

View file

@ -0,0 +1,20 @@
{{- if .Values.certController.prometheus.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics
labels:
{{- include "external-secrets.labels" . | nindent 4 }}
annotations:
prometheus.io/path: "/metrics"
prometheus.io/scrape: "true"
prometheus.io/port: {{ .Values.certController.prometheus.service.port | quote }}
spec:
type: ClusterIP
ports:
- port: {{ .Values.certController.prometheus.service.port }}
protocol: TCP
name: metrics
selector:
{{- include "external-secrets-cert-controller.selectorLabels" . | nindent 4 }}
{{- end }}

View file

@ -0,0 +1,13 @@
{{- if .Values.certController.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "external-secrets-cert-controller.serviceAccountName" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "external-secrets-cert-controller.labels" . | nindent 4 }}
{{- with .Values.certController.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}

View file

@ -0,0 +1,94 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "external-secrets.fullname" . }}-webhook
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "external-secrets-webhook.labels" . | nindent 4 }}
{{- with .Values.webhook.deploymentAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
replicas: {{ .Values.webhook.replicaCount }}
selector:
matchLabels:
{{- include "external-secrets-webhook.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.webhook.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "external-secrets-webhook.selectorLabels" . | nindent 8 }}
{{- with .Values.webhook.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.webhook.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "external-secrets-webhook.serviceAccountName" . }}
{{- with .Values.webhook.podSecurityContext }}
securityContext:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: webhook
{{- with .Values.webhook.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
image: "{{ .Values.webhook.image.repository }}:{{ .Values.webhook.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.webhook.image.pullPolicy }}
{{- range $key, $value := .Values.webhook.extraArgs }}
{{- if $value }}
- --{{ $key }}={{ $value }}
{{- else }}
- --{{ $key }}
{{- end }}
{{- end }}
ports:
- containerPort: {{ .Values.webhook.prometheus.service.port }}
protocol: TCP
name: metrics
- containerPort: 9443
protocol: TCP
name: webhook
readinessProbe:
tcpSocket:
port: 9443
initialDelaySeconds: 20
periodSeconds: 5
{{- with .Values.webhook.extraEnv }}
env:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.webhook.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
- name: certs
mountPath: {{ .Values.webhook.certDir }}
volumes:
- name: certs
secret:
secretName: {{ include "external-secrets.fullname" . }}-webhook
{{- with .Values.webhook.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.webhook.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.webhook.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- if .Values.webhook.priorityClassName }}
priorityClassName: {{ .Values.webhook.priorityClassName }}
{{- end }}

View file

@ -4,6 +4,6 @@ kind: Secret
metadata:
name: {{ include "external-secrets.fullname" . }}-webhook
labels:
{{- include "external-secrets.labels" . | nindent 4 }}
{{- include "external-secrets-webhook.labels" . | nindent 4 }}
external-secrets.io/component : webhook
{{- end }}

View file

@ -4,7 +4,7 @@ kind: Service
metadata:
name: {{ include "external-secrets.fullname" . }}-webhook
labels:
{{- include "external-secrets.labels" . | nindent 4 }}
{{- include "external-secrets-webhook.labels" . | nindent 4 }}
external-secrets.io/component : webhook
spec:
type: ClusterIP

View file

@ -0,0 +1,13 @@
{{- if .Values.webhook.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "external-secrets-webhook.serviceAccountName" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "external-secrets-webhook.labels" . | nindent 4 }}
{{- with .Values.webhook.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}

View file

@ -78,9 +78,6 @@ prometheus:
service:
port: 8080
webhook:
enabled: true
certDir: /tmp/k8s-webhook-server/serving-certs
nodeSelector: {}
tolerations: []
@ -89,3 +86,128 @@ affinity: {}
# -- Pod priority class name.
priorityClassName: ""
webhook:
certDir: /tmp/k8s-webhook-server/serving-certs
image:
repository: ghcr.io/external-secrets/external-secrets-webhook
pullPolicy: IfNotPresent
# -- The image tag to use. The default is the chart appVersion.
tag: ""
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
rbac:
# -- Specifies whether role and rolebinding resources should be created.
create: true
serviceAccount:
# -- Specifies whether a service account should be created.
create: true
# -- Annotations to add to the service account.
annotations: {}
# -- The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template.
name: ""
nodeSelector: {}
tolerations: []
affinity: {}
# -- Pod priority class name.
priorityClassName: ""
prometheus:
# -- Specifies whether to expose Service resource for collecting Prometheus metrics
enabled: false
service:
port: 8080
## -- Extra environment variables to add to container.
extraEnv: []
## -- Map of extra arguments to pass to container.
extraArgs: {}
# -- Annotations to add to Deployment
deploymentAnnotations: {}
# -- Annotations to add to Pod
podAnnotations: {}
podLabels: {}
podSecurityContext: {}
# fsGroup: 2000
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
resources: {}
# requests:
# cpu: 10m
# memory: 32Mi
certController:
image:
repository: ghcr.io/external-secrets/external-secrets-cert-controller
pullPolicy: IfNotPresent
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
rbac:
# -- Specifies whether role and rolebinding resources should be created.
create: true
serviceAccount:
# -- Specifies whether a service account should be created.
create: true
# -- Annotations to add to the service account.
annotations: {}
# -- The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template.
name: ""
nodeSelector: {}
tolerations: []
affinity: {}
# -- Pod priority class name.
priorityClassName: ""
prometheus:
# -- Specifies whether to expose Service resource for collecting Prometheus metrics
enabled: false
service:
port: 8080
## -- Extra environment variables to add to container.
extraEnv: []
## -- Map of extra arguments to pass to container.
extraArgs: {}
# -- Annotations to add to Deployment
deploymentAnnotations: {}
# -- Annotations to add to Pod
podAnnotations: {}
podLabels: {}
podSecurityContext: {}
# fsGroup: 2000
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
resources: {}
# requests:
# cpu: 10m
# memory: 32Mi

112
main.go
View file

@ -29,7 +29,6 @@ import (
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
"github.com/external-secrets/external-secrets/pkg/controllers/crds"
"github.com/external-secrets/external-secrets/pkg/controllers/externalsecret"
"github.com/external-secrets/external-secrets/pkg/controllers/secretstore"
)
@ -57,14 +56,12 @@ func main() {
var concurrent int
var loglevel string
var namespace string
var webhook bool
var storeRequeueInterval time.Duration
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
flag.StringVar(&controllerClass, "controller-class", "default", "the controller is instantiated with a specific controller name and filters ES based on this property")
flag.BoolVar(&enableLeaderElection, "enable-leader-election", false,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
flag.BoolVar(&webhook, "webhook", false, "Run as webhook") // Properly separate
flag.IntVar(&concurrent, "concurrent", 1, "The number of concurrent ExternalSecret reconciles.")
flag.StringVar(&loglevel, "loglevel", "info", "loglevel to use, one of: debug, info, warn, error, dpanic, panic, fatal")
flag.StringVar(&namespace, "namespace", "", "watch external secrets scoped in the provided namespace only. ClusterSecretStore can be used but only work if it doesn't reference resources from other namespaces")
@ -92,84 +89,37 @@ func main() {
setupLog.Error(err, "unable to start manager")
os.Exit(1)
}
if webhook {
crds := &crds.Reconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("CustomResourceDefinition"),
Scheme: mgr.GetScheme(),
SvcLabels: map[string]string{"external-secrets.io/component": "webhook"},
SecretLabels: map[string]string{"external-secrets.io/component": "webhook"},
CrdResources: []string{"externalsecrets.external-secrets.io", "clustersecretstores.external-secrets.io", "secretstores.external-secrets.io"},
CertDir: "/tmp/k8s-webhook-server/serving-certs",
CAName: "external-secrets",
CAOrganization: "external-secrets",
RestartOnSecretRefresh: true,
}
if err := crds.SetupWithManager(mgr, controller.Options{
MaxConcurrentReconciles: concurrent,
}); err != nil {
setupLog.Error(err, errCreateController, "controller", "CustomResourceDefinition")
os.Exit(1)
}
if crtsReady := crds.EnsureCertsMounted(); crtsReady {
if err = (&esv1beta1.ExternalSecret{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, errCreateWebhook, "webhook", "ExternalSecret-v1beta1")
os.Exit(1)
}
if err = (&esv1beta1.SecretStore{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, errCreateWebhook, "webhook", "SecretStore-v1beta1")
os.Exit(1)
}
if err = (&esv1beta1.ClusterSecretStore{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, errCreateWebhook, "webhook", "ClusterSecretStore-v1beta1")
os.Exit(1)
}
if err = (&esv1alpha1.ExternalSecret{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, errCreateWebhook, "webhook", "ExternalSecret-v1alpha1")
os.Exit(1)
}
if err = (&esv1alpha1.SecretStore{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, errCreateWebhook, "webhook", "SecretStore-v1alpha1")
os.Exit(1)
}
if err = (&esv1alpha1.ClusterSecretStore{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, errCreateWebhook, "webhook", "ClusterSecretStore-v1alpha1")
os.Exit(1)
}
}
} else {
if err = (&secretstore.StoreReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("contllers").WithName("SecretStore"),
Scheme: mgr.GetScheme(),
ControllerClass: controllerClass,
RequeueInterval: storeRequeueInterval,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, errCreateController, "controller", "SecretStore")
os.Exit(1)
}
if err = (&secretstore.ClusterStoreReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("ClusterSecretStore"),
Scheme: mgr.GetScheme(),
ControllerClass: controllerClass,
RequeueInterval: storeRequeueInterval,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, errCreateController, "controller", "ClusterSecretStore")
os.Exit(1)
}
if err = (&externalsecret.Reconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("ExternalSecret"),
Scheme: mgr.GetScheme(),
ControllerClass: controllerClass,
RequeueInterval: time.Hour,
}).SetupWithManager(mgr, controller.Options{
MaxConcurrentReconciles: concurrent,
}); err != nil {
setupLog.Error(err, errCreateController, "controller", "ExternalSecret")
os.Exit(1)
}
if err = (&secretstore.StoreReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("contllers").WithName("SecretStore"),
Scheme: mgr.GetScheme(),
ControllerClass: controllerClass,
RequeueInterval: storeRequeueInterval,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, errCreateController, "controller", "SecretStore")
os.Exit(1)
}
if err = (&secretstore.ClusterStoreReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("ClusterSecretStore"),
Scheme: mgr.GetScheme(),
ControllerClass: controllerClass,
RequeueInterval: storeRequeueInterval,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, errCreateController, "controller", "ClusterSecretStore")
os.Exit(1)
}
if err = (&externalsecret.Reconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("ExternalSecret"),
Scheme: mgr.GetScheme(),
ControllerClass: controllerClass,
RequeueInterval: time.Hour,
}).SetupWithManager(mgr, controller.Options{
MaxConcurrentReconciles: concurrent,
}); err != nil {
setupLog.Error(err, errCreateController, "controller", "ExternalSecret")
os.Exit(1)
}
setupLog.Info("starting manager")
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {

View file

@ -55,7 +55,7 @@ var _ = BeforeSuite(func() {
By("bootstrapping test environment")
testEnv = &envtest.Environment{
CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crds", "bases")},
CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "deploy", "crds")},
}
var ctx context.Context

9
webhook/Dockerfile Normal file
View file

@ -0,0 +1,9 @@
FROM gcr.io/distroless/static
ARG TARGETOS
ARG TARGETARCH
COPY bin/external-secrets-webhook-${TARGETOS}-${TARGETARCH} /bin/external-secrets-webhook
# Run as UID for nobody
USER 65534
ENTRYPOINT ["/bin/external-secrets-webhook"]

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,9 @@
FROM gcr.io/distroless/static
ARG TARGETOS
ARG TARGETARCH
COPY bin/external-secrets-cert-controller-${TARGETOS}-${TARGETARCH} /bin/external-secrets-cert-controller
# Run as UID for nobody
USER 65534
ENTRYPOINT ["/bin/external-secrets-cert-controller"]

View file

@ -0,0 +1,107 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"flag"
"os"
"go.uber.org/zap/zapcore"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
"github.com/external-secrets/external-secrets/pkg/controllers/crds"
)
var (
scheme = runtime.NewScheme()
setupLog = ctrl.Log.WithName("setup")
)
const (
errCreateController = "unable to create controller"
errCreateWebhook = "unable to create webhook"
)
func init() {
_ = clientgoscheme.AddToScheme(scheme)
_ = esv1beta1.AddToScheme(scheme)
_ = esv1alpha1.AddToScheme(scheme)
}
func main() {
var metricsAddr string
var enableLeaderElection bool
var concurrent int
var loglevel string
var namespace string
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
flag.BoolVar(&enableLeaderElection, "enable-leader-election", false,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
flag.StringVar(&loglevel, "loglevel", "info", "loglevel to use, one of: debug, info, warn, error, dpanic, panic, fatal")
flag.Parse()
var lvl zapcore.Level
err := lvl.UnmarshalText([]byte(loglevel))
if err != nil {
setupLog.Error(err, "error unmarshalling loglevel")
os.Exit(1)
}
logger := zap.New(zap.Level(lvl))
ctrl.SetLogger(logger)
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
MetricsBindAddress: metricsAddr,
Port: 9443,
LeaderElection: enableLeaderElection,
LeaderElectionID: "crd-certs-controller",
Namespace: namespace,
})
if err != nil {
setupLog.Error(err, "unable to start manager")
os.Exit(1)
}
crds := &crds.Reconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("webhook-certs-updater"),
Scheme: mgr.GetScheme(),
SvcLabels: map[string]string{"external-secrets.io/component": "webhook"},
SecretLabels: map[string]string{"external-secrets.io/component": "webhook"},
CrdResources: []string{"externalsecrets.external-secrets.io", "clustersecretstores.external-secrets.io", "secretstores.external-secrets.io"},
CertDir: "/tmp/k8s-webhook-server/serving-certs",
CAName: "external-secrets",
CAOrganization: "external-secrets",
RestartOnSecretRefresh: false,
}
if err := crds.SetupWithManager(mgr, controller.Options{
MaxConcurrentReconciles: concurrent,
}); err != nil {
setupLog.Error(err, errCreateController, "controller", "CustomResourceDefinition")
os.Exit(1)
}
setupLog.Info("starting manager")
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
setupLog.Error(err, "problem running manager")
os.Exit(1)
}
}

148
webhook/main.go Normal file
View file

@ -0,0 +1,148 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"flag"
"os"
"time"
"go.uber.org/zap/zapcore"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
"github.com/external-secrets/external-secrets/pkg/controllers/crds"
)
var (
scheme = runtime.NewScheme()
setupLog = ctrl.Log.WithName("setup")
)
const (
errCreateController = "unable to create controller"
errCreateWebhook = "unable to create webhook"
)
func init() {
_ = clientgoscheme.AddToScheme(scheme)
_ = esv1beta1.AddToScheme(scheme)
_ = esv1alpha1.AddToScheme(scheme)
}
func checkCerts(certDir, dnsName string) {
for {
setupLog.Info("Checking certs")
certFile := certDir + "/tls.crt"
_, err := os.Stat(certFile)
if err != nil {
setupLog.Error(err, "certs not found")
os.Exit(1)
}
ca, err := os.ReadFile(certDir + "/ca.crt")
if err != nil {
setupLog.Error(err, "error loading ca cert")
os.Exit(1)
}
cert, err := os.ReadFile(certDir + "/tls.crt")
if err != nil {
setupLog.Error(err, "error loading server cert")
os.Exit(1)
}
key, err := os.ReadFile(certDir + "/tls.key")
if err != nil {
setupLog.Error(err, "error loading server key")
os.Exit(1)
}
ok, err := crds.ValidCert(ca, cert, key, dnsName, time.Now())
if err != nil || !ok {
setupLog.Error(err, "certificates are not valid!")
os.Exit(1)
}
setupLog.Info("Certs valid")
time.Sleep(time.Hour * 24)
}
}
func main() {
var metricsAddr string
var enableLeaderElection bool
var loglevel string
var namespace string
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
flag.StringVar(&loglevel, "loglevel", "info", "loglevel to use, one of: debug, info, warn, error, dpanic, panic, fatal")
flag.BoolVar(&enableLeaderElection, "enable-leader-election", false,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
flag.StringVar(&namespace, "namespace", "", "watch external secrets scoped in the provided namespace only. ClusterSecretStore can be used but only work if it doesn't reference resources from other namespaces")
flag.Parse()
var lvl zapcore.Level
err := lvl.UnmarshalText([]byte(loglevel))
if err != nil {
setupLog.Error(err, "error unmarshalling loglevel")
os.Exit(1)
}
go checkCerts("/tmp/k8s-webhook-server/serving-certs", "host.minikube.internal")
logger := zap.New(zap.Level(lvl))
ctrl.SetLogger(logger)
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
MetricsBindAddress: metricsAddr,
Port: 9443,
LeaderElection: enableLeaderElection,
LeaderElectionID: "webhook-controller",
Namespace: namespace,
})
if err != nil {
setupLog.Error(err, "unable to start manager")
os.Exit(1)
}
if err = (&esv1beta1.ExternalSecret{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, errCreateWebhook, "webhook", "ExternalSecret-v1beta1")
os.Exit(1)
}
if err = (&esv1beta1.SecretStore{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, errCreateWebhook, "webhook", "SecretStore-v1beta1")
os.Exit(1)
}
if err = (&esv1beta1.ClusterSecretStore{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, errCreateWebhook, "webhook", "ClusterSecretStore-v1beta1")
os.Exit(1)
}
if err = (&esv1alpha1.ExternalSecret{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, errCreateWebhook, "webhook", "ExternalSecret-v1alpha1")
os.Exit(1)
}
if err = (&esv1alpha1.SecretStore{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, errCreateWebhook, "webhook", "SecretStore-v1alpha1")
os.Exit(1)
}
if err = (&esv1alpha1.ClusterSecretStore{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, errCreateWebhook, "webhook", "ClusterSecretStore-v1alpha1")
os.Exit(1)
}
setupLog.Info("starting manager")
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
setupLog.Error(err, "problem running manager")
os.Exit(1)
}
}