// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package command import ( "fmt" "io" "os" "strings" "github.com/hashicorp/vault/api" "github.com/mitchellh/cli" "github.com/posener/complete" ) var ( _ cli.Command = (*AuditEnableCommand)(nil) _ cli.CommandAutocomplete = (*AuditEnableCommand)(nil) ) type AuditEnableCommand struct { *BaseCommand flagDescription string flagPath string flagLocal bool testStdin io.Reader // For tests } func (c *AuditEnableCommand) Synopsis() string { return "Enables an audit device" } func (c *AuditEnableCommand) Help() string { helpText := ` Usage: vault audit enable [options] TYPE [CONFIG K=V...] Enables an audit device at a given path. This command enables an audit device of TYPE. Additional options for configuring the audit device can be specified after the type in the same format as the "vault write" command in key/value pairs. For example, to configure the file audit device to write audit logs at the path "/var/log/audit.log": $ vault audit enable file file_path=/var/log/audit.log ` + c.Flags().Help() return strings.TrimSpace(helpText) } func (c *AuditEnableCommand) Flags() *FlagSets { set := c.flagSet(FlagSetHTTP) f := set.NewFlagSet("Command Options") f.StringVar(&StringVar{ Name: "description", Target: &c.flagDescription, Default: "", EnvVar: "", Completion: complete.PredictAnything, Usage: "Human-friendly description for the purpose of this audit " + "device.", }) f.StringVar(&StringVar{ Name: "path", Target: &c.flagPath, Default: "", // The default is complex, so we have to manually document EnvVar: "", Completion: complete.PredictAnything, Usage: "Place where the audit device will be accessible. This must be " + "unique across all audit devices. This defaults to the \"type\" of the " + "audit device.", }) f.BoolVar(&BoolVar{ Name: "local", Target: &c.flagLocal, Default: false, EnvVar: "", Usage: "Mark the audit device as a local-only device. Local devices " + "are not replicated or removed by replication.", }) return set } func (c *AuditEnableCommand) AutocompleteArgs() complete.Predictor { return complete.PredictSet( "file", "syslog", "socket", ) } func (c *AuditEnableCommand) AutocompleteFlags() complete.Flags { return c.Flags().Completions() } func (c *AuditEnableCommand) Run(args []string) int { f := c.Flags() if err := f.Parse(args); err != nil { c.UI.Error(err.Error()) return 1 } args = f.Args() if len(args) < 1 { c.UI.Error("Error enabling audit device: audit type missing. Valid types include 'file', 'socket' and 'syslog'.") return 1 } // Grab the type auditType := strings.TrimSpace(args[0]) auditPath := c.flagPath if auditPath == "" { auditPath = auditType } auditPath = ensureTrailingSlash(auditPath) // Pull our fake stdin if needed stdin := (io.Reader)(os.Stdin) if c.testStdin != nil { stdin = c.testStdin } options, err := parseArgsDataString(stdin, args[1:]) if err != nil { c.UI.Error(fmt.Sprintf("Failed to parse K=V data: %s", err)) return 1 } client, err := c.Client() if err != nil { c.UI.Error(err.Error()) return 2 } if err := client.Sys().EnableAuditWithOptions(auditPath, &api.EnableAuditOptions{ Type: auditType, Description: c.flagDescription, Options: options, Local: c.flagLocal, }); err != nil { c.UI.Error(fmt.Sprintf("Error enabling audit device: %s", err)) return 2 } c.UI.Output(fmt.Sprintf("Success! Enabled the %s audit device at: %s", auditType, auditPath)) return 0 }