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

ALB Virtual Service HTTP Policies #706

Merged
merged 14 commits into from
Sep 13, 2024
9 changes: 9 additions & 0 deletions .changes/v2.26.0/706-features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
* Added Read and Update operations for ALB Virtual Service HTTP Request Rules via
`NsxtAlbVirtualService.GetAllHttpRequestRules` and `NsxtAlbVirtualService.UpdateHttpRequestRules`
[GH-706]
* Added Read and Update operations for ALB Virtual Service HTTP Response Rules via
`NsxtAlbVirtualService.GetAllHttpResponseRules` and
`NsxtAlbVirtualService.UpdateHttpResponseRules` [GH-706]
* Added Read and Update operations for ALB Virtual Service HTTP Security Rules via
`NsxtAlbVirtualService.GetAllHttpSecurityRules` and
`NsxtAlbVirtualService.UpdateHttpSecurityRules` [GH-706]
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,7 @@ govcd/test_cleanup_list*.json

# File cache directory
govcd/test-resources/cache/*

# MacOS artefacts
.DS_Store

3 changes: 3 additions & 0 deletions govcd/external_network_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,9 @@ func (vcdClient *VCDClient) GetTier0RouterInterfaceByName(externalNetworkId, dis
if err != nil {
return nil, fmt.Errorf("error getting %s by DisplayName '%s':%s", labelNsxtTier0RouterInterface, displayName, err)
}
if len(allT0Interfaces) == 0 {
Didainius marked this conversation as resolved.
Show resolved Hide resolved
return nil, fmt.Errorf("%s: error getting %s by DisplayName '%s'", ErrorEntityNotFound, labelNsxtTier0RouterInterface, displayName)
}

return localFilterOneOrError(labelNsxtTier0RouterInterface, allT0Interfaces, "DisplayName", displayName)
}
84 changes: 84 additions & 0 deletions govcd/nsxt_alb_virtual_service_http_policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright 2024 VMware, Inc. All rights reserved. Licensed under the Apache v2 License.
*/

package govcd

import (
"net/url"

"github.com/vmware/go-vcloud-director/v2/types/v56"
)

const labelNsxtAlbVsHttpRequestRules = "ALB Virtual Service HTTP Request Rules"
const labelNsxtAlbVsHttpResponseRules = "ALB Virtual Service HTTP Response Rules"
const labelNsxtAlbVsHttpSecurityRules = "ALB Virtual Service HTTP Security Rules"

// GetAllHttpRequestRules returns all ALB Virtual Service HTTP Request Rules
func (nsxtAlbVirtualService *NsxtAlbVirtualService) GetAllHttpRequestRules(queryParameters url.Values) ([]*types.AlbVsHttpRequestRule, error) {
c := crudConfig{
endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbVirtualServiceHttpRequestRules,
entityLabel: labelNsxtAlbVsHttpRequestRules,
endpointParams: []string{nsxtAlbVirtualService.NsxtAlbVirtualService.ID},
queryParameters: queryParameters,
}

return getAllInnerEntities[types.AlbVsHttpRequestRule](&nsxtAlbVirtualService.vcdClient.Client, c)
}

// UpdateHttpRequestRules sets ALB Virtual Service HTTP Request Rules
func (nsxtAlbVirtualService *NsxtAlbVirtualService) UpdateHttpRequestRules(config *types.AlbVsHttpRequestRules) (*types.AlbVsHttpRequestRules, error) {
c := crudConfig{
endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbVirtualServiceHttpRequestRules,
entityLabel: labelNsxtAlbVsHttpRequestRules,
endpointParams: []string{nsxtAlbVirtualService.NsxtAlbVirtualService.ID},
}

return updateInnerEntity(&nsxtAlbVirtualService.vcdClient.Client, c, config)
}

// GetAllHttpRequestRules returns all ALB Virtual Service HTTP Response Rules
func (nsxtAlbVirtualService *NsxtAlbVirtualService) GetAllHttpResponseRules(queryParameters url.Values) ([]*types.AlbVsHttpResponseRule, error) {
c := crudConfig{
endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbVirtualServiceHttpResponseRules,
entityLabel: labelNsxtAlbVsHttpResponseRules,
endpointParams: []string{nsxtAlbVirtualService.NsxtAlbVirtualService.ID},
queryParameters: queryParameters,
}

return getAllInnerEntities[types.AlbVsHttpResponseRule](&nsxtAlbVirtualService.vcdClient.Client, c)
}

