Skip to content

Commit 44e4a21

Browse files
jkhelilcursoragent
andcommitted
feat(openshift): add mTLS for Prometheus metrics
Secure component metrics endpoints with mutual TLS on OpenShift. Each reconciler syncs the Prometheus client CA bundle from kube-system/extension-apiserver-authentication into the component namespace as a metrics-client-ca ConfigMap. OpenShift's serving-cert controller is triggered via annotation on each metrics Service to provision a per-component TLS Secret. Two new manifest transformers (InjectMetricsServingCert, ApplyMetricsTLS) wire the Secret and ConfigMap as volumes and inject METRICS_PROMETHEUS_TLS_* env vars so that the knative/pkg prometheus.Server enables mTLS with require client auth. ServiceMonitor resources are updated with scheme: https, scrapeClass tls-client-certificate-auth, and tlsConfig.serverName. The existing UpdateServiceMonitorTargetNamespace transformer is extended to also patch the namespace segment inside serverName at runtime. Relates-To: SRVKP-8172 Signed-off-by: Jawed khelil <jkhelil@redhat.com> Assisted-by: Claude Sonnet 4.6 (via Cursor) Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 8d1979d commit 44e4a21

16 files changed

Lines changed: 621 additions & 24 deletions

File tree

cmd/openshift/operator/kodata/openshift-monitoring/00-monitoring.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,14 @@ metadata:
5858
spec:
5959
endpoints:
6060
- interval: 10s
61-
port: http-metrics
61+
port: https-metrics
6262
honorLabels: true
63+
scheme: https
64+
tlsConfig:
65+
caFile: /etc/prometheus/configmaps/serving-certs-ca-bundle/service-ca.crt
66+
certFile: /etc/prometheus/secrets/metrics-client-certs/tls.crt
67+
keyFile: /etc/prometheus/secrets/metrics-client-certs/tls.key
68+
serverName: tekton-pipelines-controller.openshift-pipelines.svc
6369
jobLabel: app
6470
namespaceSelector:
6571
matchNames:

cmd/openshift/operator/kodata/openshift-monitoring/01-trigger-monitoring.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,13 @@ metadata:
2525
spec:
2626
endpoints:
2727
- interval: 10s
28-
port: http-metrics
28+
port: https-metrics
29+
scheme: https
30+
tlsConfig:
31+
caFile: /etc/prometheus/configmaps/serving-certs-ca-bundle/service-ca.crt
32+
certFile: /etc/prometheus/secrets/metrics-client-certs/tls.crt
33+
keyFile: /etc/prometheus/secrets/metrics-client-certs/tls.key
34+
serverName: tekton-triggers-controller.openshift-pipelines.svc
2935
jobLabel: app
3036
namespaceSelector:
3137
matchNames:

cmd/openshift/operator/kodata/openshift-monitoring/02-chains-monitoring.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,13 @@ metadata:
2525
spec:
2626
endpoints:
2727
- interval: 10s
28-
port: http-metrics
28+
port: https-metrics
29+
scheme: https
30+
tlsConfig:
31+
caFile: /etc/prometheus/configmaps/serving-certs-ca-bundle/service-ca.crt
32+
certFile: /etc/prometheus/secrets/metrics-client-certs/tls.crt
33+
keyFile: /etc/prometheus/secrets/metrics-client-certs/tls.key
34+
serverName: tekton-chains-metrics.openshift-pipelines.svc
2935
jobLabel: app
3036
namespaceSelector:
3137
matchNames:

cmd/openshift/operator/kodata/openshift-monitoring/03-pipeline-webhook-monitoring.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ spec:
2626
endpoints:
2727
- interval: 10s
2828
port: http-metrics
29+
scheme: http
2930
jobLabel: app
3031
namespaceSelector:
3132
matchNames:

cmd/openshift/operator/kodata/openshift-monitoring/05-results-monitoring.yaml

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,14 @@ metadata:
2525
spec:
2626
endpoints:
2727
- interval: 10s
28-
port: metrics
28+
port: https-metrics
29+
honorLabels: true
30+
scheme: https
31+
tlsConfig:
32+
caFile: /etc/prometheus/configmaps/serving-certs-ca-bundle/service-ca.crt
33+
certFile: /etc/prometheus/secrets/metrics-client-certs/tls.crt
34+
keyFile: /etc/prometheus/secrets/metrics-client-certs/tls.key
35+
serverName: tekton-results-watcher.openshift-pipelines.svc
2936
jobLabel: app
3037
namespaceSelector:
3138
matchNames:
@@ -47,7 +54,14 @@ metadata:
4754
spec:
4855
endpoints:
4956
- interval: 10s
50-
port: prometheus
57+
port: https-prometheus
58+
honorLabels: true
59+
scheme: https
60+
tlsConfig:
61+
caFile: /etc/prometheus/configmaps/serving-certs-ca-bundle/service-ca.crt
62+
certFile: /etc/prometheus/secrets/metrics-client-certs/tls.crt
63+
keyFile: /etc/prometheus/secrets/metrics-client-certs/tls.key
64+
serverName: tekton-results-api-service.openshift-pipelines.svc
5165
jobLabel: app
5266
namespaceSelector:
5367
matchNames:

