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
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.
-
The OEM manages a local repository as normal:
garage-sign init --repo paris -c credentials-paris.zip garage-sign targets pull --repo paris
-
The supplier generates a key that they will use to sign their metadata:
garage-sign user-keys gen --key-name supplier01-key --type ed25519
-
The supplier sends the Public part of the key to the OEM using a secure channel.
-
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
-
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
-
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
-
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
-
The OEM pushes the signed role to the remote repository:
garage-sign delegations push --repo paris --input delegations01.json --name supplier01
-
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
-
User rotates root keys offline, see Rotate Root Keys. This usually does not happen on the same machine where the targets are pulled/pushed.
-
Pull targets
garage-sign targets pull --repo myrepo
-
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
-
Sign new targets.json
garage-sign targets sign --repo myrepo --key-name <targets key used to rotate>
-
Push new targets.json
garage-sign targets push --repo myrepo
-
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
-
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
-
Rotate Root Keys
garage-sign move-offline --repo myrepo --new-root myrepo-root \ --new-targets myrepo-targets --old-root-alias old-root
-
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
-
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 oldtargets.json
, retrieved by the server, with the newroot.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
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
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.
-
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
-
Generate new root key
garage-sign key generate --repo myrepo --name myrepo-root --type ed25519
-
Rotate Root Key
garage-sign move-offline --repo myrepo --new-root myrepo-root --old-root-alias old-root
-
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
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:
-
Get the current version of
root.json
from OTA Connectgarage-sign root pull --repo myrepo
-
Generate a new root key
garage-sign key generate --repo myrepo --name new-offline-root --type rsa
-
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
-
Remove the old key
garage-sign root key remove --repo myrepo --key-name old-root
-
Sign
root.json
with both old and new keysgarage-sign root sign --repo myrepo --key-name old-root --key-name new-offline-root
-
Upload local
root.json
to OTA Connectgarage-sign root push --repo myrepo
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.
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
.
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.
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.
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