@@ -70,6 +70,7 @@ import (
7070const (
7171 fleetWebhookCertFileName = "tls.crt"
7272 fleetWebhookKeyFileName = "tls.key"
73+ fleetWebhookCertSecretName = "fleet-webhook-server-cert" //nolint:gosec // This is a Secret name, not a credential
7374 fleetValidatingWebhookCfgName = "fleet-validating-webhook-configuration"
7475 fleetGuardRailWebhookCfgName = "fleet-guard-rail-webhook-configuration"
7576 fleetMutatingWebhookCfgName = "fleet-mutating-webhook-configuration"
@@ -154,15 +155,20 @@ type Config struct {
154155 // caPEM is a PEM encoded CA bundle which will be used to validate the webhook's server certificate.
155156 caPEM []byte
156157
158+ // certDir is the directory where certificate files will be written
159+ certDir string
160+
157161 clientConnectionType * options.WebhookClientConnectionType
158162
159163 enableGuardRail bool
160164
161165 denyModifyMemberClusterLabels bool
162166 enableWorkload bool
167+ // useCertManager indicates whether cert-manager is used for certificate management
168+ useCertManager bool
163169}
164170
165- func NewWebhookConfig (mgr manager.Manager , webhookServiceName string , port int32 , clientConnectionType * options.WebhookClientConnectionType , certDir string , enableGuardRail bool , denyModifyMemberClusterLabels bool , enableWorkload bool ) (* Config , error ) {
171+ func NewWebhookConfig (mgr manager.Manager , webhookServiceName string , port int32 , clientConnectionType * options.WebhookClientConnectionType , certDir string , enableGuardRail bool , denyModifyMemberClusterLabels bool , enableWorkload bool , useCertManager bool ) (* Config , error ) {
166172 // We assume the Pod namespace should be passed to env through downward API in the Pod spec.
167173 namespace := os .Getenv ("POD_NAMESPACE" )
168174 if namespace == "" {
@@ -174,17 +180,34 @@ func NewWebhookConfig(mgr manager.Manager, webhookServiceName string, port int32
174180 serviceNamespace : namespace ,
175181 serviceName : webhookServiceName ,
176182 serviceURL : fmt .Sprintf ("https://%s.%s.svc.cluster.local:%d" , webhookServiceName , namespace , port ),
183+ certDir : certDir ,
177184 clientConnectionType : clientConnectionType ,
178185 enableGuardRail : enableGuardRail ,
179186 denyModifyMemberClusterLabels : denyModifyMemberClusterLabels ,
180187 enableWorkload : enableWorkload ,
188+ useCertManager : useCertManager ,
181189 }
182- caPEM , err := w .genCertificate (certDir )
183- if err != nil {
184- return nil , err
190+
191+ var caPEM []byte
192+ var err error
193+
194+ if useCertManager {
195+ // When using cert-manager, certificates are mounted as files by Kubernetes
196+ // cert-manager creates tls.crt and tls.key, but we need ca.crt for the webhook config
197+ caPEM , err = w .loadCertManagerCA (certDir )
198+ if err != nil {
199+ return nil , fmt .Errorf ("failed to load cert-manager CA certificate: %w" , err )
200+ }
201+ } else {
202+ // Use self-signed certificate generation (original flow)
203+ caPEM , err = w .genCertificate (certDir )
204+ if err != nil {
205+ return nil , err
206+ }
185207 }
208+
186209 w .caPEM = caPEM
187- return & w , err
210+ return & w , nil
188211}
189212
190213func (w * Config ) Start (ctx context.Context ) error {
@@ -214,12 +237,19 @@ func (w *Config) createFleetWebhookConfiguration(ctx context.Context) error {
214237
215238// createMutatingWebhookConfiguration creates the MutatingWebhookConfiguration object for the webhook.
216239func (w * Config ) createMutatingWebhookConfiguration (ctx context.Context , webhooks []admv1.MutatingWebhook , configName string ) error {
240+ annotations := map [string ]string {}
241+ if w .useCertManager {
242+ // Tell cert-manager's CA injector to automatically inject the CA bundle
243+ annotations ["cert-manager.io/inject-ca-from" ] = fmt .Sprintf ("%s/%s" , w .serviceNamespace , fleetWebhookCertSecretName )
244+ }
245+
217246 mutatingWebhookConfig := admv1.MutatingWebhookConfiguration {
218247 ObjectMeta : metav1.ObjectMeta {
219248 Name : configName ,
220249 Labels : map [string ]string {
221250 "admissions.enforcer/disabled" : "true" ,
222251 },
252+ Annotations : annotations ,
223253 },
224254 Webhooks : webhooks ,
225255 }
@@ -267,12 +297,19 @@ func (w *Config) buildFleetMutatingWebhooks() []admv1.MutatingWebhook {
267297}
268298
269299func (w * Config ) createValidatingWebhookConfiguration (ctx context.Context , webhooks []admv1.ValidatingWebhook , configName string ) error {
300+ annotations := map [string ]string {}
301+ if w .useCertManager {
302+ // Tell cert-manager's CA injector to automatically inject the CA bundle
303+ annotations ["cert-manager.io/inject-ca-from" ] = fmt .Sprintf ("%s/%s" , w .serviceNamespace , fleetWebhookCertSecretName )
304+ }
305+
270306 validatingWebhookConfig := admv1.ValidatingWebhookConfiguration {
271307 ObjectMeta : metav1.ObjectMeta {
272308 Name : configName ,
273309 Labels : map [string ]string {
274310 "admissions.enforcer/disabled" : "true" ,
275311 },
312+ Annotations : annotations ,
276313 },
277314 Webhooks : webhooks ,
278315 }
@@ -657,6 +694,26 @@ func (w *Config) genCertificate(certDir string) ([]byte, error) {
657694 return caPEM , nil
658695}
659696
697+ // loadCertManagerCA loads the CA certificate from the mounted cert-manager Secret.
698+ // When using cert-manager, Kubernetes mounts the Secret as files in the certDir.
699+ // cert-manager creates: ca.crt, tls.crt, and tls.key
700+ // The tls.crt and tls.key are automatically used by the webhook server.
701+ // We only need to read ca.crt for the webhook configuration's CABundle.
702+ func (w * Config ) loadCertManagerCA (certDir string ) ([]byte , error ) {
703+ caPath := filepath .Join (certDir , "ca.crt" )
704+ caCert , err := os .ReadFile (caPath )
705+ if err != nil {
706+ return nil , fmt .Errorf ("failed to read ca.crt from %s: %w" , caPath , err )
707+ }
708+
709+ if len (caCert ) == 0 {
710+ return nil , fmt .Errorf ("ca.crt is empty at %s" , caPath )
711+ }
712+
713+ klog .V (2 ).InfoS ("Successfully loaded CA certificate from cert-manager mounted Secret" , "path" , caPath )
714+ return caCert , nil
715+ }
716+
660717// genSelfSignedCert generates the self signed Certificate/Key pair
661718func (w * Config ) genSelfSignedCert () (caPEMByte , certPEMByte , keyPEMByte []byte , err error ) {
662719 // CA config
0 commit comments