diff --git a/docs/CLI.md b/docs/CLI.md index f9843d4850..3e37c99e9b 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -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 ``` ---- + + + + + + + + +# 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. +``` diff --git a/docs/CLI_EXAMPLES.md b/docs/CLI_EXAMPLES.md deleted file mode 100644 index 4ae9035306..0000000000 --- a/docs/CLI_EXAMPLES.md +++ /dev/null @@ -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. -``` diff --git a/docs/GETTING_STARTED.rst b/docs/GETTING_STARTED.rst index 29552808ee..fad0d847fb 100644 --- a/docs/GETTING_STARTED.rst +++ b/docs/GETTING_STARTED.rst @@ -1,9 +1,10 @@ Getting Started --------------- +- `Overview of TUF `_ - `Installation `_ -- `Contributors `_ -- `Quickstart `_ -- `CLI `_ -- `CLI Usage Examples `_ -- `Tutorial `_ +- Beginner Tutorials (using the basic command-line interface): + - `Quickstart `_ + - `CLI Documentation and Examples `_ +- `Advanced Tutorial `_ +- `Guidelines for Contributors `_ diff --git a/docs/QUICKSTART.md b/docs/QUICKSTART.md index c6ea4ed24f..d56d97c262 100644 --- a/docs/QUICKSTART.md +++ b/docs/QUICKSTART.md @@ -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! diff --git a/docs/TUTORIAL.md b/docs/TUTORIAL.md index ccc07c5d71..52f9735cd9 100644 --- a/docs/TUTORIAL.md +++ b/docs/TUTORIAL.md @@ -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)