Skip to content

Commit

Permalink
feat: Add Device.Certificate namespace
Browse files Browse the repository at this point in the history
  • Loading branch information
shinmog committed Nov 19, 2021
1 parent 90c6c27 commit b3d00ee
Show file tree
Hide file tree
Showing 12 changed files with 831 additions and 0 deletions.
23 changes: 23 additions & 0 deletions dev/certificate/certs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package certificate

// Pem is a PEM certificate suitable to be imported into PAN-OS.
//
// Importing the certificate and the private key are two separate API
// calls. If the PrivateKey is left unspecified, then the 2nd API call
// will not be made.
type Pem struct {
Name string
Certificate string
CertificateFilename string
PrivateKey string
PrivateKeyFilename string
Passphrase string
}

// Pkcs12 is a PKCS12 certificate suitable to be imported into PAN-OS.
type Pkcs12 struct {
Name string
Certificate string
CertificateFilename string
Passphrase string
}
12 changes: 12 additions & 0 deletions dev/certificate/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package certificate

// Valid values for Entry.Status.
const (
StatusValid = "valid"
StatusRevoked = "revoked"
)

const (
singular = "certificate"
plural = "certificates"
)
20 changes: 20 additions & 0 deletions dev/certificate/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
Package certificate is the client.Device.Certificate namespace.
For Panorama, there are two possibilities: managing this object on Panorama
itself or inside of a Template.
To manage objects on Panorama, leave "tmpl" and "vsys" params empty.
To manage objects in a template, specify the template name and the vsys (if
unspecified, defaults to "shared").
Configuring things such as "Forward Trust Certificate", "Forward Untrust
Certificate", and "Trusted Root CA" is done from the Device.SslDecrypt
namespace.
Note: PAN-OS 7.1+
Normalized object: Entry
*/
package certificate
174 changes: 174 additions & 0 deletions dev/certificate/entry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package certificate

import (
"encoding/xml"

"github.com/PaloAltoNetworks/pango/util"
"github.com/PaloAltoNetworks/pango/version"
)

// Entry is a normalized, version independent representation of a
// certificate.
//
// PAN-OS 7.1+.
type Entry struct {
Name string
CommonName string
Algorithm string
Ca bool
NotValidAfter string
NotValidBefore string
ExpiryEpoch string
Subject string
SubjectHash string
Issuer string
IssuerHash string
Csr string
PublicKey string
PrivateKey string
PrivateKeyOnHsm bool
Status string
RevokeDateEpoch string
}

// Copy copies the information from source Entry `s` to this object. As the
// Name field relates to the XPATH of this object, this field is not copied.
func (o *Entry) Copy(s Entry) {
o.CommonName = s.CommonName
o.Algorithm = s.Algorithm
o.Ca = s.Ca
o.NotValidAfter = s.NotValidAfter
o.NotValidBefore = s.NotValidBefore
o.ExpiryEpoch = s.ExpiryEpoch
o.Subject = s.Subject
o.SubjectHash = s.SubjectHash
o.Issuer = s.Issuer
o.IssuerHash = s.IssuerHash
o.Csr = s.Csr
o.PublicKey = s.PublicKey
o.PrivateKey = s.PrivateKey
o.PrivateKeyOnHsm = s.PrivateKeyOnHsm
o.Status = s.Status
o.RevokeDateEpoch = s.RevokeDateEpoch
}

/** Structs / functions for this namespace. **/

func (o Entry) Specify(v version.Number) (string, interface{}) {
_, fn := versioning(v)
return o.Name, fn(o)
}

type normalizer interface {
Normalize() []Entry
Names() []string
}

type container_v1 struct {
Answer []entry_v1 `xml:"entry"`
}

func (o *container_v1) Normalize() []Entry {
ans := make([]Entry, 0, len(o.Answer))
for i := range o.Answer {
ans = append(ans, o.Answer[i].normalize())
}

return ans
}

func (o *container_v1) Names() []string {
ans := make([]string, 0, len(o.Answer))
for i := range o.Answer {
ans = append(ans, o.Answer[i].Name)
}

return ans
}

func (o *entry_v1) normalize() Entry {
ans := Entry{
Name: o.Name,
CommonName: o.CommonName,
Algorithm: o.Algorithm,
Ca: util.AsBool(o.Ca),
NotValidAfter: o.NotValidAfter,
NotValidBefore: o.NotValidBefore,
ExpiryEpoch: o.ExpiryEpoch,
Subject: o.Subject,
SubjectHash: o.SubjectHash,
Issuer: o.Issuer,
IssuerHash: o.IssuerHash,
Csr: o.Csr,
PublicKey: o.PublicKey,
PrivateKey: o.PrivateKey,
PrivateKeyOnHsm: util.AsBool(o.PrivateKeyOnHsm),
Status: o.Status,
RevokeDateEpoch: o.RevokeDateEpoch,
}

return ans
}

