Skip to content

Latest commit

 

History

History
290 lines (182 loc) · 10.3 KB

README.adoc

File metadata and controls

290 lines (182 loc) · 10.3 KB

tuf command line tools

Obtaining the binary

Binaries are compiled for each push to master and stored in s3.

Download the archive file, unpack and run:

tar xvf <file>
cd garage-sign/
bin/garage-sign --help

Delegations

There are two actors in a delegations use case. The OEM, which owns the remote repository managed by ota-tuf, and the Supplier, which will sign metadata about a component they build.

The OEM runs garage-sign against a local repository initialized using garage-sign init. The changes can then be pushed as normal to a remote ota-tuf repository.

The Supplier runs garage-sign but does not have a local repository, instead the supplier edits metadata files using garage-sign. The resulting files can then be sent to the OEM using a secure channel (e.g. encrypted email), which adds that data to their local and remote repositories.

The basic use case for delegations works as follows.

  1. The OEM manages a local repository as normal:

    garage-sign init --repo paris -c credentials-paris.zip
    garage-sign targets pull --repo paris
  2. The supplier generates a key that they will use to sign their metadata:

    garage-sign user-keys gen --key-name supplier01-key --type ed25519
  3. The supplier sends the Public part of the key to the OEM using a secure channel.

  4. The OEM adds the delegation to their local targets.json, using the new key

    garage-sign targets delegations add --name supplier01 --prefix 'supplier01*' --key tuf/user-keys/supplier01-key.pub --repo paris
  5. The OEM signs the new targets.json and pushes it to the remote repository:

    garage-sign targets sign --repo paris --key-name targets
    garage-sign targets push --repo paris
  6. The Supplier initializes a delegations file and adds metadata about their images to the file.

    garage-sign delegations init > delegations01.json
    garage-sign delegations add-target --input delegations01.json  --inplace \
       --length 1024 \
       --name supplier01-target01.tar.gz \
       --version 0.0.1 \
       --sha256 766644289a2036c54f3485f5eae5144a08d003fc2f897de5faf8dc45bb2b0ea1 \
       --hardwareids laptop
       --url https://example.com
  7. The supplier signs the delegations metadata and sends it to the OEM:

    garage-sign delegations sign --inplace --input delegations01.json --key-name supplier01-key

    After signing the delegations the file will need to be converted back to an unsigned file to be modified, for example to add another target. This can be done with:

    jq .signed delegations01.json  > delegations01-unsigned.json
  8. The OEM pushes the signed role to the remote repository:

    garage-sign delegations push --repo paris --input delegations01.json --name supplier01
  9. The delegation and targets are ready for the client to validate:

    garage-sign targets pull --repo paris
    garage-sign delegations pull --repo paris --name supplier01

Offline signing use case

  1. User rotates root keys offline, see Rotate Root Keys. This usually does not happen on the same machine where the targets are pulled/pushed.

  2. Pull targets

    garage-sign targets pull --repo myrepo
  3. Add a target

    garage-sign targets add --repo myrepo \
    --format binary \
    --length 5877 \
    --name dashboards \
    --version 0.0.2 \
    --sha256 a0d3e88637d93e20e37b8eaf85fe8e8ac8ac5018337e881a452c85f8b64df0a4 \
    --hardwareids hwid01 \
    --url http://localhost/dashboards.json
  4. Sign new targets.json

    garage-sign targets sign --repo myrepo --key-name <targets key used to rotate>
  5. Push new targets.json

    garage-sign targets push --repo myrepo

Rotate Root Keys

Rotate Repo Server Root Keys

  1. Initialize a local ota-plus cache using credentials.zip downloaded from ATS Garage:

    garage-sign init --repo myrepo --servertype reposerver --credentials credentials.zip --reposerver <reposerver uri>

    or

    garage-sign init --repo myrepo --servertype reposerver --credentials credentials.zip
  2. Generate new root and target keys

    garage-sign key generate --repo myrepo --name myrepo-root --type ed25519
    garage-sign key generate --repo myrepo --name myrepo-targets --type ed25519
  3. Rotate Root Keys

    garage-sign move-offline --repo myrepo --new-root myrepo-root \
    --new-targets myrepo-targets --old-root-alias old-root
  4. Check repository

    tree tuf/myrepo/
    tuf/myrepo
    ├── auth.json
    ├── keys
    │   ├── myrepo-root.pub
    │   ├── myrepo-root.sec
    │   ├── myrepo-targets.pub
    │   ├── myrepo-targets.sec
    │   ├── old-root.pub
    │   └── old-root.sec
    └── roles
        └── root.json
    cat tuf/myrepo/root.json
  5. It is recommended that at this point you sign targets.json with the new keys and upload it to reposerver, otherwise clients will get an error when trying to validate the old targets.json, retrieved by the server, with the new root.json.

    cat tuf/myrepo/roles/unsigned/targets.json
    # verify unsigned targets.json, this should have been pulled
    # during `rotate`.
    garage-sign targets sign --repo myrepo --key-name myrepo-targets
    garage-sign targets push --repo myrepo

