Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the CLI experience #160

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,11 @@ Expects a staged, fully signed `targets` metadata file and stages an appropriate
`snapshot` metadata file. Optionally one can set number of days after which
the `snapshot` metadata will expire.

#### `tuf timestamp`
#### `tuf timestamp [--expires=<days>]`

Stages an appropriate `timestamp` metadata file. If a `snapshot` metadata file is staged,
it must be fully signed.
it must be fully signed. Optionally one can set number of days after which
the timestamp metadata will expire.

#### `tuf sign <metadata>`

Expand Down Expand Up @@ -114,9 +115,13 @@ should be distributed to clients for performing initial updates.

#### `tuf set-threshold <role> <threshold>`

Sets the `role` threshold, the required number of keys for signing, to
Sets `role`'s threshold (required number of keys for signing) to
`threshold`.

#### `tuf get-threshold <role>`

Outputs `role`'s threshold (required number of keys for signing).

#### Usage of environment variables

The `tuf` CLI supports receiving passphrases via environment variables in
Expand Down
2 changes: 1 addition & 1 deletion cmd/tuf/get_threshold.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ func cmdGetThreshold(args *docopt.Args, repo *tuf.Repo) error {
return err
}

fmt.Println("Got", role, "threshold", threshold)
fmt.Println("The threshold for", role, "role is", threshold)
return nil
}
1 change: 1 addition & 0 deletions cmd/tuf/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Commands:
clean Remove all staged metadata files
root-keys Output a JSON serialized array of root keys to STDOUT
set-threshold Sets the threshold for a role
get-threshold Outputs the threshold for a role

