Skip to content

Commit

Permalink
feat: expose endpoint for CA certificate
Browse files Browse the repository at this point in the history
  • Loading branch information
streambinder committed Jul 15, 2022
1 parent 62b2ecd commit 624ff6d
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 19 deletions.
2 changes: 1 addition & 1 deletion cmd/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ var cmdGen = &cobra.Command{
log.Info().Str("public", fmt.Sprintf("%v", key.Public())).Msg("key generated")

log.Info().Msg("wrapping certificate")
crtBytes, keyBytes, err := pki.Wrap(crt, key, crt, key.Value)
crtBytes, keyBytes, err := pki.Wrap(crt, key, crt, key)
if err != nil {
log.Fatal().Err(err).Msg("unable to wrap certificate")
}
Expand Down
29 changes: 22 additions & 7 deletions pki/bundle.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package pki

import (
"crypto"
"crypto/rand"
"crypto/x509"
"encoding/pem"
Expand All @@ -10,20 +9,36 @@ import (
"strings"
)

func Wrap(crt *x509.Certificate, key *Key, ca *x509.Certificate, signer crypto.PrivateKey) (*pem.Block, *pem.Block, error) {
crtBytes, err := x509.CreateCertificate(rand.Reader, crt, ca, key.Public(), signer)
func WrapCrt(crt *x509.Certificate, key *Key, ca *x509.Certificate, signer *Key) (*pem.Block, error) {
bytes, err := x509.CreateCertificate(rand.Reader, crt, ca, key.Public(), signer.Value)
if err != nil {
return nil, err
}

return &pem.Block{Type: "CERTIFICATE", Bytes: bytes}, nil
}

func WrapKey(key *Key) (*pem.Block, error) {
bytes, err := x509.MarshalPKCS8PrivateKey(key.Value)
if err != nil {
return nil, err
}

return &pem.Block{Type: "PRIVATE KEY", Bytes: bytes}, nil
}

func Wrap(crt *x509.Certificate, key *Key, ca *x509.Certificate, signer *Key) (*pem.Block, *pem.Block, error) {
crtBlock, err := WrapCrt(crt, key, ca, signer)
if err != nil {
return nil, nil, err
}
crtBlock := pem.Block{Type: "CERTIFICATE", Bytes: crtBytes}

keyBytes, err := x509.MarshalPKCS8PrivateKey(key.Value)
keyBlock, err := WrapKey(key)
if err != nil {
return nil, nil, err
}
keyBlock := pem.Block{Type: "PRIVATE KEY", Bytes: keyBytes}

return &crtBlock, &keyBlock, nil
return crtBlock, keyBlock, nil
}

func Export(block *pem.Block, path string) (err error) {
Expand Down
4 changes: 2 additions & 2 deletions pki/crt.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func Parse(path string) (*x509.Certificate, error) {
return crt, nil
}

func ParseKeyPair(crtPath, keyPath string) (*x509.Certificate, *tls.Certificate, error) {
func ParseKeyPair(crtPath, keyPath string) (*x509.Certificate, *Key, error) {
tls, err := tls.LoadX509KeyPair(crtPath, keyPath)
if err != nil {
return nil, nil, err
Expand All @@ -51,7 +51,7 @@ func ParseKeyPair(crtPath, keyPath string) (*x509.Certificate, *tls.Certificate,
return nil, nil, err
}

return crt, &tls, nil
return crt, &Key{Value: tls.PrivateKey}, nil
}

func NewRequest(names ...string) Request {
Expand Down
19 changes: 16 additions & 3 deletions pki/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

type Key struct {
Value any
Algo int
}

const (
Expand All @@ -30,12 +31,24 @@ func ParseKey(path string) (*Key, error) {
}

block, _ := pem.Decode(data)
key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
keyData, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
key := Key{keyData, UnsupportedAlgorithm}

return &Key{key}, nil
switch keyData.(type) {
case *rsa.PrivateKey:
key.Algo = RSA
case *ecdsa.PrivateKey:
key.Algo = ECDSA
case ed25519.PrivateKey:
key.Algo = EDDSA
default:
key.Algo = UnsupportedAlgorithm
}

return &key, nil
}

func newKey(algo int) (*Key, error) {
Expand All @@ -57,7 +70,7 @@ func newKey(algo int) (*Key, error) {
if err != nil {
return nil, err
}
return &Key{key}, nil
return &Key{key, algo}, nil
}

func (key *Key) Public() any {
Expand Down
12 changes: 11 additions & 1 deletion provider/abstract.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ type Provider interface {
Tune(options ...string) error
For(name string) bool
Get(name string, options map[string]string) (*pem.Block, *pem.Block, error)
CA() (*pem.Block, error)
}

func Get(id string, options ...string) (*Provider, error) {
func Find(id string, options ...string) (*Provider, error) {
for _, provider := range []Provider{
new(Local),
} {
Expand All @@ -36,3 +37,12 @@ func GetFor(name string, options map[string]string, providers []*Provider) *Prov
}
return nil
}

func Get(id string, providers []*Provider) *Provider {
for _, p := range providers {
if (*p).ID() == id {
return p
}
}
return nil
}
11 changes: 7 additions & 4 deletions provider/local.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package provider

import (
"crypto/tls"
"crypto/x509"
"encoding/pem"
"fmt"
Expand All @@ -13,7 +12,7 @@ import (
type Local struct {
Provider
crt *x509.Certificate
tls *tls.Certificate
key *pki.Key
}

func (p Local) ID() string {
Expand All @@ -25,7 +24,7 @@ func (p *Local) Tune(options ...string) (err error) {
return fmt.Errorf("invalid number of options for provider %s: %s", p.ID(), options)
}

p.crt, p.tls, err = pki.ParseKeyPair(options[0], options[1])
p.crt, p.key, err = pki.ParseKeyPair(options[0], options[1])
return
}

Expand All @@ -44,5 +43,9 @@ func (p *Local) Get(name string, options map[string]string) (*pem.Block, *pem.Bl
return nil, nil, err
}

return pki.Wrap(crt, key, p.crt, p.tls.PrivateKey)
return pki.Wrap(crt, key, p.crt, p.key)
}

func (p *Local) CA() (*pem.Block, error) {
return pki.WrapCrt(p.crt, p.key, p.crt, p.key)
}
2 changes: 1 addition & 1 deletion server/config/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func Parse(path string) (*Config, error) {
}

for _, provPuppet := range cfg.Origins {
prov, err := provider.Get(provPuppet.Type, strings.Split(provPuppet.Options, " ")...)
prov, err := provider.Find(provPuppet.Type, strings.Split(provPuppet.Options, " ")...)
if err != nil {
return nil, err
}
Expand Down
14 changes: 14 additions & 0 deletions server/inca.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,20 @@ func Spinup(path string) (*Inca, error) {
log.Info().Str("fname", keyFname).Err(err).Msg("cached key not found")
return c.SendStatus(fiber.StatusNotFound)
})
inca.Get("/ca/:provider", func(c *fiber.Ctx) error {
p := provider.Get(c.Params("provider"), inca.Cfg.Providers)
if p == nil {
return c.SendStatus(fiber.StatusNotFound)
}

caCrt, err := (*p).CA()
if err != nil {
log.Error().Err(err).Msg("unable to retrieve CA certificate")
return c.SendStatus(fiber.StatusBadRequest)
}

return c.SendStream(bytes.NewReader(caCrt.Bytes), len(caCrt.Bytes))
})
inca.Get("/revoke/:name", func(c *fiber.Ctx) error {
return c.SendString(fmt.Sprintf("revoke %s", c.Params("name")))
})
Expand Down

0 comments on commit 624ff6d

Please sign in to comment.