Package release workflow with Monitor Worker

The diagram below illustrates a generic package release workflow with Rugged TUF signing integrated.

Examples:

See the Operations section below for a description of the Monitor workers’ functionality. For more details, see the Monitor worker operating environment page.

sequenceDiagram participant PP as Packaging
Pipeline participant POST as Post-to-TUF
Directory (NFS) participant TUF as Monitor
Worker participant FS as Shared
Filesystem(s) participant TARGETS as Targets
Worker participant SNAPSHOT as Snapshot
Worker participant TIMESTAMP as Timestamp
Worker autonumber activate TUF rect rgba(0, 0, 0, .05) note over POST,TUF: Part 1: Periodic scan for new targets loop Every 5 seconds TUF->>POST: Scan post-to-TUF directory activate POST POST->>TUF: List of post-to-TUF directory contents deactivate POST break If a target is being processed TUF--xTUF: STOP
- - (Allow currently processing target to complete) - - deactivate TUF end activate TUF break If no targets are ready to be processed TUF--xTUF: STOP
- - - - - - - - - - - (Nothing to do) - - - - - - - - - - - - deactivate TUF end end end rect rgba(0, 255, 255, .1) note over PP: Part 2: Regular packaging pipeline activate PP PP->>PP: Clone code PP->>PP: Build package note right of PP: <PACKAGE>-<VERSION>.zip PP->>PP: Generate package
metadata note right of PP: <PACKAGE>.json end rect rgba(255, 0, 0, .1) note over PP,TUF: Part 3: Post to TUF PP->>PP: Generate timestamp PP->>POST: Create unique temporary directory activate POST note left of POST: tuf_tmp_<TIMESTAMP>/ loop Every 5 seconds TUF->>POST: Scan post-to-TUF directory activate TUF POST->>TUF: List of post-to-TUF directory contents break If no targets are ready TUF--xTUF: STOP
- - (Monitor worker only looks for 'tuf_ready_') - - deactivate TUF end end PP->>POST: Copy target files to directory
(across network filesystem boundary) PP->>POST: Rename temporary directory deactivate PP deactivate POST note left of POST: tuf_ready_<TIMESTAMP>/ loop Every 5 seconds TUF->>POST: Scan post-to-TUF directory activate TUF activate POST POST->>TUF: List of post-to-TUF directory contents deactivate POST break If another target is being processed TUF--xTUF: STOP
- - (Allow currently processing target to complete) - - deactivate TUF end end end rect rgba(0, 255, 0, .1) note over POST,FS: Part 4: Prepare inbound targets loop Every 5 seconds TUF->>POST: Scan post-to-TUF directory activate TUF activate POST POST->>TUF: List of post-to-TUF directory contents TUF-->TUF: No currently processing targets critical Ready target is detected TUF->>POST: Rename directory to indicate processing note right of POST: tuf_processing_<TIMESTAMP>/ POST->>FS: Create processing directory in inbound directory activate FS note left of FS: tuf_processing_<TIMESTAMP>/ TUF->>POST: POST->>FS: Move target files
to inbound processing directory
(across network filesystem boundary) TUF->>FS: Move target files
from inbound processing directory
to inbound directory TUF->>FS: Delete inbound processing directory TUF->>TARGETS: Trigger signing of target files activate TARGETS end end end rect rgba(0, 0, 0, .05) note over TUF,TIMESTAMP: Part 5: Regular TUF signing TARGETS->>FS: Scan inbound directory loop For each target file FS-->>TARGETS: Read target file TARGETS->>TARGETS: Update Targets metadata
(with signature of target file) end TARGETS->>TARGETS: Sign Targets metadata TARGETS-->>FS: Write updated Targets metadata note right of FS: targets.json TARGETS->>TUF: Return status deactivate TARGETS TUF->>SNAPSHOT: Trigger Snapshot update activate SNAPSHOT SNAPSHOT->>SNAPSHOT: Update and sign
Snapshot metadata SNAPSHOT-->>FS: Write updated Snapshot metadata note right of FS: snapshot.json SNAPSHOT ->>TUF: Return status deactivate SNAPSHOT TUF->>TIMESTAMP: Trigger Timestamp update activate TIMESTAMP TIMESTAMP->>TIMESTAMP: Update and sign
Timestamp metadata TIMESTAMP-->>FS: Write updated Timestamp metadata note right of FS: timestamp.json TIMESTAMP->>TUF: Return status deactivate FS deactivate TIMESTAMP end rect rgba(0, 0, 0, .05) note over POST,TUF: Part 6: Clean up and release semaphore TUF->>POST: Delete processing directory deactivate POST deactivate TUF end

Operations

Part 1: Periodic scan for new targets

The Monitor Worker uses a cron-like mechanism (provided by Celery) to schedule periodic tasks. In particular, it schedules a find-new-targets task to run every 5 seconds. The interval is configurable using the scheduler_scan_period option.