// UpdateHttpRequestRules sets ALB Virtual Service HTTP Response Rules
func (nsxtAlbVirtualService *NsxtAlbVirtualService) UpdateHttpResponseRules(config *types.AlbVsHttpResponseRules) (*types.AlbVsHttpResponseRules, error) {
c := crudConfig{
endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbVirtualServiceHttpResponseRules,
entityLabel: labelNsxtAlbVsHttpResponseRules,
endpointParams: []string{nsxtAlbVirtualService.NsxtAlbVirtualService.ID},
}

return updateInnerEntity(&nsxtAlbVirtualService.vcdClient.Client, c, config)
}

// GetAllHttpRequestRules returns all ALB Virtual Service HTTP Security Rules
func (nsxtAlbVirtualService *NsxtAlbVirtualService) GetAllHttpSecurityRules(queryParameters url.Values) ([]*types.AlbVsHttpSecurityRule, error) {
c := crudConfig{
endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbVirtualServiceHttpSecurityRules,
entityLabel: labelNsxtAlbVsHttpSecurityRules,
endpointParams: []string{nsxtAlbVirtualService.NsxtAlbVirtualService.ID},
queryParameters: queryParameters,
}

return getAllInnerEntities[types.AlbVsHttpSecurityRule](&nsxtAlbVirtualService.vcdClient.Client, c)
}

// UpdateHttpRequestRules sets ALB Virtual Service HTTP Security Rules
func (nsxtAlbVirtualService *NsxtAlbVirtualService) UpdateHttpSecurityRules(config *types.AlbVsHttpSecurityRules) (*types.AlbVsHttpSecurityRules, error) {
c := crudConfig{
endpoint: types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbVirtualServiceHttpSecurityRules,
entityLabel: labelNsxtAlbVsHttpSecurityRules,
endpointParams: []string{nsxtAlbVirtualService.NsxtAlbVirtualService.ID},
}

return updateInnerEntity(&nsxtAlbVirtualService.vcdClient.Client, c, config)
}
128 changes: 128 additions & 0 deletions govcd/nsxt_alb_virtual_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
. "gopkg.in/check.v1"
)

