crl: add cache control headers (#8011)
The crl-storer passes along Cache-Control and Expires from the crl-updater (because the crl-updater knows the UpdatePeriod). The crl-updater calculates the Expires header based on when it expects to update the CRL, plus a margin of error. Fixes #8004
This commit is contained in:
parent
a8b2fd6960
commit
e0e5a17899
|
|
@ -116,6 +116,37 @@ type Config struct {
|
|||
// load of said run. The default is 1.
|
||||
MaxAttempts int `validate:"omitempty,min=1"`
|
||||
|
||||
// ExpiresMargin adds a small increment to the CRL's HTTP Expires time.
|
||||
//
|
||||
// When uploading a CRL, its Expires field in S3 is set to the expected time
|
||||
// the next CRL will be uploaded (by this instance). That allows our CDN
|
||||
// instances to cache for that long. However, since the next update might be
|
||||
// slow or delayed, we add a margin of error.
|
||||
//
|
||||
// Tradeoffs: A large ExpiresMargin reduces the chance that a CRL becomes
|
||||
// uncacheable and floods S3 with traffic (which might result in 503s while
|
||||
// S3 scales out).
|
||||
//
|
||||
// A small ExpiresMargin means revocations become visible sooner, including
|
||||
// admin-invoked revocations that may have a time requirement.
|
||||
ExpiresMargin config.Duration
|
||||
|
||||
// CacheControl is a string passed verbatim to the crl-storer to store on
|
||||
// the S3 object.
|
||||
//
|
||||
// Note: if this header contains max-age, it will override
|
||||
// Expires. https://www.rfc-editor.org/rfc/rfc9111.html#name-calculating-freshness-lifet
|
||||
// Cache-Control: max-age has the disadvantage that it caches for a fixed
|
||||
// amount of time, regardless of how close the CRL is to replacement. So
|
||||
// if max-age is used, the worst-case time for a revocation to become visible
|
||||
// is UpdatePeriod + the value of max age.
|
||||
//
|
||||
// The stale-if-error and stale-while-revalidate headers may be useful here:
|
||||
// https://aws.amazon.com/about-aws/whats-new/2023/05/amazon-cloudfront-stale-while-revalidate-stale-if-error-cache-control-directives/
|
||||
//
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
|
||||
CacheControl string
|
||||
|
||||
Features features.Config
|
||||
}
|
||||
|
||||
|
|
@ -189,6 +220,8 @@ func main() {
|
|||
c.CRLUpdater.UpdateTimeout.Duration,
|
||||
c.CRLUpdater.MaxParallelism,
|
||||
c.CRLUpdater.MaxAttempts,
|
||||
c.CRLUpdater.CacheControl,
|
||||
c.CRLUpdater.ExpiresMargin.Duration,
|
||||
c.CRLUpdater.TemporallyShardedSerialPrefixes,
|
||||
sac,
|
||||
cac,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
|
@ -107,9 +108,11 @@ type CRLMetadata struct {
|
|||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
IssuerNameID int64 `protobuf:"varint,1,opt,name=issuerNameID,proto3" json:"issuerNameID,omitempty"`
|
||||
Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
|
||||
ShardIdx int64 `protobuf:"varint,3,opt,name=shardIdx,proto3" json:"shardIdx,omitempty"`
|
||||
IssuerNameID int64 `protobuf:"varint,1,opt,name=issuerNameID,proto3" json:"issuerNameID,omitempty"`
|
||||
Number int64 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"`
|
||||
ShardIdx int64 `protobuf:"varint,3,opt,name=shardIdx,proto3" json:"shardIdx,omitempty"`
|
||||
Expires *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=expires,proto3" json:"expires,omitempty"`
|
||||
CacheControl string `protobuf:"bytes,5,opt,name=cacheControl,proto3" json:"cacheControl,omitempty"`
|
||||
}
|
||||
|
||||
func (x *CRLMetadata) Reset() {
|
||||
|
|
@ -165,35 +168,57 @@ func (x *CRLMetadata) GetShardIdx() int64 {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (x *CRLMetadata) GetExpires() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.Expires
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *CRLMetadata) GetCacheControl() string {
|
||||
if x != nil {
|
||||
return x.CacheControl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_storer_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_storer_proto_rawDesc = []byte{
|
||||
0x0a, 0x0c, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06,
|
||||
0x73, 0x74, 0x6f, 0x72, 0x65, 0x72, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x22, 0x6e, 0x0a, 0x10, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x52, 0x4c,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64,
|
||||
0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x74, 0x6f, 0x72,
|
||||
0x65, 0x72, 0x2e, 0x43, 0x52, 0x4c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, 0x00,
|
||||
0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x08, 0x63, 0x72,
|
||||
0x6c, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x08,
|
||||
0x63, 0x72, 0x6c, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c,
|
||||
0x6f, 0x61, 0x64, 0x22, 0x65, 0x0a, 0x0b, 0x43, 0x52, 0x4c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
|
||||
0x74, 0x61, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65,
|
||||
0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72,
|
||||
0x4e, 0x61, 0x6d, 0x65, 0x49, 0x44, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1a,
|
||||
0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
|
||||
0x52, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x78, 0x32, 0x4e, 0x0a, 0x09, 0x43, 0x52,
|
||||
0x4c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x09, 0x55, 0x70, 0x6c, 0x6f, 0x61,
|
||||
0x64, 0x43, 0x52, 0x4c, 0x12, 0x18, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x55, 0x70,
|
||||
0x6c, 0x6f, 0x61, 0x64, 0x43, 0x52, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16,
|
||||
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
|
||||
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x28, 0x01, 0x42, 0x31, 0x5a, 0x2f, 0x67, 0x69,
|
||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x65, 0x74, 0x73, 0x65, 0x6e, 0x63,
|
||||
0x72, 0x79, 0x70, 0x74, 0x2f, 0x62, 0x6f, 0x75, 0x6c, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x72, 0x6c,
|
||||
0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6e, 0x0a, 0x10, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x52,
|
||||
0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61,
|
||||
0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x65, 0x72, 0x2e, 0x43, 0x52, 0x4c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48,
|
||||
0x00, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x08, 0x63,
|
||||
0x72, 0x6c, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52,
|
||||
0x08, 0x63, 0x72, 0x6c, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79,
|
||||
0x6c, 0x6f, 0x61, 0x64, 0x22, 0xbf, 0x01, 0x0a, 0x0b, 0x43, 0x52, 0x4c, 0x4d, 0x65, 0x74, 0x61,
|
||||
0x64, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x4e, 0x61,
|
||||
0x6d, 0x65, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x69, 0x73, 0x73, 0x75,
|
||||
0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x49, 0x44, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62,
|
||||
0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
|
||||
0x12, 0x1a, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x78, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x03, 0x52, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x78, 0x12, 0x34, 0x0a, 0x07,
|
||||
0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
|
||||
0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72,
|
||||
0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x6f, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x61, 0x63, 0x68, 0x65, 0x43,
|
||||
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x32, 0x4e, 0x0a, 0x09, 0x43, 0x52, 0x4c, 0x53, 0x74, 0x6f,
|
||||
0x72, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x09, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x52, 0x4c,
|
||||
0x12, 0x18, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64,
|
||||
0x43, 0x52, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f,
|
||||
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70,
|
||||
0x74, 0x79, 0x22, 0x00, 0x28, 0x01, 0x42, 0x31, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x65, 0x74, 0x73, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74,
|
||||
0x2f, 0x62, 0x6f, 0x75, 0x6c, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x73, 0x74, 0x6f,
|
||||
0x72, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
@ -210,19 +235,21 @@ func file_storer_proto_rawDescGZIP() []byte {
|
|||
|
||||
var file_storer_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_storer_proto_goTypes = []interface{}{
|
||||
(*UploadCRLRequest)(nil), // 0: storer.UploadCRLRequest
|
||||
(*CRLMetadata)(nil), // 1: storer.CRLMetadata
|
||||
(*emptypb.Empty)(nil), // 2: google.protobuf.Empty
|
||||
(*UploadCRLRequest)(nil), // 0: storer.UploadCRLRequest
|
||||
(*CRLMetadata)(nil), // 1: storer.CRLMetadata
|
||||
(*timestamppb.Timestamp)(nil), // 2: google.protobuf.Timestamp
|
||||
(*emptypb.Empty)(nil), // 3: google.protobuf.Empty
|
||||
}
|
||||
var file_storer_proto_depIdxs = []int32{
|
||||
1, // 0: storer.UploadCRLRequest.metadata:type_name -> storer.CRLMetadata
|
||||
0, // 1: storer.CRLStorer.UploadCRL:input_type -> storer.UploadCRLRequest
|
||||
2, // 2: storer.CRLStorer.UploadCRL:output_type -> google.protobuf.Empty
|
||||
2, // [2:3] is the sub-list for method output_type
|
||||
1, // [1:2] is the sub-list for method input_type
|
||||
1, // [1:1] is the sub-list for extension type_name
|
||||
1, // [1:1] is the sub-list for extension extendee
|
||||
0, // [0:1] is the sub-list for field type_name
|
||||
2, // 1: storer.CRLMetadata.expires:type_name -> google.protobuf.Timestamp
|
||||
0, // 2: storer.CRLStorer.UploadCRL:input_type -> storer.UploadCRLRequest
|
||||
3, // 3: storer.CRLStorer.UploadCRL:output_type -> google.protobuf.Empty
|
||||
3, // [3:4] is the sub-list for method output_type
|
||||
2, // [2:3] is the sub-list for method input_type
|
||||
2, // [2:2] is the sub-list for extension type_name
|
||||
2, // [2:2] is the sub-list for extension extendee
|
||||
0, // [0:2] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_storer_proto_init() }
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ package storer;
|
|||
option go_package = "github.com/letsencrypt/boulder/crl/storer/proto";
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
service CRLStorer {
|
||||
rpc UploadCRL(stream UploadCRLRequest) returns (google.protobuf.Empty) {}
|
||||
|
|
@ -20,4 +21,6 @@ message CRLMetadata {
|
|||
int64 issuerNameID = 1;
|
||||
int64 number = 2;
|
||||
int64 shardIdx = 3;
|
||||
google.protobuf.Timestamp expires = 4;
|
||||
string cacheControl = 5;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ func (cs *crlStorer) UploadCRL(stream grpc.ClientStreamingServer[cspb.UploadCRLR
|
|||
var shardIdx int64
|
||||
var crlNumber *big.Int
|
||||
crlBytes := make([]byte, 0)
|
||||
var cacheControl string
|
||||
var expires time.Time
|
||||
|
||||
// Read all of the messages from the input stream.
|
||||
for {
|
||||
|
|
@ -125,6 +127,9 @@ func (cs *crlStorer) UploadCRL(stream grpc.ClientStreamingServer[cspb.UploadCRLR
|
|||
return errors.New("got incomplete metadata message")
|
||||
}
|
||||
|
||||
cacheControl = payload.Metadata.CacheControl
|
||||
expires = payload.Metadata.Expires.AsTime()
|
||||
|
||||
shardIdx = payload.Metadata.ShardIdx
|
||||
crlNumber = crl.Number(time.Unix(0, payload.Metadata.Number))
|
||||
|
||||
|
|
@ -229,6 +234,8 @@ func (cs *crlStorer) UploadCRL(stream grpc.ClientStreamingServer[cspb.UploadCRLR
|
|||
ChecksumSHA256: &checksumb64,
|
||||
ContentType: &crlContentType,
|
||||
Metadata: map[string]string{"crlNumber": crlNumber.String()},
|
||||
Expires: &expires,
|
||||
CacheControl: &cacheControl,
|
||||
})
|
||||
|
||||
latency := cs.clk.Now().Sub(start)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ func TestRunOnce(t *testing.T) {
|
|||
[]*issuance.Certificate{e1, r3},
|
||||
2, 18*time.Hour, 24*time.Hour,
|
||||
6*time.Hour, time.Minute, 1, 1,
|
||||
"stale-if-error=60",
|
||||
5*time.Minute,
|
||||
nil,
|
||||
&fakeSAC{revokedCerts: revokedCertsStream{err: errors.New("db no worky")}, maxNotAfter: clk.Now().Add(90 * 24 * time.Hour)},
|
||||
&fakeCA{gcc: generateCRLStream{}},
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ type crlUpdater struct {
|
|||
maxParallelism int
|
||||
maxAttempts int
|
||||
|
||||
cacheControl string
|
||||
expiresMargin time.Duration
|
||||
|
||||
temporallyShardedPrefixes []string
|
||||
|
||||
sa sapb.StorageAuthorityClient
|
||||
|
|
@ -58,6 +61,8 @@ func NewUpdater(
|
|||
updateTimeout time.Duration,
|
||||
maxParallelism int,
|
||||
maxAttempts int,
|
||||
cacheControl string,
|
||||
expiresMargin time.Duration,
|
||||
temporallyShardedPrefixes []string,
|
||||
sa sapb.StorageAuthorityClient,
|
||||
ca capb.CRLGeneratorClient,
|
||||
|
|
@ -117,6 +122,8 @@ func NewUpdater(
|
|||
updateTimeout,
|
||||
maxParallelism,
|
||||
maxAttempts,
|
||||
cacheControl,
|
||||
expiresMargin,
|
||||
temporallyShardedPrefixes,
|
||||
sa,
|
||||
ca,
|
||||
|
|
@ -392,6 +399,8 @@ func (cu *crlUpdater) updateShard(ctx context.Context, atTime time.Time, issuerN
|
|||
IssuerNameID: int64(issuerNameID),
|
||||
Number: atTime.UnixNano(),
|
||||
ShardIdx: int64(shardIdx),
|
||||
CacheControl: cu.cacheControl,
|
||||
Expires: timestamppb.New(atTime.Add(cu.updatePeriod).Add(cu.expiresMargin)),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -225,6 +225,8 @@ func TestUpdateShard(t *testing.T) {
|
|||
[]*issuance.Certificate{e1, r3},
|
||||
2, 18*time.Hour, 24*time.Hour,
|
||||
6*time.Hour, time.Minute, 1, 1,
|
||||
"stale-if-error=60",
|
||||
5*time.Minute,
|
||||
nil,
|
||||
&fakeSAC{
|
||||
revokedCerts: revokedCertsStream{},
|
||||
|
|
@ -406,6 +408,8 @@ func TestUpdateShardWithRetry(t *testing.T) {
|
|||
[]*issuance.Certificate{e1, r3},
|
||||
2, 18*time.Hour, 24*time.Hour,
|
||||
6*time.Hour, time.Minute, 1, 1,
|
||||
"stale-if-error=60",
|
||||
5*time.Minute,
|
||||
nil,
|
||||
&fakeSAC{revokedCerts: revokedCertsStream{err: sentinelErr}, maxNotAfter: clk.Now().Add(90 * 24 * time.Hour)},
|
||||
&fakeCA{gcc: generateCRLStream{}},
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@
|
|||
"lookbackPeriod": "24h",
|
||||
"updatePeriod": "10m",
|
||||
"updateTimeout": "1m",
|
||||
"expiresMargin": "5m",
|
||||
"cacheControl": "stale-if-error=60",
|
||||
"temporallyShardedSerialPrefixes": [
|
||||
"7f"
|
||||
],
|
||||
|
|
|
|||
Loading…
Reference in New Issue