add refresh
This adds the facilities to refresh resources automatically.
This commit is contained in:
parent
bc410d2d10
commit
89e7ac94f5
|
@ -88,9 +88,9 @@ func listCertificate(args []string, client *pkiadm.Client) error {
|
|||
return nil
|
||||
}
|
||||
out := tabwriter.NewWriter(os.Stdout, 2, 2, 1, ' ', tabwriter.AlignRight)
|
||||
fmt.Fprintf(out, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n", "id", "private", "csr", "ca", "serial", "created", "duration", "self-signed")
|
||||
fmt.Fprintf(out, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n", "id", "private", "csr", "ca", "serial", "created", "duration", "self-signed")
|
||||
for _, cert := range certs {
|
||||
fmt.Fprintf(out, "%s\t%s\t%s\t%s\t%s\t%s\t%t\t\n", cert.ID, cert.PrivateKey.ID, cert.CSR.ID, cert.CA.ID, cert.Serial.ID, cert.Created, cert.Duration, cert.IsCA)
|
||||
fmt.Fprintf(out, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%t\t\n", cert.ID, cert.PrivateKey.ID, cert.CSR.ID, cert.CA.ID, cert.Serial.ID, cert.Created, cert.Duration, cert.IsCA)
|
||||
}
|
||||
out.Flush()
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/gibheer/pkiadm"
|
||||
|
@ -185,6 +186,7 @@ func list(args []string, c *pkiadm.Client) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sort.Sort(resources)
|
||||
out := tabwriter.NewWriter(os.Stdout, 0, 4, 1, ' ', 0)
|
||||
fmt.Fprintf(out, "%s\t%s\t\n", "type", "id")
|
||||
for _, res := range resources {
|
||||
|
|
|
@ -22,6 +22,7 @@ type (
|
|||
ID string
|
||||
Type pkiadm.CAType
|
||||
Certificate pkiadm.ResourceName
|
||||
Interval Interval
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -87,12 +88,18 @@ func (ca *CA) Name() pkiadm.ResourceName {
|
|||
return pkiadm.ResourceName{ca.ID, pkiadm.RTCA}
|
||||
}
|
||||
|
||||
// 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. In this case, this is a NOOP.
|
||||
func (ca *CA) Refresh(*Storage) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RefreshInterval returns the dates and interval settings which are used to
|
||||
// decide when to trigger a refresh for the resource.
|
||||
// For CAs, this is a NOOP, as the underlying cert needs the refresh.
|
||||
func (ca *CA) RefreshInterval() Interval {
|
||||
return NoInterval
|
||||
}
|
||||
|
||||
// Return the PEM output of the contained resource.
|
||||
func (ca *CA) Pem() ([]byte, error) { return []byte{}, nil }
|
||||
func (ca *CA) Checksum() []byte { return []byte{} }
|
||||
|
|
|
@ -18,6 +18,8 @@ type (
|
|||
ID string
|
||||
|
||||
IsCA bool
|
||||
Interval Interval
|
||||
// TODO remove obsolete field - got replaced with interval
|
||||
Duration time.Duration
|
||||
Created time.Time
|
||||
|
||||
|
@ -31,6 +33,11 @@ type (
|
|||
)
|
||||
|
||||
func NewCertificate(id string, privateKey, serial, csr, ca pkiadm.ResourceName, selfSign bool, duration time.Duration) (*Certificate, error) {
|
||||
|
||||
if id == "" {
|
||||
return nil, ENoIDGiven
|
||||
}
|
||||
|
||||
return &Certificate{
|
||||
ID: id,
|
||||
PrivateKey: privateKey,
|
||||
|
@ -39,6 +46,10 @@ func NewCertificate(id string, privateKey, serial, csr, ca pkiadm.ResourceName,
|
|||
CA: ca,
|
||||
IsCA: selfSign,
|
||||
Duration: duration,
|
||||
Interval: Interval{
|
||||
Created: time.Now(),
|
||||
RefreshAfter: duration,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -86,10 +97,16 @@ func (c *Certificate) Refresh(lookup *Storage) error {
|
|||
return err
|
||||
}
|
||||
c.Data = pem.EncodeToMemory(&block)
|
||||
// TODO remove obsolete field
|
||||
c.Created = time.Now()
|
||||
c.Interval.LastRefresh = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Certificate) RefreshInterval() Interval {
|
||||
return c.Interval
|
||||
}
|
||||
|
||||
func (c *Certificate) GetCertificate() (*pki.Certificate, error) {
|
||||
// TODO fix this, we must check if there is anything else
|
||||
block, _ := pem.Decode(c.Data)
|
||||
|
@ -156,6 +173,7 @@ func (s *Server) SetCertificate(changeset pkiadm.CertificateChange, res *pkiadm.
|
|||
switch field {
|
||||
case "duration":
|
||||
cert.Duration = change.Duration
|
||||
cert.Interval.RefreshAfter = change.Duration
|
||||
case "private":
|
||||
cert.PrivateKey = change.PrivateKey
|
||||
case "csr":
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/pem"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/gibheer/pki"
|
||||
"github.com/gibheer/pkiadm"
|
||||
|
@ -14,6 +15,9 @@ type (
|
|||
// ID is the unique identifier of the CSR.
|
||||
ID string
|
||||
|
||||
// Interval represents the refresh timing information.
|
||||
Interval Interval
|
||||
|
||||
// The following options are used to generate the content of the CSR.
|
||||
DNSNames []string
|
||||
EmailAddresses []string
|
||||
|
@ -30,7 +34,8 @@ type (
|
|||
|
||||
// NewCSR creates a new CSR.
|
||||
func NewCSR(id string, pk, subject pkiadm.ResourceName, dnsNames []string,
|
||||
emailAddresses []string, iPAddresses []net.IP) (*CSR, error) {
|
||||
emailAddresses []string, iPAddresses []net.IP, refreshAfter time.Duration,
|
||||
invalidAfter time.Duration) (*CSR, error) {
|
||||
return &CSR{
|
||||
ID: id,
|
||||
Subject: subject,
|
||||
|
@ -38,6 +43,11 @@ func NewCSR(id string, pk, subject pkiadm.ResourceName, dnsNames []string,
|
|||
EmailAddresses: emailAddresses,
|
||||
IPAddresses: iPAddresses,
|
||||
PrivateKey: pk,
|
||||
Interval: Interval{
|
||||
Created: time.Now(),
|
||||
RefreshAfter: refreshAfter,
|
||||
InvalidAfter: invalidAfter,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -78,9 +88,14 @@ func (c *CSR) Refresh(lookup *Storage) error {
|
|||
return err
|
||||
}
|
||||
c.Data = pem.EncodeToMemory(&block)
|
||||
c.Interval.LastRefresh = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CSR) RefreshInterval() Interval {
|
||||
return c.Interval
|
||||
}
|
||||
|
||||
// Return the PEM output of the contained resource.
|
||||
func (c *CSR) Pem() ([]byte, error) { return c.Data, nil }
|
||||
func (c *CSR) Checksum() []byte { return Hash(c.Data) }
|
||||
|
@ -111,6 +126,7 @@ func (s *Server) CreateCSR(inCSR pkiadm.CSR, res *pkiadm.Result) error {
|
|||
inCSR.DNSNames,
|
||||
inCSR.EmailAddresses,
|
||||
inCSR.IPAddresses,
|
||||
0, 0,
|
||||
)
|
||||
if err != nil {
|
||||
res.SetError(err, "Could not create new private key '%s'", inCSR.ID)
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"github.com/gibheer/pkiadm"
|
||||
)
|
||||
|
@ -23,10 +24,13 @@ type (
|
|||
|
||||
Path string
|
||||
Dependencies []pkiadm.ResourceName
|
||||
|
||||
Interval Interval
|
||||
}
|
||||
)
|
||||
|
||||
func NewLocation(id, path, preCom, postCom string, res []pkiadm.ResourceName) (*Location, error) {
|
||||
func NewLocation(id, path, preCom, postCom string, res []pkiadm.ResourceName,
|
||||
interval Interval) (*Location, error) {
|
||||
if id == "" {
|
||||
return nil, ENoIDGiven
|
||||
}
|
||||
|
@ -37,6 +41,7 @@ func NewLocation(id, path, preCom, postCom string, res []pkiadm.ResourceName) (*
|
|||
ID: id,
|
||||
Path: path,
|
||||
Dependencies: res,
|
||||
Interval: interval,
|
||||
}
|
||||
return l, nil
|
||||
}
|
||||
|
@ -78,9 +83,14 @@ func (l *Location) Refresh(lookup *Storage) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
l.Interval.LastRefresh = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Location) RefreshInterval() Interval {
|
||||
return l.Interval
|
||||
}
|
||||
|
||||
func (l *Location) DependsOn() []pkiadm.ResourceName { return l.Dependencies }
|
||||
|
||||
// Pem is not used by location, as it does not contain any data.
|
||||
|
@ -97,7 +107,7 @@ func (s *Server) CreateLocation(inLoc pkiadm.Location, res *pkiadm.Result) error
|
|||
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)
|
||||
loc, err := NewLocation(inLoc.ID, inLoc.Path, inLoc.PreCommand, inLoc.PostCommand, deps, NoInterval)
|
||||
if err != nil {
|
||||
res.SetError(err, "Could not create location '%s'", inLoc.ID)
|
||||
return nil
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"net/rpc"
|
||||
"os"
|
||||
"os/signal"
|
||||
"time"
|
||||
|
||||
"github.com/gibheer/pkiadm"
|
||||
)
|
||||
|
@ -19,20 +20,42 @@ const (
|
|||
EAlreadyExist = Error("resource already exists")
|
||||
)
|
||||
|
||||
var (
|
||||
NoInterval = Interval{}
|
||||
)
|
||||
|
||||
type (
|
||||
Resource interface {
|
||||
// Return the unique 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
|
||||
// RefreshInterval returns the dates and interval settings which are used to
|
||||
// decide when to trigger a refresh for the resource.
|
||||
RefreshInterval() Interval
|
||||
// Return the PEM output of the contained resource.
|
||||
Pem() ([]byte, error)
|
||||
// Return the checksum of the PEM content.
|
||||
Checksum() []byte
|
||||
// DependsOn must return the resource names it is depending on.
|
||||
DependsOn() []pkiadm.ResourceName
|
||||
}
|
||||
|
||||
Interval struct {
|
||||
// Created states the time, the resource was created.
|
||||
Created time.Time
|
||||
// LastRefresh is the time, when the resource was last refreshed.
|
||||
LastRefresh time.Time
|
||||
// RefreshAfter is the duration after which the refresh of the resource
|
||||
// is triggered.
|
||||
RefreshAfter time.Duration
|
||||
// InvalidAfter is the duration after which this resource becomes invalid.
|
||||
// The decision when a resource becomes invalid is based on the created time
|
||||
// and the duration. When the refresh duration is less than the invalid
|
||||
// duration, then the resource will never be invalid.
|
||||
InvalidAfter time.Duration
|
||||
}
|
||||
|
||||
Error string
|
||||
)
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"crypto/elliptic"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/gibheer/pki"
|
||||
"github.com/gibheer/pkiadm"
|
||||
|
@ -17,14 +18,15 @@ const (
|
|||
|
||||
type (
|
||||
PrivateKey struct {
|
||||
ID string
|
||||
PKType pkiadm.PrivateKeyType
|
||||
Bits uint
|
||||
Key []byte
|
||||
ID string
|
||||
PKType pkiadm.PrivateKeyType
|
||||
Bits uint
|
||||
Key []byte
|
||||
Interval Interval
|
||||
}
|
||||
)
|
||||
|
||||
func NewPrivateKey(id string, pkType pkiadm.PrivateKeyType, bits uint) (*PrivateKey, error) {
|
||||
func NewPrivateKey(id string, pkType pkiadm.PrivateKeyType, bits uint, interval Interval) (*PrivateKey, error) {
|
||||
if id == "" {
|
||||
return nil, ENoIDGiven
|
||||
}
|
||||
|
@ -32,9 +34,10 @@ func NewPrivateKey(id string, pkType pkiadm.PrivateKeyType, bits uint) (*Private
|
|||
return nil, err
|
||||
}
|
||||
pk := PrivateKey{
|
||||
ID: id,
|
||||
PKType: pkType,
|
||||
Bits: bits,
|
||||
ID: id,
|
||||
PKType: pkType,
|
||||
Bits: bits,
|
||||
Interval: interval,
|
||||
}
|
||||
return &pk, nil
|
||||
}
|
||||
|
@ -88,9 +91,16 @@ func (p *PrivateKey) Refresh(_ *Storage) error {
|
|||
return err
|
||||
}
|
||||
p.Key = pem.EncodeToMemory(&block)
|
||||
p.Interval.LastRefresh = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
// RefreshInterval returns the dates and interval settings which are used to
|
||||
// decide when to trigger a refresh for the resource.
|
||||
func (p *PrivateKey) RefreshInterval() Interval {
|
||||
return p.Interval
|
||||
}
|
||||
|
||||
func (p *PrivateKey) GetKey() (pki.PrivateKey, error) {
|
||||
var (
|
||||
err error
|
||||
|
@ -139,7 +149,7 @@ func (s *Server) CreatePrivateKey(inPk pkiadm.PrivateKey, res *pkiadm.Result) er
|
|||
s.lock()
|
||||
defer s.unlock()
|
||||
|
||||
pk, err := NewPrivateKey(inPk.ID, inPk.Type, inPk.Bits)
|
||||
pk, err := NewPrivateKey(inPk.ID, inPk.Type, inPk.Bits, NoInterval)
|
||||
if err != nil {
|
||||
res.SetError(err, "Could not create new private key '%s'", inPk.ID)
|
||||
return nil
|
||||
|
|
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/gibheer/pkiadm"
|
||||
)
|
||||
|
@ -14,13 +15,21 @@ type (
|
|||
PrivateKey pkiadm.ResourceName
|
||||
Type pkiadm.PrivateKeyType // mark the type of the public key
|
||||
Key []byte
|
||||
|
||||
Interval Interval
|
||||
}
|
||||
)
|
||||
|
||||
func NewPublicKey(id string, pk pkiadm.ResourceName) (*PublicKey, error) {
|
||||
func NewPublicKey(id string, pk pkiadm.ResourceName, refreshAfter time.Duration,
|
||||
invalidAfter time.Duration) (*PublicKey, error) {
|
||||
pub := PublicKey{
|
||||
ID: id,
|
||||
PrivateKey: pk,
|
||||
Interval: Interval{
|
||||
Created: time.Now(),
|
||||
RefreshAfter: refreshAfter,
|
||||
InvalidAfter: invalidAfter,
|
||||
},
|
||||
}
|
||||
return &pub, nil
|
||||
}
|
||||
|
@ -45,9 +54,14 @@ func (p *PublicKey) Refresh(lookup *Storage) error {
|
|||
return err
|
||||
}
|
||||
p.Key = pem.EncodeToMemory(&block)
|
||||
p.Interval.LastRefresh = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PublicKey) RefreshInterval() Interval {
|
||||
return p.Interval
|
||||
}
|
||||
|
||||
func (p *PublicKey) DependsOn() []pkiadm.ResourceName {
|
||||
return []pkiadm.ResourceName{p.PrivateKey}
|
||||
}
|
||||
|
@ -64,7 +78,7 @@ func (s *Server) CreatePublicKey(inPub pkiadm.PublicKey, res *pkiadm.Result) err
|
|||
s.lock()
|
||||
defer s.unlock()
|
||||
|
||||
pub, err := NewPublicKey(inPub.ID, inPub.PrivateKey)
|
||||
pub, err := NewPublicKey(inPub.ID, inPub.PrivateKey, 0, 0)
|
||||
if err != nil {
|
||||
res.SetError(err, "Could not create public key '%s'", inPub.ID)
|
||||
return nil
|
||||
|
|
|
@ -33,7 +33,6 @@ func NewSerial(id string, min, max int64) (*Serial, error) {
|
|||
// Return the unique ResourceName
|
||||
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.
|
||||
func (s *Serial) Refresh(*Storage) error {
|
||||
// This is a NOOP, because there is nothing to refresh. Depending resources
|
||||
|
@ -41,6 +40,11 @@ func (s *Serial) Refresh(*Storage) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// RefreshInterval is a NOOP here, as serials can't be refreshed.
|
||||
func (s *Serial) RefreshInterval() Interval {
|
||||
return NoInterval
|
||||
}
|
||||
|
||||
// Return the PEM output of the contained resource.
|
||||
func (s *Serial) Pem() ([]byte, error) { return []byte{}, nil }
|
||||
func (s *Serial) Checksum() []byte { return []byte{} }
|
||||
|
|
|
@ -33,26 +33,10 @@ func (s *Server) store(res *pkiadm.Result) error {
|
|||
}
|
||||
|
||||
func (s *Server) List(filter pkiadm.Filter, result *pkiadm.ResultResource) error {
|
||||
for _, res := range s.storage.PrivateKeys {
|
||||
result.Resources = append(result.Resources, res.Name())
|
||||
}
|
||||
for _, res := range s.storage.PublicKeys {
|
||||
result.Resources = append(result.Resources, res.Name())
|
||||
}
|
||||
for _, res := range s.storage.Locations {
|
||||
result.Resources = append(result.Resources, res.Name())
|
||||
}
|
||||
for _, res := range s.storage.Certificates {
|
||||
result.Resources = append(result.Resources, res.Name())
|
||||
}
|
||||
for _, res := range s.storage.CSRs {
|
||||
result.Resources = append(result.Resources, res.Name())
|
||||
}
|
||||
for _, res := range s.storage.Serials {
|
||||
result.Resources = append(result.Resources, res.Name())
|
||||
}
|
||||
for _, res := range s.storage.Subjects {
|
||||
result.Resources = append(result.Resources, res.Name())
|
||||
resources := s.storage.List()
|
||||
result.Resources = make([]pkiadm.ResourceName, len(resources))
|
||||
for i, res := range resources {
|
||||
result.Resources[i] = res.Name()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import (
|
|||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/gibheer/pkiadm"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -28,6 +30,19 @@ type (
|
|||
// dependencies maps from a resource name to all resources which depend
|
||||
// on it.
|
||||
dependencies map[string]map[string]Resource
|
||||
// refresh order contains all resources in the order they need to be
|
||||
// refreshed next.
|
||||
refreshOrder RefreshList
|
||||
refreshTimer *time.Timer
|
||||
}
|
||||
|
||||
// RefreshList is a list of resources
|
||||
RefreshList []RefreshSet
|
||||
// RefreshSet contains the vital information to decide, when to refresh
|
||||
// the specified resource.
|
||||
RefreshSet struct {
|
||||
Name pkiadm.ResourceName
|
||||
Interval Interval
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -68,6 +83,7 @@ func (s *Storage) load() error {
|
|||
if err := s.refreshDependencies(); err != nil {
|
||||
return err
|
||||
}
|
||||
s.scanForRefresh()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -101,6 +117,69 @@ func (s *Storage) refreshDependencies() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// scanForRefresh updates the list of resources that need an update.
|
||||
func (s *Storage) scanForRefresh() {
|
||||
if s.refreshTimer != nil {
|
||||
s.refreshTimer.Stop()
|
||||
}
|
||||
refList := RefreshList{}
|
||||
for _, res := range s.PrivateKeys {
|
||||
refList.Add(res)
|
||||
}
|
||||
for _, res := range s.PublicKeys {
|
||||
refList.Add(res)
|
||||
}
|
||||
for _, res := range s.CSRs {
|
||||
refList.Add(res)
|
||||
}
|
||||
for _, res := range s.Certificates {
|
||||
refList.Add(res)
|
||||
}
|
||||
for _, res := range s.Locations {
|
||||
refList.Add(res)
|
||||
}
|
||||
sort.Sort(refList)
|
||||
if len(refList) == 0 {
|
||||
log.Println("nothing found to refresh, looking again in 24h")
|
||||
s.refreshTimer = time.AfterFunc(24*time.Hour, s.scanForRefresh)
|
||||
return
|
||||
}
|
||||
s.refreshOrder = refList
|
||||
duration := refList[0].Interval.LastRefresh.
|
||||
Add(refList[0].Interval.RefreshAfter).
|
||||
Sub(time.Now())
|
||||
if duration <= 5*time.Second {
|
||||
duration = 5 * time.Second
|
||||
}
|
||||
log.Printf("next refresh planned for '%s' in %s", refList[0].Name, duration)
|
||||
s.refreshTimer = time.AfterFunc(
|
||||
duration,
|
||||
s.refresh,
|
||||
)
|
||||
}
|
||||
|
||||
func (s *Storage) refresh() {
|
||||
if len(s.refreshOrder) == 0 {
|
||||
return
|
||||
}
|
||||
resName := s.refreshOrder[0].Name
|
||||
res, err := s.Get(resName)
|
||||
if err != nil {
|
||||
// the resource doesn't exist anymore, so just rescan
|
||||
log.Printf("resource to refresh has gone away: %s", resName)
|
||||
goto rescan
|
||||
}
|
||||
if err := res.Refresh(s); err != nil {
|
||||
log.Printf("error refreshing resource '%s': %s", res.Name(), err)
|
||||
}
|
||||
if err := s.store(); err != nil {
|
||||
log.Printf("could not update resources: %s", err)
|
||||
}
|
||||
rescan:
|
||||
log.Printf("rescanning for new entries")
|
||||
s.scanForRefresh()
|
||||
}
|
||||
|
||||
// addDependency adds a resource to the dependency graph.
|
||||
func (s *Storage) addDependency(r Resource) error {
|
||||
for _, rn := range r.DependsOn() {
|
||||
|
@ -138,6 +217,7 @@ func (s *Storage) AddSerial(se *Serial) error {
|
|||
return err
|
||||
}
|
||||
s.Serials[se.Name().ID] = se
|
||||
s.scanForRefresh()
|
||||
return s.addDependency(se)
|
||||
}
|
||||
|
||||
|
@ -150,6 +230,7 @@ func (s *Storage) AddSubject(se *Subject) error {
|
|||
return err
|
||||
}
|
||||
s.Subjects[se.Name().ID] = se
|
||||
s.scanForRefresh()
|
||||
return s.addDependency(se)
|
||||
}
|
||||
|
||||
|
@ -159,6 +240,7 @@ func (s *Storage) AddPrivateKey(pk *PrivateKey) error {
|
|||
return err
|
||||
}
|
||||
s.PrivateKeys[pk.Name().ID] = pk
|
||||
s.scanForRefresh()
|
||||
return s.addDependency(pk)
|
||||
}
|
||||
|
||||
|
@ -168,6 +250,7 @@ func (s *Storage) AddPublicKey(pub *PublicKey) error {
|
|||
return err
|
||||
}
|
||||
s.PublicKeys[pub.Name().ID] = pub
|
||||
s.scanForRefresh()
|
||||
return s.addDependency(pub)
|
||||
}
|
||||
|
||||
|
@ -177,6 +260,7 @@ func (s *Storage) AddCertificate(cert *Certificate) error {
|
|||
return err
|
||||
}
|
||||
s.Certificates[cert.Name().ID] = cert
|
||||
s.scanForRefresh()
|
||||
return s.addDependency(cert)
|
||||
}
|
||||
|
||||
|
@ -186,6 +270,7 @@ func (s *Storage) AddCSR(csr *CSR) error {
|
|||
return err
|
||||
}
|
||||
s.CSRs[csr.Name().ID] = csr
|
||||
s.scanForRefresh()
|
||||
return s.addDependency(csr)
|
||||
}
|
||||
|
||||
|
@ -195,6 +280,7 @@ func (s *Storage) AddLocation(l *Location) error {
|
|||
return err
|
||||
}
|
||||
s.Locations[l.Name().ID] = l
|
||||
s.scanForRefresh()
|
||||
return s.addDependency(l)
|
||||
}
|
||||
|
||||
|
@ -203,6 +289,7 @@ func (s *Storage) AddCA(ca *CA) error {
|
|||
return err
|
||||
}
|
||||
s.CAs[ca.Name().ID] = ca
|
||||
s.scanForRefresh()
|
||||
return s.addDependency(ca)
|
||||
}
|
||||
|
||||
|
@ -326,6 +413,7 @@ func (s *Storage) Remove(r Resource) error {
|
|||
delete(deps, r.Name().String())
|
||||
}
|
||||
}
|
||||
s.scanForRefresh()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -364,5 +452,65 @@ func (s *Storage) Update(rn pkiadm.ResourceName) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
s.scanForRefresh()
|
||||
return nil
|
||||
}
|
||||
|
||||
// List returns all currently registered resources.
|
||||
func (s *Storage) List() []Resource {
|
||||
resources := []Resource{}
|
||||
for _, res := range s.PrivateKeys {
|
||||
resources = append(resources, res)
|
||||
}
|
||||
for _, res := range s.PublicKeys {
|
||||
resources = append(resources, res)
|
||||
}
|
||||
for _, res := range s.Locations {
|
||||
resources = append(resources, res)
|
||||
}
|
||||
for _, res := range s.Certificates {
|
||||
resources = append(resources, res)
|
||||
}
|
||||
for _, res := range s.CSRs {
|
||||
resources = append(resources, res)
|
||||
}
|
||||
for _, res := range s.Serials {
|
||||
resources = append(resources, res)
|
||||
}
|
||||
for _, res := range s.Subjects {
|
||||
resources = append(resources, res)
|
||||
}
|
||||
return resources
|
||||
}
|
||||
|
||||
// Add adds a resource to the refreshList when it should be refreshed.
|
||||
func (refList *RefreshList) Add(res Resource) {
|
||||
refSet := RefreshSet{
|
||||
Name: res.Name(),
|
||||
Interval: res.RefreshInterval(),
|
||||
}
|
||||
if refSet.Interval.RefreshAfter <= 0 {
|
||||
return
|
||||
}
|
||||
newRefList := append(*refList, refSet)
|
||||
*refList = newRefList
|
||||
}
|
||||
|
||||
// Len is the number of elements in the collection.
|
||||
func (refList RefreshList) Len() int { return len(refList) }
|
||||
|
||||
// Less reports whether the element with
|
||||
// index i should sort before the element with index j.
|
||||
func (refList RefreshList) Less(i, j int) bool {
|
||||
return 0 > refList[i].Interval.LastRefresh.Add(
|
||||
refList[i].Interval.RefreshAfter,
|
||||
).Sub(
|
||||
refList[j].Interval.LastRefresh.Add(
|
||||
refList[j].Interval.RefreshAfter),
|
||||
)
|
||||
}
|
||||
|
||||
// Swap swaps the elements with indexes i and j.
|
||||
func (refList RefreshList) Swap(i, j int) {
|
||||
refList[i], refList[j] = refList[j], refList[i]
|
||||
}
|
||||
|
|
|
@ -3,14 +3,16 @@ package main
|
|||
import (
|
||||
"crypto/x509/pkix"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/gibheer/pkiadm"
|
||||
)
|
||||
|
||||
type (
|
||||
Subject struct {
|
||||
ID string
|
||||
Data pkix.Name
|
||||
ID string
|
||||
Data pkix.Name
|
||||
Created time.Time
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -26,11 +28,14 @@ func NewSubject(id string, name pkix.Name) (*Subject, error) {
|
|||
// Return the unique ResourceName
|
||||
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.
|
||||
// This is a NOOP as it does not have any dependencies.
|
||||
func (sub *Subject) Refresh(_ *Storage) error { return nil }
|
||||
|
||||
// RefreshInterval returns the dates and interval settings which are used to
|
||||
// decide when to trigger a refresh for the resource.
|
||||
func (sub *Subject) RefreshInterval() Interval { return Interval{Created: sub.Created} }
|
||||
|
||||
// Return the PEM output of the contained resource.
|
||||
func (sub *Subject) Pem() ([]byte, error) { return []byte{}, nil }
|
||||
func (sub *Subject) Checksum() []byte { return []byte{} }
|
||||
|
|
17
transport.go
17
transport.go
|
@ -49,6 +49,21 @@ type ResourceType uint
|
|||
|
||||
func (r ResourceName) String() string { return r.Type.String() + "/" + r.ID }
|
||||
|
||||
type ResourceNameList []ResourceName
|
||||
|
||||
func (r ResourceNameList) Len() int {
|
||||
return len(r)
|
||||
}
|
||||
func (r ResourceNameList) Less(i, j int) bool {
|
||||
if r[i].Type != r[j].Type {
|
||||
return r[i].Type < r[j].Type
|
||||
}
|
||||
return r[i].ID < r[j].ID
|
||||
}
|
||||
func (r ResourceNameList) Swap(i, j int) {
|
||||
r[i], r[j] = r[j], r[i]
|
||||
}
|
||||
|
||||
type Filter struct{}
|
||||
|
||||
type ResultResource struct {
|
||||
|
@ -56,7 +71,7 @@ type ResultResource struct {
|
|||
Resources []ResourceName
|
||||
}
|
||||
|
||||
func (c *Client) List() ([]ResourceName, error) {
|
||||
func (c *Client) List() (ResourceNameList, error) {
|
||||
result := ResultResource{}
|
||||
if err := c.query("List", Filter{}, &result); err != nil {
|
||||
return []ResourceName{}, err
|
||||
|
|
Loading…
Reference in New Issue