This task checks for new targets that are ready to process in the “post-to-tuf” directory. The path to this directory is configurable using the post_to_tuf_path option.

Note that we’re copying files across network-mounted file-system boundaries, and this can take a while to complete. With a high enough volume, a second monitor-worker process could be triggered before the current one ends. This could result in targets.json being written by the first process, while the second one had not yet signed all of its targets. Since we need the targets.json to include all targets for a given package, we need to process packages serially.

As we’ll see in Part 4 (“Prepare inbound targets”), the Monitor Worker renames the directory it’s currently processing to tuf_processing_<TIMESTAMP>. This directory acts as a semaphore to indicate to subsequent scheduled runs that Rugged is already occupied processing a batch of targets.

So, at this point in the periodic scan, monitor-worker looks for a directory starting with tuf_processing_. If it finds one, then it ends the current process. If not, it proceeds to look for a target that is ready for processing, indicated by the tuf_ready_ prefix. We’ll explore this in Part 3 (“Post to TUF”).

Part 2: Regular packaging pipeline

This part reflects a typical packaging process. Generally it will result in multiple artifacts, usually consisting of at least an archive of the package source code, and a file containing metadata for use by the package manager and repository.

Nothing has to be modified in this process to accomodate TUF-signing by Rugged.

Part 3: Post to TUF

This part describes the steps necessary for the packaging pipeline to provide its packages to the Monitor Worker.

N.B. The packaging pipeline must mount a network filesystem (typically NFS, or similar) that contains the “post-to-TUF” directory. This filesystem is shared with the Monitor Worker, but not the other workers that make up the Rugged TUF Server.

A script running in the packaging pipeline environment must perform the following steps:

  1. Generate a timestamp (using microtime)
  2. Create a temporary directory locally (tuf_tmp_<TIMESTAMP>/) in the post-to-TUF directory
  3. Copy the artifacts for signing into the temporary directory (note: this crosses a network filesystem boundary)
  4. Rename the temporary directory (to tuf_ready_<TIMESTAMP>) (note: this must not cross a filesystem boundary)

The timestamp uses microseconds in order to ensure the uniqueness of the subsequently created directories.

The Monitor Worker will ignore the presense of the temporary directory. This is intended to ensure consistency in writing to the network filesystem.

Renaming the directory to tuf_ready_<TIMESTAMP> indicates to the Monitor Worker that this package’s targets are ready for processing. Any ready target directories ought to be ordered by the timestamp embedded in the filename. This will ensure that they are processed in order, on a first-in, first-out basis.

As mentioned in Part 1, and elaborated further in Part 4 (below), if another target is being processed, this will be indicated by the presence of a tuf_processing_<TIMESTAMP> directory within the post-to-tuf directory. If such a directory exists, the Monitor worker will not proceed with processing any ready targets.

Part 4: Prepare inbound targets

When the Monitor Worker detects that there are no currently processing targets, it will select the first ready target, based on the oldest timestamp. Immediately upon selecting a directory containing ready targets, it will rename it to tuf_processing_<TIMESTAMP>. As previously noted, this will block any further periodic processes from starting to process additional targets.

Next, the Monitor Worker creates a new directory with the same name (tuf_processing_<TIMESTAMP>), in Rugged’s “inbound” directory, preserving the existing timestamp. This directory (and its contents) will be ignored by the Targets Worker.

It then moves the target files from the post-to-tuf processing directory, to the identically named one in the inbound directory. This may cross a network filesystem boundary, and thus may take a non-trivial amount of time to complete.

In order to prepare the target files for signing, the Monitor Worker then moves the files from the inbound processing directory (typically /var/rugged/inbound_targets/tuf_processing_<TIMESTAMP>/ on the Rugged shared filesystem) to the inbound directory (typically /var/rugged/inbound_targets/ on the Rugged shared filesystem). It then deletes the now-empty inbound processing directory.

Finally, the Monitor worker triggers the signing of target files by posting a task for the Targets Worker to add targets.

Part 5: Regular TUF signing

At this point, the regular TUF signing process begins. The Targets Worker, having received an add-targets task proceeds to:

  1. Scan the inbound directory
  2. Add metadata about each target file, including a hash of each target file’s content
  3. Sign the targets metadata
  4. Write the targets metadata to targets.json
  5. Return its status to the Monitor Worker.

The Monitor worker then proceeds to trigger a Snapshot update, followed by a Timestamp update.

Part 6: Cleanup and release semaphore

With the TUF metadata now fully updated and consistent, the Monitor Worker deletes the tuf_processing_<TIMESTAMP> directory within the post-to-tuf directory. This allows the subsequent Monitor Worker periodic task to proceed with processing the next ready target (if any).

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
Rugged TUF Server is a trademark of Consensus Enterprises.