Skip to content

Commit 6349d8b

Browse files
committed
Refactor webhook validation functions to standalone with minimal args
- Convert validateSecretExistsForProfile to standalone function - Convert validateSecretConflictsForProfile to validateSaFileSecretConflicts - Convert validateSppInSecret to standalone function - Extract getSppFromPtp4lConf and getSaFileFromPtp4lConf helpers - Remove redundant nil checks already performed by caller - Simplify function signatures to accept only necessary parameters - Remove unused apierrors import - Flatten nested if statements for improved readability
1 parent ff2846c commit 6349d8b

File tree

1 file changed

+59
-105
lines changed

1 file changed

+59
-105
lines changed

api/v1/ptpconfig_webhook.go

Lines changed: 59 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -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

432386
var _ webhook.Validator = &PtpConfig{}

0 commit comments

Comments
 (0)