Skip to content

Commit

Permalink
Add label selector logic to ca-injector scheduled check (#32)
Browse files Browse the repository at this point in the history
* First step

* Added logic
  • Loading branch information
rembik committed May 23, 2024
1 parent 09097fb commit d5119af
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 15 deletions.
7 changes: 7 additions & 0 deletions charts/ca-injector/templates/clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ metadata:
app.kubernetes.io/name: {{ include "ca-injector.name" . }}
{{- include "ca-injector.labels" . | indent 4 }}
rules:
- apiGroups:
- ""
resources:
- namespaces
verbs:
- read
- list
- apiGroups:
- ""
resources:
Expand Down
28 changes: 28 additions & 0 deletions charts/ca-injector/templates/configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{{- define "deploymentConfig" -}}
caBundle.annotation: {{ .Values.admissionWebhook.labelSelector }}
{{- if .Values.caBundle.configMap }}
caBundle.configMap: {{ .Values.caBundle.configMap }}
{{- end }}
{{- if .Values.caBundle.crt }}
caBundle.crt: {{ .Values.caBundle.crt }}
{{- end }}
{{- if .Values.admissionWebhook.labelSelector }}
admissionWebhook.labelSelector: {{ .Values.admissionWebhook.labelSelector }}
{{- end }}
{{- if .Values.admissionWebhook.enableNamespacesByDefault }}
admissionWebhook.enableNamespacesByDefault: true
{{- $admissionWebhookIgnoreDefaultNamespaces := (list "kube-system" "kube-public" "kube-node-lease" "local-path-storage") }}
admissionWebhook.ignoreNamespaces: '{{ join " " ((concat $admissionWebhookIgnoreDefaultNamespaces .Values.admissionWebhook.ignoreAdditionalNamespaces) | uniq) }}'
{{- end }}
{{- end -}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "ca-injector.fullname" . }}-config
namespace: {{ include "ca-injector.namespace" . }}
labels:
app.kubernetes.io/name: {{ include "ca-injector.name" . }}
{{- include "ca-injector.labels" . | indent 4 }}
data:
config.yaml: |
{{ include "deploymentConfig" . | indent 4 }}
18 changes: 9 additions & 9 deletions charts/ca-injector/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ metadata:
namespace: {{ include "ca-injector.namespace" . }}
labels:
app.kubernetes.io/name: {{ include "ca-injector.name" . }}
{{ .Values.admissionWebhook.labelSelector }}: "false"
{{- include "ca-injector.labels" . | indent 4 }}
{{- if .Values.labels }}
{{- toYaml .Values.labels | nindent 4 }}
Expand Down Expand Up @@ -48,15 +49,6 @@ spec:
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
{{- end }}
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
env:
{{- if .Values.caBundle.configMap }}
- name: CAINJECTOR_CABUNDLE_CONFIGMAP
value: {{ .Values.caBundle.configMap }}
{{- end }}
{{- if .Values.caBundle.crt }}
- name: CAINJECTOR_CABUNDLE_CRT
value: {{ .Values.caBundle.crt }}
{{- end }}
ports:
- containerPort: {{ .Values.internalPort }}
name: https
Expand All @@ -68,11 +60,19 @@ spec:
- name: tls-secret
mountPath: /cert
readOnly: true
- name: ca-injector-config
mountPath: /etc/ca-injector
volumes:
- name: tls-secret
secret:
defaultMode: 420
secretName: {{ include "ca-injector.fullname" . }}-admission
- name: ca-injector-config
configMap:
name: {{ include "ca-injector.fullname" . }}-config
items:
- key: config.yaml
path: config.yaml
{{- with .Values.dnsConfig }}
dnsConfig:
{{- toYaml . | nindent 8 }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"failurePolicy" (include "whFailurePolicy" .)
"timeoutSeconds" .Values.admissionWebhook.timeoutSeconds
"caBundle" (include "whCaBundle" .) -}}
{{- $admissionWebhookIgnoreDefaultNamespaces := (list "kube-system" "kube-public" "kube-node-lease" "local-path-storage") }}
{{- define "whCore" -}}
- name: {{ .prefix }}ca-injector.zeiss.com
failurePolicy: {{ .failurePolicy }}
Expand Down Expand Up @@ -94,7 +95,10 @@ webhooks:
operator: DoesNotExist
- key: "kubernetes.io/metadata.name"
operator: "NotIn"
values: ["kube-system","kube-public","kube-node-lease","local-path-storage"]
values:
{{- range ((concat $admissionWebhookIgnoreDefaultNamespaces .Values.admissionWebhook.ignoreAdditionalNamespaces) | uniq) }}
- {{ . }}
{{- end }}
objectSelector:
matchExpressions:
- key: {{ .Values.admissionWebhook.labelSelector }}
Expand Down
10 changes: 8 additions & 2 deletions charts/ca-injector/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,15 @@ admissionWebhook:
# name: "issuer"
# kind: "ClusterIssuer"

