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"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -110,6 +111,8 @@ type CRLMetadata struct {
 | 
			
		|||
	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 (
 | 
			
		||||
| 
						 | 
				
			
			@ -212,17 +237,19 @@ 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
 | 
			
		||||
	(*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