Exporting credentials

After Rotate Root Keys, you will need the new root.json and keys to sign targets using targets-sign. If the user signing the new targets is not the same as the user rotating the root keys, you’ll need to export the new credentials:

garage-sign  export-credentials --repo myrepo --target-key-name targets --to creds_export.zip

Rotate Director Root Keys

Target keys and meta data are managed by the director even in the offline case, so they don’t need to be dealt with here.

  1. Initialize a local ota-plus cache using credentials.zip downloaded from ATS Garage:

    garage-sign init --repo myrepo --servertype director --credentials credentials.zip --reposerver <reposerver uri>

    or

    garage-sign init --repo myrepo --servertype director --credentials credentials.zip
  2. Generate new root key

    garage-sign key generate --repo myrepo --name myrepo-root --type ed25519
  3. Rotate Root Key

    garage-sign move-offline --repo myrepo --new-root myrepo-root --old-root-alias old-root
  4. Check repository

    tree tuf/myrepo/
    tuf/myrepo
    ├── auth.json
    ├── keys
    │   ├── myrepo-root.pub
    │   ├── myrepo-root.sec
    │   ├── old-root.pub
    │   └── old-root.sec
    └── roles
        └── root.json
    cat tuf/myrepo/root.json

Rotate Offline Root Key

After rotating an online root key, the environment is updated to use locally stored offline keys. In order to rotate an offline key, follow these steps:

  1. Get the current version of root.json from OTA Connect

    garage-sign root pull --repo myrepo
  2. Generate a new root key

    garage-sign key generate --repo myrepo --name new-offline-root --type rsa
  3. Add the generated key to the list of keys authorized to sign root-of-trust metadata:

    garage-sign root key add --repo myrepo --key-name new-offline-root
  4. Remove the old key

    garage-sign root key remove --repo myrepo --key-name old-root
  5. Sign root.json with both old and new keys

    garage-sign root sign --repo myrepo --key-name old-root --key-name new-offline-root
  6. Upload local root.json to OTA Connect

    garage-sign root push --repo myrepo

Finding the role JSON files

Initially you can find the signed root.json in credentials.zip which you provide when initializing the repository.

The unsigned versions of root.json and targets.json are pulled from the OTA server with root pull and targets pull respectively and are stored under tuf/<reponame>/roles/unsigned path. If you haven’t previously created any targets - targets init will create the unsigned targets.json.

Managing an offline root.json

A root.json can be managed entirely offline by a user using garage-sign.

This can be done by pulling a root with root pull, editing the root using the root key commands, or directly editing the unsigned root file, and signing the new root with root sign. The resulting root can then be pushed to the server with root push.

Client TLS Authentication support

cli has experimental support for authentication to a tuf repository using TLS credentials. If the credentials.zip file used to initialize a repository contains a valid PKCS #12 file for client authentication, cli will use that certificate for authentication and ignore the oauth credentials.

If you already have an initialized repository, you can use the import-client-cert command to add a client certificate to your repository.

If you have a valid credentials.zip containing a client certificate, you can add this certificate to an already initialized repository using the following command

unzip -p -l <path to credentials.zip> client_cert.p12 | garage-sign --tuf-repo ... import-client-cert --client-cert /dev/stdin

All subsequent garage-sign operations will use this certificate for authentication to a tuf repository.

Appendix: Giving expiration dates on the command line

The commands garage-sign sign root and garage-sign sign targets take the date from the unsigned metadata by default. If the date lies in the past, they refuse to sign. The expired date can still be used in that case by giving the option --force. If you want to change the date of the signed metadata you need to give a new date with --expires or --expire-after which also checks if it is in the past, which can again be overwritten with --force.

--expires takes an absolute UTC instant such as 2018-01-01T00:01:00Z. --expire-after takes a relative expiration delay in years, months and days (each optional, but in that order), such as 1Y3M5D.

Uploading a target binary to reposerver

The garage-sign tool supports uploading binary files to reposerver. These binaries can then be easily added to the user’s targets.json.

garage-sign targets pull --repo dev
garage-sign targets upload --repo dev --input bigfile.bin --name name-of-target --version 0.0.2
garage-sign targets add-uploaded --repo dev --input bigfile.bin- --name name-of-target --version 0.0.2 --hardwareids <hardware-id1>,<hardware-id2>
garage-sign targets sign --repo dev --key-name targets
garage-sign targets push --repo dev