Skip to content

Commit

Permalink
feat: Added Location, VPN credential bulk delete and rule type mapping (
Browse files Browse the repository at this point in the history
  • Loading branch information
willguibr authored Aug 11, 2024
1 parent 77f1f97 commit edcf91d
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 36 deletions.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# Changelog

# 2.71.0 (August 11, 2024)

## Notes
- Golang: **v1.22**

### ZIA Additions

#### VPN Credentials and Location Management
- Added `POST /locations/bulkDelete` Bulk delete locations up to a maximum of 100 locations per request. The response returns the location IDs that were successfully deleted. [PR #270](https://github.com/zscaler/zscaler-sdk-go/pull/270)

- Added `POST /vpnCredentials/bulkDelete` Bulk delete vpn credentails up to a maximum of 100 vpn credentials per request. The response returns the vpn credential IDs that were successfully deleted. [PR #270](https://github.com/zscaler/zscaler-sdk-go/pull/270)

#### Cloud App Control Policies

- Added `GET /webApplicationRules/ruleTypeMapping` to return backend keys that match the application type string.

### Bug Fixes

[PR #270](https://github.com/zscaler/zscaler-sdk-go/pull/270) - Fixed `ports` attribute from `string` to `slice of string` in `locationmanagement`.

# 2.70.0 (July 23, 2024)

## Notes
Expand Down
22 changes: 21 additions & 1 deletion docs/guides/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,30 @@ Track all Zscaler SDK GO releases. New resources, features, and bug fixes will b

---

``Last updated: v2.70.0``
``Last updated: v2.71.0``

---

# 2.71.0 (August 11, 2024)

## Notes
- Golang: **v1.22**

### ZIA Additions

#### VPN Credentials and Location Management
- Added `POST /locations/bulkDelete` Bulk delete locations up to a maximum of 100 locations per request. The response returns the location IDs that were successfully deleted. [PR #270](https://github.com/zscaler/zscaler-sdk-go/pull/270)

- Added `POST /vpnCredentials/bulkDelete` Bulk delete vpn credentails up to a maximum of 100 vpn credentials per request. The response returns the vpn credential IDs that were successfully deleted. [PR #270](https://github.com/zscaler/zscaler-sdk-go/pull/270)

#### Cloud App Control Policies

- Added `GET /webApplicationRules/ruleTypeMapping` to return backend keys that match the application type string.

### Bug Fixes

[PR #270](https://github.com/zscaler/zscaler-sdk-go/pull/270) - Fixed `ports` attribute from `string` to `slice of string` in `locationmanagement`.

# 2.70.0 (July 23, 2024)

## Notes
Expand Down
62 changes: 28 additions & 34 deletions zia/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,40 +152,6 @@ func (client *Client) WithFreshCache() {
client.freshCache = true
}

// // Create send HTTP Post request.
// func (c *Client) Create(endpoint string, o interface{}) (interface{}, error) {
// if o == nil {
// return nil, errors.New("tried to create with a nil payload not a Struct")
// }
// t := reflect.TypeOf(o)
// if t.Kind() != reflect.Struct {
// return nil, errors.New("tried to create with a " + t.Kind().String() + " not a Struct")
// }
// data, err := json.Marshal(o)
// if err != nil {
// return nil, err
// }

// resp, err := c.Request(endpoint, "POST", data, "application/json")
// if err != nil {
// return nil, err
// }
// if len(resp) > 0 {
// responseObject := reflect.New(t).Interface()
// err = json.Unmarshal(resp, &responseObject)
// if err != nil {
// return nil, err
// }
// id := reflect.Indirect(reflect.ValueOf(responseObject)).FieldByName("ID")

// c.Logger.Printf("Created Object with ID %v", id)
// return responseObject, nil
// } else {
// // in case of 204 no content
// return nil, nil
// }
// }

// Create sends an HTTP POST request.
func (c *Client) Create(endpoint string, o interface{}) (interface{}, error) {
if o == nil {
Expand Down Expand Up @@ -335,3 +301,31 @@ func (c *Client) Delete(endpoint string) error {
}
return nil
}

// BulkDelete sends an HTTP POST request for bulk deletion and expects a 204 No Content response.
func (c *Client) BulkDelete(endpoint string, payload interface{}) (*http.Response, error) {
if payload == nil {
return nil, errors.New("tried to delete with a nil payload, expected a struct")
}

// Marshal the payload into JSON
data, err := json.Marshal(payload)
if err != nil {
return nil, err
}

// Send the POST request
resp, err := c.Request(endpoint, "POST", data, "application/json")
if err != nil {
return nil, err
}

// Check the status code (204 No Content expected)
if len(resp) == 0 {
c.Logger.Printf("[DEBUG] Bulk delete successful with 204 No Content")
return &http.Response{StatusCode: 204}, nil
}

// If the response is not empty, this might indicate an error or unexpected behavior
return &http.Response{StatusCode: 200}, fmt.Errorf("unexpected response: %s", string(resp))
}
17 changes: 17 additions & 0 deletions zia/services/cloudappcontrol/cloudappcontrol.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,20 @@ func AllAvailableActions(service *services.Service, ruleType string, payload Ava
service.Client.Logger.Printf("[DEBUG] returning available actions: %+v", availableActions)
return availableActions, nil
}

// GetRuleTypeMapping retrieves the rule type mapping from the API.
func GetRuleTypeMapping(service *services.Service) (map[string]string, error) {
// Initialize a map to hold the response
var ruleTypeMapping map[string]string

// Perform the GET request
err := service.Client.Read(webApplicationRulesEndpoint+"/ruleTypeMapping", &ruleTypeMapping)
if err != nil {
return nil, err
}

// Log the retrieved data
service.Client.Logger.Printf("[DEBUG] Returning web application rule type mapping: %+v", ruleTypeMapping)

return ruleTypeMapping, nil
}
45 changes: 45 additions & 0 deletions zia/services/cloudappcontrol/cloudappcontrol_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package cloudappcontrol

import (
"bytes"
"encoding/json"
"fmt"
"log"
"strings"
Expand Down Expand Up @@ -232,6 +234,49 @@ func TestAllAvailableActions(t *testing.T) {
}
}

func TestRuleTypeMapping(t *testing.T) {
ziaClient, err := tests.NewZiaClient()
if err != nil {
t.Fatalf("Error creating client: %v", err)
}
service := services.New(ziaClient)

// Invoke the GetRuleTypeMapping function
mappings, err := GetRuleTypeMapping(service)
if err != nil {
t.Fatalf("Error getting rule type mappings: %v", err)
}

// Check if the response is not empty
if len(mappings) == 0 {
t.Error("Expected rule type mappings, but got an empty response")
}

// Optionally, check if specific keys are present in the response
expectedKeys := []string{
"Webmail", "Social Networking", "Finance", "Legal", "AI & ML Applications",
}

for _, key := range expectedKeys {
if _, exists := mappings[key]; !exists {
t.Errorf("Expected key %s in the response, but it was not found", key)
}
}

// Convert the map back to JSON for logging with HTML escaping disabled
buffer := &bytes.Buffer{}
encoder := json.NewEncoder(buffer)
encoder.SetEscapeHTML(false)
encoder.SetIndent("", " ")

err = encoder.Encode(mappings)
if err != nil {
t.Fatalf("Error marshalling rule type mappings to JSON: %v", err)
}

t.Logf("Rule Type Mappings: %s", buffer.String())
}

func TestRetrieveNonExistentResource(t *testing.T) {
client, err := tests.NewZiaClient()
if err != nil {
Expand Down
17 changes: 16 additions & 1 deletion zia/services/location/locationmanagement/locationmanagement.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
const (
locationsEndpoint = "/locations"
subLocationEndpoint = "/sublocations"
maxBulkDeleteIDs = 100
)

// Gets locations only, not sub-locations. When a location matches the given search parameter criteria only its parent location is included in the result set, not its sub-locations.
Expand Down Expand Up @@ -55,7 +56,7 @@ type Locations struct {
IPAddresses []string `json:"ipAddresses,omitempty"`

// IP ports that are associated with the location
Ports string `json:"ports,omitempty"`
Ports []string `json:"ports,omitempty"`

// VPN User Credentials that are associated with the location.
VPNCredentials []VPNCredentials `json:"vpnCredentials,omitempty"`
Expand Down Expand Up @@ -355,6 +356,20 @@ func Delete(service *services.Service, locationID int) (*http.Response, error) {
return nil, nil
}

func BulkDelete(service *services.Service, ids []int) (*http.Response, error) {
if len(ids) > maxBulkDeleteIDs {
// Truncate the list to the first 100 IDs
ids = ids[:maxBulkDeleteIDs]
service.Client.Logger.Printf("[INFO] Truncating IDs list to the first %d items", maxBulkDeleteIDs)
}

// Define the payload
payload := map[string][]int{
"ids": ids,
}
return service.Client.BulkDelete(locationsEndpoint+"/bulkDelete", payload)
}

func GetAll(service *services.Service) ([]Locations, error) {
var locations []Locations
// We are assuming this location name will be in the firsy 1000 obejcts
Expand Down
18 changes: 18 additions & 0 deletions zia/services/trafficforwarding/vpncredentials/vpncredentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

const (
vpnCredentialsEndpoint = "/vpnCredentials"
maxBulkDeleteIDs = 100
)

type VPNCredentials struct {
Expand Down Expand Up @@ -145,6 +146,23 @@ func Delete(service *services.Service, vpnCredentialID int) error {
return nil
}

// BulkDeleteVPNCredentials sends a bulk delete request for VPN credentials.
func BulkDelete(service *services.Service, ids []int) (*http.Response, error) {
if len(ids) > maxBulkDeleteIDs {
// Truncate the list to the first 100 IDs
ids = ids[:maxBulkDeleteIDs]
service.Client.Logger.Printf("[INFO] Truncating IDs list to the first %d items", maxBulkDeleteIDs)
}

// Define the payload
payload := map[string][]int{
"ids": ids,
}

// Call the generalized BulkDelete function from the client
return service.Client.BulkDelete(vpnCredentialsEndpoint+"/bulkDelete", payload)
}

func GetAll(service *services.Service) ([]VPNCredentials, error) {
var vpnTypes []VPNCredentials
err := common.ReadAllPages(service.Client, vpnCredentialsEndpoint, &vpnTypes)
Expand Down

0 comments on commit edcf91d

Please sign in to comment.