type entry_v1 struct {
XMLName xml.Name `xml:"entry"`
Name string `xml:"name,attr"`
CommonName string `xml:"common-name"`
Algorithm string `xml:"algorithm,omitempty"`
Ca string `xml:"ca,omitempty"`
NotValidAfter string `xml:"not-valid-after,omitempty"`
NotValidBefore string `xml:"not-valid-before,omitempty"`
ExpiryEpoch string `xml:"expiry-epoch,omitempty"`
Subject string `xml:"subject,omitempty"`
SubjectHash string `xml:"subject-hash,omitempty"`
Issuer string `xml:"issuer,omitempty"`
IssuerHash string `xml:"issuer-hash,omitempty"`
Csr string `xml:"csr,omitempty"`
PublicKey string `xml:"public-key,omitempty"`
PrivateKey string `xml:"private-key,omitempty"`
PrivateKeyOnHsm string `xml:"private-key-on-hsm,omitempty"`
Status string `xml:"status,omitempty"`
RevokeDateEpoch string `xml:"revoke-date-epoch,omitempty"`
}

func (e *entry_v1) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
type local entry_v1
ans := local{
Status: StatusValid,
}
if err := d.DecodeElement(&ans, &start); err != nil {
return err
}
*e = entry_v1(ans)
return nil
}

func specify_v1(e Entry) interface{} {
ans := entry_v1{
Name: e.Name,
CommonName: e.CommonName,
Algorithm: e.Algorithm,
NotValidAfter: e.NotValidAfter,
NotValidBefore: e.NotValidBefore,
ExpiryEpoch: e.ExpiryEpoch,
Subject: e.Subject,
SubjectHash: e.SubjectHash,
Issuer: e.Issuer,
IssuerHash: e.IssuerHash,
Csr: e.Csr,
PublicKey: e.PublicKey,
PrivateKey: e.PrivateKey,
Status: e.Status,
RevokeDateEpoch: e.RevokeDateEpoch,
}

if e.Ca {
ans.Ca = util.YesNo(e.Ca)
}

if e.PrivateKeyOnHsm {
ans.PrivateKeyOnHsm = util.YesNo(e.PrivateKeyOnHsm)
}

return ans
}
88 changes: 88 additions & 0 deletions dev/certificate/funcs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package certificate

import (
"fmt"

"github.com/PaloAltoNetworks/pango/namespace"
"github.com/PaloAltoNetworks/pango/util"
"github.com/PaloAltoNetworks/pango/version"
)

func versioning(v version.Number) (normalizer, func(Entry) interface{}) {
return &container_v1{}, specify_v1
}

func specifier(e ...Entry) []namespace.Specifier {
ans := make([]namespace.Specifier, 0, len(e))

var val namespace.Specifier
for _, x := range e {
val = x
ans = append(ans, val)
}

return ans
}

func container(v version.Number) normalizer {
r, _ := versioning(v)
return r
}

func first(ans normalizer, err error) (Entry, error) {
if err != nil {
return Entry{}, err
}

return ans.Normalize()[0], nil
}

func all(ans normalizer, err error) ([]Entry, error) {
if err != nil {
return nil, err
}

return ans.Normalize(), nil
}

func toNames(e []interface{}) ([]string, error) {
ans := make([]string, len(e))
for i := range e {
switch v := e[i].(type) {
case string:
ans[i] = v
case Entry:
ans[i] = v.Name
default:
return nil, fmt.Errorf("invalid type: %s", v)
}
}

return ans, nil
}

// FirewallNamespace returns an initialized namespace.
func FirewallNamespace(client util.XapiClient) *Firewall {
return &Firewall{
ns: &namespace.Standard{
Common: namespace.Common{
Singular: singular,
Plural: plural,
Client: client,
},
},
}
}

// PanoramaNamespace returns an initialized namespace.
func PanoramaNamespace(client util.XapiClient) *Panorama {
return &Panorama{
ns: &namespace.Standard{
Common: namespace.Common{
Singular: singular,
Plural: plural,
Client: client,
},
},
}
}
Loading

0 comments on commit b3d00ee

Please sign in to comment.