Skip to content

Commit

Permalink
Merge pull request #1 from pimielowski/improve_validate_option
Browse files Browse the repository at this point in the history
Improve validation option in Panorama
  • Loading branch information
pimielowski committed Oct 12, 2023
2 parents dba4c15 + e8ae9dd commit 5d817ec
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 38 deletions.
65 changes: 27 additions & 38 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,19 @@ import (
//
// The bit-wise flags are as follows:
//
// * LogQuiet: disables all logging
// * LogAction: action being performed (Set / Edit / Delete functions)
// * LogQuery: queries being run (Get / Show functions)
// * LogOp: operation commands (Op functions)
// * LogUid: User-Id commands (Uid functions)
// * LogLog: log retrieval commands
// * LogExport: log export commands
// * LogXpath: the resultant xpath
// * LogSend: xml docuemnt being sent
// * LogReceive: xml responses being received
// * LogOsxCurl: output an OSX cURL command for the data being sent in
// * LogCurlWithPersonalData: If doing a curl style logging, then include
// personal data in the curl command instead of tokens.
// - LogQuiet: disables all logging
// - LogAction: action being performed (Set / Edit / Delete functions)
// - LogQuery: queries being run (Get / Show functions)
// - LogOp: operation commands (Op functions)
// - LogUid: User-Id commands (Uid functions)
// - LogLog: log retrieval commands
// - LogExport: log export commands
// - LogXpath: the resultant xpath
// - LogSend: xml docuemnt being sent
// - LogReceive: xml responses being received
// - LogOsxCurl: output an OSX cURL command for the data being sent in
// - LogCurlWithPersonalData: If doing a curl style logging, then include
// personal data in the curl command instead of tokens.
const (
LogQuiet = 1 << (iota + 1)
LogAction
Expand Down Expand Up @@ -168,10 +168,10 @@ func (c *Client) Plugins() []plugin.Info {
// client's SystemInfo map.
//
// If not specified, the following is assumed:
// * Protocol: https
// * Port: (unspecified)
// * Timeout: 10
// * Logging: LogAction | LogUid
// - Protocol: https
// - Port: (unspecified)
// - Timeout: 10
// - Logging: LogAction | LogUid
func (c *Client) Initialize() error {
if len(c.rb) == 0 {
var e error
Expand Down Expand Up @@ -318,34 +318,23 @@ func (c *Client) RequestPasswordHash(val string) (string, error) {

// ValidateConfig performs a commit config validation check.
//
// Setting sync to true means that this function will block until the job
// finishes.
//
//
// The sleep param is an optional sleep duration to wait between polling for
// job completion. This param is only used if sync is set to true.
// # Cmd interface contained a formatted XML string struct which can be used to either marshalled into XML or one of the
// validate function.
//
// This function returns the job ID and if any errors were encountered.
func (c *Client) ValidateConfig(sync bool, sleep time.Duration) (uint, error) {
func (c *Client) ValidateConfig(cmd interface{}) (uint, []byte, error) {
var err error
data := url.Values{}
data.Set("type", "op")

c.LogOp("(op) validating config")
type op_req struct {
XMLName xml.Name `xml:"validate"`
Cmd string `xml:"full"`
}
job_ans := util.JobResponse{}
_, err = c.Op(op_req{}, "", nil, &job_ans)
if err != nil {
return 0, err
if err = addToData("cmd", cmd, true, &data); err != nil {
return 0, nil, err
}

id := job_ans.Id
if !sync {
return id, nil
}
ans := util.JobResponse{}

return id, c.WaitForJob(id, sleep, nil, nil)
b, _, err := c.Communicate(data, &ans)
return ans.Id, b, err
}

// RevertToRunningConfig discards any changes made and reverts to the last
Expand Down
81 changes: 81 additions & 0 deletions commit/validate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package commit

import (
"encoding/xml"
"github.com/PaloAltoNetworks/pango/util"
)

// PanoramaValidate is a Panorama Valid structure contained all option for Client.ValidateConfig().
type PanoramaValidate struct {
Admins []string
DeviceGroups []string
LogCollectors []string
LogCollectorGroups []string
Templates []string
TemplateStacks []string
WildfireAppliances []string
WildfireApplianceClusters []string
ExcludeDeviceAndNetwork bool
ExcludeSharedObjects bool
Full bool
}

// PanoramaValidateAll it is a shell struct for doing validate all changes in Panorama.
type PanoramaValidateAll struct{}

// Element this function return an interface ready to be marshalled into XML for validate.
func (o PanoramaValidate) Element() interface{} {
ans := panoValidate{}

var p *panoValidatePartial
if len(o.Admins) > 0 || len(o.DeviceGroups) > 0 || len(o.Templates) > 0 ||
len(o.TemplateStacks) > 0 || len(o.LogCollectors) > 0 || len(o.LogCollectorGroups) > 0 {
p = &panoValidatePartial{
Admins: util.StrToMem(o.Admins),
DeviceGroups: util.StrToMem(o.DeviceGroups),
Templates: util.StrToMem(o.Templates),
TemplateStacks: util.StrToMem(o.TemplateStacks),
WildfireAppliances: util.StrToMem(o.WildfireAppliances),
WildfireClusters: util.StrToMem(o.WildfireApplianceClusters),
LogCollectors: util.StrToMem(o.LogCollectors),
LogCollectorGroups: util.StrToMem(o.LogCollectorGroups),
}

if o.ExcludeSharedObjects {
p.ExcludeSharedObjects = "excluded"
}

if o.ExcludeDeviceAndNetwork {
p.ExcludeDeviceAndNetwork = "excluded"
}
} else {
ans.Full = &panoValidateFull{}
}

ans.Partial = p

return ans
}

// panoValidate main XML structure for validate, it contains main 'validate' option and regarded for the action
// it can be either 'full' or 'partial'
type panoValidate struct {
XMLName xml.Name `xml:"validate"`
Full *panoValidateFull `xml:"full"`
Partial *panoValidatePartial `xml:"partial"`
}

type panoValidateFull struct{}

type panoValidatePartial struct {
Admins *util.MemberType `xml:"admin"`
DeviceGroups *util.MemberType `xml:"device-group"`
Templates *util.MemberType `xml:"template"`
TemplateStacks *util.MemberType `xml:"template-stack"`
WildfireAppliances *util.MemberType `xml:"wildfire-appliance"`
WildfireClusters *util.MemberType `xml:"wildfire-appliance-cluster"`
LogCollectors *util.MemberType `xml:"log-collector"`
LogCollectorGroups *util.MemberType `xml:"log-collector-group"`
ExcludeDeviceAndNetwork string `xml:"device-and-network,omitempty"`
ExcludeSharedObjects string `xml:"shared-object,omitempty"`
}
63 changes: 63 additions & 0 deletions commit/validate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package commit

import (
"encoding/xml"
"strings"
"testing"
)

func TestPanoramaValidate_ValidateElement(t *testing.T) {
testS := []string{
"<validate>",
"<partial>",
"<admin><member>admin1</member><member>admin2</member></admin>",
"<device-group><member>dg1</member></device-group>",
"<template><member>tmpl1</member></template>",
"<template-stack><member>ts1</member></template-stack>",
"<wildfire-appliance><member>wfa1</member></wildfire-appliance>",
"<wildfire-appliance-cluster><member>wfc1</member></wildfire-appliance-cluster>",
"<log-collector><member>lc1</member></log-collector>",
"<log-collector-group><member>lcg1</member></log-collector-group>",
"<device-and-network>excluded</device-and-network>",
"<shared-object>excluded</shared-object>",
"</partial>",
"</validate>",
}

expected := strings.Join(testS, "")

validateStruct := PanoramaValidate{
Admins: []string{"admin1", "admin2"},
DeviceGroups: []string{"dg1"},
LogCollectors: []string{"lc1"},
LogCollectorGroups: []string{"lcg1"},
Templates: []string{"tmpl1"},
TemplateStacks: []string{"ts1"},
WildfireAppliances: []string{"wfa1"},
WildfireApplianceClusters: []string{"wfc1"},
ExcludeDeviceAndNetwork: true,
ExcludeSharedObjects: true,
}

marshV, _ := xml.Marshal(validateStruct.Element())
if expected != string(marshV) {
t.Errorf("Expected(%s) got(%s)", expected, marshV)
}
}

func TestPanoramaValidateAll_ValidateAllElement(t *testing.T) {
testS := []string{
"<validate>",
"<full>",
"</full>",
"</validate>",
}

expected := strings.Join(testS, "")
validateStruct := PanoramaValidate{}

marshV, _ := xml.Marshal(validateStruct.Element())
if expected != string(marshV) {
t.Errorf("Expected(%s) got(%s)", expected, marshV)
}
}

0 comments on commit 5d817ec

Please sign in to comment.