From b9456bfd8b9eec89db45521e29c846721911aed1 Mon Sep 17 00:00:00 2001 From: Gibheer Date: Sat, 3 Jun 2017 21:56:32 +0200 Subject: [PATCH] add public key support This adds public key support. This also moves some of the type files around or removes it, because they weren't used anymore. --- cmd/pkiadm/public_key.go | 93 ++++++++++++++++++++++ cmd/pkiadmd/public_key.go | 119 +++++++++++++++++++++++----- cmd/pkiadmd/publickeytype_string.go | 16 ---- cmd/pkiadmd/resourcetype_string.go | 16 ---- public_key.go | 62 +++++++++++++++ 5 files changed, 254 insertions(+), 52 deletions(-) create mode 100644 cmd/pkiadm/public_key.go delete mode 100644 cmd/pkiadmd/publickeytype_string.go delete mode 100644 cmd/pkiadmd/resourcetype_string.go create mode 100644 public_key.go diff --git a/cmd/pkiadm/public_key.go b/cmd/pkiadm/public_key.go new file mode 100644 index 0000000..aeadd2a --- /dev/null +++ b/cmd/pkiadm/public_key.go @@ -0,0 +1,93 @@ +package main + +import ( + "encoding/base64" + "fmt" + "os" + "text/tabwriter" + + "github.com/gibheer/pkiadm" + "github.com/pkg/errors" + flag "github.com/spf13/pflag" +) + +func createPublicKey(args []string, client *pkiadm.Client) error { + fs := flag.NewFlagSet("pkiadm create-public", flag.ExitOnError) + id := fs.String("id", "", "the id to set for the public key") + pk := fs.String("private-key", "", "the id of the private key to use for public key creation") + fs.Parse(args) + + pkName := pkiadm.ResourceName{ID: *pk, Type: pkiadm.RTPrivateKey} + if err := client.CreatePublicKey( + pkiadm.PublicKey{ID: *id, PrivateKey: pkName}, + ); err != nil { + return errors.Wrap(err, "Could not create public key") + } + return nil +} +func setPublicKey(args []string, client *pkiadm.Client) error { + fs := flag.NewFlagSet("pkiadm set-public", flag.ExitOnError) + id := fs.String("id", "", "the id of the public key to change") + pk := fs.String("private-key", "", "the id of the new private key to use for public key generation") + fs.Parse(args) + + if !fs.Lookup("private-key").Changed { + return nil + } + pkName := pkiadm.ResourceName{ID: *pk, Type: pkiadm.RTPrivateKey} + if err := client.SetPublicKey( + pkiadm.PublicKey{ID: *id, PrivateKey: pkName}, + []string{"private-key"}, + ); err != nil { + return errors.Wrap(err, "Could not change public key") + } + return nil +} +func deletePublicKey(args []string, client *pkiadm.Client) error { + fs := flag.NewFlagSet("pkiadm delete-public", flag.ExitOnError) + id := fs.String("id", "", "the id of the public key to delete") + fs.Parse(args) + + if err := client.DeletePublicKey(pkiadm.PublicKey{ID: *id}); err != nil { + return errors.Wrap(err, "Could not delete public key") + } + return nil +} +func listPublicKey(args []string, client *pkiadm.Client) error { + fs := flag.NewFlagSet("list-private", flag.ExitOnError) + fs.Parse(args) + + pubs, err := client.ListPublicKey() + if err != nil { + return err + } + + if len(pubs) == 0 { + return nil + } + out := tabwriter.NewWriter(os.Stdout, 2, 2, 1, ' ', tabwriter.AlignRight) + fmt.Fprintf(out, "%s\t%s\t%s\t\n", "id", "type", "private-key") + for _, pub := range pubs { + fmt.Fprintf(out, "%s\t%s\t%s\t\n", pub.ID, pub.Type.String(), pub.PrivateKey) + } + out.Flush() + + return nil +} +func showPublicKey(args []string, client *pkiadm.Client) error { + fs := flag.NewFlagSet("show-private", flag.ExitOnError) + var id = fs.String("id", "", "set the id of the private key to show") + fs.Parse(args) + + pub, err := client.ShowPublicKey(*id) + if err != nil { + return err + } + out := tabwriter.NewWriter(os.Stdout, 2, 2, 1, ' ', tabwriter.AlignRight) + fmt.Fprintf(out, "ID:\t%s\t\n", pub.ID) + fmt.Fprintf(out, "type:\t%s\t\n", pub.Type.String()) + fmt.Fprintf(out, "private:\t%s\t\n", pub.PrivateKey) + fmt.Fprintf(out, "checksum:\t%s\t\n", base64.StdEncoding.EncodeToString(pub.Checksum)) + out.Flush() + return nil +} diff --git a/cmd/pkiadmd/public_key.go b/cmd/pkiadmd/public_key.go index 2dc33cc..7700458 100644 --- a/cmd/pkiadmd/public_key.go +++ b/cmd/pkiadmd/public_key.go @@ -2,26 +2,19 @@ package main import ( "encoding/pem" + "fmt" "github.com/gibheer/pkiadm" ) -const ( - PUTRSA PublicKeyType = iota - PUTECDSA - PUTED25519 -) - type ( PublicKey struct { ID string PrivateKey pkiadm.ResourceName - Type PublicKeyType // mark the type of the public key + Type pkiadm.PrivateKeyType // mark the type of the public key Key []byte } - - PublicKeyType uint ) func NewPublicKey(id string, pk pkiadm.ResourceName) (*PublicKey, error) { @@ -37,14 +30,11 @@ func (p *PublicKey) Name() pkiadm.ResourceName { } func (p *PublicKey) Refresh(lookup *Storage) error { - r, err := lookup.Get(p.PrivateKey) + pk, err := lookup.GetPrivateKey(p.PrivateKey) if err != nil { return err } - pk, ok := r.(*PrivateKey) - if !ok { - return EUnknownType - } + p.Type = pk.PKType privateKey, err := pk.GetKey() if err != nil { return err @@ -71,9 +61,98 @@ func (p *PublicKey) Checksum() []byte { return Hash(p.Key) } -//func (p *PublicKey) MarshalJSON() ([]byte, error) { -// return json.Marshal(*p) -//} -//func (p *PublicKey) UnmarshalJSON(raw []byte) error { -// return json.Unmarshal(raw, p) -//} +func (s *Server) CreatePublicKey(inPub pkiadm.PublicKey, res *pkiadm.Result) error { + s.lock() + defer s.unlock() + + pub, err := NewPublicKey(inPub.ID, inPub.PrivateKey) + if err != nil { + res.SetError(err, "Could not create public key '%s'", inPub.ID) + return nil + } + if err := s.storage.AddPublicKey(pub); err != nil { + res.SetError(err, "Could not add new public key '%s'", inPub.ID) + return nil + } + return s.store(res) +} +func (s *Server) SetPublicKey(inPub pkiadm.PublicKeyChange, res *pkiadm.Result) error { + s.lock() + defer s.unlock() + + pub, err := s.storage.GetPublicKey(pkiadm.ResourceName{ + inPub.PublicKey.ID, + pkiadm.RTPublicKey, + }) + if err != nil { + res.SetError(err, "Could not find public key '%s'", inPub.PublicKey.ID) + return nil + } + for _, field := range inPub.FieldList { + switch field { + case "private-key": + pub.PrivateKey = pkiadm.ResourceName{ + inPub.PublicKey.ID, + pkiadm.RTPrivateKey, + } + default: + res.SetError(fmt.Errorf("unknown field"), "unknown field '%s'", field) + } + } + if err := s.storage.Update(pub.Name()); err != nil { + res.SetError(err, "Could not update new public key '%s'", inPub.PublicKey.ID) + return nil + } + return s.store(res) +} +func (s *Server) DeletePublicKey(inPub pkiadm.PublicKey, res *pkiadm.Result) error { + s.lock() + defer s.unlock() + + pub, err := s.storage.GetPublicKey(pkiadm.ResourceName{ + inPub.ID, + pkiadm.RTPublicKey, + }) + if err != nil { + res.SetError(err, "Could not find public key '%s'", inPub.ID) + return nil + } + if err := s.storage.Remove(pub); err != nil { + res.SetError(err, "Could not remove public key '%s'", inPub.ID) + return nil + } + return s.store(res) +} +func (s *Server) ShowPublicKey(inPub pkiadm.ResourceName, res *pkiadm.ResultPublicKey) error { + s.lock() + defer s.unlock() + + pub, err := s.storage.GetPublicKey(inPub) + if err != nil { + res.Result.SetError(err, "Could not find public key '%s'", inPub.ID) + return nil + } + res.PublicKeys = []pkiadm.PublicKey{ + pkiadm.PublicKey{ + ID: pub.ID, + PrivateKey: pub.PrivateKey, + Type: pub.Type, + Checksum: pub.Checksum(), + }, + } + return nil +} +func (s *Server) ListPublicKey(filter pkiadm.Filter, res *pkiadm.ResultPublicKey) error { + s.lock() + defer s.unlock() + + for _, pub := range s.storage.PublicKeys { + res.PublicKeys = append(res.PublicKeys, pkiadm.PublicKey{ + ID: pub.ID, + PrivateKey: pub.PrivateKey, + Type: pub.Type, + Checksum: pub.Checksum(), + }) + } + return nil +} diff --git a/cmd/pkiadmd/publickeytype_string.go b/cmd/pkiadmd/publickeytype_string.go deleted file mode 100644 index 891eebd..0000000 --- a/cmd/pkiadmd/publickeytype_string.go +++ /dev/null @@ -1,16 +0,0 @@ -// Code generated by "stringer -type PublicKeyType"; DO NOT EDIT - -package main - -import "fmt" - -const _PublicKeyType_name = "PUTRSAPUTECDSAPUTED25519" - -var _PublicKeyType_index = [...]uint8{0, 6, 14, 24} - -func (i PublicKeyType) String() string { - if i >= PublicKeyType(len(_PublicKeyType_index)-1) { - return fmt.Sprintf("PublicKeyType(%d)", i) - } - return _PublicKeyType_name[_PublicKeyType_index[i]:_PublicKeyType_index[i+1]] -} diff --git a/cmd/pkiadmd/resourcetype_string.go b/cmd/pkiadmd/resourcetype_string.go deleted file mode 100644 index 320a789..0000000 --- a/cmd/pkiadmd/resourcetype_string.go +++ /dev/null @@ -1,16 +0,0 @@ -// Code generated by "stringer -type ResourceType"; DO NOT EDIT - -package main - -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) { - return fmt.Sprintf("ResourceType(%d)", i) - } - return _ResourceType_name[_ResourceType_index[i]:_ResourceType_index[i+1]] -} diff --git a/public_key.go b/public_key.go new file mode 100644 index 0000000..cb6d7af --- /dev/null +++ b/public_key.go @@ -0,0 +1,62 @@ +package pkiadm + +type ( + PublicKey struct { + ID string + + PrivateKey ResourceName + // The following attributes are filled in by the server and ignored + // otherwise. + Type PrivateKeyType // mark the type of the public key + Checksum []byte + } + + PublicKeyChange struct { + FieldList []string + PublicKey PublicKey + } + + ResultPublicKey struct { + Result Result + PublicKeys []PublicKey + } +) + +func (c *Client) CreatePublicKey(pub PublicKey) error { + return c.exec("CreatePublicKey", pub) +} + +func (c *Client) SetPublicKey(pub PublicKey, fieldList []string) error { + changeset := PublicKeyChange{fieldList, pub} + return c.exec("SetPublicKey", changeset) +} + +func (c *Client) DeletePublicKey(pub PublicKey) error { + return c.exec("DeletePublicKey", pub) +} + +func (c *Client) ListPublicKey() ([]PublicKey, error) { + result := &ResultPublicKey{} + if err := c.query("ListPublicKey", Filter{}, result); err != nil { + return []PublicKey{}, err + } + if result.Result.HasError { + return []PublicKey{}, result.Result.Error + } + return result.PublicKeys, nil +} + +func (c *Client) ShowPublicKey(id string) (PublicKey, error) { + pk := ResourceName{ID: id, Type: RTPublicKey} + result := &ResultPublicKey{} + if err := c.query("ShowPublicKey", pk, result); err != nil { + return PublicKey{}, err + } + if result.Result.HasError { + return PublicKey{}, result.Result.Error + } + for _, publicKey := range result.PublicKeys { + return publicKey, nil + } + return PublicKey{}, nil +}