aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2016-03-09 23:06:31 +0100
committerDimitri Sokolyuk <demon@dim13.org>2016-03-09 23:06:31 +0100
commitb4dd257d920efbae2ab1f400c08b49982593881a (patch)
treeeed16c14ecd9be30248ab1b261813bcabfeb74f8
parentc12834eb15a69bb8c9f676998029f8a338c6b294 (diff)
Split stages
-rw-r--r--cmd/acme/config.go20
-rw-r--r--cmd/acme/main.go206
-rw-r--r--desire.go4
-rw-r--r--solve_dns.go2
-rw-r--r--solve_http.go3
-rw-r--r--solve_pop.go2
-rw-r--r--solve_tls.go3
-rw-r--r--solver.go5
8 files changed, 136 insertions, 109 deletions
diff --git a/cmd/acme/config.go b/cmd/acme/config.go
index ebdcb76..6a0dc4b 100644
--- a/cmd/acme/config.go
+++ b/cmd/acme/config.go
@@ -46,12 +46,13 @@ type account struct {
}
type domain struct {
- Altnames []string
- KeySize int
- KeyFile string
- CrtFile string
- Webroot string
- Hook []string
+ Gracetime time.Duration
+ Altnames []string
+ KeySize int
+ KeyFile string
+ CrtFile string
+ Webroot string
+ Hook []string
}
var (
@@ -115,6 +116,9 @@ func LoadConfig(fname string) (*Config, error) {
}
pro.Account[i] = acc
for i, dom := range acc.Domain {
+ if dom.Gracetime != 0 {
+ dom.Gracetime = c.Gracetime
+ }
if dom.KeySize == 0 {
dom.KeySize = c.KeySize
}
@@ -167,6 +171,6 @@ func checkWWW(altnames []string) []string {
return altnames
}
-func (c Config) renew(cert *x509.Certificate) bool {
- return time.Now().Add(c.Gracetime).After(cert.NotAfter)
+func (d domain) renew(cert *x509.Certificate) bool {
+ return time.Now().Add(d.Gracetime).After(cert.NotAfter)
}
diff --git a/cmd/acme/main.go b/cmd/acme/main.go
index e994189..577afbf 100644
--- a/cmd/acme/main.go
+++ b/cmd/acme/main.go
@@ -9,117 +9,129 @@ import (
)
var (
- confName = flag.String("conf", "", "configuration file")
- forceRenew = flag.Bool("force", false, "force renew")
+ confName = flag.String("conf", "", "configuration file")
+ forceRenew = flag.Bool("force", false, "force renew")
+ httpSol, tlsSol acme.Solver
)
-func main() {
- flag.Parse()
-
- conf, err := LoadConfig(*confName)
+func dialProvider(p provider) error {
+ log.Println("Dial", p.Directory)
+ prov, err := acme.DialProvider(p.Directory)
if err != nil {
- log.Fatal(err)
+ return err
+ }
+ for _, a := range p.Account {
+ if err := loadAccount(prov, a); err != nil {
+ return err
+ }
}
+ return nil
+}
- var httpSol, tlsSol acme.Solver
- if conf.Listen != "" {
- httpSol, err = acme.NewHTTPSolver(conf.Listen)
+func loadAccount(prov *acme.Provider, a account) error {
+ var mustRegister bool
+ key, err := a.Load()
+ if err != nil {
+ key, err = acme.NewKey(a.KeySize)
if err != nil {
- log.Println(err)
+ return err
}
+ if err := a.Save(key); err != nil {
+ return err
+ }
+ mustRegister = true
}
- if conf.ListenTLS != "" {
- tlsSol, err = acme.NewTLSSolver(conf.ListenTLS)
+
+ acc, err := acme.NewAccount(key)
+ if err != nil {
+ return err
+ }
+
+ if mustRegister {
+ con, err := acme.NewContacts(a.Mail, a.Phone)
if err != nil {
- log.Println(err)
+ return err
+ }
+
+ log.Println("Register", con)
+ if err := prov.Register(acc, con); err != nil {
+ return err
}
}
- for _, v := range conf.Provider {
- log.Println("Dial", v.Directory)
- prov, err := acme.DialProvider(v.Directory)
- if err != nil {
- log.Fatal(err)
+ for _, d := range a.Domain {
+ if err := requestCert(prov, acc, d); err != nil {
+ return err
}
+ }
+ return nil
+}
+
+func requestCert(prov *acme.Provider, acc *acme.Account, d domain) error {
+ c, err := d.Load()
+ if err != nil {
+ return err
+ }
+ if c.Leaf != nil && !d.renew(c.Leaf) && !*forceRenew {
+ log.Println("valid until", c.Leaf.NotAfter, "skip")
+ return nil
+ }
+
+ key, err := acme.NewKey(d.KeySize)
+ if err != nil {
+ return err
+ }
- for _, v := range v.Account {
- var mustRegister bool
-
- log.Println("Load", v.KeyFile)
- key, err := v.Load()
- if err != nil {
- key, err = acme.NewKey(v.KeySize)
- if err != nil {
- log.Fatal(err)
- }
- if err := v.Save(key); err != nil {
- log.Fatal(err)
- }
- mustRegister = true
- }
-
- acc, err := acme.NewAccount(key)
- if err != nil {
- log.Fatal(err)
- }
-
- if mustRegister {
- con, err := acme.NewContacts(v.Mail, v.Phone)
- if err != nil {
- log.Fatal(err)
- }
-
- log.Println("Register", con)
- err = prov.Register(acc, con)
- if err != nil {
- log.Fatal(err)
- }
- }
-
- for _, v := range v.Domain {
- c, err := v.Load()
- if err != nil {
- log.Println(err)
- }
- if c.Leaf != nil && !conf.renew(c.Leaf) && !*forceRenew {
- log.Println("valid until", c.Leaf.NotAfter, "sipping")
- continue
- }
-
- key, err := acme.NewKey(v.KeySize)
- if err != nil {
- log.Fatal(err)
- }
- des := acme.NewDesire(key, v.Altnames)
- if v.Webroot != "" {
- sol := acme.NewWebrootSolver(v.Webroot)
- des.RegisterSolver(sol)
- } else if httpSol != nil {
- des.RegisterSolver(httpSol)
- }
- if tlsSol != nil {
- des.RegisterSolver(tlsSol)
- }
- if !des.HasSolver() {
- log.Fatal("no solver")
- }
-
- log.Println("Authorize", v.Altnames)
- if err := prov.Authorize(acc, des); err != nil {
- log.Fatal(err)
- }
-
- log.Println("Request bundle for", v.Altnames)
- cert, err := prov.Bundle(acc, des)
- if err != nil {
- log.Fatal(err)
- }
-
- log.Println("Save", v.CrtFile, v.KeyFile)
- if err := v.Save(cert); err != nil {
- log.Fatal(err)
- }
- }
+ des := acme.NewDesire(key, d.Altnames)
+ if d.Webroot != "" {
+ des.RegisterSolver(acme.NewWebrootSolver(d.Webroot))
+ } else if httpSol != nil {
+ des.RegisterSolver(httpSol)
+ }
+
+ if tlsSol != nil {
+ des.RegisterSolver(tlsSol)
+ }
+
+ log.Println("Authorize", d.Altnames)
+ if err := prov.Authorize(acc, des); err != nil {
+ return err
+ }
+
+ log.Println("Request bundle")
+ cert, err := prov.Bundle(acc, des)
+ if err != nil {
+ return err
+ }
+
+ log.Println("Save", d.CrtFile, d.KeyFile)
+ if err := d.Save(cert); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func main() {
+ flag.Parse()
+
+ conf, err := LoadConfig(*confName)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ httpSol, err = acme.NewHTTPSolver(conf.Listen)
+ if err != nil {
+ log.Println("HTTP Solver", err)
+ }
+ tlsSol, err = acme.NewTLSSolver(conf.ListenTLS)
+ if err != nil {
+ log.Println("TLS Solver", err)
+ }
+
+ for _, p := range conf.Provider {
+ if err := dialProvider(p); err != nil {
+ log.Fatal(err)
}
}
}
diff --git a/desire.go b/desire.go
index 1d99433..670aca6 100644
--- a/desire.go
+++ b/desire.go
@@ -17,7 +17,9 @@ func NewDesire(key crypto.PrivateKey, altnames []string) *Desire {
}
func (d *Desire) RegisterSolver(s Solver) {
- d.solver[s.Type()] = s
+ if s != nil {
+ d.solver[s.Type()] = s
+ }
}
func (d *Desire) HasSolver() bool {
diff --git a/solve_dns.go b/solve_dns.go
index 805ed45..a71398b 100644
--- a/solve_dns.go
+++ b/solve_dns.go
@@ -6,6 +6,6 @@ func NewDNSSolver() Solver {
return &dnsSolver{}
}
-func (dnsSolver) Solve(_ Challenge) error { return errNotImplemented }
+func (dnsSolver) Solve(_ Challenge) error { return ErrNotImplemented }
func (dnsSolver) Solved() error { return nil }
func (dnsSolver) Type() ChalType { return ChallengeDNS }
diff --git a/solve_http.go b/solve_http.go
index f0923a5..2b9a4a6 100644
--- a/solve_http.go
+++ b/solve_http.go
@@ -14,6 +14,9 @@ type httpSolver struct {
}
func NewHTTPSolver(addr string) (Solver, error) {
+ if addr == "" {
+ return nil, ErrSkipped
+ }
return &httpSolver{Server: http.Server{Addr: addr}}, nil
}
diff --git a/solve_pop.go b/solve_pop.go
index cc6dd4c..72130d0 100644
--- a/solve_pop.go
+++ b/solve_pop.go
@@ -6,6 +6,6 @@ func NewPOPSolver() Solver {
return &popSolver{}
}
-func (popSolver) Solve(_ Challenge) error { return errNotImplemented }
+func (popSolver) Solve(_ Challenge) error { return ErrNotImplemented }
func (popSolver) Solved() error { return nil }
func (popSolver) Type() ChalType { return ChallengePOP }
diff --git a/solve_tls.go b/solve_tls.go
index babc5e4..8dbf496 100644
--- a/solve_tls.go
+++ b/solve_tls.go
@@ -29,6 +29,9 @@ func (s *tlsSolver) getCert(h *tls.ClientHelloInfo) (*tls.Certificate, error) {
}
func NewTLSSolver(addr string) (Solver, error) {
+ if addr == "" {
+ return nil, ErrSkipped
+ }
// we need at least one cert
dummy, err := newCert("dummy" + AcmeInvalid)
if err != nil {
diff --git a/solver.go b/solver.go
index 33e8493..8671f21 100644
--- a/solver.go
+++ b/solver.go
@@ -2,7 +2,10 @@ package acme
import "errors"
-var errNotImplemented = errors.New("not implemented")
+var (
+ ErrNotImplemented = errors.New("not implemented")
+ ErrSkipped = errors.New("solver skipped")
+)
// WellKnown URL path
const WellKnown = `/.well-known/acme-challenge/`