// Test_AlbVirtualService also tests:
// * HTTP Request, Response and Security policies
func (vcd *TestVCD) Test_AlbVirtualService(check *C) {
if vcd.skipAdminTests {
check.Skip(fmt.Sprintf(TestRequiresSysAdminPrivileges, check.TestName()))
Expand Down Expand Up @@ -73,6 +75,17 @@ func (vcd *TestVCD) Test_AlbVirtualService(check *C) {
check.Assert(err, IsNil)
}

// On VCD 10.5.0+ test LB Virtual Service Policies:
// * HTTP Request rules
// * HTTP Response rules
// * HTTP Security rules
if vcd.client.Client.APIVCDMaxVersionIs(">= 38.0") {
printVerbose("# Running 10.5.0+ ALB Virtual Service Policy tests as Sysadmin user ")
testAlbVirtualServicePolicies(check, edge, albPool, seGroup, vcd, vcd.client)
printVerbose("# Running 10.5.0+ ALB Virtual Service Policy tests as Org user ")
testAlbVirtualServicePolicies(check, edge, albPool, seGroup, vcd, orgUserVcdClient)
}

// teardown prerequisites
tearDownAlbVirtualServicePrerequisites(check, albPool, seGroupAssignment, edge, seGroup, cloud, controller)

Expand Down Expand Up @@ -571,3 +584,118 @@ func tearDownAlbVirtualServicePrerequisites(check *C, albPool *NsxtAlbPool, assi
err = controller.Delete()
check.Assert(err, IsNil)
}

func testAlbVirtualServicePolicies(check *C, edge *NsxtEdgeGateway, pool *NsxtAlbPool, seGroup *NsxtAlbServiceEngineGroup, vcd *TestVCD, client *VCDClient) {
virtualServiceConfig := &types.NsxtAlbVirtualService{
Name: check.TestName(),
Enabled: addrOf(true),
ApplicationProfile: types.NsxtAlbVirtualServiceApplicationProfile{
SystemDefined: true,
Type: "HTTP",
},
GatewayRef: types.OpenApiReference{ID: edge.EdgeGateway.ID},
LoadBalancerPoolRef: types.OpenApiReference{ID: pool.NsxtAlbPool.ID},
ServiceEngineGroupRef: types.OpenApiReference{ID: seGroup.NsxtAlbServiceEngineGroup.ID},
ServicePorts: []types.NsxtAlbVirtualServicePort{
{
PortStart: addrOf(80),
},
},
VirtualIpAddress: edge.EdgeGateway.EdgeGatewayUplinks[0].Subnets.Values[0].PrimaryIP,
}

createdVirtualService, err := client.CreateNsxtAlbVirtualService(virtualServiceConfig)
check.Assert(err, IsNil)

openApiEndpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbVirtualServices + createdVirtualService.NsxtAlbVirtualService.ID
PrependToCleanupListOpenApi(createdVirtualService.NsxtAlbVirtualService.Name, check.TestName(), openApiEndpoint)

// Check that no rules are present
reqRules, err := createdVirtualService.GetAllHttpRequestRules(nil)
check.Assert(err, IsNil)
check.Assert(len(reqRules), Equals, 0)

respRules, err := createdVirtualService.GetAllHttpResponseRules(nil)
check.Assert(err, IsNil)
check.Assert(len(respRules), Equals, 0)

secRules, err := createdVirtualService.GetAllHttpSecurityRules(nil)
check.Assert(err, IsNil)
check.Assert(len(secRules), Equals, 0)

// Create request rule
reqType := types.AlbVsHttpRequestRule{
Name: check.TestName() + "req-1",
Active: true,
Logging: false,
MatchCriteria: types.AlbVsHttpRequestAndSecurityRuleMatchCriteria{
ClientIPMatch: &types.AlbVsHttpRequestRuleClientIPMatch{MatchCriteria: "IS_IN", Addresses: []string{"1.1.1.1", "2.2.2.2"}},
MethodMatch: &types.AlbVsHttpRequestRuleMethodMatch{MatchCriteria: "IS_NOT_IN", Methods: []string{"POST", "PATCH"}},
},
HeaderActions: []*types.AlbVsHttpRequestRuleHeaderActions{
&types.AlbVsHttpRequestRuleHeaderActions{
Action: "ADD",
Name: "X-NEW-H",
Value: "new",
},
},
}

respType := types.AlbVsHttpResponseRule{
Name: check.TestName() + "resp-1",
Active: true,
Logging: false,
MatchCriteria: types.AlbVsHttpResponseRuleMatchCriteria{CookieMatch: &types.AlbVsHttpRequestRuleCookieMatch{
MatchCriteria: "BEGINS_WITH",
Key: "cookie-key",
Value: "cookie-value",
}},
RewriteLocationHeaderAction: &types.AlbVsHttpRespRuleRewriteLocationHeaderAction{
Protocol: "HTTP",
Host: "other",
Port: addrOf(81),
Path: "/new",
KeepQuery: false,
},
}

securityType := types.AlbVsHttpSecurityRule{
Name: check.TestName() + "sec-1",
Active: true,
Logging: true,
MatchCriteria: types.AlbVsHttpRequestAndSecurityRuleMatchCriteria{
QueryMatch: []string{"q1", "q2"},
},
AllowOrCloseConnectionAction: "CLOSE",
}

newReqRules, err := createdVirtualService.UpdateHttpRequestRules(&types.AlbVsHttpRequestRules{Values: []types.AlbVsHttpRequestRule{reqType}})
check.Assert(err, IsNil)
check.Assert(len(newReqRules.Values), Equals, 1)

newRespRules, err := createdVirtualService.UpdateHttpResponseRules(&types.AlbVsHttpResponseRules{Values: []types.AlbVsHttpResponseRule{respType}})
check.Assert(err, IsNil)
check.Assert(len(newRespRules.Values), Equals, 1)

newSecRules, err := createdVirtualService.UpdateHttpSecurityRules(&types.AlbVsHttpSecurityRules{Values: []types.AlbVsHttpSecurityRule{securityType}})
check.Assert(err, IsNil)
check.Assert(len(newSecRules.Values), Equals, 1)

// Cleanup and check
valueCountReq, err := createdVirtualService.UpdateHttpRequestRules(&types.AlbVsHttpRequestRules{})
check.Assert(err, IsNil)
check.Assert(len(valueCountReq.Values), Equals, 0)

valueCountResp, err := createdVirtualService.UpdateHttpResponseRules(&types.AlbVsHttpResponseRules{})
check.Assert(err, IsNil)
check.Assert(len(valueCountResp.Values), Equals, 0)

valueCountSec, err := createdVirtualService.UpdateHttpSecurityRules(&types.AlbVsHttpSecurityRules{})
check.Assert(err, IsNil)
check.Assert(len(valueCountSec.Values), Equals, 0)

// remove ALB VS
err = createdVirtualService.Delete()
check.Assert(err, IsNil)
fmt.Printf("Done.\n")
}
37 changes: 20 additions & 17 deletions govcd/openapi_endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ var endpointMinApiVersions = map[string]string{
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointRdeEntitiesTypes: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointRdeEntitiesResolve: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointRdeEntitiesBehaviorsInvocations: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointExternalEndpoints: "37.3", // VCD 10.4.3+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointApiFilters: "37.3", // VCD 10.4.3+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointExternalEndpoints: "38.1", // VCD 10.5.1+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointApiFilters: "38.1", // VCD 10.5.1+

// IP Spaces
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaces: "37.1", // VCD 10.4.1+
Expand All @@ -88,21 +88,24 @@ var endpointMinApiVersions = map[string]string{
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointIpSpaceFloatingIpSuggestions: "37.1", // VCD 10.4.1+

// NSX-T ALB (Advanced/AVI Load Balancer) support was introduced in 10.2
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbController: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbImportableClouds: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbImportableServiceEngineGroups: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbCloud: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbServiceEngineGroups: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbEdgeGateway: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbServiceEngineGroupAssignments: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbPools: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbPoolSummaries: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbVirtualServices: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbVirtualServiceSummaries: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointSSLCertificateLibrary: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointSSLCertificateLibraryOld: "35.0", // VCD 10.2+ and deprecated from 10.3
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcGroupsDfwRules: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointNetworkContextProfiles: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbController: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbImportableClouds: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbImportableServiceEngineGroups: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbCloud: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbServiceEngineGroups: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbEdgeGateway: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbServiceEngineGroupAssignments: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbPools: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbPoolSummaries: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbVirtualServices: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbVirtualServiceSummaries: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbVirtualServiceHttpRequestRules: "38.0", // VCD 10.5+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbVirtualServiceHttpResponseRules: "38.0", // VCD 10.5+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointAlbVirtualServiceHttpSecurityRules: "38.0", // VCD 10.5+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointSSLCertificateLibrary: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointSSLCertificateLibraryOld: "35.0", // VCD 10.2+ and deprecated from 10.3
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcGroupsDfwRules: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointNetworkContextProfiles: "35.0", // VCD 10.2+

types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeBgpNeighbor: "35.0", // VCD 10.2+
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeBgpConfigPrefixLists: "35.0", // VCD 10.2+
Expand Down
2 changes: 1 addition & 1 deletion govcd/openapi_endpoints_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func TestClient_getOpenApiHighestElevatedVersion(t *testing.T) {
name: fmt.Sprintf("%s_minimum_version_%s", minimumRequiredVersion, endpointName),
// Put a list of versions which always satisfied minimum requirement
supportedVersions: renderSupportedVersions([]string{
"27.0", "28.0", "29.0", "30.0", "31.0", "32.0", "33.0", "34.0", "35.0", "35.1", "35.2", "36.0", "37.0", "38.0",
"27.0", "28.0", "29.0", "30.0", "31.0", "32.0", "33.0", "34.0", "35.0", "35.1", "35.2", "36.0", "37.0", "38.0", "39.0", "40.0", "41.0",
}),
endpoint: endpointName,
wantVersion: wantVersion,
Expand Down
13 changes: 8 additions & 5 deletions types/v56/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -498,11 +498,14 @@ const (
OpenApiEndpointAlbPools = "loadBalancer/pools/"
// OpenApiEndpointAlbPoolSummaries returns a limited subset of data provided by OpenApiEndpointAlbPools
// however only the summary endpoint can list all available pools for an edge gateway
OpenApiEndpointAlbPoolSummaries = "edgeGateways/%s/loadBalancer/poolSummaries" // %s contains edge gateway
OpenApiEndpointAlbVirtualServices = "loadBalancer/virtualServices/"
OpenApiEndpointAlbVirtualServiceSummaries = "edgeGateways/%s/loadBalancer/virtualServiceSummaries" // %s contains edge gateway
OpenApiEndpointAlbServiceEngineGroupAssignments = "loadBalancer/serviceEngineGroups/assignments/"
OpenApiEndpointAlbEdgeGateway = "edgeGateways/%s/loadBalancer"
OpenApiEndpointAlbPoolSummaries = "edgeGateways/%s/loadBalancer/poolSummaries" // %s contains edge gateway
OpenApiEndpointAlbVirtualServices = "loadBalancer/virtualServices/"
OpenApiEndpointAlbVirtualServiceHttpRequestRules = "loadBalancer/virtualServices/%s/httpPolicy/requestRules"
OpenApiEndpointAlbVirtualServiceHttpResponseRules = "loadBalancer/virtualServices/%s/httpPolicy/responseRules"
OpenApiEndpointAlbVirtualServiceHttpSecurityRules = "loadBalancer/virtualServices/%s/httpPolicy/securityRules"
OpenApiEndpointAlbVirtualServiceSummaries = "edgeGateways/%s/loadBalancer/virtualServiceSummaries" // %s contains edge gateway
OpenApiEndpointAlbServiceEngineGroupAssignments = "loadBalancer/serviceEngineGroups/assignments/"
OpenApiEndpointAlbEdgeGateway = "edgeGateways/%s/loadBalancer"

// OpenApiEndpointServiceAccountGrant is needed for granting a Service Account
OpenApiEndpointServiceAccountGrant = "deviceLookup/grant"
Expand Down
Loading
Loading