1package command
2
3import (
4	"flag"
5	"fmt"
6	"strconv"
7	"strings"
8	"time"
9
10	"github.com/hashicorp/vault/api"
11	"github.com/mitchellh/cli"
12	"github.com/posener/complete"
13)
14
15var _ cli.Command = (*AuthTuneCommand)(nil)
16var _ cli.CommandAutocomplete = (*AuthTuneCommand)(nil)
17
18type AuthTuneCommand struct {
19	*BaseCommand
20
21	flagAuditNonHMACRequestKeys  []string
22	flagAuditNonHMACResponseKeys []string
23	flagDefaultLeaseTTL          time.Duration
24	flagDescription              string
25	flagListingVisibility        string
26	flagMaxLeaseTTL              time.Duration
27	flagOptions                  map[string]string
28	flagTokenType                string
29	flagVersion                  int
30}
31
32func (c *AuthTuneCommand) Synopsis() string {
33	return "Tunes an auth method configuration"
34}
35
36func (c *AuthTuneCommand) Help() string {
37	helpText := `
38Usage: vault auth tune [options] PATH
39
40  Tunes the configuration options for the auth method at the given PATH. The
41  argument corresponds to the PATH where the auth method is enabled, not the
42  TYPE!
43
44  Tune the default lease for the github auth method:
45
46      $ vault auth tune -default-lease-ttl=72h github/
47
48` + c.Flags().Help()
49
50	return strings.TrimSpace(helpText)
51}
52
53func (c *AuthTuneCommand) Flags() *FlagSets {
54	set := c.flagSet(FlagSetHTTP)
55
56	f := set.NewFlagSet("Command Options")
57
58	f.StringSliceVar(&StringSliceVar{
59		Name:   flagNameAuditNonHMACRequestKeys,
60		Target: &c.flagAuditNonHMACRequestKeys,
61		Usage: "Comma-separated string or list of keys that will not be HMAC'd by audit" +
62			"devices in the request data object.",
63	})
64
65	f.StringSliceVar(&StringSliceVar{
66		Name:   flagNameAuditNonHMACResponseKeys,
67		Target: &c.flagAuditNonHMACResponseKeys,
68		Usage: "Comma-separated string or list of keys that will not be HMAC'd by audit" +
69			"devices in the response data object.",
70	})
71
72	f.DurationVar(&DurationVar{
73		Name:       "default-lease-ttl",
74		Target:     &c.flagDefaultLeaseTTL,
75		Default:    0,
76		EnvVar:     "",
77		Completion: complete.PredictAnything,
78		Usage: "The default lease TTL for this auth method. If unspecified, this " +
79			"defaults to the Vault server's globally configured default lease TTL, " +
80			"or a previously configured value for the auth method.",
81	})
82
83	f.StringVar(&StringVar{
84		Name:   flagNameDescription,
85		Target: &c.flagDescription,
86		Usage: "Human-friendly description of the this auth method. This overrides" +
87			"the current stored value, if any.",
88	})
89
90	f.StringVar(&StringVar{
91		Name:   flagNameListingVisibility,
92		Target: &c.flagListingVisibility,
93		Usage: "Determines the visibility of the mount in the UI-specific listing" +
94			"endpoint.",
95	})
96
97	f.DurationVar(&DurationVar{
98		Name:       "max-lease-ttl",
99		Target:     &c.flagMaxLeaseTTL,
100		Default:    0,
101		EnvVar:     "",
102		Completion: complete.PredictAnything,
103		Usage: "The maximum lease TTL for this auth method. If unspecified, this " +
104			"defaults to the Vault server's globally configured maximum lease TTL, " +
105			"or a previously configured value for the auth method.",
106	})
107
108	f.StringMapVar(&StringMapVar{
109		Name:       "options",
110		Target:     &c.flagOptions,
111		Completion: complete.PredictAnything,
112		Usage: "Key-value pair provided as key=value for the mount options. " +
113			"This can be specified multiple times.",
114	})
115
116	f.StringVar(&StringVar{
117		Name:   flagNameTokenType,
118		Target: &c.flagTokenType,
119		Usage:  "Sets a forced token type for the mount.",
120	})
121
122	f.IntVar(&IntVar{
123		Name:    "version",
124		Target:  &c.flagVersion,
125		Default: 0,
126		Usage:   "Select the version of the auth method to run. Not supported by all auth methods.",
127	})
128
129	return set
130}
131
132func (c *AuthTuneCommand) AutocompleteArgs() complete.Predictor {
133	return c.PredictVaultAuths()
134}
135
136func (c *AuthTuneCommand) AutocompleteFlags() complete.Flags {
137	return c.Flags().Completions()
138}
139
140func (c *AuthTuneCommand) Run(args []string) int {
141	f := c.Flags()
142
143	if err := f.Parse(args); err != nil {
144		c.UI.Error(err.Error())
145		return 1
146	}
147
148	args = f.Args()
149	switch {
150	case len(args) < 1:
151		c.UI.Error(fmt.Sprintf("Not enough arguments (expected 1, got %d)", len(args)))
152		return 1
153	case len(args) > 1:
154		c.UI.Error(fmt.Sprintf("Too many arguments (expected 1, got %d)", len(args)))
155		return 1
156	}
157
158	client, err := c.Client()
159	if err != nil {
160		c.UI.Error(err.Error())
161		return 2
162	}
163
164	if c.flagVersion > 0 {
165		if c.flagOptions == nil {
166			c.flagOptions = make(map[string]string)
167		}
168		c.flagOptions["version"] = strconv.Itoa(c.flagVersion)
169	}
170
171	mountConfigInput := api.MountConfigInput{
172		DefaultLeaseTTL: ttlToAPI(c.flagDefaultLeaseTTL),
173		MaxLeaseTTL:     ttlToAPI(c.flagMaxLeaseTTL),
174		Options:         c.flagOptions,
175	}
176
177	// Set these values only if they are provided in the CLI
178	f.Visit(func(fl *flag.Flag) {
179		if fl.Name == flagNameAuditNonHMACRequestKeys {
180			mountConfigInput.AuditNonHMACRequestKeys = c.flagAuditNonHMACRequestKeys
181		}
182
183		if fl.Name == flagNameAuditNonHMACResponseKeys {
184			mountConfigInput.AuditNonHMACResponseKeys = c.flagAuditNonHMACResponseKeys
185		}
186
187		if fl.Name == flagNameDescription {
188			mountConfigInput.Description = &c.flagDescription
189		}
190
191		if fl.Name == flagNameListingVisibility {
192			mountConfigInput.ListingVisibility = c.flagListingVisibility
193		}
194
195		if fl.Name == flagNameTokenType {
196			mountConfigInput.TokenType = c.flagTokenType
197		}
198	})
199
200	// Append /auth (since that's where auths live) and a trailing slash to
201	// indicate it's a path in output
202	mountPath := ensureTrailingSlash(sanitizePath(args[0]))
203
204	if err := client.Sys().TuneMount("/auth/"+mountPath, mountConfigInput); err != nil {
205		c.UI.Error(fmt.Sprintf("Error tuning auth method %s: %s", mountPath, err))
206		return 2
207	}
208
209	c.UI.Output(fmt.Sprintf("Success! Tuned the auth method at: %s", mountPath))
210	return 0
211}
212