diff --git a/alerts/README.md b/alerts/README.md index ac939fa5..a7e17f8c 100644 --- a/alerts/README.md +++ b/alerts/README.md @@ -60,7 +60,10 @@ Greenhouse regularly performs integration tests that are bundled with **alerts** | Name | Description | Value | | ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- | ------- | +| `global.caCert` | Additional caCert to add to the CA bundle | `""` | | `alerts.commonLabels` | Labels to apply to all resources | `{}` | +| `alerts.defaultRules.create` | Creates community Alertmanager alert rules. | `true` | +| `alerts.defaultRules.labels` | kube-monitoring `plugin: ` to evaluate Alertmanager rules. | `{}` | | `alerts.alertmanager.enabled` | Deploy Prometheus Alertmanager | `true` | | `alerts.alertmanager.annotations` | Annotations for Alertmanager | `{}` | | `alerts.alertmanager.config` | Alertmanager configuration directives. | `{}` | @@ -76,18 +79,15 @@ Greenhouse regularly performs integration tests that are bundled with **alerts** | `alerts.alertmanager.alertmanagerConfig.webhook.routes[].name` | Name of the webhook route. | `""` | | `alerts.alertmanager.alertmanagerConfig.webhook.routes[].url` | Webhook url to post alerts to. | `""` | | `alerts.alertmanager.alertmanagerConfig.webhook.routes[].matchers` | List of matchers that the alert's label should match. matchType , name , regex , value | `[]` | +| `alerts.alertmanager.alertmanagerSpec.alertmanagerConfiguration` | AlermanagerConfig to be used as top level configuration | `false` | +| `alerts.alertmanager.alertmanagerConfig.webhook.routes[].matchers` | List of matchers that the alert's label should match. matchType , name , regex , value | `[]` | -| `alerts.auth.secretName` | Use custom secret for Alertmanager authentication | `""` | -| `alerts.auth.autoGenerateCert.enabled` | TLS Certificate Option 1: Use Helm to automatically generate self-signed certificate. | `true` | -| `alerts.auth.autoGenerateCert.recreate` | If set to true, new key/certificate is generated on Helm upgrade. | `false` | -| `alerts.auth.autoGenerateCert.certPeriodDays` | Cert period time in days. The default is 365 days. | `365` | -| `alerts.auth.certFile` | Path to your own PEM-encoded certificate. | `""` | -| `alerts.auth.keyFile` | Path to your own PEM-encoded private key. | `""` | -| `alerts.auth.caFile` | Path to CA cert. | `""` | +### cert-manager options -| `alerts.defaultRules.create` | Creates community Alertmanager alert rules. | `true` | -| `alerts.defaultRules.labels` | kube-monitoring `plugin: ` to evaluate Alertmanager rules. | `{}` | -| `alerts.alertmanager.alertmanagerSpec.alertmanagerConfiguration` | AlermanagerConfig to be used as top level configuration | `false` | +| `alerts.certManager.enabled` | Creates `jetstack/cert-manager` resources to generate Issuer and Certificates for Prometheus authentication. | `true` | +| `alerts.certManager.rootCert.duration` | Duration, how long the root certificate is valid. | `"5y"` | +| `alerts.certManager.admissionCert.duration` | Duration, how long the admission certificate is valid. | `"1y"` | +| `alerts.certManager.issuerRef.name` | Name of the existing Issuer to use. | `""` | ### Supernova options @@ -216,11 +216,9 @@ alertmanagerConfiguration: ## TLS Certificate Requirement -Greenhouse onboarded Prometheus installations need to communicate with the Alertmanager component to enable advanced processing of alerts. The Alertmanager Ingress requires a TLS certificate to be configured and trusted by Prometheus to ensure the communication. There are various ways in which you can generate/configure the required TLS certificate. +Greenhouse onboarded Prometheus installations need to communicate with the Alertmanager component to enable processing of alerts. If an Alertmanager Ingress is enabled, this requires a TLS certificate to be configured and trusted by Alertmanger to ensure the communication. To enable automatic self-signed TLS certificate provisioning via cert-manager, set the `alerts.certManager.enabled` value to `true`. - - You can use an automatically generated self-signed certificate by setting `alerts.auth.autoGenerateCert.enabled` to `true`. Helm will create a self-signed cert and a secret for you. - - You can use your own generated self-signed certificate by setting `alerts.auth.autoGenerateCert.enabled` to `false`. You should provide the necessary values to `alerts.auth.certFile`, `alerts.auth.keyFile`, and `alerts.auth.caFile`. - - You can also sideload custom certificate by disabling `alerts.auth.autoGenerateCert.enabled` to `false` while setting your custom cert secret name in `alerts.auth.secretName` +Note: Prerequisite of this feature is a installed [jetstack/cert-manager](https://github.com/jetstack/cert-manager) which can be implemented via the Greenhouse [cert-manager](https://github.com/cloudoperators/greenhouse-extensions/tree/main/cert-manager) Plugin. ## Examples diff --git a/alerts/charts/Chart.yaml b/alerts/charts/Chart.yaml index a716b759..a3f327e2 100644 --- a/alerts/charts/Chart.yaml +++ b/alerts/charts/Chart.yaml @@ -8,7 +8,7 @@ maintainers: name: alerts sources: - https://github.com/cloudoperators/greenhouse-extensions -version: 0.18.0 +version: 0.19.0 keywords: - prometheus-alertmanager dependencies: diff --git a/alerts/ci/test-values.yaml b/alerts/charts/ci/test-values.yaml similarity index 86% rename from alerts/ci/test-values.yaml rename to alerts/charts/ci/test-values.yaml index 93171684..f928beb3 100644 --- a/alerts/ci/test-values.yaml +++ b/alerts/charts/ci/test-values.yaml @@ -6,3 +6,5 @@ alerts: enabled: true hosts: - dummy-host + certManager: + enabled: false diff --git a/alerts/charts/templates/_helper.tpl b/alerts/charts/templates/_helper.tpl index be36810d..37f634b9 100644 --- a/alerts/charts/templates/_helper.tpl +++ b/alerts/charts/templates/_helper.tpl @@ -47,36 +47,3 @@ plugin: {{ $root.Release.Name }} {{- end }} {{- end }} {{- end }} - -{{/* -Return certificate and CA for Prometheus to push alerts. -It handles variants when a cert has to be generated by Helm, -a cert is loaded from an existing secret or is provided via `.Values` -*/}} -{{- define "alerts.generateCert" -}} -{{- $caCertEnc := "" }} -{{- $certCrtEnc := "" }} -{{- $certKeyEnc := "" }} -{{- if .Values.alerts.auth.autoGenerateCert.enabled }} -{{- $prevSecret := (lookup "v1" "Secret" .Release.Namespace (default (printf "%s-monitoring-ca" .Release.Namespace) .Values.alerts.auth.secretName )) }} -{{- if and (not .Values.alerts.auth.autoGenerateCert.recreate) $prevSecret }} -{{- $certCrtEnc = index $prevSecret "data" "tls.crt" }} -{{- $certKeyEnc = index $prevSecret "data" "tls.key" }} -{{- $caCertEnc = index $prevSecret "data" "ca.crt" }} -{{- else }} -{{- $altNames := list ( printf "%s-alertmanager.%s" .Release.Name .Release.Namespace ) ( printf "%s-alertmanager.%s.svc" .Release.Name .Release.Namespace ) -}} -{{- $tmpperioddays := int .Values.alerts.auth.autoGenerateCert.certPeriodDays | default 365 }} -{{- $ca := genCA "greenhouse-monitoring-ca" $tmpperioddays }} -{{- $cert := genSignedCert .Release.Name nil $altNames $tmpperioddays $ca }} -{{- $certCrtEnc = b64enc $cert.Cert }} -{{- $certKeyEnc = b64enc $cert.Key }} -{{- $caCertEnc = b64enc $ca.Cert }} -{{- end }} -{{- else }} -{{- $certCrtEnc = .Files.Get .Values.alerts.auth.certFile | b64enc }} -{{- $certKeyEnc = .Files.Get .Values.alerts.auth.keyFile | b64enc }} -{{- $caCertEnc = .Files.Get .Values.alerts.auth.caFile | b64enc }} -{{- end }} -{{- $result := dict "crt" $certCrtEnc "key" $certKeyEnc "ca" $caCertEnc }} -{{- $result | toYaml }} -{{- end }} diff --git a/alerts/charts/templates/am-ca-bundle-secret.yaml b/alerts/charts/templates/am-ca-bundle-secret.yaml deleted file mode 100644 index 08995739..00000000 --- a/alerts/charts/templates/am-ca-bundle-secret.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if and .Values.alerts.alertmanager.enabled .Values.alerts.alertmanager.ingress.enabled }} -{{- $extCASecret := (lookup "v1" "Secret" "greenhouse" "ingress-ca-cert").data }} -{{- $extCABundle := get $extCASecret "ca.crt" | b64dec }} -{{- $intCASecret := (lookup "v1" "Secret" $.Release.Namespace (printf "%s-%s" $.Release.Namespace "monitoring-ca")).data }} -{{- $intCABundle := get $intCASecret "tls.crt" | b64dec }} -apiVersion: v1 -kind: Secret -type: Opaque -metadata: - name: {{ $.Release.Namespace }}-ca-bundle - labels: -{{- include "kube-prometheus-stack.labels" . | indent 4 }} - annotations: - "helm.sh/hook": post-install, post-upgrade - "helm.sh/hook-weight": "5" -data: - ca.crt: {{ printf "%s%s" $extCABundle $intCABundle | b64enc | quote }} -{{- end }} diff --git a/alerts/charts/templates/am-webhook-secrets.yaml b/alerts/charts/templates/am-webhook-secrets.yaml deleted file mode 100644 index 895804bc..00000000 --- a/alerts/charts/templates/am-webhook-secrets.yaml +++ /dev/null @@ -1,23 +0,0 @@ -{{- if or .Values.alerts.alertmanagerConfig.slack.routes .Values.alerts.alertmanagerConfig.webhook.routes }} -apiVersion: v1 -kind: Secret -type: Opaque - -metadata: - name: {{ $.Release.Name }}-webhook-urls - labels: -{{- include "kube-prometheus-stack.labels" . | indent 4 }} - annotations: - "helm.sh/hook": pre-install, pre-upgrade -data: -{{- if .Values.alerts.alertmanagerConfig.slack.routes }} -{{- range $route := .Values.alerts.alertmanagerConfig.slack.routes }} - {{ $route.name }}: {{ $route.webhookURL | b64enc | quote }} -{{- end }} -{{- end }} -{{- if .Values.alerts.alertmanagerConfig.webhook.routes }} -{{- range $route := .Values.alerts.alertmanagerConfig.webhook.routes }} - {{ $route.name }}: {{ $route.url | b64enc | quote }} -{{- end }} -{{- end }} -{{- end }} diff --git a/alerts/charts/templates/ca-secret-issuer-cert.yaml b/alerts/charts/templates/ca-secret-issuer-cert.yaml deleted file mode 100644 index b6bf7780..00000000 --- a/alerts/charts/templates/ca-secret-issuer-cert.yaml +++ /dev/null @@ -1,55 +0,0 @@ -{{- if and .Values.alerts.alertmanager.enabled .Values.alerts.alertmanager.ingress.enabled }} -{{- $cert := fromYaml (include "alerts.generateCert" .) }} -{{- $caCertEnc := $cert.ca }} -{{- $certCrtEnc := $cert.crt }} -{{- $certKeyEnc := $cert.key }} -apiVersion: v1 -kind: Secret -type: kubernetes.io/tls -metadata: - annotations: - "helm.sh/hook": "pre-install,pre-upgrade" - labels: -{{- include "kube-prometheus-stack.labels" . | nindent 4 }} - name: {{ $.Release.Namespace }}-monitoring-ca - namespace: {{ .Release.Namespace }} -data: - tls.crt: {{ $certCrtEnc }} - tls.key: {{ $certKeyEnc }} - ca.crt: {{ $caCertEnc }} -{{- if .Capabilities.APIVersions.Has "cert-manager.io/v1" }} ---- -apiVersion: cert-manager.io/v1 -kind: Issuer -metadata: - annotations: - "helm.sh/hook": "pre-install,pre-upgrade" - "helm.sh/hook-delete-policy": "before-hook-creation" - labels: -{{- include "kube-prometheus-stack.labels" . | indent 4 }} - name: {{ $.Release.Namespace }}-monitoring-issuer - namespace: {{ $.Release.Namespace }} -spec: - ca: - secretName: {{ $.Release.Namespace }}-monitoring-ca ---- -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - annotations: - "helm.sh/hook": "pre-install,pre-upgrade" - "helm.sh/hook-delete-policy": "before-hook-creation" - labels: -{{- include "kube-prometheus-stack.labels" . | indent 4 }} - name: {{ $.Release.Namespace }}-prometheus-auth - namespace: {{ $.Release.Namespace }} -spec: - dnsNames: - - {{ .Values.global.greenhouse.baseDomain | default "greenhouse.io" }} - issuerRef: - group: cert-manager.io - kind: Issuer - name: {{ $.Release.Namespace }}-monitoring-issuer - secretName: tls-{{ $.Release.Namespace }}-prometheus-auth -{{- end }} -{{- end }} diff --git a/alerts/charts/templates/certmanager.yaml b/alerts/charts/templates/certmanager.yaml new file mode 100644 index 00000000..fbec7dbc --- /dev/null +++ b/alerts/charts/templates/certmanager.yaml @@ -0,0 +1,85 @@ +{{- if .Values.alerts.certManager.enabled -}} +{{- if not .Values.alerts.certManager.issuerRef -}} +# Create a selfsigned Issuer in order to create a root CA certificate for the org +# signing alertmanager serving certificates +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ .Release.Namespace }}-prometheus-issuer + labels: +{{- include "kube-prometheus-stack.labels" . | indent 4 }} +spec: + selfSigned: {} +--- +# Generate a CA Certificate used to sign certificates for the alertmanager +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ .Release.Namespace }}-prometheus-root-cert + labels: +{{- include "kube-prometheus-stack.labels" . | indent 4 }} +spec: + secretName: {{ .Release.Namespace }}-prometheus-root-cert + duration: {{ .Values.alerts.certManager.rootCert.duration | default "43800h0m0s" | quote }} + issuerRef: + name: {{ .Release.Namespace }}-prometheus-issuer + commonName: "ca.prometheus.greenhouse" + isCA: true +--- +# Create an Issuer that uses the above generated CA certificate to issue certs +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ .Release.Namespace }}-prometheus-root-issuer + labels: +{{- include "kube-prometheus-stack.labels" . | indent 4 }} +spec: + ca: + secretName: {{ .Release.Namespace }}-root-cert +{{- end }} +--- +# generate a server certificate for the alertmanager to use +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ include "kube-prometheus-stack.fullname" . }}-cert + labels: +{{- include "kube-prometheus-stack.labels" . | indent 4 }} +spec: + secretName: tls-{{ include "kube-prometheus-stack.fullname" . }}-cert + duration: {{ .Values.alerts.certManager.admissionCert.duration | default "8760h0m0s" | quote }} + issuerRef: + {{- if .Values.alerts.certManager.issuerRef }} + {{- toYaml .Values.alerts.certManager.issuerRef | nindent 4 }} + {{- else }} + name: {{ .Release.Namespace }}-root-issuer + {{- end }} + dnsNames: + - {{ include "kube-prometheus-stack.fullname" . }} + - {{ include "kube-prometheus-stack.fullname" . }}.{{ .Release.Namespace }} + - {{ include "kube-prometheus-stack.fullname" . }}.{{ .Release.Namespace }}.svc +{{- if and .Values.alerts.alertmanager.ingress.enabled .Values.alerts.alertmanager.ingress.hosts }} +{{ toYaml .Values.alerts.alertmanager.ingress.hosts | indent 2 }} +{{- end }} +--- +# generate a shared client certificate for prometheus to use +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: prometheus-{{ .Release.Namespace }}-cert + labels: +{{- include "kube-prometheus-stack.labels" . | indent 4 }} +spec: + secretName: tls-prometheus-{{ .Release.Namespace }} + duration: {{ .Values.alerts.certManager.admissionCert.duration | default "8760h0m0s" | quote }} + issuerRef: + {{- if .Values.alerts.certManager.issuerRef }} + {{- toYaml .Values.alerts.certManager.issuerRef | nindent 4 }} + {{- else }} + name: {{ .Release.Namespace }}-root-issuer + {{- end }} + dnsNames: +{{- if .Values.global.greenhouse.baseDomain }} + - {{ printf "*.s%" .Values.global.greenhouse.baseDomain }} +{{- end }} +{{- end -}} diff --git a/alerts/charts/templates/hooks/caBundle-secret.yaml b/alerts/charts/templates/hooks/caBundle-secret.yaml new file mode 100644 index 00000000..a97d58b3 --- /dev/null +++ b/alerts/charts/templates/hooks/caBundle-secret.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.alerts.alertmanager.enabled .Values.alerts.alertmanager.ingress.enabled .Values.global.caCert }} +{{- $extCABundle := .Values.global.caCert }} +{{- $intCASecret := (lookup "v1" "Secret" $.Release.Namespace (printf "%s-%s" (include "kube-prometheus-stack.fullname") "-root-cert")).data }} +{{- $intCABundle := get $intCASecret "ca.crt" | b64dec }} +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: {{ $.Release.Namespace }}-ca-bundle + labels: +{{- include "kube-prometheus-stack.labels" . | indent 4 }} + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + ## Ensure this is run before release installation and upgrade + "helm.sh/hook-weight": "-5" +data: + ca.crt: {{ printf "%s%s" $extCABundle $intCABundle | b64enc | quote }} +{{- end }} diff --git a/alerts/charts/templates/tests/test-alerts-config.yaml b/alerts/charts/templates/tests/test-alerts-config.yaml index cfe9d719..3b0b65fd 100644 --- a/alerts/charts/templates/tests/test-alerts-config.yaml +++ b/alerts/charts/templates/tests/test-alerts-config.yaml @@ -49,11 +49,11 @@ data: } {{- end }} - {{- if and .Values.alerts.auth.autoGenerateCert.enabled .Values.alerts.alertmanager.ingress.enabled .Values.alerts.alertmanager.ingress.hosts (.Capabilities.APIVersions.Has "cert-manager.io/v1") }} - @test "Verify certificate creation and validation against the API endpoint of the alert manager" { + {{- if and .Values.alerts.alertmanager.ingress.enabled .Values.alerts.alertmanager.ingress.hosts .Values.alerts.certManager.enabled }} + @test "Generated server certificate for the Prometheus Alertmanager to use" { verify "there is 1 issuer named '{{ .Release.Namespace }}-monitoring-issuer'" - verify "there is 1 certificate named '{{ .Release.Namespace }}-prometheus-auth'" - verify "there is 1 secret named 'tls-{{ .Release.Namespace }}-prometheus-auth'" + verify "there is 1 certificate named '{{ include "kube-prometheus-stack.fullname" . }}-cert'" + verify "there is 1 secret named '{{ include "kube-prometheus-stack.fullname" . }}-cert'" url="https://{{ first .Values.alerts.alertmanager.ingress.hosts }}/-/healthy" diff --git a/alerts/charts/templates/tests/test-alerts.yaml b/alerts/charts/templates/tests/test-alerts.yaml index 71c4965d..3f8631e6 100644 --- a/alerts/charts/templates/tests/test-alerts.yaml +++ b/alerts/charts/templates/tests/test-alerts.yaml @@ -20,20 +20,20 @@ spec: - name: tests mountPath: /tests readOnly: true - {{- if and .Values.alerts.auth.autoGenerateCert.enabled (.Capabilities.APIVersions.Has "cert-manager.io/v1") }} + {{- if and .Values.alerts.alertmanager.ingress.enabled .Values.alerts.alertmanager.ingress.hosts .Values.alerts.certManager.enabled }} - name: tls-cert mountPath: /tls-assets readOnly: true - {{- end }} + {{- end }} volumes: - name: tests configMap: name: {{ .Release.Name }}-test - {{- if and .Values.alerts.auth.autoGenerateCert.enabled (.Capabilities.APIVersions.Has "cert-manager.io/v1") }} + {{- if and .Values.alerts.alertmanager.ingress.enabled .Values.alerts.alertmanager.ingress.hosts .Values.alerts.certManager.enabled }} - name: tls-cert secret: defaultMode: 420 secretName: {{ print "tls-%s-prometheus-auth" $.Release.Namespace }} - {{- end }} + {{- end }} restartPolicy: Never {{- end -}} diff --git a/alerts/charts/values.yaml b/alerts/charts/values.yaml index 0dc2b8cb..a62f1218 100644 --- a/alerts/charts/values.yaml +++ b/alerts/charts/values.yaml @@ -3,34 +3,30 @@ global: ## commonLabels: {} + ## Additional caCert to add to the CA bundle + ## + caCert: "" + + ## common greenhouse values to use + ## + greenhouse: + # base domain of the greenhouse organisation + baseDomain: + # kube-prometheus-stack configuration scoped to alerts alerts: - ## Authentication configuration for Alertmanager - ## - auth: - - ## Use existing secret for Alertmanager authentication - secretName: "" - - ## TLS Certificate Option 1: Use Helm to automatically generate self-signed certificate. - autoGenerateCert: - enabled: true - # If set to true, new key/certificate is generated on helm upgrade. - recreate: false - # Cert period time in days. The default is 365 days. - certPeriodDays: 365 - - ## TLS Certificate Option 2: Use your own self-signed certificate. - ## The chart reads the contents of the file paths with the helm .Files.Get function. - ## Refer to this doc https://helm.sh/docs/chart_template_guide/accessing_files/ to understand - ## limitations of file paths accessible to the chart. - ## Path to your own PEM-encoded certificate. - certFile: "" - ## Path to your own PEM-encoded private key. - keyFile: "" - ## Path to the CA cert. - caFile: "" + # Use certmanager to generate alertmanager certs + certManager: + enabled: true + # self-signed root certificate + rootCert: + duration: "" # default to be 5y + admissionCert: + duration: "" # default to be 1y + issuerRef: + # name: "issuer" + # kind: "ClusterIssuer" ## Create default rules for monitoring the cluster ## diff --git a/alerts/plugindefinition.yaml b/alerts/plugindefinition.yaml index 7ee95ace..b3d1baca 100644 --- a/alerts/plugindefinition.yaml +++ b/alerts/plugindefinition.yaml @@ -6,7 +6,7 @@ kind: PluginDefinition metadata: name: alerts spec: - version: 2.6.0 + version: 2.7.0 weight: 0 displayName: Alerts description: The Alerts Plugin consists of both Prometheus Alertmanager and Supernova, the holistic alert management UI @@ -15,11 +15,15 @@ spec: helmChart: name: alerts repository: oci://ghcr.io/cloudoperators/greenhouse-extensions/charts - version: 0.18.0 + version: 0.19.0 uiApplication: name: supernova version: "latest" options: + - name: global.caCert + description: Additional caCert to add to the CA bundle + required: false + type: secret # supernova options - name: endpoint description: Alertmanager API Endpoint URL @@ -52,19 +56,13 @@ spec: required: false default: false type: bool - # alertmanager options - - name: alerts.auth.secretName - description: Use custom secret for Alertmanager authentication - required: false - type: string - - name: alerts.auth.autoGenerateCert.enabled - description: TLS Certificate Option 1 - Use Helm to automatically generate self-signed certificate. - required: false + # cert-manager options + - name: alerts.certManager.enabled + description: Needs the `cert-manager` Plugin installed first. Creates `jetstack/cert-manager` resources to generate Issuer and Certificates for Prometheus authentication. + required: true + default: true type: bool - - name: alerts.auth.autoGenerateCert.certPeriodDays - description: Cert period time in days. The default is 365 days. - default: 365 - type: int + # alertmanager options - name: alerts.defaultRules.create description: Additional labels for Alertmanager PrometheusRule alerts. Name of the kube-monitoring Plugin to evaluate Alertmanager alerts. default: true