Merge pull request #849 from theupdateframework/clarify_role_of_cli

Reframe CLI, revise quickstart, and reorganize tutorials
This commit is contained in:
Sebastien Awwad 2019-04-08 15:23:22 -04:00 committed by GitHub
commit 4f01a31346
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 312 additions and 235 deletions

View file

@ -1,11 +1,15 @@
# CLI #
# Command-Line Interface #
The CLI requires a few dependencies and C extensions that can be installed with
`pip install securesystemslib[crypto,pynacl]`.
The TUF command-line interface (CLI) requires a full
[TUF installation](INSTALLATION.rst). Be sure to include the installation of
extra dependencies and C extensions (
```pip install securesystemslib[crypto,pynacl]```).
[CLI_EXAMPLES.md](CLI_EXAMPLES.md) covers more complex examples.
The use of the CLI is documented with examples below.
----
# Basic Examples #
## Create a repository ##
Create a TUF repository in the current working directory. A cryptographic key
@ -235,3 +239,211 @@ $ repo.py --clean
$ repo.py --clean --path </path/to/dirty/repo>
```
----
# Further Examples #
## Basic Update Delivery ##
Steps:
(1) initialize a repo.
(2) delegate trust of target files to another role.
(3) add a trusted file to the delegated role.
(4) fetch the trusted file from the delegated role.
```Bash
Step (1)
$ repo.py --init
Step (2)
$ repo.py --key ed25519 --filename mykey
$ repo.py --delegate "README.*" --delegatee myrole --pubkeys tufkeystore/mykey.pub
$ repo.py --sign tufkeystore/mykey --role myrole
Enter a password for the encrypted key (tufkeystore/mykey):
$ echo "my readme text" > README.txt
Step (3)
$ repo.py --add README.txt --role myrole --sign tufkeystore/mykey
Enter a password for the encrypted key (tufkeystore/mykey):
```
Serve the repo
```Bash
$ cd tufrepo/
$ python -m SimpleHTTPServer 8001
```
```Bash
Step (4)
$ client.py --repo http://localhost:8001 README.txt
$ tree .
.
├── tuf.log
├── tufrepo
│   └── metadata
│   ├── current
│   │   ├── 1.root.json
│   │   ├── myrole.json
│   │   ├── root.json
│   │   ├── snapshot.json
│   │   ├── targets.json
│   │   └── timestamp.json
│   └── previous
│   ├── 1.root.json
│   ├── root.json
│   ├── snapshot.json
│   ├── targets.json
│   └── timestamp.json
└── tuftargets
└── README.txt
5 directories, 13 files
```
## Correcting a Key ##
The filename of the top-level keys must be "root_key," "targets_key,"
"snapshot_key," and "root_key." The filename can vary for any additional
top-level key.
Steps:
(1) initialize a repo containing default keys for the top-level roles.
(2) distrust the default key for the root role.
(3) create a new key and trust its use with the root role.
(4) sign the root metadata file.
```Bash
Step (1)
$ repo.py --init
Step (2)
$ repo.py --distrust --pubkeys tufkeystore/root_key.pub --role root
Step (3)
$ repo.py --key ed25519 --filename root_key
$ repo.py --trust --pubkeys tufkeystore/root_key.pub --role root
Step (4)
$ repo.py --sign tufkeystore/root_key --role root
Enter a password for the encrypted key (tufkeystore/root_key):
```
## More Update Delivery ##
Steps:
(1) create a bare repo.
(2) add keys to the top-level roles.
(3) delegate trust of particular target files to another role X, where role X
has a signature threshold 2 and is marked as a terminating delegation. The
keys for role X and Y should be created prior to performing the delegation.
(4) Delegate from role X to role Y.
(5) have role X sign for a file also signed by the Targets role, to demonstrate
the expected file that should be downloaded by the client.
(6) perform an update.
(7) halt the server, add README.txt to the Targets role, restart the server,
and fetch the Target's role README.txt.
(8) Add LICENSE to 'role_y' and demonstrate that the client must not fetch it
because 'role_x' is a terminating delegation (and hasn't signed for it).
```Bash
Steps (1) and (2)
$ repo.py --init --consistent --bare
$ repo.py --key ed25519 --filename root_key
$ repo.py --trust --pubkeys tufkeystore/root_key.pub --role root
$ repo.py --key ecdsa --filename targets_key
$ repo.py --trust --pubkeys tufkeystore/targets_key.pub --role targets
$ repo.py --key rsa --filename snapshot_key
$ repo.py --trust --pubkeys tufkeystore/snapshot_key.pub --role snapshot
$ repo.py --key ecdsa --filename timestamp_key
$ repo.py --trust --pubkeys tufkeystore/timestamp_key.pub --role timestamp
$ repo.py --sign tufkeystore/root_key --role root
Enter a password for the encrypted key (tufkeystore/root_key):
$ repo.py --sign tufkeystore/targets_key --role targets
Enter a password for the encrypted key (tufkeystore/targets_key):
```
```Bash
Steps (3) and (4)
$ repo.py --key ed25519 --filename key_x
$ repo.py --key ed25519 --filename key_x2
$ repo.py --delegate "README.*" "LICENSE" --delegatee role_x --pubkeys
tufkeystore/key_x.pub tufkeystore/key_x2.pub --threshold 2 --terminating
$ repo.py --sign tufkeystore/key_x tufkeystore/key_x2 --role role_x
$ repo.py --key ed25519 --filename key_y
$ repo.py --delegate "README.*" "LICENSE" --delegatee role_y --role role_x
--pubkeys tufkeystore/key_y.pub --sign tufkeystore/key_x tufkeystore/key_x2
$ repo.py --sign tufkeystore/key_y --role role_y
```
```Bash
Steps (5) and (6)
$ echo "role_x's readme" > README.txt
$ repo.py --add README.txt --role role_x --sign tufkeystore/key_x tufkeystore/key_x2
```
Serve the repo
```Bash
$ cd tufrepo/
$ python -m SimpleHTTPServer 8001
```
Fetch the role x's README.txt
```Bash
$ client.py --repo http://localhost:8001 README.txt
$ cat tuftargets/README.txt
role_x's readme
```
```Bash
Step (7)
halt the server...
$ echo "Target role's readme" > README.txt
$ repo.py --add README.txt
restart the server...
```
```Bash
$ rm -rf tuftargets/ tuf.log
$ client.py --repo http://localhost:8001 README.txt
$ cat tuftargets/README.txt
Target role's readme
```
```Bash
Step (8)
$ echo "role_y's license" > LICENSE
$ repo.py --add LICENSE --role role_y --sign tufkeystore/key_y
```
```Bash
$ rm -rf tuftargets/ tuf.log
$ client.py --repo http://localhost:8001 LICENSE
Error: 'LICENSE' not found.
```

View file

@ -1,204 +0,0 @@
# CLI Usage Examples #
This document contains a few examples of creating repositories with the CLI.
The sections below correspond with a different example, and each begins with an
outline of the steps to be followed by the user.
## A basic example ##
Steps:
(1) initialize a repo.
(2) delegate trust of target files to another role.
(3) add a trusted file to the delegated role.
(4) fetch the trusted file from the delegated role.
```Bash
Step (1)
$ repo.py --init
Step (2)
$ repo.py --key ed25519 --filename mykey
$ repo.py --delegate "README.*" --delegatee myrole --pubkeys tufkeystore/mykey.pub
$ repo.py --sign tufkeystore/mykey --role myrole
Enter a password for the encrypted key (tufkeystore/mykey):
$ echo "my readme text" > README.txt
Step (3)
$ repo.py --add README.txt --role myrole --sign tufkeystore/mykey
Enter a password for the encrypted key (tufkeystore/mykey):
```
Serve the repo
```Bash
$ cd tufrepo/
$ python -m SimpleHTTPServer 8001
```
```Bash
Step (4)
$ client.py --repo http://localhost:8001 README.txt
$ tree .
.
├── tuf.log
├── tufrepo
│   └── metadata
│   ├── current
│   │   ├── 1.root.json
│   │   ├── myrole.json
│   │   ├── root.json
│   │   ├── snapshot.json
│   │   ├── targets.json
│   │   └── timestamp.json
│   └── previous
│   ├── 1.root.json
│   ├── root.json
│   ├── snapshot.json
│   ├── targets.json
│   └── timestamp.json
└── tuftargets
└── README.txt
5 directories, 13 files
```
## An example of replacing a top-level key ##
The filename of the top-level keys must be "root_key," "targets_key,"
"snapshot_key," and "root_key." The filename can vary for any additional
top-level key.
Steps:
(1) initialize a repo containing default keys for the top-level roles.
(2) distrust the default key for the root role.
(3) create a new key and trust its use with the root role.
(4) sign the root metadata file.
```Bash
Step (1)
$ repo.py --init
Step (2)
$ repo.py --distrust --pubkeys tufkeystore/root_key.pub --role root
Step (3)
$ repo.py --key ed25519 --filename root_key
$ repo.py --trust --pubkeys tufkeystore/root_key.pub --role root
Step (4)
$ repo.py --sign tufkeystore/root_key --role root
Enter a password for the encrypted key (tufkeystore/root_key):
```
## A more complicated example ##
Steps:
(1) create a bare repo.
(2) add keys to the top-level roles.
(3) delegate trust of particular target files to another role X, where role X
has a signature threshold 2 and is marked as a terminating delegation. The
keys for role X and Y should be created prior to performing the delegation.
(4) Delegate from role X to role Y.
(5) have role X sign for a file also signed by the Targets role, to demonstrate
the expected file that should be downloaded by the client.
(6) perform an update.
(7) halt the server, add README.txt to the Targets role, restart the server,
and fetch the Target's role README.txt.
(8) Add LICENSE to 'role_y' and demonstrate that the client must not fetch it
because 'role_x' is a terminating delegation (and hasn't signed for it).
```Bash
Steps (1) and (2)
$ repo.py --init --consistent --bare
$ repo.py --key ed25519 --filename root_key
$ repo.py --trust --pubkeys tufkeystore/root_key.pub --role root
$ repo.py --key ecdsa --filename targets_key
$ repo.py --trust --pubkeys tufkeystore/targets_key.pub --role targets
$ repo.py --key rsa --filename snapshot_key
$ repo.py --trust --pubkeys tufkeystore/snapshot_key.pub --role snapshot
$ repo.py --key ecdsa --filename timestamp_key
$ repo.py --trust --pubkeys tufkeystore/timestamp_key.pub --role timestamp
$ repo.py --sign tufkeystore/root_key --role root
Enter a password for the encrypted key (tufkeystore/root_key):
$ repo.py --sign tufkeystore/targets_key --role targets
Enter a password for the encrypted key (tufkeystore/targets_key):
```
```Bash
Steps (3) and (4)
$ repo.py --key ed25519 --filename key_x
$ repo.py --key ed25519 --filename key_x2
$ repo.py --delegate "README.*" "LICENSE" --delegatee role_x --pubkeys
tufkeystore/key_x.pub tufkeystore/key_x2.pub --threshold 2 --terminating
$ repo.py --sign tufkeystore/key_x tufkeystore/key_x2 --role role_x
$ repo.py --key ed25519 --filename key_y
$ repo.py --delegate "README.*" "LICENSE" --delegatee role_y --role role_x
--pubkeys tufkeystore/key_y.pub --sign tufkeystore/key_x tufkeystore/key_x2
$ repo.py --sign tufkeystore/key_y --role role_y
```
```Bash
Steps (5) and (6)
$ echo "role_x's readme" > README.txt
$ repo.py --add README.txt --role role_x --sign tufkeystore/key_x tufkeystore/key_x2
```
Serve the repo
```Bash
$ cd tufrepo/
$ python -m SimpleHTTPServer 8001
```
Fetch the role x's README.txt
```Bash
$ client.py --repo http://localhost:8001 README.txt
$ cat tuftargets/README.txt
role_x's readme
```
```Bash
Step (7)
halt the server...
$ echo "Target role's readme" > README.txt
$ repo.py --add README.txt
restart the server...
```
```Bash
$ rm -rf tuftargets/ tuf.log
$ client.py --repo http://localhost:8001 README.txt
$ cat tuftargets/README.txt
Target role's readme
```
```Bash
Step (8)
$ echo "role_y's license" > LICENSE
$ repo.py --add LICENSE --role role_y --sign tufkeystore/key_y
```
```Bash
$ rm -rf tuftargets/ tuf.log
$ client.py --repo http://localhost:8001 LICENSE
Error: 'LICENSE' not found.
```

View file

@ -1,9 +1,10 @@
Getting Started
---------------
- `Overview of TUF <OVERVIEW.rst>`_
- `Installation <INSTALLATION.rst>`_
- `Contributors <CONTRIBUTORS.rst>`_
- `Quickstart <QUICKSTART.md>`_
- `CLI <CLI.md>`_
- `CLI Usage Examples <CLI_EXAMPLES.md>`_
- `Tutorial <TUTORIAL.md>`_
- Beginner Tutorials (using the basic command-line interface):
- `Quickstart <QUICKSTART.md>`_
- `CLI Documentation and Examples <CLI.md>`_
- `Advanced Tutorial <TUTORIAL.md>`_
- `Guidelines for Contributors <CONTRIBUTORS.rst>`_

View file

@ -1,21 +1,48 @@
# Quickstart #
The CLI requires a few dependencies and C extensions that can be installed with
`pip install securesystemslib[crypto,pynacl]`.
In this quickstart tutorial, we'll use the basic TUF command-line interface
(CLI), which includes the `repo.py` script and the `client.py` script, to set
up a repository with an update and metadata about that update, then download
and verify that update as a client.
Unlike the underlying TUF modules that the CLI uses, the CLI itself is a bit
bare-bones. Using the CLI is the easiest way to familiarize yourself with
how TUF works, however. It will serve as a very basic update system.
----
The following is a basic workflow in four steps:
**Step (1)** - Initialize a repo. The `tufrepo`, `tufkeystore`, and
`tufclient` directories are created in the current working directory.
**Step (0)** - Make sure TUF is installed.
Make sure that TUF is installed, along with some of the optional cryptographic
libraries and C extensions. Try this command to do that:
`pip install securesystemslib[crypto,pynacl] tuf`
If you run into errors during that pip command, please consult the more
detailed [TUF Installation Instructions](INSTALLATION.rst). (There are some
system libraries that you may need to install first.)
**Step (1)** - Create a basic repository and client.
The following command will set up a basic update repository and basic client
that knows about the repository. `tufrepo`, `tufkeystore`, and
`tufclient` directories will be created in the current directory.
```Bash
$ repo.py --init
```
Four sets of keys are created in the `tufkeystore` directory and metadata
is initiated in the `tufrepo` and `tufclient` directories.
**Step (2)** - Add a target file to the repo. The file size and hashes of
the target file are also written to the Targets metadata file.
Four sets of keys are created in the `tufkeystore` directory. Initial metadata
about the repository is created in the `tufrepo` directory, and also provided
to the client in the `tufclient` directory.
**Step (2)** - Add an update to the repository.
We'll create a target file that will later be delivered as an update to clients.
Metadata about that file will be created and signed, and added to the
repository's metadata.
```Bash
$ echo 'Test file' > testfile
$ repo.py --add testfile
@ -38,21 +65,38 @@ tufrepo/
3 directories, 11 files
```
The new file `testfile` is added and metadata is updated in the `tufrepo` directory.
**Step (3)** - Serve the repo
The new file `testfile` is added to the repository, and metadata is updated in
the `tufrepo` directory. The Targets metadata (`targets.json`) now includes
the file size and hashes of the `testfile` target file, and this metadata is
signed by the Targets role's key, so that clients can verify that metadata
about `testfile` and then verify `testfile` itself.
**Step (3)** - Serve the repo.
We'll host a toy http server containing the `testfile` update and the
repository's metadata.
```Bash
$ cd "tufrepo/"
$ python3 -m http.server 8001
# or, if you are using Python2:
$ python -m SimpleHTTPServer 8001
or with Python 3...
$ python3 -m http.server 8001
```
**Step (4)** - Fetch a target file from the repo. The client downloads
any required metadata and the requested target file.
**Step (4)** - Obtain and verify the `testfile` update on a client.
The client can request the package `testfile` from the repository. TUF will
download and verify metadata from the repository as necessary to determine
what the trustworthy hashes and length of `testfile` are, then download
the target `testfile` from the repository and keep it only if it matches that
trustworthy metadata.
```Bash
$ cd "tufclient/"
$ cd "../tufclient/"
$ client.py --repo http://localhost:8001 testfile
$ tree
.
@ -75,11 +119,35 @@ $ tree
5 directories, 11 files
```
client.py verified metadata from the server and downloaded content. The client has now verified and obtained `testfile`.
The scope of TUF ends here.
Now that a trustworthy update target has been obtained, an updater can proceed
however it normally would to install or use the update.
----
See [CLI.md](CLI.md) and [CLI_EXAMPLES.md](CLI_EXAMPLES.md) to learn about the
other supported CLI options. A [tutorial](TUTORIAL.md) is also available, and
intended for users that want more control over the repo creation process.
### Next Steps
TUF provides functionality for both ends of a software update system, the
**update provider** and the **update client**.
`repo.py` made use of `tuf.repository_tool`'s functionality for an update
provider, helping you produce and sign metadata about your updates.
`client.py` made use of `tuf.client.updater`'s client-side functionality,
performing download and the critical verification steps for metadata and the
update itself.
You can look at [CLI.md](CLI.md) to toy with the TUF CLI a bit more.
After that, try out using the underlying modules for a great deal more control.
The more detailed [Advanced Tutorial](TUTORIAL.md) shows you how to use the
underlying modules, `repository_tool` and `updater`.
Ultimately, a sophisticated update client will use or re-implement those
underlying modules. The TUF design is intended to play well with any update
workflow.
Please provide feedback or questions for this or other tutorials, or
TUF in general, by checking out
[our contact info](https://github.com/theupdateframework/tuf#contact), or
creating [issues](https://github.com/theupdateframework/tuf/issues) in this
repository!

View file

@ -1,4 +1,4 @@
# Tutorial #
# Advanced Tutorial #
## Table of Contents ##
- [How to Create and Modify a TUF Repository](#how-to-create-and-modify-a-tuf-repository)