Merge pull request #104384 from feiskyer/fix-nsg-case
fix: skip case sensitivity when checking Azure NSG rules
This commit is contained in:
		| @@ -1858,18 +1858,18 @@ func (az *Cloud) reconcileSecurityGroup(clusterName string, service *v1.Service, | |||||||
| 				sharedRuleName := az.getSecurityRuleName(service, port, sourceAddressPrefix) | 				sharedRuleName := az.getSecurityRuleName(service, port, sourceAddressPrefix) | ||||||
| 				sharedIndex, sharedRule, sharedRuleFound := findSecurityRuleByName(updatedRules, sharedRuleName) | 				sharedIndex, sharedRule, sharedRuleFound := findSecurityRuleByName(updatedRules, sharedRuleName) | ||||||
| 				if !sharedRuleFound { | 				if !sharedRuleFound { | ||||||
| 					klog.V(4).Infof("Expected to find shared rule %s for service %s being deleted, but did not", sharedRuleName, service.Name) | 					klog.V(4).Infof("Didn't find shared rule %s for service %s", sharedRuleName, service.Name) | ||||||
| 					return nil, fmt.Errorf("expected to find shared rule %s for service %s being deleted, but did not", sharedRuleName, service.Name) | 					continue | ||||||
| 				} | 				} | ||||||
| 				if sharedRule.DestinationAddressPrefixes == nil { | 				if sharedRule.DestinationAddressPrefixes == nil { | ||||||
| 					klog.V(4).Infof("Expected to have array of destinations in shared rule for service %s being deleted, but did not", service.Name) | 					klog.V(4).Infof("Didn't find DestinationAddressPrefixes in shared rule for service %s", service.Name) | ||||||
| 					return nil, fmt.Errorf("expected to have array of destinations in shared rule for service %s being deleted, but did not", service.Name) | 					continue | ||||||
| 				} | 				} | ||||||
| 				existingPrefixes := *sharedRule.DestinationAddressPrefixes | 				existingPrefixes := *sharedRule.DestinationAddressPrefixes | ||||||
| 				addressIndex, found := findIndex(existingPrefixes, destinationIPAddress) | 				addressIndex, found := findIndex(existingPrefixes, destinationIPAddress) | ||||||
| 				if !found { | 				if !found { | ||||||
| 					klog.V(4).Infof("Expected to find destination address %s in shared rule %s for service %s being deleted, but did not", destinationIPAddress, sharedRuleName, service.Name) | 					klog.V(4).Infof("Didn't find destination address %v in shared rule %s for service %s", destinationIPAddress, sharedRuleName, service.Name) | ||||||
| 					return nil, fmt.Errorf("expected to find destination address %s in shared rule %s for service %s being deleted, but did not", destinationIPAddress, sharedRuleName, service.Name) | 					continue | ||||||
| 				} | 				} | ||||||
| 				if len(existingPrefixes) == 1 { | 				if len(existingPrefixes) == 1 { | ||||||
| 					updatedRules = append(updatedRules[:sharedIndex], updatedRules[sharedIndex+1:]...) | 					updatedRules = append(updatedRules[:sharedIndex], updatedRules[sharedIndex+1:]...) | ||||||
| @@ -2426,7 +2426,7 @@ func findSecurityRule(rules []network.SecurityRule, rule network.SecurityRule) b | |||||||
| 		if !strings.EqualFold(to.String(existingRule.Name), to.String(rule.Name)) { | 		if !strings.EqualFold(to.String(existingRule.Name), to.String(rule.Name)) { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		if existingRule.Protocol != rule.Protocol { | 		if !strings.EqualFold(string(existingRule.Protocol), string(rule.Protocol)) { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		if !strings.EqualFold(to.String(existingRule.SourcePortRange), to.String(rule.SourcePortRange)) { | 		if !strings.EqualFold(to.String(existingRule.SourcePortRange), to.String(rule.SourcePortRange)) { | ||||||
| @@ -2443,10 +2443,10 @@ func findSecurityRule(rules []network.SecurityRule, rule network.SecurityRule) b | |||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if existingRule.Access != rule.Access { | 		if !strings.EqualFold(string(existingRule.Access), string(rule.Access)) { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		if existingRule.Direction != rule.Direction { | 		if !strings.EqualFold(string(existingRule.Direction), string(rule.Direction)) { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		return true | 		return true | ||||||
|   | |||||||
| @@ -2585,6 +2585,36 @@ func TestReconcileSecurityGroup(t *testing.T) { | |||||||
| 				}, | 				}, | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
|  | 		{ | ||||||
|  | 			desc:    "reconcileSecurityGroup shall create shared sgs for service with azure-shared-securityrule annotations", | ||||||
|  | 			service: getTestService("test1", v1.ProtocolTCP, map[string]string{ServiceAnnotationSharedSecurityRule: "true"}, true, 80), | ||||||
|  | 			existingSgs: map[string]network.SecurityGroup{"nsg": { | ||||||
|  | 				Name:                          to.StringPtr("nsg"), | ||||||
|  | 				SecurityGroupPropertiesFormat: &network.SecurityGroupPropertiesFormat{}, | ||||||
|  | 			}}, | ||||||
|  | 			lbIP:   to.StringPtr("1.2.3.4"), | ||||||
|  | 			wantLb: true, | ||||||
|  | 			expectedSg: &network.SecurityGroup{ | ||||||
|  | 				Name: to.StringPtr("nsg"), | ||||||
|  | 				SecurityGroupPropertiesFormat: &network.SecurityGroupPropertiesFormat{ | ||||||
|  | 					SecurityRules: &[]network.SecurityRule{ | ||||||
|  | 						{ | ||||||
|  | 							Name: to.StringPtr("shared-TCP-80-Internet"), | ||||||
|  | 							SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ | ||||||
|  | 								Protocol:                   network.SecurityRuleProtocol("Tcp"), | ||||||
|  | 								SourcePortRange:            to.StringPtr("*"), | ||||||
|  | 								DestinationPortRange:       to.StringPtr("80"), | ||||||
|  | 								SourceAddressPrefix:        to.StringPtr("Internet"), | ||||||
|  | 								DestinationAddressPrefixes: to.StringSlicePtr([]string{"1.2.3.4"}), | ||||||
|  | 								Access:                     network.SecurityRuleAccess("Allow"), | ||||||
|  | 								Priority:                   to.Int32Ptr(500), | ||||||
|  | 								Direction:                  network.SecurityRuleDirection("Inbound"), | ||||||
|  | 							}, | ||||||
|  | 						}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for i, test := range testCases { | 	for i, test := range testCases { | ||||||
|   | |||||||
| @@ -3336,3 +3336,156 @@ func TestInitializeCloudFromConfig(t *testing.T) { | |||||||
| 	expectedErr = fmt.Errorf("useInstanceMetadata must be enabled without Azure credentials") | 	expectedErr = fmt.Errorf("useInstanceMetadata must be enabled without Azure credentials") | ||||||
| 	assert.Equal(t, expectedErr, err) | 	assert.Equal(t, expectedErr, err) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestFindSecurityRule(t *testing.T) { | ||||||
|  | 	testRuleName := "test-rule" | ||||||
|  | 	testIP1 := "192.168.192.168" | ||||||
|  | 	sg := network.SecurityRule{ | ||||||
|  | 		Name: to.StringPtr(testRuleName), | ||||||
|  | 		SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ | ||||||
|  | 			Protocol:                 network.SecurityRuleProtocolTCP, | ||||||
|  | 			SourcePortRange:          to.StringPtr("*"), | ||||||
|  | 			SourceAddressPrefix:      to.StringPtr("Internet"), | ||||||
|  | 			DestinationPortRange:     to.StringPtr("80"), | ||||||
|  | 			DestinationAddressPrefix: to.StringPtr(testIP1), | ||||||
|  | 			Access:                   network.SecurityRuleAccessAllow, | ||||||
|  | 			Direction:                network.SecurityRuleDirectionInbound, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	testCases := []struct { | ||||||
|  | 		desc     string | ||||||
|  | 		testRule network.SecurityRule | ||||||
|  | 		expected bool | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			desc:     "false should be returned for an empty rule", | ||||||
|  | 			testRule: network.SecurityRule{}, | ||||||
|  | 			expected: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			desc: "false should be returned when rule name doesn't match", | ||||||
|  | 			testRule: network.SecurityRule{ | ||||||
|  | 				Name: to.StringPtr("not-the-right-name"), | ||||||
|  | 			}, | ||||||
|  | 			expected: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			desc: "false should be returned when protocol doesn't match", | ||||||
|  | 			testRule: network.SecurityRule{ | ||||||
|  | 				Name: to.StringPtr(testRuleName), | ||||||
|  | 				SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ | ||||||
|  | 					Protocol: network.SecurityRuleProtocolUDP, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			expected: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			desc: "false should be returned when SourcePortRange doesn't match", | ||||||
|  | 			testRule: network.SecurityRule{ | ||||||
|  | 				Name: to.StringPtr(testRuleName), | ||||||
|  | 				SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ | ||||||
|  | 					Protocol:        network.SecurityRuleProtocolUDP, | ||||||
|  | 					SourcePortRange: to.StringPtr("1.2.3.4/32"), | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			expected: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			desc: "false should be returned when SourceAddressPrefix doesn't match", | ||||||
|  | 			testRule: network.SecurityRule{ | ||||||
|  | 				Name: to.StringPtr(testRuleName), | ||||||
|  | 				SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ | ||||||
|  | 					Protocol:            network.SecurityRuleProtocolUDP, | ||||||
|  | 					SourcePortRange:     to.StringPtr("*"), | ||||||
|  | 					SourceAddressPrefix: to.StringPtr("2.3.4.0/24"), | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			expected: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			desc: "false should be returned when DestinationPortRange doesn't match", | ||||||
|  | 			testRule: network.SecurityRule{ | ||||||
|  | 				Name: to.StringPtr(testRuleName), | ||||||
|  | 				SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ | ||||||
|  | 					Protocol:             network.SecurityRuleProtocolUDP, | ||||||
|  | 					SourcePortRange:      to.StringPtr("*"), | ||||||
|  | 					SourceAddressPrefix:  to.StringPtr("Internet"), | ||||||
|  | 					DestinationPortRange: to.StringPtr("443"), | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			expected: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			desc: "false should be returned when DestinationAddressPrefix doesn't match", | ||||||
|  | 			testRule: network.SecurityRule{ | ||||||
|  | 				Name: to.StringPtr(testRuleName), | ||||||
|  | 				SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ | ||||||
|  | 					Protocol:                 network.SecurityRuleProtocolUDP, | ||||||
|  | 					SourcePortRange:          to.StringPtr("*"), | ||||||
|  | 					SourceAddressPrefix:      to.StringPtr("Internet"), | ||||||
|  | 					DestinationPortRange:     to.StringPtr("80"), | ||||||
|  | 					DestinationAddressPrefix: to.StringPtr("192.168.0.3"), | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			expected: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			desc: "false should be returned when Access doesn't match", | ||||||
|  | 			testRule: network.SecurityRule{ | ||||||
|  | 				Name: to.StringPtr(testRuleName), | ||||||
|  | 				SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ | ||||||
|  | 					Protocol:                 network.SecurityRuleProtocolUDP, | ||||||
|  | 					SourcePortRange:          to.StringPtr("*"), | ||||||
|  | 					SourceAddressPrefix:      to.StringPtr("Internet"), | ||||||
|  | 					DestinationPortRange:     to.StringPtr("80"), | ||||||
|  | 					DestinationAddressPrefix: to.StringPtr(testIP1), | ||||||
|  | 					Access:                   network.SecurityRuleAccessDeny, | ||||||
|  | 					// Direction:                network.SecurityRuleDirectionInbound, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			expected: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			desc: "false should be returned when Direction doesn't match", | ||||||
|  | 			testRule: network.SecurityRule{ | ||||||
|  | 				Name: to.StringPtr(testRuleName), | ||||||
|  | 				SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ | ||||||
|  | 					Protocol:                 network.SecurityRuleProtocolUDP, | ||||||
|  | 					SourcePortRange:          to.StringPtr("*"), | ||||||
|  | 					SourceAddressPrefix:      to.StringPtr("Internet"), | ||||||
|  | 					DestinationPortRange:     to.StringPtr("80"), | ||||||
|  | 					DestinationAddressPrefix: to.StringPtr(testIP1), | ||||||
|  | 					Access:                   network.SecurityRuleAccessAllow, | ||||||
|  | 					Direction:                network.SecurityRuleDirectionOutbound, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			expected: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			desc: "true should be returned when everything matches but protocol is in different case", | ||||||
|  | 			testRule: network.SecurityRule{ | ||||||
|  | 				Name: to.StringPtr(testRuleName), | ||||||
|  | 				SecurityRulePropertiesFormat: &network.SecurityRulePropertiesFormat{ | ||||||
|  | 					Protocol:                 network.SecurityRuleProtocol("TCP"), | ||||||
|  | 					SourcePortRange:          to.StringPtr("*"), | ||||||
|  | 					SourceAddressPrefix:      to.StringPtr("Internet"), | ||||||
|  | 					DestinationPortRange:     to.StringPtr("80"), | ||||||
|  | 					DestinationAddressPrefix: to.StringPtr(testIP1), | ||||||
|  | 					Access:                   network.SecurityRuleAccessAllow, | ||||||
|  | 					Direction:                network.SecurityRuleDirectionInbound, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			expected: true, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			desc:     "true should be returned when everything matches", | ||||||
|  | 			testRule: sg, | ||||||
|  | 			expected: true, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for i := range testCases { | ||||||
|  | 		found := findSecurityRule([]network.SecurityRule{sg}, testCases[i].testRule) | ||||||
|  | 		assert.Equal(t, testCases[i].expected, found, testCases[i].desc) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Kubernetes Prow Robot
					Kubernetes Prow Robot