From af97641139b08ebd4a3b1432d80c4faaa6431ceb Mon Sep 17 00:00:00 2001 From: Ryan Belgrave Date: Thu, 19 Dec 2024 14:48:38 -0600 Subject: [PATCH] easy certificates and mtls --- .github/workflows/pr.yml | 31 +++++++ charts/warpstream-agent/CHANGELOG.md | 4 + charts/warpstream-agent/Chart.yaml | 2 +- .../ci/playground-sts-cert-mtls-values.yaml | 46 +++++++++++ .../ci/playground-sts-cert-values.yaml | 33 ++++++++ .../templates/deployment.yaml | 41 +++++++++- .../templates/tests/test-connection.yaml | 80 +++++++++++++++++++ charts/warpstream-agent/values.yaml | 22 +++++ 8 files changed, 256 insertions(+), 3 deletions(-) create mode 100644 charts/warpstream-agent/ci/playground-sts-cert-mtls-values.yaml create mode 100644 charts/warpstream-agent/ci/playground-sts-cert-values.yaml diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index f9c7a2c..6b19687 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -55,6 +55,37 @@ jobs: run: | kubectl create secret generic external-secret --from-literal=agentkey=${DefaultVirtualClusterAgentKeySecret} + - name: Generate Certificate for TLS testing + run: | + mkdir /tmp/certificates + cd /tmp/certificates + mkdir -p ca/private + chmod 700 ca/private + + # Generate CA + openssl req -x509 -nodes -days 3650 -newkey rsa:4096 -keyout ca/private/ca_key.pem -out ca/ca_cert.pem -subj "/C=US/ST=Acme State/L=Acme City/O=Acme Inc./CN=example.com" + + # Create server private key and certificate request + mkdir -p server/private + chmod 700 ca/private + openssl genrsa -out server/private/server_key.pem 4096 + openssl req -new -key server/private/server_key.pem -out server/server.csr -subj "/C=US/ST=Acme State/L=Acme City/O=Acme Inc./CN=WarpStream Agent" -addext 'subjectAltName = DNS:playground-sts-cert, DNS:playground-sts-cert-kafka, DNS:playground-sts-cert.default.svc.cluster.local, DNS:*.playground-sts-cert-headless.default.svc.cluster.local' + + # Create client private key and certificate request + mkdir -p client/private + chmod 700 client/private + openssl genrsa -out client/private/client_key.pem 4096 + openssl req -new -key client/private/client_key.pem -out client/client.csr -subj "/C=US/ST=Acme State/L=Acme City/O=Acme Inc./CN=WarpStream Client" + + # Generate certificates + openssl x509 -req -days 1460 -in server/server.csr -CA ca/ca_cert.pem -CAkey ca/private/ca_key.pem -CAcreateserial -out server/server_cert.pem -copy_extensions copyall + openssl x509 -req -days 1460 -in client/client.csr -CA ca/ca_cert.pem -CAkey ca/private/ca_key.pem -CAcreateserial -out client/client_cert.pem -copy_extensions copyall + + # Create Kubernetes Secrets + kubectl create secret tls ci-certificate --cert=server/server_cert.pem --key=server/private/server_key.pem + kubectl create secret tls ci-certificate-client --cert=client/client_cert.pem --key=client/private/client_key.pem + kubectl create secret generic ci-certificate-ca --from-file=ca.crt=ca/ca_cert.pem + - name: Run chart-testing (install) if: steps.list-changed.outputs.changed == 'true' run: ct install --namespace default --target-branch ${{ github.event.repository.default_branch }} --upgrade --skip-missing-values diff --git a/charts/warpstream-agent/CHANGELOG.md b/charts/warpstream-agent/CHANGELOG.md index c42d625..15cefa6 100644 --- a/charts/warpstream-agent/CHANGELOG.md +++ b/charts/warpstream-agent/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.13.69] - 2024-12-XX + +- Make certificates first class variables so it is easier to configure without having to use volumes and env variables + ## [0.13.68] - 2024-12-19 - Update WarpStream Agent to v609. diff --git a/charts/warpstream-agent/Chart.yaml b/charts/warpstream-agent/Chart.yaml index dfd7733..6f19c4c 100644 --- a/charts/warpstream-agent/Chart.yaml +++ b/charts/warpstream-agent/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: warpstream-agent description: WarpStream Agent for Kubernetes. type: application -version: 0.13.68 +version: 0.13.69 appVersion: v609 icon: https://avatars.githubusercontent.com/u/132156278 home: https://docs.warpstream.com/warpstream/ diff --git a/charts/warpstream-agent/ci/playground-sts-cert-mtls-values.yaml b/charts/warpstream-agent/ci/playground-sts-cert-mtls-values.yaml new file mode 100644 index 0000000..4965cb6 --- /dev/null +++ b/charts/warpstream-agent/ci/playground-sts-cert-mtls-values.yaml @@ -0,0 +1,46 @@ +# Need override os we have a static release name for certificates while testing +fullnameOverride: "playground-sts-cert" + +config: + playground: true + +# testing with statefulset +deploymentKind: StatefulSet + +certificate: + # Set to true to enable TLS termination on the WarpStream agent + # see TLS documentation for details https://docs.warpstream.com/warpstream/byoc/advanced-agent-deployment-options/protect-data-in-motion-with-tls-encryption#tls-encryption-overview + enableTLS: true + + # The Kubernetes TLS secret that contains a certificate and private key + # see https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets + secretName: "ci-certificate" + + mtls: + # Set to true to enable mutual TLS on the WarpStream agent, requires enableTLS set to true + # see mTLS documentation for details https://docs.warpstream.com/warpstream/byoc/authentication/mutual-tls-mtls + enabled: true + + # The secret key reference for the certificate authority public key + # If not set, the container's root certificate pool will be used for mtls client certificate verification + # It is recommend to always set this to your CA's public key and not rely on the root certificate pool + # see mTLS documentation for details on why using the root certificate pool is not recommended + certificateAuthoritySecretKeyRef: + name: "ci-certificate-ca" + key: "ca.crt" + +# overriding resources so it fits on a runner +resources: + requests: + cpu: 1 + memory: 4Gi + # we do not need the disk space, but Kubernetes will count some logs that it emits + # about our containers towards our containers ephemeral usage and if we requested + # 0 storage we could end up getting evicted unnecessarily when the node is under disk pressure. + ephemeral-storage: "100Mi" + limits: + memory: 4Gi + +extraEnv: + - name: WARPSTREAM_ADVERTISE_HOSTNAME_STRATEGY + value: auto-ip4 # playground mode defaults to local so we need to override it for tests to pass diff --git a/charts/warpstream-agent/ci/playground-sts-cert-values.yaml b/charts/warpstream-agent/ci/playground-sts-cert-values.yaml new file mode 100644 index 0000000..68cc044 --- /dev/null +++ b/charts/warpstream-agent/ci/playground-sts-cert-values.yaml @@ -0,0 +1,33 @@ +# Need override os we have a static release name for certificates while testing +fullnameOverride: "playground-sts-cert" + +config: + playground: true + +# testing with statefulset +deploymentKind: StatefulSet + +certificate: + # Set to true to enable TLS termination on the WarpStream agent + # see TLS documentation for details https://docs.warpstream.com/warpstream/byoc/advanced-agent-deployment-options/protect-data-in-motion-with-tls-encryption#tls-encryption-overview + enableTLS: true + + # The Kubernetes TLS secret that contains a certificate and private key + # see https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets + secretName: "ci-certificate" + +# overriding resources so it fits on a runner +resources: + requests: + cpu: 1 + memory: 4Gi + # we do not need the disk space, but Kubernetes will count some logs that it emits + # about our containers towards our containers ephemeral usage and if we requested + # 0 storage we could end up getting evicted unnecessarily when the node is under disk pressure. + ephemeral-storage: "100Mi" + limits: + memory: 4Gi + +extraEnv: + - name: WARPSTREAM_ADVERTISE_HOSTNAME_STRATEGY + value: auto-ip4 # playground mode defaults to local so we need to override it for tests to pass diff --git a/charts/warpstream-agent/templates/deployment.yaml b/charts/warpstream-agent/templates/deployment.yaml index 51bc7fa..5baab5e 100644 --- a/charts/warpstream-agent/templates/deployment.yaml +++ b/charts/warpstream-agent/templates/deployment.yaml @@ -74,6 +74,19 @@ spec: {{- range .Values.extraArgs }} - {{ . }} {{- end }} + {{- with .Values.certificate }} + {{- if .enableTLS }} + - -kafkaTLS=true + - -tlsServerCertFile=/etc/private/ssl/agent/tls.crt + - -tlsServerPrivateKeyFile=/etc/private/ssl/agent/tls.key + {{- if .mtls.enabled }} + - -requireMTLSAuthentication=true + {{- if .mtls.certificateAuthoritySecretKeyRef.name }} + - -tlsClientCACertFile=/etc/private/ssl/agent-mtls/{{ .mtls.certificateAuthoritySecretKeyRef.key }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} readinessProbe: httpGet: path: /v1/status @@ -151,13 +164,25 @@ spec: - name: schema-registry containerPort: 9094 protocol: TCP - {{- if or (.Values.volumeMounts) (not .Values.config.playground) }} + {{- if or (.Values.volumeMounts) (not .Values.config.playground) (.Values.certificate) }} volumeMounts: {{- if not .Values.config.playground }} - name: agent-key mountPath: /app/agent-key readOnly: true {{- end }} + {{- with .Values.certificate }} + {{- if .enableTLS }} + - name: agent-certs + mountPath: "/etc/private/ssl/agent" + readOnly: true + {{- if .mtls.certificateAuthoritySecretKeyRef.name }} + - name: agent-mtls-certs + mountPath: "/etc/private/ssl/agent-mtls" + readOnly: true + {{- end }} + {{- end }} + {{- end }} {{- with .Values.volumeMounts }} {{- toYaml . | nindent 12 }} {{- end }} @@ -186,13 +211,25 @@ spec: topologySpreadConstraints: {{- toYaml . | nindent 8 }} {{- end }} - {{- if or (.Values.volumes) (not .Values.config.playground) }} + {{- if or (.Values.volumes) (not .Values.config.playground) (.Values.certificate) }} volumes: {{- if not .Values.config.playground }} - name: agent-key secret: secretName: {{ include "warpstream-agent.agentKey.secretName" . }} {{- end }} + {{- with .Values.certificate }} + {{- if .enableTLS }} + - name: agent-certs + secret: + secretName: {{ .secretName }} + {{- if .mtls.certificateAuthoritySecretKeyRef.name }} + - name: agent-mtls-certs + secret: + secretName: {{ .mtls.certificateAuthoritySecretKeyRef.name }} + {{- end }} + {{- end }} + {{- end }} {{- with .Values.volumes }} {{- toYaml . | nindent 8 }} {{- end }} diff --git a/charts/warpstream-agent/templates/tests/test-connection.yaml b/charts/warpstream-agent/templates/tests/test-connection.yaml index 2276862..8c41010 100644 --- a/charts/warpstream-agent/templates/tests/test-connection.yaml +++ b/charts/warpstream-agent/templates/tests/test-connection.yaml @@ -16,9 +16,49 @@ spec: - kcmd - -bootstrap-host - '{{ include "warpstream-agent.fullname" . }}' + {{- with .Values.certificate }} + {{- if .enableTLS }} + - -tls + - -tlsServerCACertFile=/etc/private/ssl/agent/ca.crt + {{- end }} + {{- if .mtls.enabled }} + - -tlsClientCertFile=/etc/private/ssl/agent-mtls/tls.crt + - -tlsClientPrivateKeyFile=/etc/private/ssl/agent-mtls/tls.key + {{- end }} + {{- end }} - -type - diagnose-connection + {{- if .Values.certificate }} + volumeMounts: + {{- with .Values.certificate }} + {{- if .enableTLS }} + - mountPath: "/etc/private/ssl/agent" + name: agent-ca + readOnly: true + {{- end }} + {{- if .mtls.enabled }} + - mountPath: "/etc/private/ssl/agent-mtls" + name: agent-mtls + readOnly: true + {{- end }} + {{- end }} + {{- end }} restartPolicy: Never + {{- if .Values.certificate }} + volumes: + {{- with .Values.certificate }} + {{- if .enableTLS }} + - name: agent-ca + secret: + secretName: ci-certificate-ca + {{- end }} + {{- if .mtls.enabled }} + - name: agent-mtls + secret: + secretName: ci-certificate-client + {{- end }} + {{- end }} + {{- end }} {{- with .Values.affinity }} affinity: {{- toYaml . | nindent 8 }} @@ -43,9 +83,49 @@ spec: - kcmd - -bootstrap-host - '{{ include "warpstream-agent.fullname" . }}-kafka' + {{- with .Values.certificate }} + {{- if .enableTLS }} + - -tls + - -tlsServerCACertFile=/etc/private/ssl/agent/ca.crt + {{- end }} + {{- if .mtls.enabled }} + - -tlsClientCertFile=/etc/private/ssl/agent-mtls/tls.crt + - -tlsClientPrivateKeyFile=/etc/private/ssl/agent-mtls/tls.key + {{- end }} + {{- end }} - -type - diagnose-connection + {{- if .Values.certificate }} + volumeMounts: + {{- with .Values.certificate }} + {{- if .enableTLS }} + - mountPath: "/etc/private/ssl/agent" + name: agent-ca + readOnly: true + {{- end }} + {{- if .mtls.enabled }} + - mountPath: "/etc/private/ssl/agent-mtls" + name: agent-mtls + readOnly: true + {{- end }} + {{- end }} + {{- end }} restartPolicy: Never + {{- if .Values.certificate }} + volumes: + {{- with .Values.certificate }} + {{- if .enableTLS }} + - name: agent-ca + secret: + secretName: ci-certificate-ca + {{- end }} + {{- if .mtls.enabled }} + - name: agent-mtls + secret: + secretName: ci-certificate-client + {{- end }} + {{- end }} + {{- end }} {{- with .Values.affinity }} affinity: {{- toYaml . | nindent 8 }} diff --git a/charts/warpstream-agent/values.yaml b/charts/warpstream-agent/values.yaml index 587e590..ca3d1b1 100644 --- a/charts/warpstream-agent/values.yaml +++ b/charts/warpstream-agent/values.yaml @@ -43,6 +43,28 @@ statefulSetConfig: # see https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies type: RollingUpdate +certificate: + # Set to true to enable TLS termination on the WarpStream agent + # see TLS documentation for details https://docs.warpstream.com/warpstream/byoc/advanced-agent-deployment-options/protect-data-in-motion-with-tls-encryption#tls-encryption-overview + enableTLS: false + + # The Kubernetes TLS secret that contains a certificate and private key + # see https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets + secretName: "" + + mtls: + # Set to true to enable mutual TLS on the WarpStream agent, requires enableTLS set to true + # see mTLS documentation for details https://docs.warpstream.com/warpstream/byoc/authentication/mutual-tls-mtls + enabled: false + + # The secret key reference for the certificate authority public key + # If not set, the container's root certificate pool will be used for mtls client certificate verification + # It is recommend to always set this to your CA's public key and not rely on the root certificate pool + # see mTLS documentation for details on why using the root certificate pool is not recommended + certificateAuthoritySecretKeyRef: + name: "" + key: "" + terminationGracePeriodSeconds: 300 serviceAccount: