Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix standalone distributed firewall rule management #680

Merged
merged 7 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .changes/v2.25.0/680-bug-fixes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* Patched `VdcGroup.CreateDistributedFirewallRule` method that returned incorrect single rule when
`optionalAboveRuleId` is specified [GH-680]
3 changes: 2 additions & 1 deletion govcd/nsxt_distributed_firewall.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ func (vdcGroup *VdcGroup) CreateDistributedFirewallRule(optionalAboveRuleId stri
return nil, nil, err
}

// 2. Converting the give `rule` (*types.DistributedFirewallRule) into json.RawMessage so that
// 2. Converting the given `rule` (*types.DistributedFirewallRule) into json.RawMessage so that
// it is provided in the same format as other already retrieved rules
newRuleRawJson, err := firewallRuleToRawJson(rule)
if err != nil {
Expand Down Expand Up @@ -199,6 +199,7 @@ func (vdcGroup *VdcGroup) CreateDistributedFirewallRule(optionalAboveRuleId stri
}
// 3.2.2 Find index for specified 'optionalAboveRuleId' rule
newFwRuleSliceIndex, err := getFirewallRuleIndexById(dfwRules, optionalAboveRuleId)
newRuleSlicePosition = newFwRuleSliceIndex // Set rule position for returning single firewall rule
if err != nil {
return nil, nil, err
}
Expand Down
102 changes: 96 additions & 6 deletions govcd/nsxt_distributed_firewall_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,10 +315,41 @@ func (vcd *TestVCD) Test_NsxtDistributedFirewallRule(check *C) {
}()

fmt.Println("# Running Distributed Firewall tests for single Rule")
test_NsxtDistributedFirewallRule(vcd, check, vdcGroup.VdcGroup.Id, vcd.client, vdc)
test_NsxtDistributedFirewallRule(vcd, check, vdcGroup.VdcGroup.Id, vcd.client, vdc, true)
}

