@@ -12,39 +12,63 @@ import (
12
12
13
13
"github.com/theupdateframework/go-tuf/data"
14
14
"github.com/theupdateframework/go-tuf/encrypted"
15
+ "github.com/theupdateframework/go-tuf/internal/sets"
15
16
"github.com/theupdateframework/go-tuf/pkg/keys"
16
17
"github.com/theupdateframework/go-tuf/util"
17
18
)
18
19
19
- func signers (privateKeys []* data.PrivateKey ) []keys.Signer {
20
- res := make ([]keys.Signer , 0 , len (privateKeys ))
21
- for _ , k := range privateKeys {
22
- signer , err := keys .GetSigner (k )
23
- if err != nil {
24
- continue
25
- }
26
- res = append (res , signer )
27
- }
28
- return res
20
+ type LocalStore interface {
21
+ // GetMeta returns a map from metadata file names (e.g. root.json) to their raw JSON payload or an error.
22
+ GetMeta () (map [string ]json.RawMessage , error )
23
+
24
+ // SetMeta is used to update a metadata file name with a JSON payload.
25
+ SetMeta (name string , meta json.RawMessage ) error
26
+
27
+ // WalkStagedTargets calls targetsFn for each staged target file in paths.
28
+ // If paths is empty, all staged target files will be walked.
29
+ WalkStagedTargets (paths []string , targetsFn TargetsWalkFunc ) error
30
+
31
+ // Commit is used to publish staged files to the repository
32
+ Commit (consistentSnapshot bool , versions map [string ]int , hashes map [string ]data.Hashes ) error
33
+
34
+ // GetSigners return a list of signers for a role.
35
+ GetSigners (role string ) ([]keys.Signer , error )
36
+
37
+ // SaveSigner adds a signer to a role.
38
+ SaveSigner (role string , signer keys.Signer ) error
39
+
40
+ // SignersForRole return a list of signing keys for a role.
41
+ SignersForKeyIDs (keyIDs []string ) []keys.Signer
42
+
43
+ // Clean is used to remove all staged manifests.
44
+ Clean () error
45
+ }
46
+
47
+ type PassphraseChanger interface {
48
+ // ChangePassphrase changes the passphrase for a role keys file.
49
+ ChangePassphrase (string ) error
29
50
}
30
51
31
52
func MemoryStore (meta map [string ]json.RawMessage , files map [string ][]byte ) LocalStore {
32
53
if meta == nil {
33
54
meta = make (map [string ]json.RawMessage )
34
55
}
35
56
return & memoryStore {
36
- meta : meta ,
37
- stagedMeta : make (map [string ]json.RawMessage ),
38
- files : files ,
39
- signers : make (map [string ][]keys.Signer ),
57
+ meta : meta ,
58
+ stagedMeta : make (map [string ]json.RawMessage ),
59
+ files : files ,
60
+ signerForKeyID : make (map [string ]keys.Signer ),
61
+ keyIDsForRole : make (map [string ][]string ),
40
62
}
41
63
}
42
64
43
65
type memoryStore struct {
44
66
meta map [string ]json.RawMessage
45
67
stagedMeta map [string ]json.RawMessage
46
68
files map [string ][]byte
47
- signers map [string ][]keys.Signer
69
+
70
+ signerForKeyID map [string ]keys.Signer
71
+ keyIDsForRole map [string ][]string
48
72
}
49
73
50
74
func (m * memoryStore ) GetMeta () (map [string ]json.RawMessage , error ) {
@@ -96,14 +120,53 @@ func (m *memoryStore) Commit(consistentSnapshot bool, versions map[string]int, h
96
120
}
97
121
98
122
func (m * memoryStore ) GetSigners (role string ) ([]keys.Signer , error ) {
99
- return m .signers [role ], nil
123
+ keyIDs , ok := m .keyIDsForRole [role ]
124
+ if ok {
125
+ return m .SignersForKeyIDs (keyIDs ), nil
126
+ }
127
+
128
+ return nil , nil
100
129
}
101
130
102
131
func (m * memoryStore ) SaveSigner (role string , signer keys.Signer ) error {
103
- m .signers [role ] = append (m .signers [role ], signer )
132
+ keyIDs := signer .PublicData ().IDs ()
133
+
134
+ for _ , keyID := range keyIDs {
135
+ m .signerForKeyID [keyID ] = signer
136
+ }
137
+
138
+ mergedKeyIDs := sets .DeduplicateStrings (append (m .keyIDsForRole [role ], keyIDs ... ))
139
+ m .keyIDsForRole [role ] = mergedKeyIDs
104
140
return nil
105
141
}
106
142
143
+ func (m * memoryStore ) SignersForKeyIDs (keyIDs []string ) []keys.Signer {
144
+ signers := []keys.Signer {}
145
+ keyIDsSeen := map [string ]struct {}{}
146
+
147
+ for _ , keyID := range keyIDs {
148
+ signer , ok := m .signerForKeyID [keyID ]
149
+ if ! ok {
150
+ continue
151
+ }
152
+ addSigner := false
153
+
154
+ for _ , skid := range signer .PublicData ().IDs () {
155
+ if _ , seen := keyIDsSeen [skid ]; ! seen {
156
+ addSigner = true
157
+ }
158
+
159
+ keyIDsSeen [skid ] = struct {}{}
160
+ }
161
+
162
+ if addSigner {
163
+ signers = append (signers , signer )
164
+ }
165
+ }
166
+
167
+ return signers
168
+ }
169
+
107
170
func (m * memoryStore ) Clean () error {
108
171
return nil
109
172
}
@@ -117,16 +180,17 @@ func FileSystemStore(dir string, p util.PassphraseFunc) LocalStore {
117
180
return & fileSystemStore {
118
181
dir : dir ,
119
182
passphraseFunc : p ,
120
- signers : make (map [string ][]keys.Signer ),
183
+ signerForKeyID : make (map [string ]keys.Signer ),
184
+ keyIDsForRole : make (map [string ][]string ),
121
185
}
122
186
}
123
187
124
188
type fileSystemStore struct {
125
189
dir string
126
190
passphraseFunc util.PassphraseFunc
127
191
128
- // signers is a cache of persisted keys to avoid decrypting multiple times
129
- signers map [string ][]keys. Signer
192
+ signerForKeyID map [ string ] keys. Signer
193
+ keyIDsForRole map [string ][]string
130
194
}
131
195
132
196
func (f * fileSystemStore ) repoDir () string {
@@ -319,18 +383,63 @@ func (f *fileSystemStore) Commit(consistentSnapshot bool, versions map[string]in
319
383
}
320
384
321
385
func (f * fileSystemStore ) GetSigners (role string ) ([]keys.Signer , error ) {
322
- if keys , ok := f .signers [role ]; ok {
323
- return keys , nil
386
+ keyIDs , ok := f .keyIDsForRole [role ]
387
+ if ok {
388
+ return f .SignersForKeyIDs (keyIDs ), nil
324
389
}
325
- keys , _ , err := f .loadPrivateKeys (role )
390
+
391
+ privKeys , _ , err := f .loadPrivateKeys (role )
326
392
if err != nil {
327
393
if os .IsNotExist (err ) {
328
394
return nil , nil
329
395
}
330
396
return nil , err
331
397
}
332
- f .signers [role ] = signers (keys )
333
- return f .signers [role ], nil
398
+
399
+ signers := []keys.Signer {}
400
+ for _ , key := range privKeys {
401
+ signer , err := keys .GetSigner (key )
402
+ if err != nil {
403
+ return nil , err
404
+ }
405
+
406
+ // Cache the signers.
407
+ for _ , keyID := range signer .PublicData ().IDs () {
408
+ f .keyIDsForRole [role ] = append (f .keyIDsForRole [role ], keyID )
409
+ f .signerForKeyID [keyID ] = signer
410
+ }
411
+ signers = append (signers , signer )
412
+ }
413
+
414
+ return signers , nil
415
+ }
416
+
417
+ func (f * fileSystemStore ) SignersForKeyIDs (keyIDs []string ) []keys.Signer {
418
+ signers := []keys.Signer {}
419
+ keyIDsSeen := map [string ]struct {}{}
420
+
421
+ for _ , keyID := range keyIDs {
422
+ signer , ok := f .signerForKeyID [keyID ]
423
+ if ! ok {
424
+ continue
425
+ }
426
+
427
+ addSigner := false
428
+
429
+ for _ , skid := range signer .PublicData ().IDs () {
430
+ if _ , seen := keyIDsSeen [skid ]; ! seen {
431
+ addSigner = true
432
+ }
433
+
434
+ keyIDsSeen [skid ] = struct {}{}
435
+ }
436
+
437
+ if addSigner {
438
+ signers = append (signers , signer )
439
+ }
440
+ }
441
+
442
+ return signers
334
443
}
335
444
336
445
// ChangePassphrase changes the passphrase for a role keys file. Implements
@@ -377,15 +486,15 @@ func (f *fileSystemStore) SaveSigner(role string, signer keys.Signer) error {
377
486
}
378
487
379
488
// add the key to the existing keys (if any)
380
- keys , pass , err := f .loadPrivateKeys (role )
489
+ privKeys , pass , err := f .loadPrivateKeys (role )
381
490
if err != nil && ! os .IsNotExist (err ) {
382
491
return err
383
492
}
384
493
key , err := signer .MarshalPrivateKey ()
385
494
if err != nil {
386
495
return err
387
496
}
388
- keys = append (keys , key )
497
+ privKeys = append (privKeys , key )
389
498
390
499
// if loadPrivateKeys didn't return a passphrase (because no keys yet exist)
391
500
// and passphraseFunc is set, get the passphrase so the keys file can
@@ -400,13 +509,13 @@ func (f *fileSystemStore) SaveSigner(role string, signer keys.Signer) error {
400
509
401
510
pk := & persistedKeys {}
402
511
if pass != nil {
403
- pk .Data , err = encrypted .Marshal (keys , pass )
512
+ pk .Data , err = encrypted .Marshal (privKeys , pass )
404
513
if err != nil {
405
514
return err
406
515
}
407
516
pk .Encrypted = true
408
517
} else {
409
- pk .Data , err = json .MarshalIndent (keys , "" , "\t " )
518
+ pk .Data , err = json .MarshalIndent (privKeys , "" , "\t " )
410
519
if err != nil {
411
520
return err
412
521
}
@@ -418,7 +527,26 @@ func (f *fileSystemStore) SaveSigner(role string, signer keys.Signer) error {
418
527
if err := util .AtomicallyWriteFile (f .keysPath (role ), append (data , '\n' ), 0600 ); err != nil {
419
528
return err
420
529
}
421
- f .signers [role ] = append (f .signers [role ], signer )
530
+
531
+ innerKeyIdsForRole := f .keyIDsForRole [role ]
532
+
533
+ for _ , key := range privKeys {
534
+ signer , err := keys .GetSigner (key )
535
+ if err != nil {
536
+ return err
537
+ }
538
+
539
+ keyIDs := signer .PublicData ().IDs ()
540
+
541
+ for _ , keyID := range keyIDs {
542
+ f .signerForKeyID [keyID ] = signer
543
+ }
544
+
545
+ innerKeyIdsForRole = append (innerKeyIdsForRole , keyIDs ... )
546
+ }
547
+
548
+ f .keyIDsForRole [role ] = sets .DeduplicateStrings (innerKeyIdsForRole )
549
+
422
550
return nil
423
551
}
424
552
0 commit comments