Skip to content

Commit a207137

Browse files
Added Validation for webhook
Signed-off-by: anirudhAgniRedhat <[email protected]>
1 parent ac84cec commit a207137

File tree

379 files changed

+5829
-42337
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

379 files changed

+5829
-42337
lines changed

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,3 +266,5 @@ require (
266266
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect
267267
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
268268
)
269+
270+
replace github.com/openshift/api => github.com/anirudhAgniRedhat/openshift-api v0.0.2

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pO
7171
github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE=
7272
github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw=
7373
github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I=
74+
github.com/anirudhAgniRedhat/openshift-api v0.0.2 h1:a8hXwzEWWmF3/ea/KTuZLAfF4XBJL9xKjWLpYxuWnHw=
75+
github.com/anirudhAgniRedhat/openshift-api v0.0.2/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4=
7476
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
7577
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
7678
github.com/ashanbrown/forbidigo v1.5.1 h1:WXhzLjOlnuDYPYQo/eFlcFMi8X/kLfvWLYu6CSoebis=
@@ -479,8 +481,6 @@ github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY
479481
github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw=
480482
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
481483
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
482-
github.com/openshift/api v0.0.0-20240124164020-e2ce40831f2e h1:cxgCNo/R769CO23AK5TCh45H9SMUGZ8RukiF2/Qif3o=
483-
github.com/openshift/api v0.0.0-20240124164020-e2ce40831f2e/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4=
484484
github.com/openshift/client-go v0.0.0-20240115204758-e6bf7d631d5e h1:qGjfKX8i0h4efMNEnhgTdxcdx6gwwOwhTfBJ20WFqA8=
485485
github.com/openshift/client-go v0.0.0-20240115204758-e6bf7d631d5e/go.mod h1:2am3qrggh9LlDCf/MDGzcFWMhdaushxFQi0+ZZDhdVk=
486486
github.com/openshift/library-go v0.0.0-20240116081341-964bcb3f545c h1:gLylEQQryG+A6nqWYIwE1wUzn1eFUmthjADvflMWKnM=

pkg/webhooks/machine_webhook.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,12 @@ const (
192192
powerVSImage = "image"
193193
powerVSSystemTypeE880 = "e880"
194194
powerVSSystemTypeE980 = "e980"
195+
azureProviderIDPrefix = "azure://"
196+
azureProvidersKey = "providers"
197+
azureSubscriptionsKey = "subscriptions"
198+
azureResourceGroupsLowerKey = "resourcegroups"
199+
azureLocationsKey = "locations"
200+
azureBuiltInResourceNamespace = "Microsoft.Resources"
195201
)
196202

197203
// GCP Confidential VM supports Compute Engine machine types in the following series:
@@ -925,6 +931,13 @@ func validateAzure(m *machinev1beta1.Machine, config *admissionConfig) (bool, []
925931
fmt.Sprintf("osDisk.diskSettings.ephemeralStorageLocation can either be omitted or set to %s", azureEphemeralStorageLocationLocal)))
926932
}
927933

934+
if providerSpec.CapacityReservationGroupID != "" {
935+
err := validateAzureCapacityReservationGroupID(providerSpec.CapacityReservationGroupID)
936+
if err != nil {
937+
errs = append(errs, field.Invalid(field.NewPath("providerSpec", "capacityReservationGroupID"), providerSpec.CapacityReservationGroupID, err.Error()))
938+
}
939+
}
940+
928941
switch providerSpec.OSDisk.CachingType {
929942
case azureCachingTypeNone, azureCachingTypeReadOnly, azureCachingTypeReadWrite, "":
930943
// Valid scenarios, do nothing
@@ -2055,3 +2068,65 @@ func validateGVK(gvk schema.GroupVersionKind, platform osconfigv1.PlatformType)
20552068
return true
20562069
}
20572070
}
2071+
2072+
func validateAzureCapacityReservationGroupID(capacityReservationGroupID string) error {
2073+
id := strings.TrimPrefix(capacityReservationGroupID, azureProviderIDPrefix)
2074+
err := parseAzureResourceID(id)
2075+
if err != nil {
2076+
return err
2077+
}
2078+
return nil
2079+
}
2080+
2081+
// parseAzureResourceID parses a string to an instance of ResourceID
2082+
func parseAzureResourceID(id string) error {
2083+
if len(id) == 0 {
2084+
return fmt.Errorf("invalid resource ID: id cannot be empty")
2085+
}
2086+
if !strings.HasPrefix(id, "/") {
2087+
return fmt.Errorf("invalid resource ID: resource id '%s' must start with '/'", id)
2088+
}
2089+
parts := splitStringAndOmitEmpty(id, "/")
2090+
2091+
if len(parts) < 2 {
2092+
return fmt.Errorf("invalid resource ID: %s", id)
2093+
}
2094+
if !strings.EqualFold(parts[0], azureSubscriptionsKey) && !strings.EqualFold(parts[0], azureProvidersKey) {
2095+
return fmt.Errorf("invalid resource ID: %s", id)
2096+
}
2097+
return appendNextAzureResourceIDValidation(parts, id)
2098+
}
2099+
2100+
func splitStringAndOmitEmpty(v, sep string) []string {
2101+
r := make([]string, 0)
2102+
for _, s := range strings.Split(v, sep) {
2103+
if len(s) == 0 {
2104+
continue
2105+
}
2106+
r = append(r, s)
2107+
}
2108+
return r
2109+
}
2110+
2111+
func appendNextAzureResourceIDValidation(parts []string, id string) error {
2112+
if len(parts) == 0 {
2113+
return nil
2114+
}
2115+
if len(parts) == 1 {
2116+
// subscriptions and resourceGroups are not valid ids without their names
2117+
if strings.EqualFold(parts[0], azureSubscriptionsKey) || strings.EqualFold(parts[0], azureResourceGroupsLowerKey) {
2118+
return fmt.Errorf("invalid resource ID: %s", id)
2119+
}
2120+
return nil
2121+
}
2122+
if strings.EqualFold(parts[0], azureProvidersKey) && (len(parts) == 2 || strings.EqualFold(parts[2], azureProvidersKey)) {
2123+
return appendNextAzureResourceIDValidation(parts[2:], id)
2124+
}
2125+
if len(parts) > 3 && strings.EqualFold(parts[0], azureProvidersKey) {
2126+
return appendNextAzureResourceIDValidation(parts[4:], id)
2127+
}
2128+
if len(parts) > 1 && !strings.EqualFold(parts[0], azureProvidersKey) {
2129+
return appendNextAzureResourceIDValidation(parts[2:], id)
2130+
}
2131+
return fmt.Errorf("invalid resource ID: %s", id)
2132+
}

