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 certconfig | 5 package certconfig |
6 | 6 |
7 import ( | 7 import ( |
8 "crypto/sha1" | 8 "crypto/sha1" |
9 "crypto/x509/pkix" | 9 "crypto/x509/pkix" |
10 "encoding/hex" | 10 "encoding/hex" |
11 "fmt" | 11 "fmt" |
12 "math/big" | 12 "math/big" |
13 "sync" | 13 "sync" |
14 "time" | 14 "time" |
15 | 15 |
16 "golang.org/x/net/context" | 16 "golang.org/x/net/context" |
17 | 17 |
18 ds "github.com/luci/gae/service/datastore" | 18 ds "github.com/luci/gae/service/datastore" |
19 "github.com/luci/luci-go/common/clock" | 19 "github.com/luci/luci-go/common/clock" |
20 "github.com/luci/luci-go/common/data/caching/lazyslot" | 20 "github.com/luci/luci-go/common/data/caching/lazyslot" |
21 "github.com/luci/luci-go/common/errors" | 21 "github.com/luci/luci-go/common/errors" |
22 "github.com/luci/luci-go/common/logging" | 22 "github.com/luci/luci-go/common/logging" |
23 "github.com/luci/luci-go/common/proto/google" | 23 "github.com/luci/luci-go/common/proto/google" |
| 24 "github.com/luci/luci-go/common/retry/transient" |
24 | 25 |
25 "github.com/luci/luci-go/tokenserver/api/admin/v1" | 26 "github.com/luci/luci-go/tokenserver/api/admin/v1" |
26 | 27 |
27 "github.com/luci/luci-go/tokenserver/appengine/impl/utils" | 28 "github.com/luci/luci-go/tokenserver/appengine/impl/utils" |
28 "github.com/luci/luci-go/tokenserver/appengine/impl/utils/shards" | 29 "github.com/luci/luci-go/tokenserver/appengine/impl/utils/shards" |
29 ) | 30 ) |
30 | 31 |
31 // CRLShardCount is a number of shards to use for storing CRL in the datastore. | 32 // CRLShardCount is a number of shards to use for storing CRL in the datastore. |
32 // | 33 // |
33 // Each shard can hold ~2 MB of data (taking into account zlib compression), | 34 // Each shard can hold ~2 MB of data (taking into account zlib compression), |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 } | 267 } |
267 | 268 |
268 // Have something locally already? Quickly fetch CRLShardHeader to check | 269 // Have something locally already? Quickly fetch CRLShardHeader to check |
269 // whether we need to pull a heavy CRLShardBody. | 270 // whether we need to pull a heavy CRLShardBody. |
270 hdr := CRLShardHeader{ID: shardEntityID(ch.cn, ch.shardCount, idx)} | 271 hdr := CRLShardHeader{ID: shardEntityID(ch.cn, ch.shardCount, idx)} |
271 if prevState.sha1 != "" { | 272 if prevState.sha1 != "" { |
272 switch err := ds.Get(c, &hdr); { | 273 switch err := ds.Get(c, &hdr); { |
273 case err == ds.ErrNoSuchEntity: | 274 case err == ds.ErrNoSuchEntity: |
274 return lazyslot.Value{}, fmt.Errorf("shard header %q is
missing", hdr.ID) | 275 return lazyslot.Value{}, fmt.Errorf("shard header %q is
missing", hdr.ID) |
275 case err != nil: | 276 case err != nil: |
276 » » » return lazyslot.Value{}, errors.WrapTransient(err) | 277 » » » return lazyslot.Value{}, transient.Tag.Apply(err) |
277 } | 278 } |
278 // The currently cached copy is still good enough? | 279 // The currently cached copy is still good enough? |
279 if hdr.SHA1 == prevState.sha1 { | 280 if hdr.SHA1 == prevState.sha1 { |
280 return lazyslot.Value{ | 281 return lazyslot.Value{ |
281 Value: prevState, | 282 Value: prevState, |
282 Expiration: clock.Now(c).Add(ch.cacheDuration), | 283 Expiration: clock.Now(c).Add(ch.cacheDuration), |
283 }, nil | 284 }, nil |
284 } | 285 } |
285 } | 286 } |
286 | 287 |
287 // Nothing is cached, or the datastore copy is fresher than what we have
in | 288 // Nothing is cached, or the datastore copy is fresher than what we have
in |
288 // the cache. Need to fetch a new copy, unzip and deserialize it. This e
ntity | 289 // the cache. Need to fetch a new copy, unzip and deserialize it. This e
ntity |
289 // is prepared by updateCRLShard. | 290 // is prepared by updateCRLShard. |
290 body := CRLShardBody{Parent: ds.KeyForObj(c, &hdr)} | 291 body := CRLShardBody{Parent: ds.KeyForObj(c, &hdr)} |
291 switch err := ds.Get(c, &body); { | 292 switch err := ds.Get(c, &body); { |
292 case err == ds.ErrNoSuchEntity: | 293 case err == ds.ErrNoSuchEntity: |
293 return lazyslot.Value{}, fmt.Errorf("shard body %q is missing",
hdr.ID) | 294 return lazyslot.Value{}, fmt.Errorf("shard body %q is missing",
hdr.ID) |
294 case err != nil: | 295 case err != nil: |
295 » » return lazyslot.Value{}, errors.WrapTransient(err) | 296 » » return lazyslot.Value{}, transient.Tag.Apply(err) |
296 } | 297 } |
297 | 298 |
298 // Unzip and deserialize. | 299 // Unzip and deserialize. |
299 blob, err := utils.ZlibDecompress(body.ZippedData) | 300 blob, err := utils.ZlibDecompress(body.ZippedData) |
300 if err != nil { | 301 if err != nil { |
301 return lazyslot.Value{}, err | 302 return lazyslot.Value{}, err |
302 } | 303 } |
303 shard, err := shards.ParseShard(blob) | 304 shard, err := shards.ParseShard(blob) |
304 if err != nil { | 305 if err != nil { |
305 return lazyslot.Value{}, err | 306 return lazyslot.Value{}, err |
306 } | 307 } |
307 | 308 |
308 return lazyslot.Value{ | 309 return lazyslot.Value{ |
309 Value: shardCache{ | 310 Value: shardCache{ |
310 shard: shard, | 311 shard: shard, |
311 sha1: body.SHA1, | 312 sha1: body.SHA1, |
312 }, | 313 }, |
313 Expiration: clock.Now(c).Add(ch.cacheDuration), | 314 Expiration: clock.Now(c).Add(ch.cacheDuration), |
314 }, nil | 315 }, nil |
315 } | 316 } |
OLD | NEW |