@@ -5,8 +5,12 @@ import (
55 "encoding/hex"
66 "flag"
77 "fmt"
8+ "io"
89 "log"
10+ "net/http"
911 "os"
12+ "strings"
13+ "time"
1014
1115 "filippo.io/torchwood/internal/witness"
1216 "golang.org/x/mod/sumdb/note"
@@ -23,6 +27,7 @@ func usage() {
2327 fmt .Println (" add-key -db <path> -origin <origin> -key <verifier key>" )
2428 fmt .Println (" del-key -db <path> -origin <origin> -key <verifier key>" )
2529 fmt .Println (" add-sigsum-log -db <path> -key <hex-encoded key>" )
30+ fmt .Println (" pull-logs -db <path> -source <witness url> [-verbose]" )
2631 fmt .Println (" list-logs -db <path>" )
2732 os .Exit (1 )
2833}
@@ -39,27 +44,38 @@ func main() {
3944 fs .Parse (os .Args [2 :])
4045 db := openDB (* dbFlag )
4146 addLog (db , * originFlag )
47+ log .Printf ("Added log %q." , * originFlag )
4248
4349 case "add-key" :
4450 originFlag := fs .String ("origin" , "" , "log name" )
4551 keyFlag := fs .String ("key" , "" , "verifier key" )
4652 fs .Parse (os .Args [2 :])
4753 db := openDB (* dbFlag )
54+ checkKeyMatches (* originFlag , * keyFlag )
4855 addKey (db , * originFlag , * keyFlag )
56+ log .Printf ("Added key %q for log %q." , * keyFlag , * originFlag )
4957
5058 case "del-key" :
5159 originFlag := fs .String ("origin" , "" , "log name" )
5260 keyFlag := fs .String ("key" , "" , "verifier key" )
5361 fs .Parse (os .Args [2 :])
5462 db := openDB (* dbFlag )
5563 delKey (db , * originFlag , * keyFlag )
64+ log .Printf ("Deleted key %q for log %q." , * keyFlag , * originFlag )
5665
5766 case "add-sigsum-log" :
5867 keyFlag := fs .String ("key" , "" , "hex-encoded key" )
5968 fs .Parse (os .Args [2 :])
6069 db := openDB (* dbFlag )
6170 addSigsumLog (db , * keyFlag )
6271
72+ case "pull-logs" :
73+ sourceFlag := fs .String ("source" , "" , "witness network log list URL or file path" )
74+ verboseFlag := fs .Bool ("verbose" , false , "verbose output" )
75+ fs .Parse (os .Args [2 :])
76+ db := openDB (* dbFlag )
77+ pullLogs (db , * sourceFlag , * verboseFlag )
78+
6379 case "list-logs" :
6480 fs .Parse (os .Args [2 :])
6581 db := openDB (* dbFlag )
@@ -84,22 +100,23 @@ func addLog(db *sqlite.Conn, origin string) {
84100 nil , origin , base64 .StdEncoding .EncodeToString (treeHash [:])); err != nil {
85101 log .Fatalf ("Error adding log: %v" , err )
86102 }
87- log .Printf ("Added log %q." , origin )
88103}
89104
90- func addKey ( db * sqlite. Conn , origin string , vk string ) {
105+ func checkKeyMatches ( origin string , vk string ) {
91106 v , err := note .NewVerifier (vk )
92107 if err != nil {
93108 log .Fatalf ("Error parsing verifier key: %v" , err )
94109 }
95110 if v .Name () != origin {
96111 log .Printf ("Warning: verifier key name %q does not match origin %q." , v .Name (), origin )
97112 }
98- err = sqlitex .Exec (db , "INSERT INTO key (origin, key) VALUES (?, ?)" , nil , origin , vk )
113+ }
114+
115+ func addKey (db * sqlite.Conn , origin string , vk string ) {
116+ err := sqlitex .Exec (db , "INSERT INTO key (origin, key) VALUES (?, ?)" , nil , origin , vk )
99117 if err != nil {
100118 log .Fatalf ("Error adding key: %v" , err )
101119 }
102- log .Printf ("Added key %q." , vk )
103120}
104121
105122func delKey (db * sqlite.Conn , origin string , vk string ) {
@@ -110,7 +127,6 @@ func delKey(db *sqlite.Conn, origin string, vk string) {
110127 if db .Changes () == 0 {
111128 log .Fatalf ("Key %q not found." , vk )
112129 }
113- log .Printf ("Deleted key %q." , vk )
114130}
115131
116132func addSigsumLog (db * sqlite.Conn , keyFlag string ) {
@@ -129,6 +145,83 @@ func addSigsumLog(db *sqlite.Conn, keyFlag string) {
129145 }
130146 addLog (db , origin )
131147 addKey (db , origin , vk )
148+ log .Printf ("Added Sigsum log %q with key %q." , origin , vk )
149+ }
150+
151+ func pullLogs (db * sqlite.Conn , source string , verbose bool ) {
152+ var logList []byte
153+ if strings .HasPrefix (source , "https://" ) {
154+ client := http.Client {Timeout : 30 * time .Second }
155+ resp , err := client .Get (source )
156+ if err != nil {
157+ log .Fatalf ("Error fetching log list: %v" , err )
158+ }
159+ defer resp .Body .Close ()
160+ if resp .StatusCode != http .StatusOK {
161+ log .Fatalf ("Error fetching log list: HTTP %d" , resp .StatusCode )
162+ }
163+ logList , err = io .ReadAll (resp .Body )
164+ if err != nil {
165+ log .Fatalf ("Error reading log list: %v" , err )
166+ }
167+ } else {
168+ var err error
169+ logList , err = os .ReadFile (source )
170+ if err != nil {
171+ log .Fatalf ("Error reading log list: %v" , err )
172+ }
173+ }
174+ logs , err := parseLogList (logList , verbose )
175+ if err != nil {
176+ log .Fatalf ("Error parsing log list: %v" , err )
177+ }
178+ for origin , vkey := range logs {
179+ keys , exists := logKeys (db , origin )
180+ if exists {
181+ if keys [vkey ] {
182+ // Key already exists, nothing to do.
183+ if verbose {
184+ log .Printf ("Log %q with key %q already exists, skipping." , origin , vkey )
185+ }
186+ continue
187+ }
188+ // Key is different, warn.
189+ log .Printf ("Warning: log %q is listed with a different key than the one in the database.\n " , origin )
190+ log .Printf (" - existing keys:\n " )
191+ for k := range keys {
192+ log .Printf (" - %q\n " , k )
193+ }
194+ log .Printf (" - new key:\n " )
195+ log .Printf (" - %q\n " , vkey )
196+ continue
197+ }
198+ // New log, add it.
199+ addLog (db , origin )
200+ addKey (db , origin , vkey )
201+ if verbose {
202+ log .Printf ("Added log %q with key %q." , origin , vkey )
203+ }
204+ }
205+ }
206+
207+ func logKeys (db * sqlite.Conn , origin string ) (keys map [string ]bool , exists bool ) {
208+ keys = make (map [string ]bool )
209+ if err := sqlitex .Exec (db , "SELECT 1 FROM log WHERE origin = ?" , func (stmt * sqlite.Stmt ) error {
210+ exists = true
211+ return nil
212+ }, origin ); err != nil {
213+ log .Fatalf ("Error looking for log %q: %v" , origin , err )
214+ }
215+ if ! exists {
216+ return keys , false
217+ }
218+ if err := sqlitex .Exec (db , "SELECT key FROM key WHERE origin = ?" , func (stmt * sqlite.Stmt ) error {
219+ keys [stmt .ColumnText (0 )] = true
220+ return nil
221+ }, origin ); err != nil {
222+ log .Fatalf ("Error querying keys: %v" , err )
223+ }
224+ return keys , true
132225}
133226
134227func listLogs (db * sqlite.Conn ) {
0 commit comments