func test_NsxtDistributedFirewallRule(vcd *TestVCD, check *C, vdcGroupId string, vcdClient *VCDClient, vdc *Vdc) {
func (vcd *TestVCD) Test_NsxtDistributedFirewallWithDefaultRule(check *C) {
if vcd.skipAdminTests {
check.Skip(fmt.Sprintf(TestRequiresSysAdminPrivileges, check.TestName()))
}
skipNoNsxtConfiguration(vcd, check)
skipOpenApiEndpointTest(vcd, check, types.OpenApiPathVersion1_0_0+types.OpenApiEndpointEdgeGateways)

adminOrg, err := vcd.client.GetAdminOrgByName(vcd.config.VCD.Org)
check.Assert(adminOrg, NotNil)
check.Assert(err, IsNil)

nsxtExternalNetwork, err := GetExternalNetworkV2ByName(vcd.client, vcd.config.VCD.Nsxt.ExternalNetwork)
check.Assert(nsxtExternalNetwork, NotNil)
check.Assert(err, IsNil)

vdc, vdcGroup := test_CreateVdcGroup(check, adminOrg, vcd)
check.Assert(vdc, NotNil)
check.Assert(vdcGroup, NotNil)

defer func() {
// Cleanup
err = vdcGroup.Delete()
check.Assert(err, IsNil)
err = vdc.DeleteWait(true, true)
check.Assert(err, IsNil)
}()

fmt.Println("# Running Distributed Firewall tests for single Rule (with default DFW rule enabled)")
test_NsxtDistributedFirewallRuleAboveDefault(vcd, check, vdcGroup.VdcGroup.Id, vcd.client, vdc)
}

func test_NsxtDistributedFirewallRule(vcd *TestVCD, check *C, vdcGroupId string, vcdClient *VCDClient, vdc *Vdc, deleteDefaultFirewallRule bool) {
adminOrg, err := vcdClient.GetAdminOrgByName(vcd.config.VCD.Org)
check.Assert(adminOrg, NotNil)
check.Assert(err, IsNil)
Expand Down Expand Up @@ -348,12 +379,71 @@ func test_NsxtDistributedFirewallRule(vcd *TestVCD, check *C, vdcGroupId string,
randomizedFwRuleSubSet := randomizedFwRuleDefs[0:5] // taking only first 5 rules to limit time of testing

// removing default firewall rule which is created by VCD when vdcGroup.ActivateDfw() is executed
if deleteDefaultFirewallRule {
err = vdcGroup.DeleteAllDistributedFirewallRules()
check.Assert(err, IsNil)
}

// Adding firewal rules one by one and checking that each of them is placed correctly
testDistributedFirewallRuleSequence(check, randomizedFwRuleSubSet, vdcGroup, false)
testDistributedFirewallRuleSequence(check, randomizedFwRuleSubSet, vdcGroup, true)
}

func test_NsxtDistributedFirewallRuleAboveDefault(vcd *TestVCD, check *C, vdcGroupId string, vcdClient *VCDClient, vdc *Vdc) {
adminOrg, err := vcdClient.GetAdminOrgByName(vcd.config.VCD.Org)
check.Assert(adminOrg, NotNil)
check.Assert(err, IsNil)

vdcGroup, err := adminOrg.GetVdcGroupById(vdcGroupId)
check.Assert(err, IsNil)

_, err = vdcGroup.ActivateDfw()
check.Assert(err, IsNil)

// Prep firewall rule sample to operate with
randomizedFwRuleDefs, ipSet, secGroup := createDistributedFirewallDefinitions(check, vcd, vdcGroup.VdcGroup.Id, vcdClient, vdc)
// defer cleanup function in case something goes wrong
defer func() {
dfw, err := vdcGroup.GetDistributedFirewall()
check.Assert(err, IsNil)
err = dfw.DeleteAllRules()
check.Assert(err, IsNil)
_, err = vdcGroup.DisableDefaultPolicy()
check.Assert(err, IsNil)
err = ipSet.Delete()
check.Assert(err, IsNil)
err = secGroup.Delete()
check.Assert(err, IsNil)
}()

// Get default rule by name (this name is automatically set by VCD)
defaultRuleName := fmt.Sprintf("Default_VdcGroup_%s", vdcGroup.VdcGroup.Name)
defaultRule, err := vdcGroup.GetDistributedFirewallRuleByName(defaultRuleName)
check.Assert(err, IsNil)
check.Assert(defaultRule, NotNil)

_, rule1, err := vdcGroup.CreateDistributedFirewallRule(defaultRule.Rule.ID, randomizedFwRuleDefs[0])
check.Assert(err, IsNil)

_, rule2, err := vdcGroup.CreateDistributedFirewallRule(defaultRule.Rule.ID, randomizedFwRuleDefs[1])
check.Assert(err, IsNil)

// The order should be
// * rule1 (created first, inserted above default rule)
// * rule2 (created after rule1, inserted above default rule)
// * Default DFW rule

allRules, err := vdcGroup.GetDistributedFirewall()
check.Assert(err, IsNil)
check.Assert(len(allRules.DistributedFirewallRuleContainer.Values), Equals, 3)
check.Assert(allRules.DistributedFirewallRuleContainer.Values[0].ID, Equals, rule1.Rule.ID)
check.Assert(allRules.DistributedFirewallRuleContainer.Values[1].ID, Equals, rule2.Rule.ID)
check.Assert(allRules.DistributedFirewallRuleContainer.Values[2].ID, Equals, defaultRule.Rule.ID)

// Clean up created firewall rules for next phase
err = vdcGroup.DeleteAllDistributedFirewallRules()
check.Assert(err, IsNil)

// Adding firewal rules one by one and checking that each of them is
testDistributedFirewallRuleSequence(vcd, check, randomizedFwRuleSubSet, vdcGroup, false)
testDistributedFirewallRuleSequence(vcd, check, randomizedFwRuleSubSet, vdcGroup, true)
}

// testDistributedFirewallRuleSequence tests the following:
Expand All @@ -362,7 +452,7 @@ func test_NsxtDistributedFirewallRule(vcd *TestVCD, check *C, vdcGroupId string,
// reverseOrder=true)
// * check that all IDs of created firewall rules persisted during further updates (means that no
// firewall rules were recreated during addition of new ones)
func testDistributedFirewallRuleSequence(vcd *TestVCD, check *C, randomizedFwRuleSubSet []*types.DistributedFirewallRule, vdcGroup *VdcGroup, reverseOrder bool) {
func testDistributedFirewallRuleSequence(check *C, randomizedFwRuleSubSet []*types.DistributedFirewallRule, vdcGroup *VdcGroup, reverseOrder bool) {
createdIdsFound := make(map[string]bool)
fmt.Printf("# Creating '%d' rules one by one (reverseOrder: %t)\n", len(randomizedFwRuleSubSet), reverseOrder)
previousRuleId := ""
Expand Down
Loading