aboutsummaryrefslogtreecommitdiff
path: root/provider.go
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2016-01-31 23:15:27 +0100
committerDimitri Sokolyuk <demon@dim13.org>2016-01-31 23:15:27 +0100
commitc49a0bf48ea10b54dbac3480716d9786a0ce8411 (patch)
tree3ce88f2422f3484aa95f77669fdafdfb6b2e63d9 /provider.go
parentc9038d2f35945774f6cd32ade7b3abd1cd5ba952 (diff)
Split files (experimental)
Diffstat (limited to 'provider.go')
-rw-r--r--provider.go188
1 files changed, 42 insertions, 146 deletions
diff --git a/provider.go b/provider.go
index 7cda357..69d125a 100644
--- a/provider.go
+++ b/provider.go
@@ -4,12 +4,49 @@ import (
"crypto/x509"
"encoding/json"
"errors"
- "log"
"net/http"
"regexp"
"time"
)
+const (
+ // LE1 Let's Encrypt V1
+ LE1 = `https://acme-v01.api.letsencrypt.org/directory`
+ // LES Let's Encrypt Staging
+ LES = `https://acme-staging.api.letsencrypt.org/directory`
+)
+
+type Resource string
+
+const (
+ ResNewReg Resource = "new-reg"
+ ResRecoverReg Resource = "recover-reg"
+ ResNewAuthz Resource = "new-authz"
+ ResNewCert Resource = "new-cert"
+ ResRevokeCert Resource = "revoke-cert"
+ ResReg Resource = "reg"
+ ResAuthz Resource = "authz"
+ ResChallenge Resource = "challenge"
+ ResCert Resource = "cert"
+)
+
+// Directory ...
+type Directory struct {
+ NewReg string `json:"new-reg"`
+ RecoverReg string `json:"recover-reg"`
+ NewAuthz string `json:"new-authz"`
+ NewCert string `json:"new-cert"`
+ RevokeCert string `json:"revoke-cert"`
+}
+
+// Problem description
+type Problem struct {
+ Type string `json:"type"`
+ Detail string `json:"detail"`
+ Instance string `json:"instance"`
+ Err error `json:"-"`
+}
+
// Provider ...
type Provider struct {
Directory
@@ -34,6 +71,10 @@ const (
poll = time.Second
)
+func (p Problem) Error() string {
+ return p.Detail
+}
+
// RoundTrip implements RoundTipper
func (p Provider) RoundTrip(req *http.Request) (*http.Response, error) {
resp, err := p.Transport.RoundTrip(req)
@@ -130,148 +171,3 @@ func parseCert(resp *http.Response) (*x509.Certificate, error) {
return nil, errContentType
}
}
-
-func (p *Provider) Register(s Signer, c Contacts) error {
- // first step: new-reg
- req := &Registration{
- Resource: ResNewReg,
- Contact: c,
- }
- resp, err := p.post(p.NewReg, s, req)
- if err != nil {
- return err
- }
- resp.Body.Close()
- ns := parseHeader(resp)
-
- // second step: reg, agree to tos
- req = &Registration{
- Resource: ResReg,
- Agreement: ns.Link["terms-of-service"],
- }
- resp, err = p.post(ns.Location, s, req)
- if err != nil {
- return err
- }
- resp.Body.Close()
- return nil
-}
-
-func (p *Provider) solve(s Signer, ch Challenge, sol Solver) error {
- ka, err := s.KeyAuth(ch.Token)
- if err != nil {
- return err
- }
-
- // prepare solver
- err = sol.Solve(ch.Token, ka)
- if err != nil {
- return err
- }
- defer sol.Solved()
-
- // update challenge
- ch.Resource = ResChallenge
- ch.KeyAuthorization = ka
-
- resp, err := p.post(ch.URI, s, ch)
- if err != nil {
- return err
- }
- ns := parseHeader(resp)
-
- return p.pollStatus(ns.Location)
-}
-
-func (p *Provider) authz(s Signer, domain string, sol map[ChalType]Solver) error {
- // first step: pocke
- req := &Authorization{
- Resource: ResNewAuthz,
- Identifier: Identifier{
- Type: IdentDNS,
- Value: domain,
- },
- }
- resp, err := p.post(p.NewAuthz, s, req)
- if err != nil {
- return err
- }
- err = parseJson(resp, req)
- if err != nil {
- return err
- }
- // second step: choose and start solver
- for _, ch := range req.Supported(sol) {
- if err = p.solve(s, ch, sol[ch.Type]); err != nil {
- return err
- }
- }
- return nil
-}
-
-func (p *Provider) Authorize(s Signer, d *Desire) error {
- for _, domain := range d.altnames {
- if err := p.authz(s, domain, d.solver); err != nil {
- return err
- }
- }
- return nil
-}
-
-func (p *Provider) pollStatus(uri string) error {
- t := time.NewTicker(poll)
- defer t.Stop()
- for range t.C {
- resp, err := p.Get(uri)
- if err != nil {
- return err
- }
- req := new(Challenge)
- err = parseJson(resp, req)
- if err != nil {
- return err
- }
- if req.Err != nil {
- return req.Err
- }
- log.Println("status", req.Status)
- if req.Status == StatusValid {
- return nil
- }
- }
- return nil
-}
-
-func (p *Provider) Bundle(s Signer, d *Desire) error {
- d.cert = make([]*x509.Certificate, 2)
- // first step: post csr
- csr, err := d.CSR()
- if err != nil {
- return err
- }
- req := &CSR{
- Resource: ResNewCert,
- CSR: csr,
- }
- resp, err := p.post(p.NewCert, s, req)
- if err != nil {
- return err
- }
- d.cert[0], err = parseCert(resp)
- if err != nil {
- return err
- }
- ns := parseHeader(resp)
-
- // second step: cet CA
- resp, err = p.Get(ns.Link["up"])
- if err != nil {
- return err
- }
- d.cert[1], err = parseCert(resp)
- if err != nil {
- return err
- }
-
- return nil
-}