cmd/openshift/operator/kodata/openshift-monitoring/06-pruner-monitoring.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,13 @@ metadata:
2525
spec:
2626
endpoints:
2727
- interval: 10s
28-
port: http-metrics
28+
port: https-metrics
29+
scheme: https
30+
tlsConfig:
31+
caFile: /etc/prometheus/configmaps/serving-certs-ca-bundle/service-ca.crt
32+
certFile: /etc/prometheus/secrets/metrics-client-certs/tls.crt
33+
keyFile: /etc/prometheus/secrets/metrics-client-certs/tls.key
34+
serverName: tekton-pruner-controller.openshift-pipelines.svc
2935
jobLabel: app
3036
namespaceSelector:
3137
matchNames:
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
Copyright 2026 The Tekton Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package common
18+
19+
import (
20+
"context"
21+
"fmt"
22+
23+
corev1 "k8s.io/api/core/v1"
24+
"k8s.io/apimachinery/pkg/api/errors"
25+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+
"k8s.io/client-go/kubernetes"
27+
"knative.dev/pkg/logging"
28+
)
29+
30+
const (
31+
// MetricsClientCAConfigMap is the name of the ConfigMap synced into each
32+
// component namespace so that the Prometheus metrics server can verify
33+
// the client certificate presented by Prometheus during mTLS scraping.
34+
MetricsClientCAConfigMap = "metrics-client-ca"
35+
36+
// MetricsClientCAKey is the data key within MetricsClientCAConfigMap that
37+
// holds the PEM-encoded CA bundle.
38+
MetricsClientCAKey = "client-ca-file"
39+
40+
// SourceConfigMapName is the authoritative ConfigMap in kube-system that
41+
// contains the Prometheus client CA bundle on OpenShift.
42+
//
43+
// When scrapeClass: tls-client-certificate-auth is set on a ServiceMonitor,
44+
// CMO configures Prometheus to present metrics-client-certs as the scraping
45+
// client certificate. That cert is signed by the kubernetes.io/kube-apiserver-client
46+
// signer (kubelet-signer), which is included in extension-apiserver-authentication.
47+
SourceConfigMapName = "extension-apiserver-authentication"
48+
SystemNamespace = "kube-system"
49+
)
50+
51+
// EnsureMetricsClientCA reads the Prometheus client CA from
52+
// kube-system/extension-apiserver-authentication and creates-or-updates
53+
// the metrics-client-ca ConfigMap in targetNamespace.
54+
//
55+
// The ConfigMap is mounted by Tekton component containers so that the
56+
// knative prometheus.Server can verify the Prometheus client certificate
57+
// during mTLS scraping (METRICS_PROMETHEUS_TLS_CLIENT_CA_FILE).
58+
func EnsureMetricsClientCA(ctx context.Context, kubeClient kubernetes.Interface, targetNamespace string) error {
59+
logger := logging.FromContext(ctx)
60+
61+
src, err := kubeClient.CoreV1().ConfigMaps(SystemNamespace).Get(
62+
ctx, SourceConfigMapName, metav1.GetOptions{})
63+
if err != nil {
64+
return fmt.Errorf("reading %s/%s: %w", SystemNamespace, SourceConfigMapName, err)
65+
}
66+
67+
caBundle, ok := src.Data[MetricsClientCAKey]
68+
if !ok {
69+
return fmt.Errorf("%s/%s has no %q key", SystemNamespace, SourceConfigMapName, MetricsClientCAKey)
70+
}
71+
72+
cmClient := kubeClient.CoreV1().ConfigMaps(targetNamespace)
73+
74+
existing, err := cmClient.Get(ctx, MetricsClientCAConfigMap, metav1.GetOptions{})
75+
if err != nil && !errors.IsNotFound(err) {
76+
return fmt.Errorf("getting %s/%s: %w", targetNamespace, MetricsClientCAConfigMap, err)
77+
}
78+
79+
if errors.IsNotFound(err) {
80+
logger.Infof("Creating %s/%s", targetNamespace, MetricsClientCAConfigMap)
81+
desired := &corev1.ConfigMap{
82+
ObjectMeta: metav1.ObjectMeta{
83+
Name: MetricsClientCAConfigMap,
84+
Namespace: targetNamespace,
85+
Labels: map[string]string{
86+
"app.kubernetes.io/part-of": "tekton-pipelines",
87+
},
88+
},
89+
Data: map[string]string{
90+
MetricsClientCAKey: caBundle,
91+
},
92+
}
93+
_, err = cmClient.Create(ctx, desired, metav1.CreateOptions{})
94+
return err
95+
}
96+
97+
// Already exists — update only if the CA bundle has changed.
98+
if existing.Data[MetricsClientCAKey] == caBundle {
99+
logger.Debugf("%s/%s is up to date", targetNamespace, MetricsClientCAConfigMap)
100+
return nil
101+
}
102+
103+
logger.Infof("Updating %s/%s (CA bundle changed)", targetNamespace, MetricsClientCAConfigMap)
104+
updated := existing.DeepCopy()
105+
if updated.Data == nil {
106+
updated.Data = map[string]string{}
107+
}
108+
updated.Data[MetricsClientCAKey] = caBundle
109+
_, err = cmClient.Update(ctx, updated, metav1.UpdateOptions{})
110+
return err
111+
}

0 commit comments

Comments
 (0)