github.com/vmware/go-vcloud-director/v2@v2.24.0/govcd/nsxt_firewall_test.go (about) 1 //go:build network || nsxt || functional || openapi || ALL 2 3 package govcd 4 5 import ( 6 "crypto/rand" 7 "fmt" 8 "github.com/vmware/go-vcloud-director/v2/util" 9 "math/big" 10 "os" 11 "strconv" 12 "text/tabwriter" 13 14 "github.com/vmware/go-vcloud-director/v2/types/v56" 15 . "gopkg.in/check.v1" 16 ) 17 18 // Test_NsxtFirewall creates 20 firewall rules with randomized parameters 19 func (vcd *TestVCD) Test_NsxtFirewall(check *C) { 20 skipNoNsxtConfiguration(vcd, check) 21 skipOpenApiEndpointTest(vcd, check, types.OpenApiPathVersion1_0_0+types.OpenApiEndpointFirewallGroups) 22 23 org, err := vcd.client.GetOrgByName(vcd.config.VCD.Org) 24 check.Assert(err, IsNil) 25 nsxtVdc, err := org.GetVDCByName(vcd.config.VCD.Nsxt.Vdc, false) 26 check.Assert(err, IsNil) 27 edge, err := nsxtVdc.GetNsxtEdgeGatewayByName(vcd.config.VCD.Nsxt.EdgeGateway) 28 check.Assert(err, IsNil) 29 30 // Get existing firewall rule configuration 31 fwRules, err := edge.GetNsxtFirewall() 32 check.Assert(err, IsNil) 33 34 existingDefaultRuleCount := len(fwRules.NsxtFirewallRuleContainer.DefaultRules) 35 existingSystemRuleCount := len(fwRules.NsxtFirewallRuleContainer.SystemRules) 36 37 // Create some prerequisites and generate firewall rule configurations to feed them into config 38 randomizedFwRuleDefs := createFirewallDefinitions(check, vcd) 39 fwRules.NsxtFirewallRuleContainer.UserDefinedRules = randomizedFwRuleDefs 40 41 if testVerbose { 42 dumpFirewallRulesToScreen(randomizedFwRuleDefs) 43 } 44 45 fwCreated, err := edge.UpdateNsxtFirewall(fwRules.NsxtFirewallRuleContainer) 46 check.Assert(err, IsNil) 47 48 openApiEndpoint := types.OpenApiPathVersion1_0_0 + fmt.Sprintf(types.OpenApiEndpointNsxtFirewallRules, edge.EdgeGateway.ID) 49 PrependToCleanupList(openApiEndpoint, "OpenApiEntityFirewall", edge.EdgeGateway.Name, check.TestName()) 50 51 check.Assert(fwCreated, Not(IsNil)) 52 check.Assert(len(fwCreated.NsxtFirewallRuleContainer.UserDefinedRules), Equals, len(randomizedFwRuleDefs)) 53 54 // Check that all created rules are have the same attributes and order 55 for index := range fwCreated.NsxtFirewallRuleContainer.UserDefinedRules { 56 check.Assert(fwCreated.NsxtFirewallRuleContainer.UserDefinedRules[index].Name, Equals, randomizedFwRuleDefs[index].Name) 57 check.Assert(fwCreated.NsxtFirewallRuleContainer.UserDefinedRules[index].Direction, Equals, randomizedFwRuleDefs[index].Direction) 58 check.Assert(fwCreated.NsxtFirewallRuleContainer.UserDefinedRules[index].IpProtocol, Equals, randomizedFwRuleDefs[index].IpProtocol) 59 check.Assert(fwCreated.NsxtFirewallRuleContainer.UserDefinedRules[index].Enabled, Equals, randomizedFwRuleDefs[index].Enabled) 60 check.Assert(fwCreated.NsxtFirewallRuleContainer.UserDefinedRules[index].Action, Equals, randomizedFwRuleDefs[index].Action) 61 if vcd.client.Client.IsSysAdmin { 62 // Only system administrator can handle logging 63 check.Assert(fwCreated.NsxtFirewallRuleContainer.UserDefinedRules[index].Logging, Equals, randomizedFwRuleDefs[index].Logging) 64 } 65 66 for fwGroupIndex := range fwCreated.NsxtFirewallRuleContainer.UserDefinedRules[index].SourceFirewallGroups { 67 check.Assert(fwCreated.NsxtFirewallRuleContainer.UserDefinedRules[index].SourceFirewallGroups[fwGroupIndex].ID, Equals, randomizedFwRuleDefs[index].SourceFirewallGroups[fwGroupIndex].ID) 68 } 69 70 for fwGroupIndex := range fwCreated.NsxtFirewallRuleContainer.UserDefinedRules[index].DestinationFirewallGroups { 71 check.Assert(fwCreated.NsxtFirewallRuleContainer.UserDefinedRules[index].DestinationFirewallGroups[fwGroupIndex].ID, Equals, randomizedFwRuleDefs[index].DestinationFirewallGroups[fwGroupIndex].ID) 72 } 73 74 // Ensure the same amount of Application Port Profiles are assigned and created 75 check.Assert(len(fwCreated.NsxtFirewallRuleContainer.UserDefinedRules), Equals, len(randomizedFwRuleDefs)) 76 definedAppPortProfileIds := extractIdsFromOpenApiReferences(randomizedFwRuleDefs[index].ApplicationPortProfiles) 77 for _, appPortProfile := range fwCreated.NsxtFirewallRuleContainer.UserDefinedRules[index].ApplicationPortProfiles { 78 check.Assert(contains(appPortProfile.ID, definedAppPortProfileIds), Equals, true) 79 } 80 } 81 82 // Delete a single rule by ID and check for two things: 83 // * Rule with deleted ID should not be found in list post deletion 84 // * There should be one less rule in the list 85 deleteRuleId := fwCreated.NsxtFirewallRuleContainer.UserDefinedRules[3].ID 86 err = fwCreated.DeleteRuleById(deleteRuleId) 87 check.Assert(err, IsNil) 88 89 allRulesPostDeletion, err := edge.GetNsxtFirewall() 90 check.Assert(err, IsNil) 91 92 check.Assert(len(allRulesPostDeletion.NsxtFirewallRuleContainer.UserDefinedRules), Equals, len(fwCreated.NsxtFirewallRuleContainer.UserDefinedRules)-1) 93 for _, rule := range allRulesPostDeletion.NsxtFirewallRuleContainer.UserDefinedRules { 94 check.Assert(rule.ID, Not(Equals), deleteRuleId) 95 } 96 97 err = fwRules.DeleteAllRules() 98 check.Assert(err, IsNil) 99 100 // Ensure no firewall rules left in user space post deletion, but the same amount of default and system rules still exist 101 postDeleteCheck, err := edge.GetNsxtFirewall() 102 check.Assert(err, IsNil) 103 check.Assert(len(postDeleteCheck.NsxtFirewallRuleContainer.UserDefinedRules), Equals, 0) 104 check.Assert(len(postDeleteCheck.NsxtFirewallRuleContainer.DefaultRules), Equals, existingDefaultRuleCount) 105 check.Assert(len(postDeleteCheck.NsxtFirewallRuleContainer.SystemRules), Equals, existingSystemRuleCount) 106 107 } 108 109 // createFirewallDefinitions creates some randomized firewall rule configurations to match possible configurations 110 func createFirewallDefinitions(check *C, vcd *TestVCD) []*types.NsxtFirewallRule { 111 // This number does not impact performance because all rules are created at once in the API 112 numberOfRules := 20 113 114 // Pre-Create Firewall Groups (IP Set and Security Group to randomly configure them) 115 ipSet := preCreateIpSet(check, vcd) 116 secGroup := preCreateSecurityGroup(check, vcd) 117 fwGroupIds := []string{ipSet.NsxtFirewallGroup.ID, secGroup.NsxtFirewallGroup.ID} 118 fwGroupRefs := convertSliceOfStringsToOpenApiReferenceIds(fwGroupIds) 119 appPortProfileReferences := getRandomListOfAppPortProfiles(check, vcd) 120 121 firewallRules := make([]*types.NsxtFirewallRule, numberOfRules) 122 for a := 0; a < numberOfRules; a++ { 123 124 // Feed in empty value for source and destination or a firewall group 125 src := pickRandomOpenApiRefOrEmpty(fwGroupRefs) 126 var srcValue []types.OpenApiReference 127 dst := pickRandomOpenApiRefOrEmpty(fwGroupRefs) 128 var dstValue []types.OpenApiReference 129 if src != (types.OpenApiReference{}) { 130 srcValue = []types.OpenApiReference{src} 131 } 132 if dst != (types.OpenApiReference{}) { 133 dstValue = []types.OpenApiReference{dst} 134 } 135 136 firewallRules[a] = &types.NsxtFirewallRule{ 137 Name: check.TestName() + strconv.Itoa(a), 138 Action: pickRandomString([]string{"ALLOW", "DROP"}), 139 Enabled: a%2 == 0, 140 SourceFirewallGroups: srcValue, 141 DestinationFirewallGroups: dstValue, 142 ApplicationPortProfiles: appPortProfileReferences[0:a], 143 IpProtocol: pickRandomString([]string{"IPV6", "IPV4", "IPV4_IPV6"}), 144 Logging: a%2 == 1, 145 Direction: pickRandomString([]string{"IN", "OUT", "IN_OUT"}), 146 } 147 } 148 149 return firewallRules 150 } 151 152 func pickRandomString(in []string) string { 153 randomIndex, _ := rand.Int(rand.Reader, big.NewInt(int64(len(in)))) 154 return in[randomIndex.Uint64()] 155 } 156 157 // pickRandomOpenApiRefOrEmpty picks a random OpenAPI entity or an empty one 158 func pickRandomOpenApiRefOrEmpty(in []types.OpenApiReference) types.OpenApiReference { 159 // Random value can be up to len+1 (len+1 is the special case when it should return an empty reference) 160 randomIndex, _ := rand.Int(rand.Reader, big.NewInt(int64(len(in)+1))) 161 if randomIndex.Uint64() == uint64(len(in)) { 162 return types.OpenApiReference{} 163 } 164 return in[randomIndex.Uint64()] 165 } 166 167 func preCreateIpSet(check *C, vcd *TestVCD) *NsxtFirewallGroup { 168 nsxtVdc := vcd.nsxtVdc 169 edge, err := nsxtVdc.GetNsxtEdgeGatewayByName(vcd.config.VCD.Nsxt.EdgeGateway) 170 check.Assert(err, IsNil) 171 172 ipSetDefinition := &types.NsxtFirewallGroup{ 173 Name: check.TestName() + "ipset", 174 Description: check.TestName() + "-Description", 175 Type: types.FirewallGroupTypeIpSet, 176 EdgeGatewayRef: &types.OpenApiReference{ID: edge.EdgeGateway.ID}, 177 178 IpAddresses: []string{ 179 "12.12.12.1", 180 "10.10.10.0/24", 181 "11.11.11.1-11.11.11.2", 182 // represents the block of IPv6 addresses from 2001:db8:0:0:0:0:0:0 to 2001:db8:0:ffff:ffff:ffff:ffff:ffff 183 "2001:db8::/48", 184 "2001:db6:0:0:0:0:0:0-2001:db6:0:ffff:ffff:ffff:ffff:ffff", 185 }, 186 } 187 188 // Create IP Set and add to cleanup if it was created 189 createdIpSet, err := nsxtVdc.CreateNsxtFirewallGroup(ipSetDefinition) 190 check.Assert(err, IsNil) 191 openApiEndpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointFirewallGroups + createdIpSet.NsxtFirewallGroup.ID 192 AddToCleanupListOpenApi(createdIpSet.NsxtFirewallGroup.Name, check.TestName(), openApiEndpoint) 193 194 return createdIpSet 195 } 196 197 func preCreateSecurityGroup(check *C, vcd *TestVCD) *NsxtFirewallGroup { 198 nsxtVdc := vcd.nsxtVdc 199 edge, err := nsxtVdc.GetNsxtEdgeGatewayByName(vcd.config.VCD.Nsxt.EdgeGateway) 200 check.Assert(err, IsNil) 201 202 fwGroupDefinition := &types.NsxtFirewallGroup{ 203 Name: check.TestName() + "security-group", 204 Description: check.TestName() + "-Description", 205 Type: types.FirewallGroupTypeSecurityGroup, 206 EdgeGatewayRef: &types.OpenApiReference{ID: edge.EdgeGateway.ID}, 207 } 208 209 // Create firewall group and add to cleanup if it was created 210 createdSecGroup, err := nsxtVdc.CreateNsxtFirewallGroup(fwGroupDefinition) 211 check.Assert(err, IsNil) 212 openApiEndpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointFirewallGroups + createdSecGroup.NsxtFirewallGroup.ID 213 AddToCleanupListOpenApi(check.TestName()+"sec-group", check.TestName(), openApiEndpoint) 214 215 return createdSecGroup 216 } 217 218 func getRandomListOfAppPortProfiles(check *C, vcd *TestVCD) []types.OpenApiReference { 219 org, err := vcd.client.GetOrgByName(vcd.config.VCD.Org) 220 check.Assert(err, IsNil) 221 222 appProfileSlice, err := org.GetAllNsxtAppPortProfiles(nil, types.ApplicationPortProfileScopeSystem) 223 check.Assert(err, IsNil) 224 225 openApiRefs := make([]types.OpenApiReference, len(appProfileSlice)) 226 for index, appPortProfile := range appProfileSlice { 227 openApiRefs[index].ID = appPortProfile.NsxtAppPortProfile.ID 228 openApiRefs[index].Name = appPortProfile.NsxtAppPortProfile.Name 229 } 230 231 return openApiRefs 232 } 233 234 func dumpFirewallRulesToScreen(rules []*types.NsxtFirewallRule) { 235 fmt.Println("# The following firewall rules will be created") 236 w := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0) 237 fmt.Fprintln(w, "Name\tDirection\tIP Protocol\tEnabled\tAction\tLogging\tSrc Count\tDst Count\tAppPortProfile Count") 238 239 for _, rule := range rules { 240 fmt.Fprintf(w, "%s\t%s\t%s\t%t\t%s\t%t\t%d\t%d\t%d\n", rule.Name, rule.Direction, rule.IpProtocol, 241 rule.Enabled, rule.Action, rule.Logging, len(rule.SourceFirewallGroups), len(rule.DestinationFirewallGroups), len(rule.ApplicationPortProfiles)) 242 } 243 err := w.Flush() 244 if err != nil { 245 util.Logger.Printf("Error while dumping Firewall rules to screen: %s", err) 246 } 247 }