pkg/webhooks/machine_webhook_test.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,48 @@ func TestMachineCreation(t *testing.T) {
332332
},
333333
expectedError: "",
334334
},
335+
{
336+
name: "with Azure and CapacityReservationID is empty",
337+
platformType: osconfigv1.AzurePlatformType,
338+
clusterID: "azure-cluster",
339+
providerSpecValue: &kruntime.RawExtension{
340+
Object: &machinev1beta1.AzureMachineProviderSpec{
341+
OSDisk: machinev1beta1.OSDisk{
342+
DiskSizeGB: 128,
343+
},
344+
CapacityReservationGroupID: "",
345+
},
346+
},
347+
expectedError: "",
348+
},
349+
{
350+
name: "with Azure and CapacityReservationID is valid",
351+
platformType: osconfigv1.AzurePlatformType,
352+
clusterID: "azure-cluster",
353+
providerSpecValue: &kruntime.RawExtension{
354+
Object: &machinev1beta1.AzureMachineProviderSpec{
355+
OSDisk: machinev1beta1.OSDisk{
356+
DiskSizeGB: 128,
357+
},
358+
CapacityReservationGroupID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroupName/providers/Microsoft.Compute/capacityReservationGroups/myCapacityReservationGroup",
359+
},
360+
},
361+
expectedError: "",
362+
},
363+
{
364+
name: "with Azure and CapacityReservationID is not valid",
365+
platformType: osconfigv1.AzurePlatformType,
366+
clusterID: "azure-cluster",
367+
providerSpecValue: &kruntime.RawExtension{
368+
Object: &machinev1beta1.AzureMachineProviderSpec{
369+
OSDisk: machinev1beta1.OSDisk{
370+
DiskSizeGB: 128,
371+
},
372+
CapacityReservationGroupID: "/subscri/00000000-0000-0000-0000-000000000000/resour/myResourceGroupName/providers/Microsoft.Compute/capacityReservationGroups/myCapacityReservationGroup",
373+
},
374+
},
375+
expectedError: "admission webhook \"validation.machine.machine.openshift.io\" denied the request: providerSpec.capacityReservationGroupID: Invalid value: \"/subscri/00000000-0000-0000-0000-000000000000/resour/myResourceGroupName/providers/Microsoft.Compute/capacityReservationGroups/myCapacityReservationGroup\": invalid resource ID: /subscri/00000000-0000-0000-0000-000000000000/resour/myResourceGroupName/providers/Microsoft.Compute/capacityReservationGroups/myCapacityReservationGroup",
376+
},
335377
{
336378
name: "with Azure and a Premium Disk Data Disk set",
337379
platformType: osconfigv1.AzurePlatformType,
@@ -5040,3 +5082,44 @@ func TestValidateNutanixProviderSpec(t *testing.T) {
50405082
})
50415083
}
50425084
}
5085+
5086+
func TestValidateAzureCapacityReservationGroupID(t *testing.T) {
5087+
testCases := []struct {
5088+
name string
5089+
inputID string
5090+
expectError bool
5091+
}{
5092+
{
5093+
name: "validation for capacityReservationGroupID should return nil error if field input is valid",
5094+
inputID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroupName/providers/Microsoft.Compute/capacityReservationGroups/myCapacityReservationGroup",
5095+
expectError: false,
5096+
},
5097+
{
5098+
name: "validation for capacityReservationGroupID should return error if field input does not start with '/'",
5099+
inputID: "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroupName/providers/Microsoft.Compute/capacityReservationGroups/myCapacityReservationGroup",
5100+
expectError: true,
5101+
},
5102+
{
5103+
name: "validation for capacityReservationGroupID should return error if field input does not have field name subscriptions",
5104+
inputID: "/subscripti/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroupName/providers/Microsoft.Compute/capacityReservationGroups/myCapacityReservationGroup",
5105+
expectError: true,
5106+
},
5107+
{
5108+
name: "validation for capacityReservationGroupID should return error if field input is empty",
5109+
inputID: "",
5110+
expectError: true,
5111+
},
5112+
}
5113+
5114+
for _, tc := range testCases {
5115+
t.Run(tc.name, func(t *testing.T) {
5116+
g := NewWithT(t)
5117+
err := validateAzureCapacityReservationGroupID(tc.inputID)
5118+
if tc.expectError {
5119+
g.Expect(err).To(HaveOccurred())
5120+
} else {
5121+
g.Expect(err).ToNot(HaveOccurred())
5122+
}
5123+
})
5124+
}
5125+
}

vendor/github.com/openshift/api/Makefile

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)