forked from endophage/gotuf
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
167 lines (139 loc) · 3.8 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package main
import (
"bufio"
"bytes"
"errors"
"fmt"
"log"
"os"
"strconv"
"strings"
"time"
"github.com/docker/docker/pkg/term"
"github.com/flynn/go-docopt"
"github.com/endophage/gotuf"
"github.com/endophage/gotuf/signed"
"github.com/endophage/gotuf/store"
"github.com/endophage/gotuf/utils"
)
func main() {
log.SetFlags(0)
usage := `usage: tuf [-h|--help] [-d|--dir=<dir>] [--insecure-plaintext] <command> [<args>...]
Options:
-h, --help
-d <dir> The path to the repository (defaults to the current working directory)
--insecure-plaintext Don't encrypt signing keys
Commands:
help Show usage for a specific command
gen-key Generate a new signing key for a specific manifest
revoke-key Revoke a signing key
add Add target file(s)
remove Remove a target file
snapshot Update the snapshot manifest
timestamp Update the timestamp manifest
sign Sign a manifest
commit Commit staged files to the repository
regenerate Recreate the targets manifest
clean Remove all staged manifests
root-keys Output a JSON serialized array of root keys to STDOUT
See "tuf help <command>" for more information on a specific command
`
args, _ := docopt.Parse(usage, nil, true, "", true)
cmd := args.String["<command>"]
cmdArgs := args.All["<args>"].([]string)
if cmd == "help" {
if len(cmdArgs) == 0 { // `tuf help`
fmt.Println(usage)
return
} else { // `tuf help <command>`
cmd = cmdArgs[0]
cmdArgs = []string{"--help"}
}
}
dir, ok := args.String["-d"]
if !ok {
dir = args.String["--dir"]
}
if dir == "" {
var err error
dir, err = os.Getwd()
if err != nil {
log.Fatal(err)
}
}
if err := runCommand(cmd, cmdArgs, dir, args.Bool["--insecure-plaintext"]); err != nil {
log.Fatalln("ERROR:", err)
}
}
type cmdFunc func(*docopt.Args, *tuf.Repo) error
type command struct {
usage string
f cmdFunc
}
var commands = make(map[string]*command)
func register(name string, f cmdFunc, usage string) {
commands[name] = &command{usage: usage, f: f}
}
func runCommand(name string, args []string, dir string, insecure bool) error {
argv := make([]string, 1, 1+len(args))
argv[0] = name
argv = append(argv, args...)
cmd, ok := commands[name]
if !ok {
return fmt.Errorf("%s is not a tuf command. See 'tuf help'", name)
}
parsedArgs, err := docopt.Parse(cmd.usage, argv, true, "", true)
if err != nil {
return err
}
var p utils.PassphraseFunc
if !insecure {
p = getPassphrase
}
signer := signed.Ed25519{}
repo, err := tuf.NewRepo(&signer, store.FileSystemStore(dir, p), "sha256")
if err != nil {
return err
}
return cmd.f(parsedArgs, repo)
}
func parseExpires(arg string) (time.Time, error) {
days, err := strconv.Atoi(arg)
if err != nil {
return time.Time{}, fmt.Errorf("failed to parse --expires arg: %s", err)
}
return time.Now().AddDate(0, 0, days).UTC(), nil
}
func getPassphrase(role string, confirm bool) ([]byte, error) {
if pass := os.Getenv(fmt.Sprintf("TUF_%s_PASSPHRASE", strings.ToUpper(role))); pass != "" {
return []byte(pass), nil
}
state, err := term.SaveState(0)
if err != nil {
return nil, err
}
term.DisableEcho(0, state)
defer term.RestoreTerminal(0, state)
stdin := bufio.NewReader(os.Stdin)
fmt.Printf("Enter %s keys passphrase: ", role)
passphrase, err := stdin.ReadBytes('\n')
fmt.Println()
if err != nil {
return nil, err
}
passphrase = passphrase[0 : len(passphrase)-1]
if !confirm {
return passphrase, nil
}
fmt.Printf("Repeat %s keys passphrase: ", role)
confirmation, err := stdin.ReadBytes('\n')
fmt.Println()
if err != nil {
return nil, err
}
confirmation = confirmation[0 : len(confirmation)-1]
if !bytes.Equal(passphrase, confirmation) {
return nil, errors.New("The entered passphrases do not match")
}
return passphrase, nil
}