1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package ctfe
16
17 import (
18 "context"
19 "crypto"
20 "crypto/ecdsa"
21 "crypto/ed25519"
22 "crypto/rsa"
23 "errors"
24 "fmt"
25 "net/http"
26 "strconv"
27 "strings"
28 "time"
29
30 "github.com/google/certificate-transparency-go/asn1"
31 "github.com/google/certificate-transparency-go/schedule"
32 "github.com/google/certificate-transparency-go/trillian/util"
33 "github.com/google/certificate-transparency-go/x509"
34 "github.com/google/certificate-transparency-go/x509util"
35 "github.com/google/trillian"
36 "github.com/google/trillian/crypto/keys"
37 "github.com/google/trillian/monitoring"
38 "k8s.io/klog/v2"
39 )
40
41
42 type InstanceOptions struct {
43
44
45 Validated *ValidatedLogConfig
46
47 Client trillian.TrillianLogClient
48
49 Deadline time.Duration
50
51 MetricFactory monitoring.MetricFactory
52
53
54 ErrorMapper func(error) (int, bool)
55
56 RequestLog RequestLog
57
58
59
60 RemoteQuotaUser func(*http.Request) string
61
62
63
64
65
66
67 CertificateQuotaUser func(*x509.Certificate) string
68
69
70
71 STHStorage MirrorSTHStorage
72
73
74 MaskInternalErrors bool
75 }
76
77
78
79 type Instance struct {
80 Handlers PathHandlers
81 STHGetter STHGetter
82 li *logInfo
83 }
84
85
86
87 func (i *Instance) RunUpdateSTH(ctx context.Context, period time.Duration) {
88 c := i.li.instanceOpts.Validated.Config
89 klog.Infof("Start internal get-sth operations on %v (%d)", c.Prefix, c.LogId)
90 schedule.Every(ctx, period, func(ctx context.Context) {
91 klog.V(1).Infof("Force internal get-sth for %v (%d)", c.Prefix, c.LogId)
92 if _, err := i.li.getSTH(ctx); err != nil {
93 klog.Warningf("Failed to retrieve STH for %v (%d): %v", c.Prefix, c.LogId, err)
94 }
95 })
96 }
97
98
99 func (i *Instance) GetPublicKey() crypto.PublicKey {
100 if i.li != nil && i.li.signer != nil {
101 return i.li.signer.Public()
102 }
103 return nil
104 }
105
106
107
108
109 func SetUpInstance(ctx context.Context, opts InstanceOptions) (*Instance, error) {
110 logInfo, err := setUpLogInfo(ctx, opts)
111 if err != nil {
112 return nil, err
113 }
114 handlers := logInfo.Handlers(opts.Validated.Config.Prefix)
115 return &Instance{Handlers: handlers, STHGetter: logInfo.sthGetter, li: logInfo}, nil
116 }
117
118 func setUpLogInfo(ctx context.Context, opts InstanceOptions) (*logInfo, error) {
119 vCfg := opts.Validated
120 cfg := vCfg.Config
121
122
123 if !cfg.IsMirror && len(cfg.RootsPemFile) == 0 {
124 return nil, errors.New("need to specify RootsPemFile")
125 }
126
127 roots := x509util.NewPEMCertPool()
128 for _, pemFile := range cfg.RootsPemFile {
129 if err := roots.AppendCertsFromPEMFile(pemFile); err != nil {
130 return nil, fmt.Errorf("failed to read trusted roots: %v", err)
131 }
132 }
133
134 var signer crypto.Signer
135 if !cfg.IsMirror {
136 var err error
137 if signer, err = keys.NewSigner(ctx, vCfg.PrivKey); err != nil {
138 return nil, fmt.Errorf("failed to load private key: %v", err)
139 }
140
141
142 if vCfg.PubKey != nil {
143 switch pub := vCfg.PubKey.(type) {
144 case *ecdsa.PublicKey:
145 if !pub.Equal(signer.Public()) {
146 return nil, errors.New("public key is not consistent with private key")
147 }
148 case ed25519.PublicKey:
149 if !pub.Equal(signer.Public()) {
150 return nil, errors.New("public key is not consistent with private key")
151 }
152 case *rsa.PublicKey:
153 if !pub.Equal(signer.Public()) {
154 return nil, errors.New("public key is not consistent with private key")
155 }
156 default:
157 return nil, errors.New("failed to verify consistency of public key with private key")
158 }
159 }
160 }
161
162 validationOpts := CertValidationOpts{
163 trustedRoots: roots,
164 rejectExpired: cfg.RejectExpired,
165 rejectUnexpired: cfg.RejectUnexpired,
166 notAfterStart: vCfg.NotAfterStart,
167 notAfterLimit: vCfg.NotAfterLimit,
168 acceptOnlyCA: cfg.AcceptOnlyCa,
169 extKeyUsages: vCfg.KeyUsages,
170 }
171 var err error
172 validationOpts.rejectExtIds, err = parseOIDs(cfg.RejectExtensions)
173 if err != nil {
174 return nil, fmt.Errorf("failed to parse RejectExtensions: %v", err)
175 }
176
177 logInfo := newLogInfo(opts, validationOpts, signer, new(util.SystemTimeSource))
178 return logInfo, nil
179 }
180
181 func parseOIDs(oids []string) ([]asn1.ObjectIdentifier, error) {
182 ret := make([]asn1.ObjectIdentifier, 0, len(oids))
183 for _, s := range oids {
184 bits := strings.Split(s, ".")
185 var oid asn1.ObjectIdentifier
186 for _, n := range bits {
187 p, err := strconv.Atoi(n)
188 if err != nil {
189 return nil, err
190 }
191 oid = append(oid, p)
192 }
193 ret = append(ret, oid)
194 }
195 return ret, nil
196 }
197
View as plain text