1 package ctconfig 2 3 import ( 4 "errors" 5 "fmt" 6 "time" 7 8 "github.com/letsencrypt/boulder/config" 9 ) 10 11 // LogShard describes a single shard of a temporally sharded 12 // CT log 13 type LogShard struct { 14 URI string 15 Key string 16 WindowStart time.Time 17 WindowEnd time.Time 18 } 19 20 // TemporalSet contains a set of temporal shards of a single log 21 type TemporalSet struct { 22 Name string 23 Shards []LogShard 24 } 25 26 // Setup initializes the TemporalSet by parsing the start and end dates 27 // and verifying WindowEnd > WindowStart 28 func (ts *TemporalSet) Setup() error { 29 if ts.Name == "" { 30 return errors.New("Name cannot be empty") 31 } 32 if len(ts.Shards) == 0 { 33 return errors.New("temporal set contains no shards") 34 } 35 for i := range ts.Shards { 36 if !ts.Shards[i].WindowEnd.After(ts.Shards[i].WindowStart) { 37 return errors.New("WindowStart must be before WindowEnd") 38 } 39 } 40 return nil 41 } 42 43 // pick chooses the correct shard from a TemporalSet to use for the given 44 // expiration time. In the case where two shards have overlapping windows 45 // the earlier of the two shards will be chosen. 46 func (ts *TemporalSet) pick(exp time.Time) (*LogShard, error) { 47 for _, shard := range ts.Shards { 48 if exp.Before(shard.WindowStart) { 49 continue 50 } 51 if !exp.Before(shard.WindowEnd) { 52 continue 53 } 54 return &shard, nil 55 } 56 return nil, fmt.Errorf("no valid shard available for temporal set %q for expiration date %q", ts.Name, exp) 57 } 58 59 // LogDescription contains the information needed to submit certificates 60 // to a CT log and verify returned receipts. If TemporalSet is non-nil then 61 // URI and Key should be empty. 62 type LogDescription struct { 63 URI string 64 Key string 65 SubmitFinalCert bool 66 67 *TemporalSet 68 } 69 70 // Info returns the URI and key of the log, either from a plain log description 71 // or from the earliest valid shard from a temporal log set 72 func (ld LogDescription) Info(exp time.Time) (string, string, error) { 73 if ld.TemporalSet == nil { 74 return ld.URI, ld.Key, nil 75 } 76 shard, err := ld.TemporalSet.pick(exp) 77 if err != nil { 78 return "", "", err 79 } 80 return shard.URI, shard.Key, nil 81 } 82 83 // CTGroup represents a group of CT Logs. Although capable of holding logs 84 // grouped by any arbitrary feature, is today primarily used to hold logs which 85 // are all operated by the same legal entity. 86 type CTGroup struct { 87 Name string 88 Logs []LogDescription 89 } 90 91 // CTConfig is the top-level config object expected to be embedded in an 92 // executable's JSON config struct. 93 type CTConfig struct { 94 // Stagger is duration (e.g. "200ms") indicating how long to wait for a log 95 // from one operator group to accept a certificate before attempting 96 // submission to a log run by a different operator instead. 97 Stagger config.Duration 98 // LogListFile is a path to a JSON log list file. The file must match Chrome's 99 // schema: https://www.gstatic.com/ct/log_list/v3/log_list_schema.json 100 LogListFile string `validate:"required"` 101 // SCTLogs is a list of CT log names to submit precerts to in order to get SCTs. 102 SCTLogs []string `validate:"min=1,dive,required"` 103 // InfoLogs is a list of CT log names to submit precerts to on a best-effort 104 // basis. Logs are included here for the sake of wider distribution of our 105 // precerts, and to exercise logs that in the qualification process. 106 InfoLogs []string 107 // FinalLogs is a list of CT log names to submit final certificates to. 108 // This may include duplicates from the lists above, to submit both precerts 109 // and final certs to the same log. 110 FinalLogs []string 111 } 112 113 // LogID holds enough information to uniquely identify a CT Log: its log_id 114 // (the base64-encoding of the SHA-256 hash of its public key) and its human- 115 // readable name/description. This is used to extract other log parameters 116 // (such as its URL and public key) from the Chrome Log List. 117 type LogID struct { 118 Name string 119 ID string 120 SubmitFinal bool 121 } 122