5
5
"flag"
6
6
"fmt"
7
7
"os"
8
+ "path/filepath"
8
9
"strconv"
9
10
"strings"
10
11
"time"
@@ -19,13 +20,12 @@ import (
19
20
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
20
21
ctrl "sigs.k8s.io/controller-runtime"
21
22
"sigs.k8s.io/controller-runtime/pkg/cache"
23
+ "sigs.k8s.io/controller-runtime/pkg/certwatcher"
22
24
"sigs.k8s.io/controller-runtime/pkg/healthz"
23
25
"sigs.k8s.io/controller-runtime/pkg/log/zap"
24
26
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
25
27
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
26
- ctrlwebhook "sigs.k8s.io/controller-runtime/pkg/webhook"
27
-
28
- buildInfo "github.com/epam/edp-common/pkg/config"
28
+ "sigs.k8s.io/controller-runtime/pkg/webhook"
29
29
30
30
keycloakApi "github.com/epam/edp-keycloak-operator/api/v1"
31
31
keycloakApi1alpha1 "github.com/epam/edp-keycloak-operator/api/v1alpha1"
@@ -57,19 +57,26 @@ const (
57
57
keycloakOperatorLock = "edp-keycloak-operator-lock"
58
58
successReconcileTimeout = "SUCCESS_RECONCILE_TIMEOUT"
59
59
operatorNamespaceEnv = "OPERATOR_NAMESPACE"
60
- managerPort = 9443
61
60
)
62
61
63
- func main () {
64
- var (
65
- metricsAddr string
66
- probeAddr string
67
- enableLeaderElection bool
68
- secureMetrics bool
69
- enableHTTP2 bool
70
- tlsOpts []func (* tls.Config )
71
- )
62
+ func init () {
63
+ utilruntime .Must (clientgoscheme .AddToScheme (scheme ))
64
+ utilruntime .Must (keycloakApi .AddToScheme (scheme ))
65
+ utilruntime .Must (keycloakApi1alpha1 .AddToScheme (scheme ))
66
+ utilruntime .Must (corev1 .AddToScheme (scheme ))
67
+ // +kubebuilder:scaffold:scheme
68
+ }
72
69
70
+ // nolint:gocyclo
71
+ func main () {
72
+ var metricsAddr string
73
+ var metricsCertPath , metricsCertName , metricsCertKey string
74
+ var webhookCertPath , webhookCertName , webhookCertKey string
75
+ var enableLeaderElection bool
76
+ var probeAddr string
77
+ var secureMetrics bool
78
+ var enableHTTP2 bool
79
+ var tlsOpts []func (* tls.Config )
73
80
flag .StringVar (& metricsAddr , "metrics-bind-address" , "0" , "The address the metrics endpoint binds to. " +
74
81
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service." )
75
82
flag .StringVar (& probeAddr , "health-probe-bind-address" , ":8081" , "The address the probe endpoint binds to." )
@@ -78,29 +85,23 @@ func main() {
78
85
"Enabling this will ensure there is only one active controller manager." )
79
86
flag .BoolVar (& secureMetrics , "metrics-secure" , true ,
80
87
"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead." )
88
+ flag .StringVar (& webhookCertPath , "webhook-cert-path" , "" , "The directory that contains the webhook certificate." )
89
+ flag .StringVar (& webhookCertName , "webhook-cert-name" , "tls.crt" , "The name of the webhook certificate file." )
90
+ flag .StringVar (& webhookCertKey , "webhook-cert-key" , "tls.key" , "The name of the webhook key file." )
91
+ flag .StringVar (& metricsCertPath , "metrics-cert-path" , "" ,
92
+ "The directory that contains the metrics server certificate." )
93
+ flag .StringVar (& metricsCertName , "metrics-cert-name" , "tls.crt" , "The name of the metrics server certificate file." )
94
+ flag .StringVar (& metricsCertKey , "metrics-cert-key" , "tls.key" , "The name of the metrics server key file." )
81
95
flag .BoolVar (& enableHTTP2 , "enable-http2" , false ,
82
96
"If set, HTTP/2 will be enabled for the metrics and webhook servers" )
83
-
84
97
opts := zap.Options {
85
98
Development : true ,
86
99
}
87
-
88
100
opts .BindFlags (flag .CommandLine )
89
101
flag .Parse ()
90
102
91
103
ctrl .SetLogger (zap .New (zap .UseFlagOptions (& opts )))
92
104
93
- v := buildInfo .Get ()
94
-
95
- setupLog .Info ("Starting the Keycloak Operator" ,
96
- "version" , v .Version ,
97
- "git-commit" , v .GitCommit ,
98
- "git-tag" , v .GitTag ,
99
- "build-date" , v .BuildDate ,
100
- "go-version" , v .Go ,
101
- "go-client" , v .KubectlVersion ,
102
- "platform" , v .Platform ,
103
- )
104
105
// if the enable-http2 flag is false (the default), http/2 should be disabled
105
106
// due to its vulnerabilities. More specifically, disabling http/2 will
106
107
// prevent from being vulnerable to the HTTP/2 Stream Cancellation and
@@ -109,56 +110,94 @@ func main() {
109
110
// - https://github.com/advisories/GHSA-4374-p667-p6c8
110
111
disableHTTP2 := func (c * tls.Config ) {
111
112
setupLog .Info ("disabling http/2" )
112
-
113
113
c .NextProtos = []string {"http/1.1" }
114
114
}
115
115
116
116
if ! enableHTTP2 {
117
117
tlsOpts = append (tlsOpts , disableHTTP2 )
118
118
}
119
119
120
- webhookServer := ctrlwebhook .NewServer (ctrlwebhook.Options {
121
- TLSOpts : tlsOpts ,
120
+ // Create watchers for metrics and webhooks certificates
121
+ var metricsCertWatcher , webhookCertWatcher * certwatcher.CertWatcher
122
+
123
+ // Initial webhook TLS options
124
+ webhookTLSOpts := tlsOpts
125
+
126
+ if len (webhookCertPath ) > 0 {
127
+ setupLog .Info ("Initializing webhook certificate watcher using provided certificates" ,
128
+ "webhook-cert-path" , webhookCertPath , "webhook-cert-name" , webhookCertName , "webhook-cert-key" , webhookCertKey )
129
+
130
+ var err error
131
+ webhookCertWatcher , err = certwatcher .New (
132
+ filepath .Join (webhookCertPath , webhookCertName ),
133
+ filepath .Join (webhookCertPath , webhookCertKey ),
134
+ )
135
+ if err != nil {
136
+ setupLog .Error (err , "Failed to initialize webhook certificate watcher" )
137
+ os .Exit (1 )
138
+ }
139
+
140
+ webhookTLSOpts = append (webhookTLSOpts , func (config * tls.Config ) {
141
+ config .GetCertificate = webhookCertWatcher .GetCertificate
142
+ })
143
+ }
144
+
145
+ webhookServer := webhook .NewServer (webhook.Options {
146
+ TLSOpts : webhookTLSOpts ,
122
147
})
123
148
124
149
// Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server.
125
150
// More info:
126
- // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19 .0/pkg/metrics/server
151
+ // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21 .0/pkg/metrics/server
127
152
// - https://book.kubebuilder.io/reference/metrics.html
128
153
metricsServerOptions := metricsserver.Options {
129
154
BindAddress : metricsAddr ,
130
155
SecureServing : secureMetrics ,
131
- // TLSOpts is used to allow configuring the TLS config used for the server. If certificates are
132
- // not provided, self-signed certificates will be generated by default. This option is not recommended for
133
- // production environments as self-signed certificates do not offer the same level of trust and security
134
- // as certificates issued by a trusted Certificate Authority (CA). The primary risk is potentially allowing
135
- // unauthorized access to sensitive metrics data. Consider replacing with CertDir, CertName, and KeyName
136
- // to provide certificates, ensuring the server communicates using trusted and secure certificates.
137
- TLSOpts : tlsOpts ,
156
+ TLSOpts : tlsOpts ,
138
157
}
139
158
140
159
if secureMetrics {
141
160
// FilterProvider is used to protect the metrics endpoint with authn/authz.
142
161
// These configurations ensure that only authorized users and service accounts
143
162
// can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:
144
- // https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19 .0/pkg/metrics/filters#WithAuthenticationAndAuthorization
163
+ // https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21 .0/pkg/metrics/filters#WithAuthenticationAndAuthorization
145
164
metricsServerOptions .FilterProvider = filters .WithAuthenticationAndAuthorization
146
165
}
147
166
148
- utilruntime .Must (clientgoscheme .AddToScheme (scheme ))
149
- utilruntime .Must (keycloakApi .AddToScheme (scheme ))
150
- utilruntime .Must (keycloakApi1alpha1 .AddToScheme (scheme ))
151
- utilruntime .Must (corev1 .AddToScheme (scheme ))
167
+ // If the certificate is not specified, controller-runtime will automatically
168
+ // generate self-signed certificates for the metrics server. While convenient for development and testing,
169
+ // this setup is not recommended for production.
170
+ //
171
+ // TODO(user): If you enable certManager, uncomment the following lines:
172
+ // - [METRICS-WITH-CERTS] at config/default/kustomization.yaml to generate and use certificates
173
+ // managed by cert-manager for the metrics server.
174
+ // - [PROMETHEUS-WITH-CERTS] at config/prometheus/kustomization.yaml for TLS certification.
175
+ if len (metricsCertPath ) > 0 {
176
+ setupLog .Info ("Initializing metrics certificate watcher using provided certificates" ,
177
+ "metrics-cert-path" , metricsCertPath , "metrics-cert-name" , metricsCertName , "metrics-cert-key" , metricsCertKey )
178
+
179
+ var err error
180
+ metricsCertWatcher , err = certwatcher .New (
181
+ filepath .Join (metricsCertPath , metricsCertName ),
182
+ filepath .Join (metricsCertPath , metricsCertKey ),
183
+ )
184
+ if err != nil {
185
+ setupLog .Error (err , "to initialize metrics certificate watcher" , "error" , err )
186
+ os .Exit (1 )
187
+ }
188
+
189
+ metricsServerOptions .TLSOpts = append (metricsServerOptions .TLSOpts , func (config * tls.Config ) {
190
+ config .GetCertificate = metricsCertWatcher .GetCertificate
191
+ })
192
+ }
152
193
153
194
ns , err := util .GetWatchNamespace ()
154
195
if err != nil {
155
196
setupLog .Error (err , "unable to get watch namespace" )
156
197
os .Exit (1 )
157
198
}
158
199
159
- cfg := ctrl .GetConfigOrDie ()
160
-
161
- mgr , err := ctrl .NewManager (cfg , ctrl.Options {
200
+ mgr , err := ctrl .NewManager (ctrl .GetConfigOrDie (), ctrl.Options {
162
201
Scheme : scheme ,
163
202
Metrics : metricsServerOptions ,
164
203
WebhookServer : webhookServer ,
@@ -275,6 +314,23 @@ func main() {
275
314
}
276
315
//+kubebuilder:scaffold:builder
277
316
317
+
318
+ if metricsCertWatcher != nil {
319
+ setupLog .Info ("Adding metrics certificate watcher to manager" )
320
+ if err := mgr .Add (metricsCertWatcher ); err != nil {
321
+ setupLog .Error (err , "Unable to add metrics certificate watcher to manager" )
322
+ os .Exit (1 )
323
+ }
324
+ }
325
+
326
+ if webhookCertWatcher != nil {
327
+ setupLog .Info ("Adding webhook certificate watcher to manager" )
328
+ if err := mgr .Add (webhookCertWatcher ); err != nil {
329
+ setupLog .Error (err , "Unable to add webhook certificate watcher to manager" )
330
+ os .Exit (1 )
331
+ }
332
+ }
333
+
278
334
if err := mgr .AddHealthzCheck ("healthz" , healthz .Ping ); err != nil {
279
335
setupLog .Error (err , "unable to set up health check" )
280
336
os .Exit (1 )
@@ -285,7 +341,7 @@ func main() {
285
341
os .Exit (1 )
286
342
}
287
343
288
- setupLog .Info ("starting manager" )
344
+ setupLog .Info ("Starting manager" )
289
345
290
346
if err := mgr .Start (ctrl .SetupSignalHandler ()); err != nil {
291
347
setupLog .Error (err , "problem running manager" )
0 commit comments