Skip to content

Commit

Permalink
POC of dynamic authority
Browse files Browse the repository at this point in the history
Signed-off-by: Erik Godding Boye <[email protected]>
  • Loading branch information
erikgb committed Nov 23, 2024
1 parent b1a0474 commit 64bfd23
Show file tree
Hide file tree
Showing 13 changed files with 62 additions and 231 deletions.
10 changes: 9 additions & 1 deletion cmd/trust-manager/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ limitations under the License.
package app

import (
"crypto/tls"
"errors"
"fmt"
"net/http"

"github.com/erikgb/dynamic-authority/pkg/authority"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
Expand Down Expand Up @@ -70,6 +72,8 @@ func NewCommand() *cobra.Command {

ctrl.SetLogger(mlog)

certOperator := authority.ServingCertificateOperator{Options: opts.DynamicServing}

eventBroadcaster := record.NewBroadcaster()
eventBroadcaster.StartLogging(func(format string, args ...any) { mlog.V(3).Info(fmt.Sprintf(format, args...)) })
eventBroadcaster.StartRecordingToSink(&clientv1.EventSinkImpl{Interface: cl.CoreV1().Events("")})
Expand All @@ -87,7 +91,7 @@ func NewCommand() *cobra.Command {
WebhookServer: ctrlwebhook.NewServer(ctrlwebhook.Options{
Port: opts.Webhook.Port,
Host: opts.Webhook.Host,
CertDir: opts.Webhook.CertDir,
TLSOpts: []func(*tls.Config){certOperator.ServingCertificate()},
}),
Metrics: server.Options{
BindAddress: fmt.Sprintf("0.0.0.0:%d", opts.MetricsPort),
Expand Down Expand Up @@ -119,6 +123,10 @@ func NewCommand() *cobra.Command {
return fmt.Errorf("failed to create manager: %w", err)
}

if err := certOperator.SetupWithManager(mgr); err != nil {
return fmt.Errorf("failed to setup cert operator: %w", err)
}

targetCache, err := cache.New(mgr.GetConfig(), cache.Options{
HTTPClient: mgr.GetHTTPClient(),
Scheme: mgr.GetScheme(),
Expand Down
16 changes: 16 additions & 0 deletions cmd/trust-manager/app/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"os"
"time"

"github.com/erikgb/dynamic-authority/pkg/authority"
"github.com/go-logr/logr"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
Expand Down Expand Up @@ -70,6 +71,8 @@ type Options struct {

// Leader election lease renew duration
RenewDeadline time.Duration

DynamicServing authority.Options
}

type logOptions struct {
Expand Down Expand Up @@ -164,6 +167,7 @@ func (o *Options) addFlags(cmd *cobra.Command) {
o.addBundleFlags(nfs.FlagSet("Bundle"))
o.addLoggingFlags(nfs.FlagSet("Logging"))
o.addWebhookFlags(nfs.FlagSet("Webhook"))
o.addDynamicServingFlags(nfs.FlagSet("Dynamic Serving"))
o.kubeConfigFlags = genericclioptions.NewConfigFlags(true)
o.kubeConfigFlags.AddFlags(nfs.FlagSet("Kubernetes"))

Expand Down Expand Up @@ -248,3 +252,15 @@ func (o *Options) addWebhookFlags(fs *pflag.FlagSet) {
"Certificate and private key must be named 'tls.crt' and 'tls.key' "+
"respectively.")
}

func (o *Options) addDynamicServingFlags(fs *pflag.FlagSet) {
fs.StringVar(&o.DynamicServing.Namespace,
"dynamic-serving-ca-secret-namespace", "",
"Namespace of the secret used to store the CA that signs serving certificates")
fs.StringVar(&o.DynamicServing.CASecret,
"dynamic-serving-ca-secret-name", "",
"Name of the secret used to store the CA that signs serving certificates")
fs.StringSliceVar(&o.DynamicServing.DNSNames,
"dynamic-serving-dns-names", nil,
"DNS names that should be present on certificates generated by the dynamic serving CA")
}
26 changes: 0 additions & 26 deletions deploy/charts/trust-manager/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -421,32 +421,6 @@ The nodePort set on the Service used by the webhook.
> ```
Whether to issue a webhook cert using Helm, which removes the need to install cert-manager. Helm-issued certificates can be challenging to rotate and maintain, and the issued cert will have a duration of 10 years and be modified when trust-manager is updated. It's safer and easier to rely on cert-manager for issuing the webhook cert - avoid using Helm-generated certs in production.
#### **app.webhook.tls.approverPolicy.enabled** ~ `bool`
> Default value:
> ```yaml
> false
> ```
Whether to create an approver-policy CertificateRequestPolicy allowing auto-approval of the trust-manager webhook certificate. If you have approver-policy installed, you almost certainly want to enable this.
#### **app.webhook.tls.approverPolicy.certManagerNamespace** ~ `string`
> Default value:
> ```yaml
> cert-manager
> ```
The namespace in which cert-manager was installed. Only used if `app.webhook.tls.approverPolicy.enabled` is true.
#### **app.webhook.tls.approverPolicy.certManagerServiceAccount** ~ `string`
> Default value:
> ```yaml
> cert-manager
> ```
The name of cert-manager's Service Account. Only used if `app.webhook.tls.approverPolicy.enabled` is true.
#### **app.webhook.tls.certificate.secretTemplate** ~ `object`
> Default value:
> ```yaml
> {}
> ```
#### **app.webhook.hostNetwork** ~ `bool`
> Default value:
> ```yaml
Expand Down
94 changes: 0 additions & 94 deletions deploy/charts/trust-manager/templates/certificate.yaml

This file was deleted.

13 changes: 13 additions & 0 deletions deploy/charts/trust-manager/templates/clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ metadata:
{{- include "trust-manager.labels" . | nindent 4 }}
name: {{ include "trust-manager.name" . }}
rules:
- apiGroups:
- "admissionregistration.k8s.io"
resources:
- "validatingwebhookconfigurations"
verbs: ["get", "list", "watch"]
- apiGroups:
- "admissionregistration.k8s.io"
resources:
- "validatingwebhookconfigurations"
verbs: ["patch"]
resourceNames:
- {{ include "trust-manager.name" . }}

- apiGroups:
- "trust.cert-manager.io"
resources:
Expand Down
18 changes: 10 additions & 8 deletions deploy/charts/trust-manager/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ spec:
# webhook
- "--webhook-host={{.Values.app.webhook.host}}"
- "--webhook-port={{.Values.app.webhook.port}}"
- "--webhook-certificate-dir=/tls"
- "--dynamic-serving-ca-secret-namespace={{ include "trust-manager.namespace" . }}"
- "--dynamic-serving-ca-secret-name={{ include "trust-manager.name" . }}-dynamic-ca"
- "--dynamic-serving-dns-names={{ include "trust-manager.name" . }}"
- "--dynamic-serving-dns-names={{ include "trust-manager.name" . }}.$(POD_NAMESPACE)"
- "--dynamic-serving-dns-names={{ include "trust-manager.name" . }}.$(POD_NAMESPACE).svc"
{{- if .Values.defaultPackage.enabled }}
- "--default-package-location=/packages/cert-manager-package-debian.json"
{{- end }}
Expand All @@ -97,10 +101,12 @@ spec:
{{- if .Values.filterExpiredCertificates.enabled }}
- "--filter-expired-certificates=true"
{{- end }}
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumeMounts:
- mountPath: /tls
name: tls
readOnly: true
- mountPath: /packages
name: packages
readOnly: true
Expand Down Expand Up @@ -140,10 +146,6 @@ spec:
- name: packages
emptyDir:
sizeLimit: 50M
- name: tls
secret:
defaultMode: 420
secretName: {{ include "trust-manager.name" . }}-tls
{{- if .Values.app.webhook.hostNetwork }}
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
Expand Down
9 changes: 9 additions & 0 deletions deploy/charts/trust-manager/templates/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ rules:
- "get"
- "list"
- "watch"
- apiGroups:
- ""
resources:
- "secrets"
verbs:
- "create"
- "patch"
resourceNames:
- {{ include "trust-manager.name" . }}-dynamic-ca
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
Expand Down
10 changes: 2 additions & 8 deletions deploy/charts/trust-manager/templates/webhook.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
{{- if and .Values.app.webhook.tls.helmCert.enabled .Values.app.webhook.tls.approverPolicy.enabled -}}
{{- fail "cannot set .app.webhook.tls.helmCert.enabled and .Values.app.webhook.tls.approverPolicy.enabled" }}
{{- end -}}

{{- /*
$ca is always generated here even if .Values.app.webhook.tls.helmCert.enabled is false because we need it to be
visible in the scope for the ValidatingWebhookConfiguration below.
Expand Down Expand Up @@ -83,10 +79,8 @@ metadata:
labels:
app: {{ include "trust-manager.name" . }}
{{- include "trust-manager.labels" . | nindent 4 }}
{{ if not .Values.app.webhook.tls.helmCert.enabled }}
annotations:
cert-manager.io/inject-ca-from: "{{ include "trust-manager.namespace" . }}/{{ include "trust-manager.name" . }}"
{{ end }}
cert-manager.io/inject-dynamic-ca-from-secret-namespace: "{{ include "trust-manager.namespace" . }}"
cert-manager.io/inject-dynamic-ca-from-secret-name: "{{ include "trust-manager.name" . }}-dynamic-ca"

webhooks:
- name: trust.cert-manager.io
Expand Down
49 changes: 0 additions & 49 deletions deploy/charts/trust-manager/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -389,61 +389,12 @@
"helm-values.app.webhook.tls": {
"additionalProperties": false,
"properties": {
"approverPolicy": {
"$ref": "#/$defs/helm-values.app.webhook.tls.approverPolicy"
},
"certificate": {
"$ref": "#/$defs/helm-values.app.webhook.tls.certificate"
},
"helmCert": {
"$ref": "#/$defs/helm-values.app.webhook.tls.helmCert"
}
},
"type": "object"
},
"helm-values.app.webhook.tls.approverPolicy": {
"additionalProperties": false,
"properties": {
"certManagerNamespace": {
"$ref": "#/$defs/helm-values.app.webhook.tls.approverPolicy.certManagerNamespace"
},
"certManagerServiceAccount": {
"$ref": "#/$defs/helm-values.app.webhook.tls.approverPolicy.certManagerServiceAccount"
},
"enabled": {
"$ref": "#/$defs/helm-values.app.webhook.tls.approverPolicy.enabled"
}
},
"type": "object"
},
"helm-values.app.webhook.tls.approverPolicy.certManagerNamespace": {
"default": "cert-manager",
"description": "The namespace in which cert-manager was installed. Only used if `app.webhook.tls.approverPolicy.enabled` is true.",
"type": "string"
},
"helm-values.app.webhook.tls.approverPolicy.certManagerServiceAccount": {
"default": "cert-manager",
"description": "The name of cert-manager's Service Account. Only used if `app.webhook.tls.approverPolicy.enabled` is true.",
"type": "string"
},
"helm-values.app.webhook.tls.approverPolicy.enabled": {
"default": false,
"description": "Whether to create an approver-policy CertificateRequestPolicy allowing auto-approval of the trust-manager webhook certificate. If you have approver-policy installed, you almost certainly want to enable this.",
"type": "boolean"
},
"helm-values.app.webhook.tls.certificate": {
"additionalProperties": false,
"properties": {
"secretTemplate": {
"$ref": "#/$defs/helm-values.app.webhook.tls.certificate.secretTemplate"
}
},
"type": "object"
},
"helm-values.app.webhook.tls.certificate.secretTemplate": {
"default": {},
"type": "object"
},
"helm-values.app.webhook.tls.helmCert": {
"additionalProperties": false,
"properties": {
Expand Down
20 changes: 0 additions & 20 deletions deploy/charts/trust-manager/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -242,26 +242,6 @@ app:
# It's safer and easier to rely on cert-manager for issuing the webhook cert - avoid using Helm-generated certs in production.
enabled: false

approverPolicy:
# Whether to create an approver-policy CertificateRequestPolicy allowing auto-approval of the trust-manager webhook certificate. If you have approver-policy installed, you almost certainly want to enable this.
enabled: false

# The namespace in which cert-manager was installed. Only used if `app.webhook.tls.approverPolicy.enabled` is true.
certManagerNamespace: "cert-manager"

# The name of cert-manager's Service Account. Only used if `app.webhook.tls.approverPolicy.enabled` is true.
certManagerServiceAccount: "cert-manager"

# Add labels/annotations to secrets created by Certificate resources when using cert-manager provisioned TLS certificate.
certificate:
secretTemplate: {}
# For example:
# annotations:
# my-secret-annotation-1: "foo"
# my-secret-annotation-2: "bar"
# labels:
# my-secret-label: foo

# This value specifies if the app should be started in hostNetwork mode. It is required for use in some managed Kubernetes clusters (such as AWS EKS) with custom CNI.
hostNetwork: false

Expand Down
Loading

0 comments on commit 64bfd23

Please sign in to comment.