-
Notifications
You must be signed in to change notification settings - Fork 0
/
clientreg.go
110 lines (89 loc) · 2.55 KB
/
clientreg.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package acme
import (
"crypto"
"crypto/ecdsa"
"fmt"
"net/http"
"github.com/tommie/acme-go/protocol"
"gopkg.in/square/go-jose.v2"
)
// RegisterAccount performs an account registration and returns a
// client account on success. dirURI is the ACME directory URI.
func RegisterAccount(dirURI string, accountKey crypto.PrivateKey, opts ...RegistrationOpt) (*ClientAccount, *Registration, error) {
a, err := NewClientAccount(dirURI, "", accountKey)
if err != nil {
return nil, nil, err
}
d, err := a.directory()
if err != nil {
return nil, nil, err
}
reg, err := doRegistration(a.http, d.NewReg, &protocol.Registration{Resource: protocol.ResourceNewReg}, opts...)
if err != nil {
return nil, nil, err
}
a.URI = reg.URI
return a, reg, nil
}
type RegistrationOpt func(*protocol.Registration)
func WithContactURIs(contacts ...string) RegistrationOpt {
return func(r *protocol.Registration) {
r.ContactURIs = contacts
}
}
func WithAgreementURI(u string) RegistrationOpt {
return func(r *protocol.Registration) {
r.AgreementURI = u
}
}
func WithRecoveryKeyMaterial(key *ecdsa.PrivateKey, len int) RegistrationOpt {
return func(r *protocol.Registration) {
r.RecoveryKey = &protocol.RecoveryKey{
Client: &jose.JSONWebKey{Key: key},
Length: len,
}
}
}
// doRegistration runs a registration. req needs to have at least
// Resource set. Returns ErrPending and the registration URL if the
// registration is not yet complete.
func doRegistration(hc protocol.Poster, uri string, req *protocol.Registration, opts ...RegistrationOpt) (*Registration, error) {
for _, opt := range opts {
opt(req)
}
var recPriv *ecdsa.PrivateKey
if req.RecoveryKey != nil {
// Save the private key and insert just the public key.
// The key was assigned through WithRecoveryKeyMaterial,
// so must be an ecdsa.PrivateKey.
recPriv = req.RecoveryKey.Client.Key.(*ecdsa.PrivateKey)
req.RecoveryKey.Client.Key = recPriv.Public()
}
reg, resp, err := protocol.PostRegistration(hc, uri, req)
if err != nil {
return nil, err
}
u, _ := resp.Location()
switch resp.StatusCode {
case http.StatusAccepted, http.StatusCreated:
// TODO: Unspecified behavior.
// ResourceReg returns StatusAccepted in Boulder.
break
default:
return nil, fmt.Errorf("unexpected HTTP status code: %s", resp.Status)
}
ret, err := newRegistration(reg, req, recPriv)
if err != nil {
return nil, err
}
if u == nil {
ret.URI = uri
} else {
ret.URI = u.String()
}
us := links(resp, "terms-of-service")
if len(us) > 0 {
ret.TermsOfServiceURI = us[0]
}
return ret, nil
}