@@ -20,6 +20,7 @@ import (
2020 "crypto/tls"
2121 "flag"
2222 "os"
23+ "path/filepath"
2324 "strconv"
2425
2526 "github.com/securesign/operator/internal/images"
@@ -46,7 +47,9 @@ import (
4647 utilruntime "k8s.io/apimachinery/pkg/util/runtime"
4748 clientgoscheme "k8s.io/client-go/kubernetes/scheme"
4849 ctrl "sigs.k8s.io/controller-runtime"
50+ "sigs.k8s.io/controller-runtime/pkg/certwatcher"
4951 "sigs.k8s.io/controller-runtime/pkg/healthz"
52+ "sigs.k8s.io/controller-runtime/pkg/metrics/filters"
5053 metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
5154 "sigs.k8s.io/controller-runtime/pkg/webhook"
5255
@@ -79,26 +82,43 @@ func init() {
7982 //+kubebuilder:scaffold:scheme
8083}
8184
85+ // nolint:gocyclo
8286func main () {
8387 var (
8488 metricsAddr string
89+ metricsCertPath string
90+ metricsCertName string
91+ metricsCertKey string
92+ webhookCertPath string
93+ webhookCertName string
94+ webhookCertKey string
8595 enableLeaderElection bool
8696 probeAddr string
8797 pprofAddr string
8898 secureMetrics bool
8999 enableHTTP2 bool
100+ tlsOpts []func (* tls.Config )
90101 )
91102
92103 flag .StringVar (& pprofAddr , "pprof-address" , "" , "The address to expose the pprof server. Default is empty string which disables the pprof server." )
93- flag .StringVar (& metricsAddr , "metrics-bind-address" , ":8080" , "The address the metric endpoint binds to." )
104+ flag .StringVar (& metricsAddr , "metrics-bind-address" , ":8080" , "The address the metrics endpoint binds to. " +
105+ "Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service." )
94106 flag .StringVar (& probeAddr , "health-probe-bind-address" , ":8081" , "The address the probe endpoint binds to." )
95107 flag .BoolVar (& enableLeaderElection , "leader-elect" , false ,
96108 "Enable leader election for controller manager. " +
97109 "Enabling this will ensure there is only one active controller manager." )
98- flag .BoolVar (& secureMetrics , "metrics-secure" , false ,
99- "If set the metrics endpoint is served securely" )
110+ flag .BoolVar (& secureMetrics , "metrics-secure" , true ,
111+ "If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead." )
112+ flag .StringVar (& webhookCertPath , "webhook-cert-path" , "" , "The directory that contains the webhook certificate." )
113+ flag .StringVar (& webhookCertName , "webhook-cert-name" , "tls.crt" , "The name of the webhook certificate file." )
114+ flag .StringVar (& webhookCertKey , "webhook-cert-key" , "tls.key" , "The name of the webhook key file." )
115+ flag .StringVar (& metricsCertPath , "metrics-cert-path" , "" ,
116+ "The directory that contains the metrics server certificate." )
117+ flag .StringVar (& metricsCertName , "metrics-cert-name" , "tls.crt" , "The name of the metrics server certificate file." )
118+ flag .StringVar (& metricsCertKey , "metrics-cert-key" , "tls.key" , "The name of the metrics server key file." )
100119 flag .BoolVar (& enableHTTP2 , "enable-http2" , false ,
101120 "If set, HTTP/2 will be enabled for the metrics and webhook servers" )
121+
102122 flag .Int64Var (& constants .CreateTreeDeadline , "create-tree-deadline" , constants .CreateTreeDeadline , "The time allowance (in seconds) for the create tree job to run before failing." )
103123 utils .BoolFlagOrEnv (& constants .Openshift , "openshift" , "OPENSHIFT" , false , "Enable to ensures the operator applies OpenShift specific configurations." )
104124 utils .RelatedImageFlag ("trillian-log-signer-image" , images .TrillianLogSigner , "The image used for trillian log signer." )
@@ -135,22 +155,87 @@ func main() {
135155 c .NextProtos = []string {"http/1.1" }
136156 }
137157
138- tlsOpts := []func (* tls.Config ){}
139158 if ! enableHTTP2 {
140159 tlsOpts = append (tlsOpts , disableHTTP2 )
141160 }
142161
162+ // Create watchers for metrics and webhooks certificates
163+ var metricsCertWatcher , webhookCertWatcher * certwatcher.CertWatcher
164+
165+ // Initial webhook TLS options
166+ webhookTLSOpts := tlsOpts
167+
168+ if len (webhookCertPath ) > 0 {
169+ setupLog .Info ("Initializing webhook certificate watcher using provided certificates" ,
170+ "webhook-cert-path" , webhookCertPath , "webhook-cert-name" , webhookCertName , "webhook-cert-key" , webhookCertKey )
171+
172+ var err error
173+ webhookCertWatcher , err = certwatcher .New (
174+ filepath .Join (webhookCertPath , webhookCertName ),
175+ filepath .Join (webhookCertPath , webhookCertKey ),
176+ )
177+ if err != nil {
178+ setupLog .Error (err , "Failed to initialize webhook certificate watcher" )
179+ os .Exit (1 )
180+ }
181+
182+ webhookTLSOpts = append (webhookTLSOpts , func (config * tls.Config ) {
183+ config .GetCertificate = webhookCertWatcher .GetCertificate
184+ })
185+ }
186+
143187 webhookServer := webhook .NewServer (webhook.Options {
144- TLSOpts : tlsOpts ,
188+ TLSOpts : webhookTLSOpts ,
145189 })
146190
191+ // Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server.
192+ // More info:
193+ // - https://pkg.go.dev/sigs.k8s.io/[email protected] /pkg/metrics/server 194+ // - https://book.kubebuilder.io/reference/metrics.html
195+ metricsServerOptions := metricsserver.Options {
196+ BindAddress : metricsAddr ,
197+ SecureServing : secureMetrics ,
198+ TLSOpts : tlsOpts ,
199+ }
200+
201+ if secureMetrics {
202+ // FilterProvider is used to protect the metrics endpoint with authn/authz.
203+ // These configurations ensure that only authorized users and service accounts
204+ // can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:
205+ // https://pkg.go.dev/sigs.k8s.io/[email protected] /pkg/metrics/filters#WithAuthenticationAndAuthorization 206+ metricsServerOptions .FilterProvider = filters .WithAuthenticationAndAuthorization
207+ }
208+
209+ // If the certificate is not specified, controller-runtime will automatically
210+ // generate self-signed certificates for the metrics server. While convenient for development and testing,
211+ // this setup is not recommended for production.
212+ //
213+ // TODO(user): If you enable certManager, uncomment the following lines:
214+ // - [METRICS-WITH-CERTS] at config/default/kustomization.yaml to generate and use certificates
215+ // managed by cert-manager for the metrics server.
216+ // - [PROMETHEUS-WITH-CERTS] at config/prometheus/kustomization.yaml for TLS certification.
217+ if len (metricsCertPath ) > 0 {
218+ setupLog .Info ("Initializing metrics certificate watcher using provided certificates" ,
219+ "metrics-cert-path" , metricsCertPath , "metrics-cert-name" , metricsCertName , "metrics-cert-key" , metricsCertKey )
220+
221+ var err error
222+ metricsCertWatcher , err = certwatcher .New (
223+ filepath .Join (metricsCertPath , metricsCertName ),
224+ filepath .Join (metricsCertPath , metricsCertKey ),
225+ )
226+ if err != nil {
227+ setupLog .Error (err , "to initialize metrics certificate watcher" , "error" , err )
228+ os .Exit (1 )
229+ }
230+
231+ metricsServerOptions .TLSOpts = append (metricsServerOptions .TLSOpts , func (config * tls.Config ) {
232+ config .GetCertificate = metricsCertWatcher .GetCertificate
233+ })
234+ }
235+
147236 mgr , err := ctrl .NewManager (ctrl .GetConfigOrDie (), ctrl.Options {
148- Scheme : scheme ,
149- Metrics : metricsserver.Options {
150- BindAddress : metricsAddr ,
151- SecureServing : secureMetrics ,
152- TLSOpts : tlsOpts ,
153- },
237+ Scheme : scheme ,
238+ Metrics : metricsServerOptions ,
154239 WebhookServer : webhookServer ,
155240 HealthProbeBindAddress : probeAddr ,
156241 PprofBindAddress : pprofAddr ,
@@ -233,6 +318,22 @@ func main() {
233318 }
234319 //+kubebuilder:scaffold:builder
235320
321+ if metricsCertWatcher != nil {
322+ setupLog .Info ("Adding metrics certificate watcher to manager" )
323+ if err := mgr .Add (metricsCertWatcher ); err != nil {
324+ setupLog .Error (err , "unable to add metrics certificate watcher to manager" )
325+ os .Exit (1 )
326+ }
327+ }
328+
329+ if webhookCertWatcher != nil {
330+ setupLog .Info ("Adding webhook certificate watcher to manager" )
331+ if err := mgr .Add (webhookCertWatcher ); err != nil {
332+ setupLog .Error (err , "unable to add webhook certificate watcher to manager" )
333+ os .Exit (1 )
334+ }
335+ }
336+
236337 if err := mgr .AddHealthzCheck ("healthz" , healthz .Ping ); err != nil {
237338 setupLog .Error (err , "unable to set up health check" )
238339 os .Exit (1 )
0 commit comments