# This enables injection of certifcate authorities in all namespaces,
# This enables injection of certifcate authority bundles in all namespaces,
# except of namespaces and objects which defined the webhook label selector
# Only one environment should have this enabled.
enableNamespacesByDefault: false
# Only used in conjunction with admissionWebhook.enableNamespacesByDefault == True.
# Ignores namespaces besides "kube-system", "kube-public", "kube-node-lease"
# and "local-path-storage".
ignoreAdditionalNamespaces: []

labelSelector: "ca-injector.zeiss.com/inject"

networkPolicy:
Expand Down Expand Up @@ -285,7 +290,8 @@ image:

# CA bundle used from CA injection service
caBundle:
# if not set the object annotation 'ca-injector.zeiss.com/inject-ca-from' must be defined for injection
annotation: "ca-injector.zeiss.com/inject-ca-from"
# if not set the object annotation {{ .Values.caBundle.annotation }} must be defined for injection
configMap: ""
# key of the config map containing CA bundle
crt: ca.crt
8 changes: 6 additions & 2 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,21 @@ func setupConfig() *viper.Viper {
cfg.AddConfigPath(".")
cfg.AddConfigPath("$HOME/.config")
cfg.AddConfigPath("/etc/ca-injector")

cfg.SetConfigName("ca-injector")
cfg.SetConfigName("config")

cfg.AutomaticEnv()
cfg.SetEnvPrefix("cainjector") // will be uppercased automatically
cfg.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))

cfg.SetDefault("tls.key", "tls.key")
cfg.SetDefault("tls.crt", "tls.crt")
cfg.SetDefault("caBundle.annotation", "ca-injector.zeiss.com/inject-ca-from")
cfg.SetDefault("caBundle.configMap", "")
cfg.SetDefault("caBundle.crt", "ca.crt")
cfg.SetDefault("admissionWebhook.labelSelector", "ca-injector.zeiss.com/inject")
cfg.SetDefault("admissionWebhook.enableNamespacesByDefault", false)
cfg.SetDefault("admissionWebhook.ignoreNamespaces", []string{"kube-system", "kube-public", "kube-node-lease", "local-path-storage"})

cfg.SetDefault("shutdown.timeout", 10*time.Second)

if err := cfg.ReadInConfig(); err != nil {
Expand Down
30 changes: 29 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"os"
"os/signal"
"path"
"slices"
"syscall"
"time"

Expand All @@ -28,7 +29,6 @@ import (
)

const (
configMapAnnotation = "ca-injector.zeiss.com/inject-ca-from"
volumeName = "ca-injector-zeiss-com-ca"
)

Expand Down Expand Up @@ -77,6 +77,7 @@ func main() {
lg.Fatal("cert expired; shutting down")
}()

configMapAnnotation := cfg.GetString("caBundle.annotation")
configMap := cfg.GetString("caBundle.configMap")
crt := path.Join("/ssl", cfg.GetString("caBundle.crt"))
lg.WithField("file", crt).Info("generated ssl filename")
Expand Down Expand Up @@ -259,6 +260,13 @@ func main() {

lg.WithField("len(pods.Items)", len(pods.Items)).Info("got pod list")

namespaces, err := cs.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
if err != nil {
logrus.WithError(err).Fatal("error listing namespaces")
}

lg.WithField("len(namespaces.Items)", len(namespaces.Items)).Info("got namespaces list")

items:
for _, pod := range pods.Items {
lg := lg.WithFields(logrus.Fields{
Expand Down Expand Up @@ -293,6 +301,26 @@ func main() {
continue
}

webhookLabelSelector := cfg.GetString("admissionWebhook.labelSelector")
webhookEnableNamespacesByDefault := cfg.GetBool("admissionWebhook.enableNamespacesByDefault")
webhookIgnoreNamespaces := cfg.GetStringSlice("admissionWebhook.ignoreNamespaces")
webhookEnabled := false
for _, namespace := range namespaces.Items {
if namespace.Name == pod.Namespace {
if webhookEnableNamespacesByDefault && !slices.Contains(webhookIgnoreNamespaces, namespace.Name) && pod.Labels[webhookLabelSelector] == "" {
webhookEnabled = true
} else if namespace.Labels[webhookLabelSelector] == "" && pod.Labels[webhookLabelSelector] == "true" {
webhookEnabled = true
} else if namespace.Labels[webhookLabelSelector] == "true" && pod.Labels[webhookLabelSelector] == "" {
webhookEnabled = true
}
}
}
if !webhookEnabled {
lg.Debug("webhook is not enabled")
continue
}

// Look for well-known volume in list of mounts
for _, vol := range pod.Spec.Volumes {
if vol.ConfigMap != nil && vol.ConfigMap.Name == configMap && vol.Name == volumeName {
Expand Down

0 comments on commit d5119af

Please sign in to comment.