diff --git a/.goreleaser.yml b/.goreleaser.yml index 1a8546e..96640d6 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -11,7 +11,9 @@ builds: main: ./cmd/duocli/duocli.go before: hooks: - - "go run cmd/duocli/duocli.go docs --output duocli.8" + - "go run cmd/duocli/duocli.go manual --output duocli.8" + - "go run cmd/duocli/duocli.go readme --output README.md" + archives: - replacements: darwin: Darwin @@ -46,3 +48,5 @@ nfpms: dst: /usr/share/man/man8/duocli.8 - src: scripts/bash_autocomplete dst: /etc/bash_completion.d/duocli + - src: duocli.json.example + dst: /usr/share/duocli/duocli.json.example diff --git a/README.md b/README.md new file mode 100644 index 0000000..f962555 --- /dev/null +++ b/README.md @@ -0,0 +1,84 @@ +% duocli 8 + +# NAME + +duocli - CLI Interface to Duo Admin API + +# SYNOPSIS + +duocli + +``` +[--config|-c]=[value] +[--help|-h] +[--version|-v] +``` + +**Usage**: + +``` +duocli [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] +``` + +# GLOBAL OPTIONS + +**--config, -c**="": load configuration from JSON `FILE` + +**--help, -h**: show help + +**--version, -v**: print the version + + +# COMMANDS + +## user + +manage users + +### add + +add a user + +**--email, -e**="": email address of user + +**--firstName, -f**="": first name of user + +**--group, -g**="": add user to group, can be specified multiple times to add user to multiple groups + +**--lastName, -l**="": last name of user + +**--status, -s**="": status of user: active, disabled, or bypass (default: active) + +**--username, -u**="": username + +### get + +get one or more users and display as JSON + +**--username, -u**="": username, can be specified multiple times + +### modify + +modify a user's attributes, add or remove group membership + +**--addgroup, -g**="": add user to groups, adds to existing memberships, and can be specified multiple times to add user to multiple groups + +**--delgroup, -G**="": remove user from groups, removes from existing memberships, and can be specified multiple times to remove user from multiple groups + +**--email, -e**="": email address of user + +**--firstName, -f**="": first name of user + +**--lastName, -l**="": last name of user + +**--status, -s**="": status of user: active, disabled, or bypass + +**--username, -u**="": username + +### remove + +remove user and any attached phones + +**--phone, -P**: remove any phones found attached to the user before removing the user + +**--username, -u**="": username, can be specified multiple times diff --git a/cmd/duocli/duocli.go b/cmd/duocli/duocli.go index 1b73c9a..b849d87 100644 --- a/cmd/duocli/duocli.go +++ b/cmd/duocli/duocli.go @@ -24,7 +24,7 @@ func main() { &cli.StringFlag{ Name: "config", Aliases: []string{"c"}, - Usage: "load configuration from `FILE`", + Usage: "load configuration from JSON `FILE`", DefaultText: ".duocli.json", }, }, @@ -71,7 +71,7 @@ func main() { }, { Name: "remove", - Usage: "remove user and any attached phones or tokens", + Usage: "remove user and any attached phones", Action: user.Remove, Flags: []cli.Flag{ &cli.StringSliceFlag{Name: "username", Aliases: []string{"u"}, Required: true, Usage: "username, can be specified multiple times"}, @@ -81,9 +81,17 @@ func main() { }, }, { - Name: "docs", + Name: "manual", Hidden: true, - Action: docs.Generate, + Action: docs.Manual, + Flags: []cli.Flag{ + &cli.StringFlag{Name: "output", Required: true, Usage: "path to write man page"}, + }, + }, + { + Name: "readme", + Hidden: true, + Action: docs.Readme, Flags: []cli.Flag{ &cli.StringFlag{Name: "output", Required: true, Usage: "path to write man page"}, }, diff --git a/duocli.json.example b/duocli.json.example new file mode 100644 index 0000000..e40bc84 --- /dev/null +++ b/duocli.json.example @@ -0,0 +1,5 @@ +{ + "ikey": "DIXXXXXXXXXXXXXXXXXX", + "skey": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "api_host": "api-XXXXXXXX.duosecurity.com" +} \ No newline at end of file diff --git a/pkg/cli/docs/docs.go b/pkg/cli/docs/docs.go index 6ea6d15..fe33068 100644 --- a/pkg/cli/docs/docs.go +++ b/pkg/cli/docs/docs.go @@ -7,8 +7,8 @@ import ( "github.com/urfave/cli/v2" ) -// Generate writes out man page for the application to the provide path -func Generate(c *cli.Context) error { +// Manual writes out man page for the application to the provide path +func Manual(c *cli.Context) error { path := c.String("output") f, err := os.Create(path) if err != nil { @@ -24,3 +24,21 @@ func Generate(c *cli.Context) error { _, err = fmt.Fprintf(f, "%s", man) return err } + +// Readme writes out a markdown documentation page for the application to the provide path +func Readme(c *cli.Context) error { + path := c.String("output") + f, err := os.Create(path) + if err != nil { + return err + } + defer f.Close() + + md, err := c.App.ToMarkdown() + if err != nil { + return err + } + + _, err = fmt.Fprintf(f, "%s", md) + return err +}