add location support

This commit adds basic support for adding, deleting, ... locations. This
needed a bit of rework for the ResourceName, as it was kind of stupid to
have different implementations server internally and in the lib.

There is still some need for cleanup, but it works basically.
This commit is contained in:
Gibheer 2017-05-31 21:03:51 +02:00
parent bc8e1353af
commit bc84bc4a28
14 changed files with 472 additions and 98 deletions

130
cmd/pkiadm/location.go Normal file
View File

@ -0,0 +1,130 @@
package main
import (
"fmt"
"os"
"strings"
"text/tabwriter"
"github.com/gibheer/pkiadm"
"github.com/pkg/errors"
flag "github.com/spf13/pflag"
)
func createLocation(args []string, client *pkiadm.Client) error {
fs := flag.NewFlagSet("pkiadm create-location", flag.ExitOnError)
fs.Usage = func() {
fmt.Printf("Usage of %s:\n", "pkiadm create-location")
fmt.Println(`
Create a new file containing the referenced resources, which will be converted to pem format.
The pre command will be run before writing the file and the post command will be run after the file is written.
Resource names are defined as "type/id", where type is one of private, public, csr or cert.
`)
fs.PrintDefaults()
}
loc := pkiadm.Location{}
fs.StringVar(&loc.ID, "id", "", "the ID of the location to modify")
if err := parseLocationArgs(&loc, fs, args); err != nil {
return err
}
if err := client.CreateLocation(loc); err != nil {
return errors.Wrap(err, "could not create new location")
}
return nil
}
func setLocation(args []string, client *pkiadm.Client) error {
fs := flag.NewFlagSet("pkiadm set-location", flag.ExitOnError)
loc := pkiadm.Location{}
fs.StringVar(&loc.ID, "id", "", "the ID of the location to modify")
if err := parseLocationArgs(&loc, fs, args); err != nil {
return err
}
fieldList := []string{}
for _, field := range []string{"path", "pre-cmd", "post-cmd", "resources"} {
flag := fs.Lookup(field)
if flag.Changed {
fieldList = append(fieldList, field)
}
}
if err := client.SetLocation(loc, fieldList); err != nil {
return errors.Wrap(err, "could not change location")
}
return nil
}
func parseLocationArgs(loc *pkiadm.Location, fs *flag.FlagSet, args []string) error {
resources := []string{}
fs.StringVar(&loc.Path, "path", "", "the filename of the location where replaces will be placed")
fs.StringSliceVar(&resources, "resources", []string{}, "the resource description to add to the location")
fs.StringVar(&loc.PreCommand, "pre-cmd", "", "the pre command to run before writing the file")
fs.StringVar(&loc.PostCommand, "post-cmd", "", "the oste command to run after writing the file")
fs.Parse(args)
for _, res := range resources {
parts := strings.Split(res, "/")
if len(parts) != 2 {
return errors.Errorf("could not parse resource: '%s'\n", res)
}
resType, err := pkiadm.StringToResourceType(parts[0])
if err != nil {
return errors.Errorf("invalid resource type '%s'", parts[0])
}
loc.Dependencies = append(loc.Dependencies, pkiadm.ResourceName{parts[1], resType})
}
return nil
}
func deleteLocation(args []string, client *pkiadm.Client) error {
fs := flag.NewFlagSet("pkiadm delete-location", flag.ExitOnError)
id := fs.String("id", "", "the id of the location to delete")
fs.Parse(args)
if err := client.DeleteLocation(*id); err != nil {
return errors.Wrap(err, "could not remove location")
}
return nil
}
func showLocation(args []string, client *pkiadm.Client) error {
fs := flag.NewFlagSet("pkiadm show-location", flag.ExitOnError)
id := fs.String("id", "", "the id to view in detail")
fs.Parse(args)
loc, err := client.ShowLocation(*id)
if err != nil {
return err
}
deps := []string{}
for _, dep := range loc.Dependencies {
deps = append(deps, dep.String())
}
out := tabwriter.NewWriter(os.Stdout, 2, 2, 1, ' ', tabwriter.AlignRight)
fmt.Fprintf(out, "ID:\t%s\t\n", loc.ID)
fmt.Fprintf(out, "path:\t%s\t\n", loc.Path)
fmt.Fprintf(out, "pre-cmd:\t%s\t\n", ReplaceEmpty(loc.PreCommand))
fmt.Fprintf(out, "post-cmd:\t%s\t\n", ReplaceEmpty(loc.PostCommand))
fmt.Fprintf(out, "deps:\t%s\t\n", strings.Join(deps, ", "))
out.Flush()
return nil
}
func listLocation(args []string, client *pkiadm.Client) error {
fs := flag.NewFlagSet("pkiadm list-location", flag.ExitOnError)
fs.Parse(args)
locs, err := client.ListLocation()
if err != nil {
return err
}
if len(locs) == 0 {
return nil
}
out := tabwriter.NewWriter(os.Stdout, 2, 2, 1, ' ', tabwriter.AlignRight)
fmt.Fprintf(out, "%s\t%s\t%s\t\n", "id", "path", "deps")
for _, loc := range locs {
fmt.Fprintf(out, "%s\t%s\t%d\t\n", loc.ID, loc.Path, len(loc.Dependencies))
}
out.Flush()
return nil
}

