Skip to content

Commit

Permalink
fix: validate resourcePrefix in NCP DP (#650)
Browse files Browse the repository at this point in the history
In the admission controller, the `resourcePrefix` field in Device
Plugins configuration is now validated to be a valid FQDN.
  • Loading branch information
adrianchiris authored Oct 25, 2023
2 parents 62247e5 + bb5e1ac commit 9890794
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 270 deletions.
60 changes: 48 additions & 12 deletions api/v1alpha1/nicclusterpolicy_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ import (
"sigs.k8s.io/controller-runtime/pkg/webhook"
)

const (
fqdnRegex = `^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z]{2,})+$`
sriovResourceNameRegex = `^([A-Za-z0-9][A-Za-z0-9_.]*)?[A-Za-z0-9]$`
rdmaResourceNameRegex = `^([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$`
)

// log is for logging in this package.
var nicClusterPolicyLog = logf.Log.WithName("nicclusterpolicy-resource")

Expand Down Expand Up @@ -200,12 +206,9 @@ func (dp *DevicePluginSpec) validateSriovNetworkDevicePlugin(fldPath *field.Path
resourceJSONLoader := gojsonschema.NewStringLoader(string(resourceJSONString))
var selectorResult *gojsonschema.Result
var selectorErr error
resourceName := resource["resourceName"].(string)
if !isValidSriovNetworkDevicePluginResourceName(resourceName) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("Config"), dp.Config,
"Invalid Resource name, it must consist of alphanumeric characters, '_' or '.', "+
"and must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', "+
"or '123_abc', regex used for validation is '([A-Za-z0-9][A-Za-z0-9_.]*)?[A-Za-z0-9]')"))
var ok bool
ok, allErrs = validateResourceNamePrefix(resource, allErrs, fldPath, dp)
if !ok {
return allErrs
}
deviceType := resource["deviceType"]
Expand All @@ -231,6 +234,28 @@ func (dp *DevicePluginSpec) validateSriovNetworkDevicePlugin(fldPath *field.Path
return allErrs
}

func validateResourceNamePrefix(resource map[string]interface{},
allErrs field.ErrorList, fldPath *field.Path, dp *DevicePluginSpec) (bool, field.ErrorList) {
resourceName := resource["resourceName"].(string)
if !isValidSriovNetworkDevicePluginResourceName(resourceName) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("Config"), dp.Config,
"Invalid Resource name, it must consist of alphanumeric characters, '_' or '.', "+
"and must start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', "+
"or '123_abc', regex used for validation is "+sriovResourceNameRegex))
return false, allErrs
}
resourcePrefix, ok := resource["resourcePrefix"]
if ok {
if !isValidFQDN(resourcePrefix.(string)) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("Config"), dp.Config,
"Invalid Resource prefix, it must be a valid FQDN"+
"regex used for validation is "+fqdnRegex))
return false, allErrs
}
}
return true, allErrs
}

func (dp *DevicePluginSpec) validateRdmaSharedDevicePlugin(fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
var rdmaSharedDevicePluginConfigJSON map[string]interface{}
Expand Down Expand Up @@ -265,8 +290,16 @@ func (dp *DevicePluginSpec) validateRdmaSharedDevicePlugin(fldPath *field.Path)
allErrs = append(allErrs, field.Invalid(fldPath.Child("Config"),
dp.Config, "Invalid Resource name, it must consist of alphanumeric characters, "+
"'-', '_' or '.', and must start and end with an alphanumeric character "+
"(e.g. 'MyName', or 'my.name', or '123-abc', regex used for validation is '([A-Za-z0-9][-A-Za-z0"+
"-9_.]*)?[A-Za-z0-9]')"))
"(e.g. 'MyName', or 'my.name', or '123-abc') regex used for validation is "+rdmaResourceNameRegex))
}
resourcePrefix, ok := config["resourcePrefix"]
if ok {
if !isValidFQDN(resourcePrefix.(string)) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("Config"), dp.Config,
"Invalid Resource prefix, it must be a valid FQDN "+
"regex used for validation is "+fqdnRegex))
return allErrs
}
}
}
} else {
Expand Down Expand Up @@ -386,17 +419,20 @@ func isValidOFEDVersion(version string) bool {
}

func isValidSriovNetworkDevicePluginResourceName(resourceName string) bool {
resourceNamePattern := `^([A-Za-z0-9][A-Za-z0-9_.]*)?[A-Za-z0-9]$`
resourceNameRegex := regexp.MustCompile(resourceNamePattern)
resourceNameRegex := regexp.MustCompile(sriovResourceNameRegex)
return resourceNameRegex.MatchString(resourceName)
}

func isValidRdmaSharedDevicePluginResourceName(resourceName string) bool {
resourceNamePattern := `^([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$`
resourceNameRegex := regexp.MustCompile(resourceNamePattern)
resourceNameRegex := regexp.MustCompile(rdmaResourceNameRegex)
return resourceNameRegex.MatchString(resourceName)
}

func isValidFQDN(input string) bool {
regex := regexp.MustCompile(fqdnRegex)
return regex.MatchString(input)
}

// +kubebuilder:object:generate=false
type schemaValidator struct {
schemas map[string]*gojsonschema.Schema
Expand Down
Loading

0 comments on commit 9890794

Please sign in to comment.