Skip to content

Commit

Permalink
Update initializeTUF to fetch new metadata when timestamp expires
Browse files Browse the repository at this point in the history
This changes the singleton to only initialize the client once, but on
every invocation, check if the timestamp is expired.

I wrapped all of this in a mutex to prevent concurrent updates (I'm not
sure if this would be safe, I assume the TUF object is not thread-safe).

Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
  • Loading branch information
haydentherapper committed Jan 13, 2023
1 parent ad3adf3 commit 50c8aa4
Showing 1 changed file with 34 additions and 21 deletions.
55 changes: 34 additions & 21 deletions pkg/tuf/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ var (
singletonTUF *TUF
singletonTUFOnce = new(sync.Once)
singletonTUFErr error

// initMu locks concurrent calls to initializeTUF
initMu sync.Mutex
)

// getRemoteRoot is a var for testing.
Expand Down Expand Up @@ -240,28 +243,32 @@ func GetRootStatus(ctx context.Context) (*RootStatus, error) {
// * forceUpdate: indicates checking the remote for an update, even when the local
// timestamp.json is up to date.
func initializeTUF(mirror string, root []byte, embedded fs.FS, forceUpdate bool) (*TUF, error) {
initMu.Lock()
defer initMu.Unlock()

var initErr error
singletonTUFOnce.Do(func() {
t := &TUF{
mirror: mirror,
embedded: embedded,
}

t.targets = newFileImpl()
t.local, singletonTUFErr = newLocalStore()
if singletonTUFErr != nil {
t.local, initErr = newLocalStore()
if initErr != nil {
return
}

t.remote, singletonTUFErr = remoteFromMirror(t.mirror)
if singletonTUFErr != nil {
t.remote, initErr = remoteFromMirror(t.mirror)
if initErr != nil {
return
}

t.client = client.NewClient(t.local, t.remote)

trustedMeta, err := t.local.GetMeta()
if err != nil {
singletonTUFErr = fmt.Errorf("getting trusted meta: %w", err)
initErr = fmt.Errorf("getting trusted meta: %w", err)
return
}

Expand All @@ -270,33 +277,39 @@ func initializeTUF(mirror string, root []byte, embedded fs.FS, forceUpdate bool)
if root == nil {
root, err = getRoot(trustedMeta, t.embedded)
if err != nil {
singletonTUFErr = fmt.Errorf("getting trusted root: %w", err)
initErr = fmt.Errorf("getting trusted root: %w", err)
return
}
}

if err := t.client.Init(root); err != nil {
singletonTUFErr = fmt.Errorf("unable to initialize client, local cache may be corrupt: %w", err)
initErr = fmt.Errorf("unable to initialize client, local cache may be corrupt: %w", err)
return
}

// We may already have an up-to-date local store! Check to see if it needs to be updated.
trustedTimestamp, ok := trustedMeta["timestamp.json"]
if ok && !isExpiredTimestamp(trustedTimestamp) && !forceUpdate {
// We're golden so stash the TUF object for later use
singletonTUF = t
return
}
singletonTUF = t
})
if initErr != nil {
return nil, initErr
}

// Update if local is not populated or out of date.
if err := t.updateMetadataAndDownloadTargets(); err != nil {
singletonTUFErr = fmt.Errorf("updating local metadata and targets: %w", err)
return
}
trustedMeta, err := singletonTUF.local.GetMeta()
if err != nil {
return nil, fmt.Errorf("getting trusted meta: %w", err)
}

// We may already have an up-to-date local store! Check to see if it needs to be updated.
trustedTimestamp, ok := trustedMeta["timestamp.json"]
if ok && !isExpiredTimestamp(trustedTimestamp) && !forceUpdate {
// We're golden so stash the TUF object for later use
singletonTUF = t
})
return singletonTUF, nil
}

// Update if local is not populated or out of date.
if err := singletonTUF.updateMetadataAndDownloadTargets(); err != nil {
return nil, fmt.Errorf("updating local metadata and targets: %w", err)
}

return singletonTUF, singletonTUFErr
}

Expand Down

0 comments on commit 50c8aa4

Please sign in to comment.