View File

@ -50,6 +50,16 @@ func main() {
err = setPrivateKey(args, client) err = setPrivateKey(args, client)
case `show-private`: case `show-private`:
err = showPrivateKey(args, client) err = showPrivateKey(args, client)
case `create-location`:
err = createLocation(args, client)
case `delete-location`:
err = deleteLocation(args, client)
case `list-location`:
err = listLocation(args, client)
case `set-location`:
err = setLocation(args, client)
case `show-location`:
err = showLocation(args, client)
default: default:
fmt.Printf("unknown subcommand '%s'\n", cmd) fmt.Printf("unknown subcommand '%s'\n", cmd)
printCommands() printCommands()

View File

@ -5,6 +5,7 @@ import (
"time" "time"
"github.com/gibheer/pki" "github.com/gibheer/pki"
"github.com/gibheer/pkiadm"
) )
type ( type (
@ -14,16 +15,16 @@ type (
IsCA bool IsCA bool
Duration time.Duration Duration time.Duration
PrivateKey ResourceName PrivateKey pkiadm.ResourceName
Serial ResourceName Serial pkiadm.ResourceName
CSR ResourceName CSR pkiadm.ResourceName
CA ResourceName CA pkiadm.ResourceName
Data []byte Data []byte
} }
) )
func NewCertificate(id string, privateKey, serial, csr, ca ResourceName, isCA bool, duration time.Duration) (*Certificate, error) { func NewCertificate(id string, privateKey, serial, csr, ca pkiadm.ResourceName, isCA bool, duration time.Duration) (*Certificate, error) {
return &Certificate{ return &Certificate{
ID: id, ID: id,
PrivateKey: privateKey, PrivateKey: privateKey,
@ -36,8 +37,8 @@ func NewCertificate(id string, privateKey, serial, csr, ca ResourceName, isCA bo
} }
// Return the unique ResourceName // Return the unique ResourceName
func (c *Certificate) Name() ResourceName { func (c *Certificate) Name() pkiadm.ResourceName {
return ResourceName{c.ID, RTCertificate} return pkiadm.ResourceName{c.ID, pkiadm.RTCertificate}
} }
// AddDependency registers a depending resource to be retuened by Dependencies() // AddDependency registers a depending resource to be retuened by Dependencies()
@ -116,8 +117,8 @@ func (c *Certificate) Pem() ([]byte, error) { return c.Data, nil }
func (c *Certificate) Checksum() []byte { return Hash(c.Data) } func (c *Certificate) Checksum() []byte { return Hash(c.Data) }
// DependsOn must return the resource names it is depending on. // DependsOn must return the resource names it is depending on.
func (c *Certificate) DependsOn() []ResourceName { func (c *Certificate) DependsOn() []pkiadm.ResourceName {
res := []ResourceName{ res := []pkiadm.ResourceName{
c.PrivateKey, c.PrivateKey,
c.Serial, c.Serial,
c.CSR, c.CSR,

View File

@ -5,6 +5,7 @@ import (
"net" "net"
"github.com/gibheer/pki" "github.com/gibheer/pki"
"github.com/gibheer/pkiadm"
) )
type ( type (
@ -19,8 +20,8 @@ type (
IPAddresses []net.IP IPAddresses []net.IP
// PrivateKey is needed to sign the certificate sign request. // PrivateKey is needed to sign the certificate sign request.
PrivateKey ResourceName PrivateKey pkiadm.ResourceName
Subject ResourceName Subject pkiadm.ResourceName
// Data contains the pem representation of the CSR. // Data contains the pem representation of the CSR.
Data []byte Data []byte
@ -28,7 +29,7 @@ type (
) )
// NewCSR creates a new CSR. // NewCSR creates a new CSR.
func NewCSR(id string, pk, subject ResourceName, commonName string, dnsNames []string, func NewCSR(id string, pk, subject pkiadm.ResourceName, commonName string, dnsNames []string,
emailAddresses []string, iPAddresses []net.IP) (*CSR, error) { emailAddresses []string, iPAddresses []net.IP) (*CSR, error) {
return &CSR{ return &CSR{
ID: id, ID: id,
@ -42,8 +43,8 @@ func NewCSR(id string, pk, subject ResourceName, commonName string, dnsNames []s
} }
// Return the unique ResourceName // Return the unique ResourceName
func (c *CSR) Name() ResourceName { func (c *CSR) Name() pkiadm.ResourceName {
return ResourceName{c.ID, RTCSR} return pkiadm.ResourceName{c.ID, pkiadm.RTCSR}
} }
// AddDependency registers a depending resource to be retuened by Dependencies() // AddDependency registers a depending resource to be retuened by Dependencies()
@ -88,8 +89,8 @@ func (c *CSR) Pem() ([]byte, error) { return c.Data, nil }
func (c *CSR) Checksum() []byte { return Hash(c.Data) } func (c *CSR) Checksum() []byte { return Hash(c.Data) }
// DependsOn must return the resource names it is depending on. // DependsOn must return the resource names it is depending on.
func (c *CSR) DependsOn() []ResourceName { func (c *CSR) DependsOn() []pkiadm.ResourceName {
return []ResourceName{c.PrivateKey} return []pkiadm.ResourceName{c.PrivateKey}
} }
func (c *CSR) GetCSR() (*pki.CertificateRequest, error) { func (c *CSR) GetCSR() (*pki.CertificateRequest, error) {

View File

@ -2,6 +2,11 @@ package main
import ( import (
"fmt" "fmt"
"io/ioutil"
"os"
"os/exec"
"github.com/gibheer/pkiadm"
) )
const ( const (
@ -12,12 +17,15 @@ type (
Location struct { Location struct {
ID string ID string
PreCommand string
PostCommand string
Path string Path string
Dependencies []ResourceName Dependencies []pkiadm.ResourceName
} }
) )
func NewLocation(id, path string, res []ResourceName) (*Location, error) { func NewLocation(id, path, preCom, postCom string, res []pkiadm.ResourceName) (*Location, error) {
if id == "" { if id == "" {
return nil, ENoIDGiven return nil, ENoIDGiven
} }
@ -32,8 +40,8 @@ func NewLocation(id, path string, res []ResourceName) (*Location, error) {
return l, nil return l, nil
} }
func (l *Location) Name() ResourceName { func (l *Location) Name() pkiadm.ResourceName {
return ResourceName{l.ID, RTLocation} return pkiadm.ResourceName{l.ID, pkiadm.RTLocation}
} }
// Refresh writes all resources into the single file. // Refresh writes all resources into the single file.
@ -50,12 +58,25 @@ func (l *Location) Refresh(lookup *Storage) error {
} }
raw = append(raw, output...) raw = append(raw, output...)
} }
// TODO write to file if l.PreCommand != "" {
fmt.Printf("found %d characters for file: %s\n", len(raw), l.Path) cmd := exec.Command(l.PreCommand, l.Path)
if err := cmd.Run(); err != nil {
return err
}
}
if err := ioutil.WriteFile(l.Path, raw, 0600); err != nil {
return err
}
if l.PostCommand != "" {
cmd := exec.Command(l.PostCommand, l.Path)
if err := cmd.Run(); err != nil {
return err
}
}
return nil return nil
} }
func (l *Location) DependsOn() []ResourceName { return l.Dependencies } func (l *Location) DependsOn() []pkiadm.ResourceName { return l.Dependencies }
// Pem is not used by location, as it does not contain any data. // Pem is not used by location, as it does not contain any data.
func (l *Location) Pem() ([]byte, error) { return []byte{}, nil } func (l *Location) Pem() ([]byte, error) { return []byte{}, nil }
@ -63,9 +84,119 @@ func (l *Location) Pem() ([]byte, error) { return []byte{}, nil }
// Checksum is not used by Location, as it does not contain any data. // Checksum is not used by Location, as it does not contain any data.
func (l *Location) Checksum() []byte { return []byte{} } func (l *Location) Checksum() []byte { return []byte{} }
//func (l *Location) MarshalJSON() ([]byte, error) { func (s *Server) CreateLocation(inLoc pkiadm.Location, res *pkiadm.Result) error {
// return json.Marshal(*l) s.lock()
//} defer s.unlock()
//func (l *Location) UnmarshalJSON(raw []byte) error {
// return json.Unmarshal(raw, l) deps := []pkiadm.ResourceName{}
//} for _, dep := range inLoc.Dependencies {
deps = append(deps, pkiadm.ResourceName{ID: dep.ID, Type: dep.Type})
}
loc, err := NewLocation(inLoc.ID, inLoc.Path, inLoc.PreCommand, inLoc.PostCommand, deps)
if err != nil {
res.SetError(err, "Could not create location '%s'", inLoc.ID)
return nil
}
if err := s.storage.AddLocation(loc); err != nil {
res.SetError(err, "Could not add location '%s'", inLoc.ID)
return nil
}
return s.store(res)
}
func (s *Server) SetLocation(changeset pkiadm.LocationChange, res *pkiadm.Result) error {
s.lock()
defer s.unlock()
changed := changeset.Location
locName := pkiadm.ResourceName{changed.ID, pkiadm.RTLocation}
loc, err := s.storage.GetLocation(locName)
if err != nil {
res.SetError(err, "could not find location '%s'", changeset.Location.ID)
return nil
}
for _, field := range changeset.FieldList {
switch field {
case "path":
// TODO remove old file?
loc.Path = changed.Path
case "pre-cmd":
loc.PreCommand = changed.PreCommand
case "post-cmd":
loc.PostCommand = changed.PostCommand
case "resources":
loc.Dependencies = changed.Dependencies
default:
res.SetError(fmt.Errorf("unknown field"), "unknown field '%s'", field)
return nil
}
}
if err := s.storage.Update(locName); err != nil {
res.SetError(err, "Could not update location '%s'", loc.ID)
return nil
}
return s.store(res)
}
func (s *Server) DeleteLocation(inLoc pkiadm.Location, res *pkiadm.Result) error {
s.lock()
defer s.unlock()
loc, err := s.storage.GetLocation(pkiadm.ResourceName{inLoc.ID, pkiadm.RTLocation})
if err != nil {
res.SetError(err, "could not find location '%s'", inLoc.ID)
return nil
}
if err := os.Remove(loc.Path); err != nil {
res.SetError(err, "Could not remove file '%s' for location '%s'", loc.Path, loc.ID)
return nil
}
if err := s.storage.Remove(loc); err != nil {
res.SetError(err, "Could not remove location '%s'", loc.ID)
return nil
}
if loc.PostCommand != "" {
cmd := exec.Command(loc.PostCommand, loc.Path)
if err := cmd.Run(); err != nil {
res.SetError(err, "Could not run post command after deleting '%s'", loc.ID)
return nil
}
}
return s.store(res)
}
func (s *Server) ShowLocation(inLoc pkiadm.PrivateKey, res *pkiadm.ResultLocations) error {
s.lock()
defer s.unlock()
loc, err := s.storage.GetLocation(pkiadm.ResourceName{inLoc.ID, pkiadm.RTLocation})
if err != nil {
res.Result.SetError(err, "Could not find location '%s'", inLoc.ID)
return nil
}
res.Locations = []pkiadm.Location{pkiadm.Location{
ID: loc.ID,
Path: loc.Path,
PreCommand: loc.PreCommand,
PostCommand: loc.PostCommand,
Dependencies: loc.Dependencies,
}}
return nil
}
func (s *Server) ListLocation(filter pkiadm.Filter, res *pkiadm.ResultLocations) error {
s.lock()
defer s.unlock()
for _, loc := range s.storage.Locations {
res.Locations = append(res.Locations, pkiadm.Location{
ID: loc.ID,
Path: loc.Path,
PreCommand: loc.PreCommand,
PostCommand: loc.PostCommand,
Dependencies: loc.Dependencies,
})
}
return nil
}

View File

@ -10,15 +10,15 @@ import (
"github.com/gibheer/pkiadm" "github.com/gibheer/pkiadm"
) )
const ( //const (
RTPrivateKey ResourceType = iota // RTPrivateKey ResourceType = iota
RTPublicKey // RTPublicKey
RTCSR // RTCSR
RTCertificate // RTCertificate
RTLocation // RTLocation
RTSerial // RTSerial
RTSubject // RTSubject
) //)
const ( const (
ENoIDGiven = Error("no ID given") ENoIDGiven = Error("no ID given")
@ -32,7 +32,7 @@ const (
type ( type (
Resource interface { Resource interface {
// Return the unique ResourceName // Return the unique ResourceName
Name() ResourceName Name() pkiadm.ResourceName
// AddDependency registers a depending resource to be retuened by Dependencies() // AddDependency registers a depending resource to be retuened by Dependencies()
// Refresh must trigger a rebuild of the resource. // Refresh must trigger a rebuild of the resource.
Refresh(*Storage) error Refresh(*Storage) error
@ -40,21 +40,22 @@ type (
Pem() ([]byte, error) Pem() ([]byte, error)
Checksum() []byte Checksum() []byte
// DependsOn must return the resource names it is depending on. // DependsOn must return the resource names it is depending on.
DependsOn() []ResourceName DependsOn() []pkiadm.ResourceName
} }
ResourceName struct { // ResourceName struct {
ID string // ID string
Type ResourceType // Type ResourceType
} // }
ResourceType uint ResourceType uint
Error string Error string
) )
func (e Error) Error() string { return string(e) } func (e Error) Error() string { return string(e) }
func (r ResourceName) String() string { return r.Type.String() + "/" + r.ID }
//func (r ResourceName) String() string { return r.Type.String() + "/" + r.ID }
func main() { func main() {
os.Exit(_main()) os.Exit(_main())

View File

@ -39,8 +39,8 @@ func NewPrivateKey(id string, pkType pkiadm.PrivateKeyType, bits uint) (*Private
return &pk, nil return &pk, nil
} }
func (p *PrivateKey) Name() ResourceName { func (p *PrivateKey) Name() pkiadm.ResourceName {
return ResourceName{p.ID, RTPrivateKey} return pkiadm.ResourceName{p.ID, pkiadm.RTPrivateKey}
} }
func (p *PrivateKey) Checksum() []byte { func (p *PrivateKey) Checksum() []byte {
@ -51,8 +51,8 @@ func (p *PrivateKey) Pem() ([]byte, error) {
return p.Key, nil return p.Key, nil
} }
func (p *PrivateKey) DependsOn() []ResourceName { func (p *PrivateKey) DependsOn() []pkiadm.ResourceName {
return []ResourceName{} return []pkiadm.ResourceName{}
} }
func (p *PrivateKey) Refresh(_ *Storage) error { func (p *PrivateKey) Refresh(_ *Storage) error {
@ -149,13 +149,13 @@ func (s *Server) CreatePrivateKey(inPk pkiadm.PrivateKey, res *pkiadm.Result) er
res.SetError(err, "Could not add private key '%s'", inPk.ID) res.SetError(err, "Could not add private key '%s'", inPk.ID)
return nil return nil
} }
return nil return s.store(res)
} }
func (s *Server) SetPrivateKey(changeset pkiadm.PrivateKeyChange, res *pkiadm.Result) error { func (s *Server) SetPrivateKey(changeset pkiadm.PrivateKeyChange, res *pkiadm.Result) error {
s.lock() s.lock()
defer s.unlock() defer s.unlock()
pk, err := s.storage.GetPrivateKey(ResourceName{ID: changeset.PrivateKey.ID, Type: RTPrivateKey}) pk, err := s.storage.GetPrivateKey(pkiadm.ResourceName{ID: changeset.PrivateKey.ID, Type: pkiadm.RTPrivateKey})
if err != nil { if err != nil {
res.SetError(err, "Could not find private key '%s'", changeset.PrivateKey.ID) res.SetError(err, "Could not find private key '%s'", changeset.PrivateKey.ID)
return nil return nil
@ -172,7 +172,7 @@ func (s *Server) SetPrivateKey(changeset pkiadm.PrivateKeyChange, res *pkiadm.Re
return nil return nil
} }
} }
if err := s.storage.Update(ResourceName{ID: pk.ID, Type: RTPrivateKey}); err != nil { if err := s.storage.Update(pkiadm.ResourceName{ID: pk.ID, Type: pkiadm.RTPrivateKey}); err != nil {
res.SetError(err, "Could not update private key '%s'", changeset.PrivateKey.ID) res.SetError(err, "Could not update private key '%s'", changeset.PrivateKey.ID)
return nil return nil
} }
@ -182,7 +182,7 @@ func (s *Server) DeletePrivateKey(inPk pkiadm.ResourceName, res *pkiadm.Result)
s.lock() s.lock()
defer s.unlock() defer s.unlock()
pk, err := s.storage.GetPrivateKey(ResourceName{ID: inPk.ID, Type: RTPrivateKey}) pk, err := s.storage.GetPrivateKey(pkiadm.ResourceName{ID: inPk.ID, Type: pkiadm.RTPrivateKey})
if err != nil { if err != nil {
res.SetError(err, "Could not find private key '%s'", inPk.ID) res.SetError(err, "Could not find private key '%s'", inPk.ID)
return nil return nil
@ -198,7 +198,7 @@ func (s *Server) ShowPrivateKey(inPk pkiadm.ResourceName, res *pkiadm.ResultPriv
s.lock() s.lock()
defer s.unlock() defer s.unlock()
pk, err := s.storage.GetPrivateKey(ResourceName{ID: inPk.ID, Type: RTPrivateKey}) pk, err := s.storage.GetPrivateKey(pkiadm.ResourceName{ID: inPk.ID, Type: pkiadm.RTPrivateKey})
if err != nil { if err != nil {
res.Result.SetError(err, "Could not find private key '%s'", inPk.ID) res.Result.SetError(err, "Could not find private key '%s'", inPk.ID)
return nil return nil

View File

@ -2,6 +2,8 @@ package main
import ( import (
"encoding/pem" "encoding/pem"
"github.com/gibheer/pkiadm"
) )
const ( const (
@ -14,7 +16,7 @@ type (
PublicKey struct { PublicKey struct {
ID string ID string
PrivateKey ResourceName PrivateKey pkiadm.ResourceName
Type PublicKeyType // mark the type of the public key Type PublicKeyType // mark the type of the public key
Key []byte Key []byte
} }
@ -22,7 +24,7 @@ type (
PublicKeyType uint PublicKeyType uint
) )
func NewPublicKey(id string, pk ResourceName) (*PublicKey, error) { func NewPublicKey(id string, pk pkiadm.ResourceName) (*PublicKey, error) {
pub := PublicKey{ pub := PublicKey{
ID: id, ID: id,
PrivateKey: pk, PrivateKey: pk,
@ -30,8 +32,8 @@ func NewPublicKey(id string, pk ResourceName) (*PublicKey, error) {
return &pub, nil return &pub, nil
} }
func (p *PublicKey) Name() ResourceName { func (p *PublicKey) Name() pkiadm.ResourceName {
return ResourceName{p.ID, RTPublicKey} return pkiadm.ResourceName{p.ID, pkiadm.RTPublicKey}
} }
func (p *PublicKey) Refresh(lookup *Storage) error { func (p *PublicKey) Refresh(lookup *Storage) error {
@ -57,8 +59,8 @@ func (p *PublicKey) Refresh(lookup *Storage) error {
return nil return nil
} }
func (p *PublicKey) DependsOn() []ResourceName { func (p *PublicKey) DependsOn() []pkiadm.ResourceName {
return []ResourceName{p.PrivateKey} return []pkiadm.ResourceName{p.PrivateKey}
} }
func (p *PublicKey) Pem() ([]byte, error) { func (p *PublicKey) Pem() ([]byte, error) {

View File

@ -3,6 +3,8 @@ package main
import ( import (
"crypto/rand" "crypto/rand"
"math/big" "math/big"
"github.com/gibheer/pkiadm"
) )
const ( const (
@ -28,7 +30,7 @@ func NewSerial(id string, min, max int64) (*Serial, error) {
} }
// Return the unique ResourceName // Return the unique ResourceName
func (s *Serial) Name() ResourceName { return ResourceName{s.ID, RTSerial} } func (s *Serial) Name() pkiadm.ResourceName { return pkiadm.ResourceName{s.ID, pkiadm.RTSerial} }
// AddDependency registers a depending resource to be retuened by Dependencies() // AddDependency registers a depending resource to be retuened by Dependencies()
// Refresh must trigger a rebuild of the resource. // Refresh must trigger a rebuild of the resource.
@ -43,7 +45,7 @@ func (s *Serial) Pem() ([]byte, error) { return []byte{}, nil }
func (s *Serial) Checksum() []byte { return []byte{} } func (s *Serial) Checksum() []byte { return []byte{} }
// DependsOn must return the resource names it is depending on. // DependsOn must return the resource names it is depending on.
func (s *Serial) DependsOn() []ResourceName { return []ResourceName{} } func (s *Serial) DependsOn() []pkiadm.ResourceName { return []pkiadm.ResourceName{} }
// Generate generates a new serial number and stores it to avoid double // Generate generates a new serial number and stores it to avoid double
// assigning. // assigning.

View File

@ -7,6 +7,7 @@ import (
"log" "log"
"os" "os"
"github.com/gibheer/pkiadm"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -193,24 +194,24 @@ func (s *Storage) AddLocation(l *Location) error {
} }
// Get figures out the resource to the ResourceName if available. // Get figures out the resource to the ResourceName if available.
func (s *Storage) Get(r ResourceName) (Resource, error) { func (s *Storage) Get(r pkiadm.ResourceName) (Resource, error) {
if r.ID == "" { if r.ID == "" {
return nil, ENoIDGiven return nil, ENoIDGiven
} }
switch r.Type { switch r.Type {
case RTSerial: case pkiadm.RTSerial:
return s.GetSerial(r) return s.GetSerial(r)
case RTSubject: case pkiadm.RTSubject:
return s.GetSubject(r) return s.GetSubject(r)
case RTPrivateKey: case pkiadm.RTPrivateKey:
return s.GetPrivateKey(r) return s.GetPrivateKey(r)
case RTPublicKey: case pkiadm.RTPublicKey:
return s.GetPublicKey(r) return s.GetPublicKey(r)
case RTCSR: case pkiadm.RTCSR:
return s.GetCSR(r) return s.GetCSR(r)
case RTCertificate: case pkiadm.RTCertificate:
return s.GetCertificate(r) return s.GetCertificate(r)
case RTLocation: case pkiadm.RTLocation:
return s.GetLocation(r) return s.GetLocation(r)
default: default:
return nil, EUnknownType return nil, EUnknownType
@ -218,7 +219,7 @@ func (s *Storage) Get(r ResourceName) (Resource, error) {
} }
// GetSerial returns the Serial matching the ResourceName. // GetSerial returns the Serial matching the ResourceName.
func (s *Storage) GetSerial(r ResourceName) (*Serial, error) { func (s *Storage) GetSerial(r pkiadm.ResourceName) (*Serial, error) {
if se, found := s.Serials[r.ID]; found { if se, found := s.Serials[r.ID]; found {
return se, nil return se, nil
} }
@ -226,7 +227,7 @@ func (s *Storage) GetSerial(r ResourceName) (*Serial, error) {
} }
// GetSubject returns the Subject matching the ResourceName. // GetSubject returns the Subject matching the ResourceName.
func (s *Storage) GetSubject(r ResourceName) (*Subject, error) { func (s *Storage) GetSubject(r pkiadm.ResourceName) (*Subject, error) {
if se, found := s.Subjects[r.ID]; found { if se, found := s.Subjects[r.ID]; found {
return se, nil return se, nil
} }
@ -234,7 +235,7 @@ func (s *Storage) GetSubject(r ResourceName) (*Subject, error) {
} }
// GetPrivateKey returns the PrivateKey to the ResourceName. // GetPrivateKey returns the PrivateKey to the ResourceName.
func (s *Storage) GetPrivateKey(r ResourceName) (*PrivateKey, error) { func (s *Storage) GetPrivateKey(r pkiadm.ResourceName) (*PrivateKey, error) {
if pk, found := s.PrivateKeys[r.ID]; found { if pk, found := s.PrivateKeys[r.ID]; found {
return pk, nil return pk, nil
} }
@ -242,7 +243,7 @@ func (s *Storage) GetPrivateKey(r ResourceName) (*PrivateKey, error) {
} }
// GetPublicKey returns the PublicKey to the ResourceName. // GetPublicKey returns the PublicKey to the ResourceName.
func (s *Storage) GetPublicKey(r ResourceName) (*PublicKey, error) { func (s *Storage) GetPublicKey(r pkiadm.ResourceName) (*PublicKey, error) {
if res, found := s.PublicKeys[r.ID]; found { if res, found := s.PublicKeys[r.ID]; found {
return res, nil return res, nil
} }
@ -250,7 +251,7 @@ func (s *Storage) GetPublicKey(r ResourceName) (*PublicKey, error) {
} }
// GetCSR returns the CSR to the CSR. // GetCSR returns the CSR to the CSR.
func (s *Storage) GetCSR(r ResourceName) (*CSR, error) { func (s *Storage) GetCSR(r pkiadm.ResourceName) (*CSR, error) {
if res, found := s.CSRs[r.ID]; found { if res, found := s.CSRs[r.ID]; found {
return res, nil return res, nil
} }
@ -258,7 +259,7 @@ func (s *Storage) GetCSR(r ResourceName) (*CSR, error) {
} }
// GetCertificate returns the Certificate matching the ResourceName. // GetCertificate returns the Certificate matching the ResourceName.
func (s *Storage) GetCertificate(r ResourceName) (*Certificate, error) { func (s *Storage) GetCertificate(r pkiadm.ResourceName) (*Certificate, error) {
if res, found := s.Certificates[r.ID]; found { if res, found := s.Certificates[r.ID]; found {
return res, nil return res, nil
} }
@ -266,7 +267,7 @@ func (s *Storage) GetCertificate(r ResourceName) (*Certificate, error) {
} }
// GetLocation returns the Location matching the ResourceName. // GetLocation returns the Location matching the ResourceName.
func (s *Storage) GetLocation(r ResourceName) (*Location, error) { func (s *Storage) GetLocation(r pkiadm.ResourceName) (*Location, error) {
if res, found := s.Locations[r.ID]; found { if res, found := s.Locations[r.ID]; found {
return res, nil return res, nil
} }
@ -277,19 +278,19 @@ func (s *Storage) GetLocation(r ResourceName) (*Location, error) {
func (s *Storage) Remove(r Resource) error { func (s *Storage) Remove(r Resource) error {
// TODO implement unable to remove when having dependencies // TODO implement unable to remove when having dependencies
switch r.Name().Type { switch r.Name().Type {
case RTSerial: case pkiadm.RTSerial:
delete(s.Serials, r.Name().ID) delete(s.Serials, r.Name().ID)
case RTSubject: case pkiadm.RTSubject:
delete(s.Subjects, r.Name().ID) delete(s.Subjects, r.Name().ID)
case RTPrivateKey: case pkiadm.RTPrivateKey:
delete(s.PrivateKeys, r.Name().ID) delete(s.PrivateKeys, r.Name().ID)
case RTPublicKey: case pkiadm.RTPublicKey:
delete(s.PublicKeys, r.Name().ID) delete(s.PublicKeys, r.Name().ID)
case RTCSR: case pkiadm.RTCSR:
delete(s.CSRs, r.Name().ID) delete(s.CSRs, r.Name().ID)
case RTCertificate: case pkiadm.RTCertificate:
delete(s.Certificates, r.Name().ID) delete(s.Certificates, r.Name().ID)
case RTLocation: case pkiadm.RTLocation:
delete(s.Locations, r.Name().ID) delete(s.Locations, r.Name().ID)
default: default:
return EUnknownType return EUnknownType
@ -303,7 +304,7 @@ func (s *Storage) Remove(r Resource) error {
} }
// Update sends a refresh through all resources depending on the one given. // Update sends a refresh through all resources depending on the one given.
func (s *Storage) Update(rn ResourceName) error { func (s *Storage) Update(rn pkiadm.ResourceName) error {
r, err := s.Get(rn) r, err := s.Get(rn)
if err != nil { if err != nil {
return err return err

View File

@ -24,7 +24,7 @@ func NewSubject(id string, name pkix.Name) (*Subject, error) {
} }
// Return the unique ResourceName // Return the unique ResourceName
func (sub *Subject) Name() ResourceName { return ResourceName{sub.ID, RTSubject} } func (sub *Subject) Name() pkiadm.ResourceName { return pkiadm.ResourceName{sub.ID, pkiadm.RTSubject} }
// AddDependency registers a depending resource to be retuened by Dependencies() // AddDependency registers a depending resource to be retuened by Dependencies()
// Refresh must trigger a rebuild of the resource. // Refresh must trigger a rebuild of the resource.
@ -36,7 +36,7 @@ func (sub *Subject) Pem() ([]byte, error) { return []byte{}, nil }
func (sub *Subject) Checksum() []byte { return []byte{} } func (sub *Subject) Checksum() []byte { return []byte{} }
// DependsOn must return the resource names it is depending on. // DependsOn must return the resource names it is depending on.
func (sub *Subject) DependsOn() []ResourceName { return []ResourceName{} } func (sub *Subject) DependsOn() []pkiadm.ResourceName { return []pkiadm.ResourceName{} }
// GetName returns the stored name definition. // GetName returns the stored name definition.
func (sub *Subject) GetName() pkix.Name { func (sub *Subject) GetName() pkix.Name {
@ -65,7 +65,7 @@ func (s *Server) SetSubject(changeset pkiadm.SubjectChange, res *pkiadm.Result)
s.lock() s.lock()
defer s.unlock() defer s.unlock()
subj, err := s.storage.GetSubject(ResourceName{ID: changeset.Subject.ID, Type: RTSubject}) subj, err := s.storage.GetSubject(pkiadm.ResourceName{ID: changeset.Subject.ID, Type: pkiadm.RTSubject})
if err != nil { if err != nil {
res.SetError(err, "Could not find subject '%s'", changeset.Subject.ID) res.SetError(err, "Could not find subject '%s'", changeset.Subject.ID)
return nil return nil
@ -96,7 +96,7 @@ func (s *Server) SetSubject(changeset pkiadm.SubjectChange, res *pkiadm.Result)
return nil return nil
} }
} }
if err := s.storage.Update(ResourceName{ID: subj.ID, Type: RTSubject}); err != nil { if err := s.storage.Update(pkiadm.ResourceName{ID: subj.ID, Type: pkiadm.RTSubject}); err != nil {
res.SetError(err, "Could not update subject '%s'", changeset.Subject.ID) res.SetError(err, "Could not update subject '%s'", changeset.Subject.ID)
return nil return nil
} }
@ -122,7 +122,7 @@ func (s *Server) DeleteSubject(inSubj pkiadm.ResourceName, res *pkiadm.Result) e
s.lock() s.lock()
defer s.unlock() defer s.unlock()
subj, err := s.storage.Get(ResourceName{ID: inSubj.ID, Type: RTSubject}) subj, err := s.storage.Get(pkiadm.ResourceName{ID: inSubj.ID, Type: pkiadm.RTSubject})
if err == ENotFound { if err == ENotFound {
return nil return nil
} else if err != nil { } else if err != nil {
@ -142,7 +142,7 @@ func (s *Server) ShowSubject(inSubj pkiadm.ResourceName, res *pkiadm.ResultSubje
s.lock() s.lock()
defer s.unlock() defer s.unlock()
subj, err := s.storage.GetSubject(ResourceName{ID: inSubj.ID, Type: RTSubject}) subj, err := s.storage.GetSubject(pkiadm.ResourceName{ID: inSubj.ID, Type: pkiadm.RTSubject})
if err == ENotFound { if err == ENotFound {
return nil return nil
} else if err != nil { } else if err != nil {

61
location.go Normal file
View File

@ -0,0 +1,61 @@
package pkiadm
type (
Location struct {
ID string
Path string
Dependencies []ResourceName
PreCommand string
PostCommand string
Checksum []byte
}
LocationChange struct {
Location Location
FieldList []string
}
ResultLocations struct {
Result Result
Locations []Location
}
)
func (c *Client) CreateLocation(loc Location) error {
return c.exec("CreateLocation", loc)
}
func (c *Client) DeleteLocation(id string) error {
loc := ResourceName{ID: id, Type: RTLocation}
return c.exec("DeleteLocation", loc)
}
func (c *Client) SetLocation(loc Location, fieldList []string) error {
changeset := LocationChange{loc, fieldList}
return c.exec("SetLocation", changeset)
}
func (c *Client) ShowLocation(id string) (Location, error) {
loc := ResourceName{ID: id, Type: RTLocation}
result := &ResultLocations{}
if err := c.query("ShowLocation", loc, result); err != nil {
return Location{}, err
}
if result.Result.HasError {
return Location{}, result.Result.Error
}
for _, location := range result.Locations {
return location, nil
}
return Location{}, nil
}
func (c *Client) ListLocation() ([]Location, error) {
result := &ResultLocations{}
if err := c.query("ListLocation", Filter{}, result); err != nil {
return []Location{}, err
}
if result.Result.HasError {
return []Location{}, result.Result.Error
}
return result.Locations, nil
}

View File

@ -4,13 +4,46 @@ package pkiadm
import "fmt" import "fmt"
const _ResourceType_name = "RTPrivateKeyRTPublicKeyRTCSRRTCertificateRTLocationRTSerialRTSubject"
var _ResourceType_index = [...]uint8{0, 12, 23, 28, 41, 51, 59, 68}
func (i ResourceType) String() string { func (i ResourceType) String() string {
if i >= ResourceType(len(_ResourceType_index)-1) { switch i {
case RTPrivateKey:
return "private"
case RTPublicKey:
return "public"
case RTCSR:
return "csr"
case RTCertificate:
return "cert"
case RTSubject:
return "subject"
case RTSerial:
return "serial"
case RTLocation:
return "location"
case RTUnknown:
return "unknown"
default:
return fmt.Sprintf("ResourceType(%d)", i) return fmt.Sprintf("ResourceType(%d)", i)
} }
return _ResourceType_name[_ResourceType_index[i]:_ResourceType_index[i+1]] }
func StringToResourceType(in string) (ResourceType, error) {
switch in {
case "private":
return RTPrivateKey, nil
case "public":
return RTPublicKey, nil
case "csr":
return RTCSR, nil
case "cert":
return RTCertificate, nil
case "location":
return RTLocation, nil
case "subject":
return RTSubject, nil
case "serial":
return RTSerial, nil
default:
return RTUnknown, fmt.Errorf("unknown resource type")
}
} }

View File

@ -37,6 +37,7 @@ const (
RTLocation RTLocation
RTSerial RTSerial
RTSubject RTSubject
RTUnknown
) )
type ResourceName struct { type ResourceName struct {