See "tuf help <command>" for more information on a specific command
`
Expand Down
8 changes: 7 additions & 1 deletion cmd/tuf/root_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"encoding/json"
"fmt"
"os"

"github.com/flynn/go-docopt"
Expand All @@ -23,5 +24,10 @@ func cmdRootKeys(args *docopt.Args, repo *tuf.Repo) error {
if err != nil {
return err
}
return json.NewEncoder(os.Stdout).Encode(keys)
data, err := json.Marshal(keys)
if err == nil {
fmt.Fprintf(os.Stderr, "The resulting JSON should be distributed to clients for performing initial updates:\n\n")
fmt.Fprintln(os.Stdout, string(data))
}
return err
}
2 changes: 1 addition & 1 deletion cmd/tuf/set_threshold.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ func cmdSetThreshold(args *docopt.Args, repo *tuf.Repo) error {
return err
}

fmt.Println("Set ", role, "threshold to", threshold)
fmt.Println("The threshold for", role, "role is now", threshold)
return nil
}
86 changes: 70 additions & 16 deletions repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,11 @@ func (r *Repo) Init(consistentSnapshot bool) error {
}
root := data.NewRoot()
root.ConsistentSnapshot = consistentSnapshot
return r.setMeta("root.json", root)
err = r.setMeta("root.json", root)
if err == nil {
fmt.Println("Repository initialized")
}
return err
}

func (r *Repo) db() (*verify.DB, error) {
Expand Down Expand Up @@ -472,7 +476,11 @@ func (r *Repo) RevokeKeyWithExpires(keyRole, id string, expires time.Time) error
r.versionUpdated["root.json"] = struct{}{}
}

return r.setMeta("root.json", root)
err = r.setMeta("root.json", root)
if err == nil {
fmt.Println("Revoked", keyRole, "key with ID", id, "in root metadata")
}
return err
}

func (r *Repo) jsonMarshal(v interface{}) ([]byte, error) {
Expand Down Expand Up @@ -537,7 +545,11 @@ func (r *Repo) Sign(roleFilename string) error {
return err
}
r.meta[roleFilename] = b
return r.local.SetMeta(roleFilename, b)
err = r.local.SetMeta(roleFilename, b)
if err == nil {
fmt.Println("Signed", roleFilename, "with", len(keys), "key(s)")
}
return err
}

// AddOrUpdateSignature allows users to add or update a signature generated with an external tool.
Expand Down Expand Up @@ -703,7 +715,15 @@ func (r *Repo) AddTargetsWithExpires(paths []string, custom json.RawMessage, exp
t.Version++
r.versionUpdated["targets.json"] = struct{}{}
}
return r.setMeta("targets.json", t)

err = r.setMeta("targets.json", t)
if err == nil {
fmt.Println("Added/staged targets:")
for k := range t.Targets {
fmt.Println("*", k)
}
}
return err
}

func (r *Repo) RemoveTarget(path string) error {
Expand All @@ -728,19 +748,25 @@ func (r *Repo) RemoveTargetsWithExpires(paths []string, expires time.Time) error
if err != nil {
return err
}
removed_targets := []string{}
if len(paths) == 0 {
for rt := range t.Targets {
removed_targets = append(removed_targets, rt)
}
t.Targets = make(data.TargetFiles)
} else {
removed := false
for _, path := range paths {
path = util.NormalizeTarget(path)
if _, ok := t.Targets[path]; !ok {
fmt.Println("The following target is not present:", path)
continue
}
removed = true
// G2 -> we no longer desire any readers to ever observe non-prefix targets.
delete(t.Targets, "/"+path)
delete(t.Targets, path)
removed_targets = append(removed_targets, path)
}
if !removed {
return nil
Expand All @@ -751,7 +777,23 @@ func (r *Repo) RemoveTargetsWithExpires(paths []string, expires time.Time) error
t.Version++
r.versionUpdated["targets.json"] = struct{}{}
}
return r.setMeta("targets.json", t)

err = r.setMeta("targets.json", t)
if err == nil {
fmt.Println("Removed targets:")
for _, v := range removed_targets {
fmt.Println("*", v)
}
if len(t.Targets) != 0 {
fmt.Println("Added/staged targets:")
for k := range t.Targets {
fmt.Println("*", k)
}
} else {
fmt.Println("There are no added/staged targets")
}
}
return err
}

func (r *Repo) Snapshot() error {
Expand Down Expand Up @@ -787,7 +829,11 @@ func (r *Repo) SnapshotWithExpires(expires time.Time) error {
snapshot.Version++
r.versionUpdated["snapshot.json"] = struct{}{}
}
return r.setMeta("snapshot.json", snapshot)
err = r.setMeta("snapshot.json", snapshot)
if err == nil {
fmt.Println("Staged snapshot.json metadata with expiration date:", snapshot.Expires)
}
return err
}

func (r *Repo) Timestamp() error {
Expand Down Expand Up @@ -819,7 +865,12 @@ func (r *Repo) TimestampWithExpires(expires time.Time) error {
timestamp.Version++
r.versionUpdated["timestamp.json"] = struct{}{}
}
return r.setMeta("timestamp.json", timestamp)

err = r.setMeta("timestamp.json", timestamp)
if err == nil {
fmt.Println("Staged timestamp.json metadata with expiration date:", timestamp.Expires)
}
return err
}

func (r *Repo) fileVersions() (map[string]int, error) {
Expand Down Expand Up @@ -942,19 +993,22 @@ func (r *Repo) Commit() error {
return err
}

if err := r.local.Commit(root.ConsistentSnapshot, versions, hashes); err != nil {
return err
err = r.local.Commit(root.ConsistentSnapshot, versions, hashes)
if err == nil {
// We can start incrementing version numbers again now that we've
// successfully committed the metadata to the local store.
r.versionUpdated = make(map[string]struct{})
fmt.Println("Committed successfully")
}

// We can start incrementing version numbers again now that we've
// successfully committed the metadata to the local store.
r.versionUpdated = make(map[string]struct{})

return nil
return err
}

func (r *Repo) Clean() error {
return r.local.Clean()
err := r.local.Clean()
if err == nil {
fmt.Println("Removed all staged metadata and target files")
}
return err
}

func (r *Repo) verifySignature(roleFilename string, db *verify.DB) error {
Expand Down