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)
case `show-private`:
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:
fmt.Printf("unknown subcommand '%s'\n", cmd)
printCommands()

View File

@ -5,6 +5,7 @@ import (
"time"
"github.com/gibheer/pki"
"github.com/gibheer/pkiadm"
)
type (
@ -14,16 +15,16 @@ type (
IsCA bool
Duration time.Duration
PrivateKey ResourceName
Serial ResourceName
CSR ResourceName
CA ResourceName
PrivateKey pkiadm.ResourceName
Serial pkiadm.ResourceName
CSR pkiadm.ResourceName
CA pkiadm.ResourceName
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{
ID: id,
PrivateKey: privateKey,
@ -36,8 +37,8 @@ func NewCertificate(id string, privateKey, serial, csr, ca ResourceName, isCA bo
}
// Return the unique ResourceName
func (c *Certificate) Name() ResourceName {
return ResourceName{c.ID, RTCertificate}
func (c *Certificate) Name() pkiadm.ResourceName {
return pkiadm.ResourceName{c.ID, pkiadm.RTCertificate}
}
// 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) }
// DependsOn must return the resource names it is depending on.
func (c *Certificate) DependsOn() []ResourceName {
res := []ResourceName{
func (c *Certificate) DependsOn() []pkiadm.ResourceName {
res := []pkiadm.ResourceName{
c.PrivateKey,
c.Serial,
c.CSR,

View File

@ -5,6 +5,7 @@ import (
"net"
"github.com/gibheer/pki"
"github.com/gibheer/pkiadm"
)
type (
@ -19,8 +20,8 @@ type (
IPAddresses []net.IP
// PrivateKey is needed to sign the certificate sign request.
PrivateKey ResourceName
Subject ResourceName
PrivateKey pkiadm.ResourceName
Subject pkiadm.ResourceName
// Data contains the pem representation of the CSR.
Data []byte
@ -28,7 +29,7 @@ type (
)
// 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) {
return &CSR{
ID: id,
@ -42,8 +43,8 @@ func NewCSR(id string, pk, subject ResourceName, commonName string, dnsNames []s
}
// Return the unique ResourceName
func (c *CSR) Name() ResourceName {
return ResourceName{c.ID, RTCSR}
func (c *CSR) Name() pkiadm.ResourceName {
return pkiadm.ResourceName{c.ID, pkiadm.RTCSR}
}
// 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) }
// DependsOn must return the resource names it is depending on.
func (c *CSR) DependsOn() []ResourceName {
return []ResourceName{c.PrivateKey}
func (c *CSR) DependsOn() []pkiadm.ResourceName {
return []pkiadm.ResourceName{c.PrivateKey}
}
func (c *CSR) GetCSR() (*pki.CertificateRequest, error) {

View File

@ -2,6 +2,11 @@ package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"github.com/gibheer/pkiadm"
)
const (
@ -12,12 +17,15 @@ type (
Location struct {
ID string
PreCommand string
PostCommand 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 == "" {
return nil, ENoIDGiven
}
@ -32,8 +40,8 @@ func NewLocation(id, path string, res []ResourceName) (*Location, error) {
return l, nil
}
func (l *Location) Name() ResourceName {
return ResourceName{l.ID, RTLocation}
func (l *Location) Name() pkiadm.ResourceName {
return pkiadm.ResourceName{l.ID, pkiadm.RTLocation}
}
// Refresh writes all resources into the single file.
@ -50,12 +58,25 @@ func (l *Location) Refresh(lookup *Storage) error {
}
raw = append(raw, output...)
}
// TODO write to file
fmt.Printf("found %d characters for file: %s\n", len(raw), l.Path)
if l.PreCommand != "" {
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
}
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.
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.
func (l *Location) Checksum() []byte { return []byte{} }
//func (l *Location) MarshalJSON() ([]byte, error) {
// return json.Marshal(*l)
//}
//func (l *Location) UnmarshalJSON(raw []byte) error {
// return json.Unmarshal(raw, l)
//}
func (s *Server) CreateLocation(inLoc pkiadm.Location, res *pkiadm.Result) error {
s.lock()
defer s.unlock()
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"
)
const (
RTPrivateKey ResourceType = iota
RTPublicKey
RTCSR
RTCertificate
RTLocation
RTSerial
RTSubject
)
//const (
// RTPrivateKey ResourceType = iota
// RTPublicKey
// RTCSR
// RTCertificate
// RTLocation
// RTSerial
// RTSubject
//)
const (
ENoIDGiven = Error("no ID given")
@ -32,7 +32,7 @@ const (
type (
Resource interface {
// Return the unique ResourceName
Name() ResourceName
Name() pkiadm.ResourceName
// AddDependency registers a depending resource to be retuened by Dependencies()
// Refresh must trigger a rebuild of the resource.
Refresh(*Storage) error
@ -40,21 +40,22 @@ type (
Pem() ([]byte, error)
Checksum() []byte
// DependsOn must return the resource names it is depending on.
DependsOn() []ResourceName
DependsOn() []pkiadm.ResourceName
}
ResourceName struct {
ID string
Type ResourceType
}
// ResourceName struct {
// ID string
// Type ResourceType
// }
ResourceType uint
Error string
)
func (e Error) Error() string { return string(e) }
func (r ResourceName) String() string { return r.Type.String() + "/" + r.ID }
func (e Error) Error() string { return string(e) }
//func (r ResourceName) String() string { return r.Type.String() + "/" + r.ID }
func main() {
os.Exit(_main())

View File

@ -39,8 +39,8 @@ func NewPrivateKey(id string, pkType pkiadm.PrivateKeyType, bits uint) (*Private
return &pk, nil
}
func (p *PrivateKey) Name() ResourceName {
return ResourceName{p.ID, RTPrivateKey}
func (p *PrivateKey) Name() pkiadm.ResourceName {
return pkiadm.ResourceName{p.ID, pkiadm.RTPrivateKey}
}
func (p *PrivateKey) Checksum() []byte {
@ -51,8 +51,8 @@ func (p *PrivateKey) Pem() ([]byte, error) {
return p.Key, nil
}
func (p *PrivateKey) DependsOn() []ResourceName {
return []ResourceName{}
func (p *PrivateKey) DependsOn() []pkiadm.ResourceName {
return []pkiadm.ResourceName{}
}
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)
return nil
}
return nil
return s.store(res)
}
func (s *Server) SetPrivateKey(changeset pkiadm.PrivateKeyChange, res *pkiadm.Result) error {
s.lock()
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 {
res.SetError(err, "Could not find private key '%s'", changeset.PrivateKey.ID)
return nil
@ -172,7 +172,7 @@ func (s *Server) SetPrivateKey(changeset pkiadm.PrivateKeyChange, res *pkiadm.Re
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)
return nil
}
@ -182,7 +182,7 @@ func (s *Server) DeletePrivateKey(inPk pkiadm.ResourceName, res *pkiadm.Result)
s.lock()
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 {
res.SetError(err, "Could not find private key '%s'", inPk.ID)
return nil
@ -198,7 +198,7 @@ func (s *Server) ShowPrivateKey(inPk pkiadm.ResourceName, res *pkiadm.ResultPriv
s.lock()
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 {
res.Result.SetError(err, "Could not find private key '%s'", inPk.ID)
return nil

View File

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

View File

@ -3,6 +3,8 @@ package main
import (
"crypto/rand"
"math/big"
"github.com/gibheer/pkiadm"
)
const (
@ -28,7 +30,7 @@ func NewSerial(id string, min, max int64) (*Serial, error) {
}
// 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()
// 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{} }
// 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
// assigning.

View File

@ -7,6 +7,7 @@ import (
"log"
"os"
"github.com/gibheer/pkiadm"
"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.
func (s *Storage) Get(r ResourceName) (Resource, error) {
func (s *Storage) Get(r pkiadm.ResourceName) (Resource, error) {
if r.ID == "" {
return nil, ENoIDGiven
}
switch r.Type {
case RTSerial:
case pkiadm.RTSerial:
return s.GetSerial(r)
case RTSubject:
case pkiadm.RTSubject:
return s.GetSubject(r)
case RTPrivateKey:
case pkiadm.RTPrivateKey:
return s.GetPrivateKey(r)
case RTPublicKey:
case pkiadm.RTPublicKey:
return s.GetPublicKey(r)
case RTCSR:
case pkiadm.RTCSR:
return s.GetCSR(r)
case RTCertificate:
case pkiadm.RTCertificate:
return s.GetCertificate(r)
case RTLocation:
case pkiadm.RTLocation:
return s.GetLocation(r)
default:
return nil, EUnknownType
@ -218,7 +219,7 @@ func (s *Storage) Get(r ResourceName) (Resource, error) {
}
// 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 {
return se, nil
}
@ -226,7 +227,7 @@ func (s *Storage) GetSerial(r ResourceName) (*Serial, error) {
}
// 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 {
return se, nil
}
@ -234,7 +235,7 @@ func (s *Storage) GetSubject(r ResourceName) (*Subject, error) {
}
// 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 {
return pk, nil
}
@ -242,7 +243,7 @@ func (s *Storage) GetPrivateKey(r ResourceName) (*PrivateKey, error) {
}
// 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 {
return res, nil
}
@ -250,7 +251,7 @@ func (s *Storage) GetPublicKey(r ResourceName) (*PublicKey, error) {
}
// 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 {
return res, nil
}
@ -258,7 +259,7 @@ func (s *Storage) GetCSR(r ResourceName) (*CSR, error) {
}
// 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 {
return res, nil
}
@ -266,7 +267,7 @@ func (s *Storage) GetCertificate(r ResourceName) (*Certificate, error) {
}
// 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 {
return res, nil
}
@ -277,19 +278,19 @@ func (s *Storage) GetLocation(r ResourceName) (*Location, error) {
func (s *Storage) Remove(r Resource) error {
// TODO implement unable to remove when having dependencies
switch r.Name().Type {
case RTSerial:
case pkiadm.RTSerial:
delete(s.Serials, r.Name().ID)
case RTSubject:
case pkiadm.RTSubject:
delete(s.Subjects, r.Name().ID)
case RTPrivateKey:
case pkiadm.RTPrivateKey:
delete(s.PrivateKeys, r.Name().ID)
case RTPublicKey:
case pkiadm.RTPublicKey:
delete(s.PublicKeys, r.Name().ID)
case RTCSR:
case pkiadm.RTCSR:
delete(s.CSRs, r.Name().ID)
case RTCertificate:
case pkiadm.RTCertificate:
delete(s.Certificates, r.Name().ID)
case RTLocation:
case pkiadm.RTLocation:
delete(s.Locations, r.Name().ID)
default:
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.
func (s *Storage) Update(rn ResourceName) error {
func (s *Storage) Update(rn pkiadm.ResourceName) error {
r, err := s.Get(rn)
if err != nil {
return err

View File

@ -24,7 +24,7 @@ func NewSubject(id string, name pkix.Name) (*Subject, error) {
}
// 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()
// 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{} }
// 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.
func (sub *Subject) GetName() pkix.Name {
@ -65,7 +65,7 @@ func (s *Server) SetSubject(changeset pkiadm.SubjectChange, res *pkiadm.Result)
s.lock()
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 {
res.SetError(err, "Could not find subject '%s'", changeset.Subject.ID)
return nil
@ -96,7 +96,7 @@ func (s *Server) SetSubject(changeset pkiadm.SubjectChange, res *pkiadm.Result)
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)
return nil
}
@ -122,7 +122,7 @@ func (s *Server) DeleteSubject(inSubj pkiadm.ResourceName, res *pkiadm.Result) e
s.lock()
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 {
return nil
} else if err != nil {
@ -142,7 +142,7 @@ func (s *Server) ShowSubject(inSubj pkiadm.ResourceName, res *pkiadm.ResultSubje
s.lock()
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 {
return 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"
const _ResourceType_name = "RTPrivateKeyRTPublicKeyRTCSRRTCertificateRTLocationRTSerialRTSubject"
var _ResourceType_index = [...]uint8{0, 12, 23, 28, 41, 51, 59, 68}
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 _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
RTSerial
RTSubject
RTUnknown
)
type ResourceName struct {