-
Notifications
You must be signed in to change notification settings - Fork 455
/
upstreamca.go
103 lines (86 loc) · 2.19 KB
/
upstreamca.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
package x509svid
import (
"context"
"crypto/x509"
"time"
"github.com/andres-erbsen/clock"
"github.com/spiffe/go-spiffe/v2/spiffeid"
"github.com/spiffe/spire/pkg/common/x509util"
)
const (
DefaultUpstreamCABackdate = time.Second * 10
DefaultUpstreamCATTL = time.Hour
)
type UpstreamCAOptions struct {
Backdate time.Duration
Clock clock.Clock
}
type UpstreamCA struct {
keypair x509util.Keypair
trustDomain spiffeid.TrustDomain
options UpstreamCAOptions
}
func NewUpstreamCA(keypair x509util.Keypair, trustDomain spiffeid.TrustDomain, options UpstreamCAOptions) *UpstreamCA {
if options.Backdate <= 0 {
options.Backdate = DefaultUpstreamCABackdate
}
if options.Clock == nil {
options.Clock = clock.New()
}
return &UpstreamCA{
keypair: keypair,
trustDomain: trustDomain,
options: options,
}
}
func (ca *UpstreamCA) SignCSR(ctx context.Context, csrDER []byte, preferredTTL time.Duration) (*x509.Certificate, error) {
csr, err := ParseAndValidateCSR(csrDER, ca.trustDomain)
if err != nil {
return nil, err
}
keyID, err := x509util.GetSubjectKeyID(csr.PublicKey)
if err != nil {
return nil, err
}
// Use the default TTL setting unless a preferred TTL is specified.
caTTL := DefaultUpstreamCATTL
if preferredTTL > 0 {
caTTL = preferredTTL
}
now := ca.options.Clock.Now()
notBefore := now.Add(-ca.options.Backdate)
notAfter := now.Add(caTTL)
caCert, err := ca.keypair.GetCertificate(ctx)
if err != nil {
return nil, err
}
if notAfter.After(caCert.NotAfter) {
notAfter = caCert.NotAfter
}
serialNumber, err := x509util.NewSerialNumber()
if err != nil {
return nil, err
}
template := &x509.Certificate{
SerialNumber: serialNumber,
RawSubject: csr.RawSubject,
URIs: csr.URIs,
NotBefore: notBefore,
NotAfter: notAfter,
SubjectKeyId: keyID,
KeyUsage: x509.KeyUsageCertSign |
x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
IsCA: true,
ExtraExtensions: csr.Extensions,
}
certDER, err := ca.keypair.CreateCertificate(ctx, template, csr.PublicKey)
if err != nil {
return nil, err
}
cert, err := x509.ParseCertificate(certDER)
if err != nil {
return nil, err
}
return cert, nil
}