| 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" |
| 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{}, retry.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{}, retry.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 |