@@ -28,7 +28,6 @@ import (
2828
2929 "github.com/sirupsen/logrus"
3030 corev1 "k8s.io/api/core/v1"
31- apierrors "k8s.io/apimachinery/pkg/api/errors"
3231 "k8s.io/apimachinery/pkg/runtime"
3332 "k8s.io/apimachinery/pkg/types"
3433 ctrl "sigs.k8s.io/controller-runtime"
@@ -219,57 +218,36 @@ func (r *PtpConfig) validate() error {
219218
220219 // Validate secret-related settings for this profile
221220 if profile .PtpSecretName != nil && * profile .PtpSecretName != "" {
222- // Check that secret exists
223- if err := r . validateSecretExistsForProfile ( context . Background (), profile ); err != nil {
224- return err
221+ sppValue , err := getSppFromPtp4lConf ( conf )
222+ if err != nil {
223+ return fmt . Errorf ( "failed to get spp value from ptp4lConf: %w" , err )
225224 }
226-
227- // Check for conflicts with other PtpConfigs
228- if err := r .validateSecretConflictsForProfile (context .Background (), profile ); err != nil {
229- return err
225+ if err := validateSecretExists (sppValue , * profile .PtpSecretName ); err != nil {
226+ return fmt .Errorf ("failed to validate secret from profile: %w" , err )
227+ }
228+ saFilePath , err := getSaFileFromPtp4lConf (conf )
229+ if err != nil {
230+ return fmt .Errorf ("failed to get sa file path from ptp4lConf: %w" , err )
231+ }
232+ if err := validateSaFileSecretConflicts (saFilePath , * profile .PtpSecretName , r .Name , r .Namespace ); err != nil {
233+ return fmt .Errorf ("failed to validate secret conflicts from profile: %w" , err )
230234 }
231235 }
232236 }
233237 return nil
234238}
235239
236- // validateSecretConflictsForProfile checks if a single profile's sa_file + secret combination
240+ // validateSecretConflicts checks if a single profile's sa_file + secret combination
237241// conflicts with any existing PtpConfigs in the openshift-ptp namespace
238- func ( r * PtpConfig ) validateSecretConflictsForProfile ( ctx context. Context , profile PtpProfile ) error {
242+ func validateSaFileSecretConflicts ( saFilePath string , secretName string , name string , namespace string ) error {
239243 if webhookClient == nil {
240244 ptpconfiglog .Info ("webhook client not initialized, skipping cross-PtpConfig validation" )
241245 return nil
242246 }
243247
244- // Skip if profile doesn't use secrets
245- if profile .PtpSecretName == nil || * profile .PtpSecretName == "" {
246- return nil
247- }
248- if profile .Ptp4lConf == nil {
249- return nil
250- }
251-
252- // Get sa_file for THIS profile
253- conf := & Ptp4lConf {}
254- if err := conf .populatePtp4lConf (profile .Ptp4lConf , profile .Ptp4lOpts ); err != nil {
255- return nil // Skip if can't parse
256- }
257-
258- globalSection , exists := conf .sections ["[global]" ]
259- if ! exists {
260- return nil
261- }
262-
263- saFile , exists := globalSection .options ["sa_file" ]
264- if ! exists || saFile == "" {
265- return nil // No sa_file, no conflict possible
266- }
267-
268- currentSecret := * profile .PtpSecretName
269-
270248 // List all existing PtpConfigs in openshift-ptp namespace
271249 ptpConfigList := & PtpConfigList {}
272- if err := webhookClient .List (ctx , ptpConfigList , & client.ListOptions {
250+ if err := webhookClient .List (context . Background () , ptpConfigList , & client.ListOptions {
273251 Namespace : "openshift-ptp" ,
274252 }); err != nil {
275253 ptpconfiglog .Error (err , "failed to list PtpConfigs for validation" )
@@ -280,7 +258,7 @@ func (r *PtpConfig) validateSecretConflictsForProfile(ctx context.Context, profi
280258 // Check each existing PtpConfig for conflicts
281259 for _ , existingConfig := range ptpConfigList .Items {
282260 // Skip checking against ourselves (for updates)
283- if existingConfig .Name == r . Name && existingConfig .Namespace == r . Namespace {
261+ if existingConfig .Name == name && existingConfig .Namespace == namespace {
284262 continue
285263 }
286264
@@ -297,105 +275,82 @@ func (r *PtpConfig) validateSecretConflictsForProfile(ctx context.Context, profi
297275 if err := existingConf .populatePtp4lConf (existingProfile .Ptp4lConf , existingProfile .Ptp4lOpts ); err != nil {
298276 continue
299277 }
300-
301- if globalSection , exists := existingConf . sections [ "[global]" ]; exists {
302- if existingSaFile , exists := globalSection . options [ "sa_file" ]; exists && existingSaFile != "" {
303- // Check if same sa_file as our profile
304- if existingSaFile == saFile {
305- // Same sa_file - check if different secret
306- if * existingProfile . PtpSecretName != currentSecret {
307- return fmt . Errorf ( "sa_file '%s' conflict: PtpConfig '%s' already uses secret '%s' with this sa_file path, but this profile tries to use secret '%s'. All PtpConfigs using the same sa_file must reference the same secret" ,
308- saFile , existingConfig . Name , * existingProfile . PtpSecretName , currentSecret )
309- }
310- }
311- }
278+ globalSection , exists := existingConf . sections [ "[global]" ]
279+ if ! exists {
280+ continue
281+ }
282+ existingSaFile , exists := globalSection . options [ "sa_file" ]
283+ if ! exists {
284+ continue
285+ }
286+ // Check if same sa_file as our profile and different secret
287+ if existingSaFile == saFilePath && * existingProfile . PtpSecretName != secretName {
288+ return fmt . Errorf ( "sa_file '%s' conflict: PtpConfig '%s' already uses secret '%s' with this sa_file path, but this profile tries to use secret '%s'. All PtpConfigs using the same sa_file must reference the same secret" ,
289+ saFilePath , existingConfig . Name , * existingProfile . PtpSecretName , secretName )
312290 }
313291 }
314292 }
315293
316294 return nil
317295}
318296
319- // validateSecretExistsForProfile checks that a single profile's ptpSecretName references an existing secret
320- func ( r * PtpConfig ) validateSecretExistsForProfile ( ctx context. Context , profile PtpProfile ) error {
297+ // validateSecretExists checks that a single profile's ptpSecretName references an existing secret
298+ func validateSecretExists ( sppValue string , secretName string ) error {
321299 if webhookClient == nil {
322300 ptpconfiglog .Info ("webhook client not initialized, skipping secret existence validation" )
323301 return nil
324302 }
325303
326- // Skip if no secret specified
327- if profile .PtpSecretName == nil || * profile .PtpSecretName == "" {
328- return nil
329- }
330-
331- secretName := * profile .PtpSecretName
332- profileName := "unknown"
333- if profile .Name != nil {
334- profileName = * profile .Name
335- }
336-
337304 // Try to get the secret from openshift-ptp namespace
338305 secret := & corev1.Secret {}
339- err := webhookClient .Get (ctx , types.NamespacedName {
306+ err := webhookClient .Get (context . Background () , types.NamespacedName {
340307 Namespace : "openshift-ptp" ,
341308 Name : secretName ,
342309 }, secret )
343310
344311 if err != nil {
345- if apierrors .IsNotFound (err ) {
346- return fmt .Errorf ("secret '%s' referenced by profile '%s' does not exist in namespace 'openshift-ptp'. Please create the secret before referencing it in PtpConfig" ,
347- secretName , profileName )
348- }
349- // For other errors (like permission issues), fail closed - reject to ensure security
350- return fmt .Errorf ("failed to verify secret '%s' for profile '%s': %v. This may indicate webhook permission issues or API connectivity problems" ,
351- secretName , profileName , err )
312+ return fmt .Errorf ("failed to get secret %q: %w" , secretName , err )
352313 }
353314
354- ptpconfiglog .Info ("validated secret exists" , "secret" , secretName , "profile" , profileName )
355-
356315 // Validate SPP (Security Parameter Profile) if specified
357- if err := r . validateSppInSecret (profile , secret ); err != nil {
358- return err
316+ if err := validateSppInSecret (sppValue , secret ); err != nil {
317+ return fmt . Errorf ( "failed to validate spp in secret %q: %w" , secretName , err )
359318 }
360319
361320 return nil
362321}
363-
364- // validateSppInSecret checks that the spp value in ptp4lConf exists in the referenced secret
365- // Combines parsing and validation in one pass for efficiency
366- func (r * PtpConfig ) validateSppInSecret (profile PtpProfile , secret * corev1.Secret ) error {
367- // Skip if no ptp4lConf
368- if profile .Ptp4lConf == nil {
369- return nil
322+ func getSppFromPtp4lConf (conf * Ptp4lConf ) (string , error ) {
323+ globalSection , exists := conf .sections ["[global]" ]
324+ if ! exists {
325+ return "" , nil
370326 }
327+ sppValue , exists := globalSection .options ["spp" ]
371328
372- // Parse ptp4lConf to get spp value from [global] section
373- conf := & Ptp4lConf {}
374- if err := conf .populatePtp4lConf (profile .Ptp4lConf , profile .Ptp4lOpts ); err != nil {
375- // If we can't parse the config, skip validation (other validations will catch this)
376- return nil
329+ if ! exists || sppValue == "" {
330+ return "" , nil
377331 }
378-
332+ if sppValue == "" {
333+ return "" , errors .New ("spp value is not set in the ptp4lConf" )
334+ }
335+ return sppValue , nil
336+ }
337+ func getSaFileFromPtp4lConf (conf * Ptp4lConf ) (string , error ) {
379338 globalSection , exists := conf .sections ["[global]" ]
380339 if ! exists {
381- return nil
340+ return "" , nil
382341 }
383-
384- sppValue , exists := globalSection .options ["spp" ]
385- if ! exists || sppValue == "" {
386- // No spp specified, nothing to validate
387- return nil
342+ saFileValue , exists := globalSection .options ["sa_file" ]
343+ if ! exists {
344+ return "" , nil
388345 }
389-
390- profileName := "unknown"
391- if profile .Name != nil {
392- profileName = * profile .Name
346+ if saFileValue == "" {
347+ return "" , errors .New ("sa_file value is not set in the ptp4lConf" )
393348 }
349+ return saFileValue , nil
350+ }
394351
395- // Validate SPP exists in secret by iterating through secret content
396- // Early return on match for efficiency
397-
398- // Iterate through all keys in the secret
352+ // validateSppInSecret checks that the spp value in ptp4lConf exists in the referenced secret
353+ func validateSppInSecret (sppValue string , secret * corev1.Secret ) error {
399354 for key , value := range secret .Data {
400355 content := string (value )
401356 lines := strings .Split (content , "\n " )
@@ -417,16 +372,15 @@ func (r *PtpConfig) validateSppInSecret(profile PtpProfile, secret *corev1.Secre
417372
418373 // Check if this matches the PtpConfig's spp
419374 if secretSppValue == sppValue {
420- ptpconfiglog .Info ("validated spp match" , "spp" , sppValue , "secret" , secret .Name , "profile" , profileName , " key" , key )
375+ ptpconfiglog .Info ("validated spp match" , "spp" , sppValue , "secret" , secret .Name , "key" , key )
421376 return nil // Early return - validation passed ✅
422377 }
423378 }
424379 }
425380 }
426381 }
427382
428- return fmt .Errorf ("spp '%s' in profile '%s' is not found in secret '%s' " ,
429- sppValue , profileName , secret .Name )
383+ return fmt .Errorf ("spp '%s' is not found in secret '%s' " , sppValue , secret .Name )
430384}
431385
432386var _ webhook.Validator = & PtpConfig {}
0 commit comments