5
5
"flag"
6
6
"fmt"
7
7
"os"
8
+ "path/filepath"
8
9
"strconv"
9
10
"strings"
10
11
"time"
@@ -19,11 +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"
28
+ "sigs.k8s.io/controller-runtime/pkg/webhook"
27
29
28
30
buildInfo "github.com/epam/edp-common/pkg/config"
29
31
@@ -57,17 +59,27 @@ const (
57
59
keycloakOperatorLock = "edp-keycloak-operator-lock"
58
60
successReconcileTimeout = "SUCCESS_RECONCILE_TIMEOUT"
59
61
operatorNamespaceEnv = "OPERATOR_NAMESPACE"
60
- managerPort = 9443
61
62
)
62
63
64
+ func init () {
65
+ utilruntime .Must (clientgoscheme .AddToScheme (scheme ))
66
+ utilruntime .Must (keycloakApi .AddToScheme (scheme ))
67
+ utilruntime .Must (keycloakApi1alpha1 .AddToScheme (scheme ))
68
+ utilruntime .Must (corev1 .AddToScheme (scheme ))
69
+ // +kubebuilder:scaffold:scheme
70
+ }
71
+
72
+ // nolint:gocyclo
63
73
func main () {
64
74
var (
65
- metricsAddr string
66
- probeAddr string
67
- enableLeaderElection bool
68
- secureMetrics bool
69
- enableHTTP2 bool
70
- tlsOpts []func (* tls.Config )
75
+ metricsAddr string
76
+ metricsCertPath , metricsCertName , metricsCertKey string
77
+ webhookCertPath , webhookCertName , webhookCertKey string
78
+ enableLeaderElection bool
79
+ probeAddr string
80
+ secureMetrics bool
81
+ enableHTTP2 bool
82
+ tlsOpts []func (* tls.Config )
71
83
)
72
84
73
85
flag .StringVar (& metricsAddr , "metrics-bind-address" , "0" , "The address the metrics endpoint binds to. " +
@@ -78,13 +90,19 @@ func main() {
78
90
"Enabling this will ensure there is only one active controller manager." )
79
91
flag .BoolVar (& secureMetrics , "metrics-secure" , true ,
80
92
"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead." )
93
+ flag .StringVar (& webhookCertPath , "webhook-cert-path" , "" , "The directory that contains the webhook certificate." )
94
+ flag .StringVar (& webhookCertName , "webhook-cert-name" , "tls.crt" , "The name of the webhook certificate file." )
95
+ flag .StringVar (& webhookCertKey , "webhook-cert-key" , "tls.key" , "The name of the webhook key file." )
96
+ flag .StringVar (& metricsCertPath , "metrics-cert-path" , "" ,
97
+ "The directory that contains the metrics server certificate." )
98
+ flag .StringVar (& metricsCertName , "metrics-cert-name" , "tls.crt" , "The name of the metrics server certificate file." )
99
+ flag .StringVar (& metricsCertKey , "metrics-cert-key" , "tls.key" , "The name of the metrics server key file." )
81
100
flag .BoolVar (& enableHTTP2 , "enable-http2" , false ,
82
101
"If set, HTTP/2 will be enabled for the metrics and webhook servers" )
83
102
84
103
opts := zap.Options {
85
104
Development : true ,
86
105
}
87
-
88
106
opts .BindFlags (flag .CommandLine )
89
107
flag .Parse ()
90
108
@@ -101,6 +119,7 @@ func main() {
101
119
"go-client" , v .KubectlVersion ,
102
120
"platform" , v .Platform ,
103
121
)
122
+
104
123
// if the enable-http2 flag is false (the default), http/2 should be disabled
105
124
// due to its vulnerabilities. More specifically, disabling http/2 will
106
125
// prevent from being vulnerable to the HTTP/2 Stream Cancellation and
@@ -117,48 +136,89 @@ func main() {
117
136
tlsOpts = append (tlsOpts , disableHTTP2 )
118
137
}
119
138
120
- webhookServer := ctrlwebhook .NewServer (ctrlwebhook.Options {
121
- TLSOpts : tlsOpts ,
139
+ // Create watchers for metrics and webhooks certificates
140
+ var metricsCertWatcher , webhookCertWatcher * certwatcher.CertWatcher
141
+
142
+ // Initial webhook TLS options
143
+ webhookTLSOpts := tlsOpts
144
+
145
+ if len (webhookCertPath ) > 0 {
146
+ setupLog .Info ("Initializing webhook certificate watcher using provided certificates" ,
147
+ "webhook-cert-path" , webhookCertPath , "webhook-cert-name" , webhookCertName , "webhook-cert-key" , webhookCertKey )
148
+
149
+ var err error
150
+
151
+ webhookCertWatcher , err = certwatcher .New (
152
+ filepath .Join (webhookCertPath , webhookCertName ),
153
+ filepath .Join (webhookCertPath , webhookCertKey ),
154
+ )
155
+ if err != nil {
156
+ setupLog .Error (err , "Failed to initialize webhook certificate watcher" )
157
+ os .Exit (1 )
158
+ }
159
+
160
+ webhookTLSOpts = append (webhookTLSOpts , func (config * tls.Config ) {
161
+ config .GetCertificate = webhookCertWatcher .GetCertificate
162
+ })
163
+ }
164
+
165
+ webhookServer := webhook .NewServer (webhook.Options {
166
+ TLSOpts : webhookTLSOpts ,
122
167
})
123
168
124
169
// Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server.
125
170
// More info:
126
- // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19 .0/pkg/metrics/server
171
+ // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21 .0/pkg/metrics/server
127
172
// - https://book.kubebuilder.io/reference/metrics.html
128
173
metricsServerOptions := metricsserver.Options {
129
174
BindAddress : metricsAddr ,
130
175
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 ,
176
+ TLSOpts : tlsOpts ,
138
177
}
139
178
140
179
if secureMetrics {
141
180
// FilterProvider is used to protect the metrics endpoint with authn/authz.
142
181
// These configurations ensure that only authorized users and service accounts
143
182
// 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
183
+ // https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21 .0/pkg/metrics/filters#WithAuthenticationAndAuthorization
145
184
metricsServerOptions .FilterProvider = filters .WithAuthenticationAndAuthorization
146
185
}
147
186
148
- utilruntime .Must (clientgoscheme .AddToScheme (scheme ))
149
- utilruntime .Must (keycloakApi .AddToScheme (scheme ))
150
- utilruntime .Must (keycloakApi1alpha1 .AddToScheme (scheme ))
151
- utilruntime .Must (corev1 .AddToScheme (scheme ))
187
+ // If the certificate is not specified, controller-runtime will automatically
188
+ // generate self-signed certificates for the metrics server. While convenient for development and testing,
189
+ // this setup is not recommended for production.
190
+ //
191
+ // TODO(user): If you enable certManager, uncomment the following lines:
192
+ // - [METRICS-WITH-CERTS] at config/default/kustomization.yaml to generate and use certificates
193
+ // managed by cert-manager for the metrics server.
194
+ // - [PROMETHEUS-WITH-CERTS] at config/prometheus/kustomization.yaml for TLS certification.
195
+ if len (metricsCertPath ) > 0 {
196
+ setupLog .Info ("Initializing metrics certificate watcher using provided certificates" ,
197
+ "metrics-cert-path" , metricsCertPath , "metrics-cert-name" , metricsCertName , "metrics-cert-key" , metricsCertKey )
198
+
199
+ var err error
200
+
201
+ metricsCertWatcher , err = certwatcher .New (
202
+ filepath .Join (metricsCertPath , metricsCertName ),
203
+ filepath .Join (metricsCertPath , metricsCertKey ),
204
+ )
205
+ if err != nil {
206
+ setupLog .Error (err , "to initialize metrics certificate watcher" , "error" , err )
207
+ os .Exit (1 )
208
+ }
209
+
210
+ metricsServerOptions .TLSOpts = append (metricsServerOptions .TLSOpts , func (config * tls.Config ) {
211
+ config .GetCertificate = metricsCertWatcher .GetCertificate
212
+ })
213
+ }
152
214
153
215
ns , err := util .GetWatchNamespace ()
154
216
if err != nil {
155
217
setupLog .Error (err , "unable to get watch namespace" )
156
218
os .Exit (1 )
157
219
}
158
220
159
- cfg := ctrl .GetConfigOrDie ()
160
-
161
- mgr , err := ctrl .NewManager (cfg , ctrl.Options {
221
+ mgr , err := ctrl .NewManager (ctrl .GetConfigOrDie (), ctrl.Options {
162
222
Scheme : scheme ,
163
223
Metrics : metricsServerOptions ,
164
224
WebhookServer : webhookServer ,
@@ -275,6 +335,24 @@ func main() {
275
335
}
276
336
//+kubebuilder:scaffold:builder
277
337
338
+ if metricsCertWatcher != nil {
339
+ setupLog .Info ("Adding metrics certificate watcher to manager" )
340
+
341
+ if err := mgr .Add (metricsCertWatcher ); err != nil {
342
+ setupLog .Error (err , "Unable to add metrics certificate watcher to manager" )
343
+ os .Exit (1 )
344
+ }
345
+ }
346
+
347
+ if webhookCertWatcher != nil {
348
+ setupLog .Info ("Adding webhook certificate watcher to manager" )
349
+
350
+ if err := mgr .Add (webhookCertWatcher ); err != nil {
351
+ setupLog .Error (err , "Unable to add webhook certificate watcher to manager" )
352
+ os .Exit (1 )
353
+ }
354
+ }
355
+
278
356
if err := mgr .AddHealthzCheck ("healthz" , healthz .Ping ); err != nil {
279
357
setupLog .Error (err , "unable to set up health check" )
280
358
os .Exit (1 )
@@ -285,7 +363,7 @@ func main() {
285
363
os .Exit (1 )
286
364
}
287
365
288
- setupLog .Info ("starting manager" )
366
+ setupLog .Info ("Starting manager" )
289
367
290
368
if err := mgr .Start (ctrl .SetupSignalHandler ()); err != nil {
291
369
setupLog .Error (err , "problem running manager" )
0 commit comments