OLD | NEW |
1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 // Package certchecker contains implementation of CertChecker. | 5 // Package certchecker contains implementation of CertChecker. |
6 // | 6 // |
7 // CertChecker knows how to check certificate signatures and revocation status. | 7 // CertChecker knows how to check certificate signatures and revocation status. |
8 // | 8 // |
9 // Uses datastore entities managed by 'certconfig' package. | 9 // Uses datastore entities managed by 'certconfig' package. |
10 package certchecker | 10 package certchecker |
11 | 11 |
12 import ( | 12 import ( |
13 "crypto/x509" | 13 "crypto/x509" |
14 "fmt" | 14 "fmt" |
15 "time" | 15 "time" |
16 | 16 |
17 "golang.org/x/net/context" | 17 "golang.org/x/net/context" |
18 | 18 |
19 ds "github.com/luci/gae/service/datastore" | 19 ds "github.com/luci/gae/service/datastore" |
20 "github.com/luci/gae/service/info" | 20 "github.com/luci/gae/service/info" |
21 "github.com/luci/luci-go/common/clock" | 21 "github.com/luci/luci-go/common/clock" |
22 "github.com/luci/luci-go/common/data/caching/lazyslot" | 22 "github.com/luci/luci-go/common/data/caching/lazyslot" |
23 "github.com/luci/luci-go/common/data/caching/proccache" | 23 "github.com/luci/luci-go/common/data/caching/proccache" |
24 » "github.com/luci/luci-go/common/errors" | 24 » "github.com/luci/luci-go/common/retry/transient" |
25 | 25 |
26 "github.com/luci/luci-go/tokenserver/appengine/impl/certconfig" | 26 "github.com/luci/luci-go/tokenserver/appengine/impl/certconfig" |
27 ) | 27 ) |
28 | 28 |
29 const ( | 29 const ( |
30 // RefetchCAPeriod is how often to check CA entity in the datastore. | 30 // RefetchCAPeriod is how often to check CA entity in the datastore. |
31 // | 31 // |
32 // A big value here is acceptable, since CA is changing only when servic
e | 32 // A big value here is acceptable, since CA is changing only when servic
e |
33 // config is changing (which happens infrequently). | 33 // config is changing (which happens infrequently). |
34 RefetchCAPeriod = 5 * time.Minute | 34 RefetchCAPeriod = 5 * time.Minute |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 // | 133 // |
134 // It caches CertChecker objects in local memory and reuses them between | 134 // It caches CertChecker objects in local memory and reuses them between |
135 // requests. | 135 // requests. |
136 func GetCertChecker(c context.Context, cn string) (*CertChecker, error) { | 136 func GetCertChecker(c context.Context, cn string) (*CertChecker, error) { |
137 checker, err := proccache.GetOrMake(c, proccacheKey(cn), func() (interfa
ce{}, time.Duration, error) { | 137 checker, err := proccache.GetOrMake(c, proccacheKey(cn), func() (interfa
ce{}, time.Duration, error) { |
138 // To avoid storing CertChecker for non-existent CAs in local me
mory forever, | 138 // To avoid storing CertChecker for non-existent CAs in local me
mory forever, |
139 // we do a datastore check when creating the checker. It happens
once during | 139 // we do a datastore check when creating the checker. It happens
once during |
140 // the process lifetime. | 140 // the process lifetime. |
141 switch exists, err := ds.Exists(c, ds.NewKey(c, "CA", cn, 0, nil
)); { | 141 switch exists, err := ds.Exists(c, ds.NewKey(c, "CA", cn, 0, nil
)); { |
142 case err != nil: | 142 case err != nil: |
143 » » » return nil, 0, errors.WrapTransient(err) | 143 » » » return nil, 0, transient.Tag.Apply(err) |
144 case !exists.All(): | 144 case !exists.All(): |
145 return nil, 0, Error{ | 145 return nil, 0, Error{ |
146 error: fmt.Errorf("no such CA %q", cn), | 146 error: fmt.Errorf("no such CA %q", cn), |
147 Reason: NoSuchCA, | 147 Reason: NoSuchCA, |
148 } | 148 } |
149 } | 149 } |
150 checker := &CertChecker{ | 150 checker := &CertChecker{ |
151 CN: cn, | 151 CN: cn, |
152 CRL: certconfig.NewCRLChecker(cn, certconfig.CRLShardCou
nt, refetchCRLPeriod(c)), | 152 CRL: certconfig.NewCRLChecker(cn, certconfig.CRLShardCou
nt, refetchCRLPeriod(c)), |
153 } | 153 } |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 // certconfig.CA struct (that will be cached in ch.ca as usual). It acts as an | 276 // certconfig.CA struct (that will be cached in ch.ca as usual). It acts as an |
277 // indicator to GetCA to return NoSuchCA error, since returning a error here | 277 // indicator to GetCA to return NoSuchCA error, since returning a error here |
278 // would just cause a retry of 'refetchCA' later, and returning (nil, nil) is | 278 // would just cause a retry of 'refetchCA' later, and returning (nil, nil) is |
279 // forbidden (per lazyslot.Slot API). | 279 // forbidden (per lazyslot.Slot API). |
280 func (ch *CertChecker) refetchCA(c context.Context) (*certconfig.CA, error) { | 280 func (ch *CertChecker) refetchCA(c context.Context) (*certconfig.CA, error) { |
281 ca := &certconfig.CA{CN: ch.CN} | 281 ca := &certconfig.CA{CN: ch.CN} |
282 switch err := ds.Get(c, ca); { | 282 switch err := ds.Get(c, ca); { |
283 case err == ds.ErrNoSuchEntity: | 283 case err == ds.ErrNoSuchEntity: |
284 return &certconfig.CA{}, nil // GetCA knows that empty struct me
ans "no such CA" | 284 return &certconfig.CA{}, nil // GetCA knows that empty struct me
ans "no such CA" |
285 case err != nil: | 285 case err != nil: |
286 » » return nil, errors.WrapTransient(err) | 286 » » return nil, transient.Tag.Apply(err) |
287 } | 287 } |
288 | 288 |
289 parsedConf, err := ca.ParseConfig() | 289 parsedConf, err := ca.ParseConfig() |
290 if err != nil { | 290 if err != nil { |
291 return nil, fmt.Errorf("can't parse stored config for %q - %s",
ca.CN, err) | 291 return nil, fmt.Errorf("can't parse stored config for %q - %s",
ca.CN, err) |
292 } | 292 } |
293 ca.ParsedConfig = parsedConf | 293 ca.ParsedConfig = parsedConf |
294 | 294 |
295 parsedCert, err := x509.ParseCertificate(ca.Cert) | 295 parsedCert, err := x509.ParseCertificate(ca.Cert) |
296 if err != nil { | 296 if err != nil { |
297 return nil, fmt.Errorf("can't parse stored cert for %q - %s", ca
.CN, err) | 297 return nil, fmt.Errorf("can't parse stored cert for %q - %s", ca
.CN, err) |
298 } | 298 } |
299 ca.ParsedCert = parsedCert | 299 ca.ParsedCert = parsedCert |
300 | 300 |
301 return ca, nil | 301 return ca, nil |
302 } | 302 } |
OLD | NEW |