From f6545f52ada82f019ba4a3eb8cb987034251394c Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 7 Apr 2015 22:42:04 -0700 Subject: [PATCH] command/audit-enable --- command/audit_enable.go | 123 +++++++++++++++++++++++++++++++++++ command/audit_enable_test.go | 55 ++++++++++++++++ commands.go | 6 ++ 3 files changed, 184 insertions(+) create mode 100644 command/audit_enable.go create mode 100644 command/audit_enable_test.go diff --git a/command/audit_enable.go b/command/audit_enable.go new file mode 100644 index 0000000000..b03237c421 --- /dev/null +++ b/command/audit_enable.go @@ -0,0 +1,123 @@ +package command + +import ( + "fmt" + "io" + "os" + "strings" + + "github.com/hashicorp/vault/helper/kv-builder" + "github.com/mitchellh/mapstructure" +) + +// AuditEnableCommand is a Command that mounts a new mount. +type AuditEnableCommand struct { + Meta + + // A test stdin that can be used for tests + testStdin io.Reader +} + +func (c *AuditEnableCommand) Run(args []string) int { + var desc, id string + flags := c.Meta.FlagSet("audit-enable", FlagSetDefault) + flags.StringVar(&desc, "description", "", "") + flags.StringVar(&id, "id", "", "") + flags.Usage = func() { c.Ui.Error(c.Help()) } + if err := flags.Parse(args); err != nil { + return 1 + } + + args = flags.Args() + if len(args) < 1 { + flags.Usage() + c.Ui.Error(fmt.Sprintf( + "\naudit-enable expects at least one argument: the type to enable")) + return 1 + } + + auditType := args[0] + if id == "" { + id = auditType + } + + // Build the options + var stdin io.Reader = os.Stdin + if c.testStdin != nil { + stdin = c.testStdin + } + builder := &kvbuilder.Builder{Stdin: stdin} + if err := builder.Add(args[1:]...); err != nil { + c.Ui.Error(fmt.Sprintf( + "Error parsing options: %s", err)) + return 1 + } + + var opts map[string]string + if err := mapstructure.WeakDecode(builder.Map(), &opts); err != nil { + c.Ui.Error(fmt.Sprintf( + "Error parsing options: %s", err)) + return 1 + } + + client, err := c.Client() + if err != nil { + c.Ui.Error(fmt.Sprintf( + "Error initializing client: %s", err)) + return 1 + } + + err = client.Sys().EnableAudit(id, auditType, desc, opts) + if err != nil { + c.Ui.Error(fmt.Sprintf( + "Error enabling audit backend: %s", err)) + return 1 + } + + c.Ui.Output(fmt.Sprintf( + "Successfully enabled audit backend '%s'!", auditType)) + return 0 +} + +func (c *AuditEnableCommand) Synopsis() string { + return "Enable an audit backend" +} + +func (c *AuditEnableCommand) Help() string { + helpText := ` +Usage: vault audit-enable [options] type [config...] + + Enable an audit backend. + + This command enables an audit backend of type "type". Additional + options for configuring the audit backend can be specified after the + type in the same format as the "vault write" command in key/value pairs. + Example: vault audit-enable file path=audit.log + +General Options: + + -address=TODO The address of the Vault server. + + -ca-cert=path Path to a PEM encoded CA cert file to use to + verify the Vault server SSL certificate. + + -ca-path=path Path to a directory of PEM encoded CA cert files + to verify the Vault server SSL certificate. If both + -ca-cert and -ca-path are specified, -ca-path is used. + + -insecure Do not verify TLS certificate. This is highly + not recommended. This is especially not recommended + for unsealing a vault. + +Audit Enable Options: + + -description= A human-friendly description for the backend. This + shows up only when querying the enabled backends. + + -id= Specify a unique ID for this audit backend. This + is purely for referencing this audit backend. By + default this will be the backend type. + +` + return strings.TrimSpace(helpText) +} diff --git a/command/audit_enable_test.go b/command/audit_enable_test.go new file mode 100644 index 0000000000..08e54b2d84 --- /dev/null +++ b/command/audit_enable_test.go @@ -0,0 +1,55 @@ +package command + +import ( + "reflect" + "testing" + + "github.com/hashicorp/vault/http" + "github.com/hashicorp/vault/vault" + "github.com/mitchellh/cli" +) + +func TestAuditEnable(t *testing.T) { + core, _, token := vault.TestCoreUnsealed(t) + ln, addr := http.TestServer(t, core) + defer ln.Close() + + ui := new(cli.MockUi) + c := &AuditEnableCommand{ + Meta: Meta{ + ClientToken: token, + Ui: ui, + }, + } + + args := []string{ + "-address", addr, + "noop", + "foo=bar", + } + + if code := c.Run(args); code != 0 { + t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) + } + + // Get the client + client, err := c.Client() + if err != nil { + t.Fatalf("err: %#v", err) + } + + audits, err := client.Sys().ListAudit() + if err != nil { + t.Fatalf("err: %#v", err) + } + + audit, ok := audits["noop/"] + if !ok { + t.Fatalf("err: %#v", audits) + } + + expected := map[string]string{"foo": "bar"} + if !reflect.DeepEqual(audit.Options, expected) { + t.Fatalf("err: %#v", audit) + } +} diff --git a/commands.go b/commands.go index 1aeb09dcce..20a77223cf 100644 --- a/commands.go +++ b/commands.go @@ -93,6 +93,12 @@ func init() { }, nil }, + "audit-enable": func() (cli.Command, error) { + return &command.AuditEnableCommand{ + Meta: meta, + }, nil + }, + "policies": func() (cli.Command, error) { return &command.PolicyListCommand{ Meta: meta,