| // Copyright (c) HashiCorp, Inc. |
| // SPDX-License-Identifier: MPL-2.0 |
| |
| package command |
| |
| import ( |
| "fmt" |
| "strings" |
| "time" |
| |
| "github.com/hashicorp/vault/api" |
| "github.com/mitchellh/cli" |
| "github.com/posener/complete" |
| ) |
| |
| var ( |
| _ cli.Command = (*TokenCreateCommand)(nil) |
| _ cli.CommandAutocomplete = (*TokenCreateCommand)(nil) |
| ) |
| |
| type TokenCreateCommand struct { |
| *BaseCommand |
| |
| flagID string |
| flagDisplayName string |
| flagTTL time.Duration |
| flagExplicitMaxTTL time.Duration |
| flagPeriod time.Duration |
| flagRenewable bool |
| flagOrphan bool |
| flagNoDefaultPolicy bool |
| flagUseLimit int |
| flagRole string |
| flagType string |
| flagMetadata map[string]string |
| flagPolicies []string |
| flagEntityAlias string |
| } |
| |
| func (c *TokenCreateCommand) Synopsis() string { |
| return "Create a new token" |
| } |
| |
| func (c *TokenCreateCommand) Help() string { |
| helpText := ` |
| Usage: vault token create [options] |
| |
| Creates a new token that can be used for authentication. This token will be |
| created as a child of the currently authenticated token. The generated token |
| will inherit all policies and permissions of the currently authenticated |
| token unless you explicitly define a subset list policies to assign to the |
| token. |
| |
| A ttl can also be associated with the token. If a ttl is not associated |
| with the token, then it cannot be renewed. If a ttl is associated with |
| the token, it will expire after that amount of time unless it is renewed. |
| |
| Metadata associated with the token (specified with "-metadata") is written |
| to the audit log when the token is used. |
| |
| If a role is specified, the role may override parameters specified here. |
| |
| ` + c.Flags().Help() |
| |
| return strings.TrimSpace(helpText) |
| } |
| |
| func (c *TokenCreateCommand) Flags() *FlagSets { |
| set := c.flagSet(FlagSetHTTP | FlagSetOutputField | FlagSetOutputFormat) |
| |
| f := set.NewFlagSet("Command Options") |
| |
| f.StringVar(&StringVar{ |
| Name: "id", |
| Target: &c.flagID, |
| Completion: complete.PredictAnything, |
| Usage: "Value for the token. By default, this is an auto-generated " + |
| "string. Specifying this value requires sudo permissions.", |
| }) |
| |
| f.StringVar(&StringVar{ |
| Name: "display-name", |
| Target: &c.flagDisplayName, |
| Completion: complete.PredictAnything, |
| Usage: "Name to associate with this token. This is a non-sensitive value " + |
| "that can be used to help identify created secrets (e.g. prefixes).", |
| }) |
| |
| f.DurationVar(&DurationVar{ |
| Name: "ttl", |
| Target: &c.flagTTL, |
| Completion: complete.PredictAnything, |
| Usage: "Initial TTL to associate with the token. Token renewals may be " + |
| "able to extend beyond this value, depending on the configured maximum " + |
| "TTLs. This is specified as a numeric string with suffix like \"30s\" " + |
| "or \"5m\".", |
| }) |
| |
| f.DurationVar(&DurationVar{ |
| Name: "explicit-max-ttl", |
| Target: &c.flagExplicitMaxTTL, |
| Completion: complete.PredictAnything, |
| Usage: "Explicit maximum lifetime for the token. Unlike normal TTLs, the " + |
| "maximum TTL is a hard limit and cannot be exceeded. This is specified " + |
| "as a numeric string with suffix like \"30s\" or \"5m\".", |
| }) |
| |
| f.DurationVar(&DurationVar{ |
| Name: "period", |
| Target: &c.flagPeriod, |
| Completion: complete.PredictAnything, |
| Usage: "If specified, every renewal will use the given period. Periodic " + |
| "tokens do not expire (unless -explicit-max-ttl is also provided). " + |
| "Setting this value requires sudo permissions. This is specified as a " + |
| "numeric string with suffix like \"30s\" or \"5m\".", |
| }) |
| |
| f.BoolVar(&BoolVar{ |
| Name: "renewable", |
| Target: &c.flagRenewable, |
| Default: true, |
| Usage: "Allow the token to be renewed up to it's maximum TTL.", |
| }) |
| |
| f.BoolVar(&BoolVar{ |
| Name: "orphan", |
| Target: &c.flagOrphan, |
| Default: false, |
| Usage: "Create the token with no parent. This prevents the token from " + |
| "being revoked when the token which created it expires. Setting this " + |
| "value requires root or sudo permissions.", |
| }) |
| |
| f.BoolVar(&BoolVar{ |
| Name: "no-default-policy", |
| Target: &c.flagNoDefaultPolicy, |
| Default: false, |
| Usage: "Detach the \"default\" policy from the policy set for this " + |
| "token.", |
| }) |
| |
| f.IntVar(&IntVar{ |
| Name: "use-limit", |
| Target: &c.flagUseLimit, |
| Default: 0, |
| Usage: "Number of times this token can be used. After the last use, the " + |
| "token is automatically revoked. By default, tokens can be used an " + |
| "unlimited number of times until their expiration.", |
| }) |
| |
| f.StringVar(&StringVar{ |
| Name: "role", |
| Target: &c.flagRole, |
| Default: "", |
| Usage: "Name of the role to create the token against. Specifying -role " + |
| "may override other arguments. The locally authenticated Vault token " + |
| "must have permission for \"auth/token/create/<role>\".", |
| }) |
| |
| f.StringVar(&StringVar{ |
| Name: "type", |
| Target: &c.flagType, |
| Default: "service", |
| Usage: `The type of token to create. Can be "service" or "batch".`, |
| }) |
| |
| f.StringMapVar(&StringMapVar{ |
| Name: "metadata", |
| Target: &c.flagMetadata, |
| Completion: complete.PredictAnything, |
| Usage: "Arbitrary key=value metadata to associate with the token. " + |
| "This metadata will show in the audit log when the token is used. " + |
| "This can be specified multiple times to add multiple pieces of " + |
| "metadata.", |
| }) |
| |
| f.StringSliceVar(&StringSliceVar{ |
| Name: "policy", |
| Target: &c.flagPolicies, |
| Completion: c.PredictVaultPolicies(), |
| Usage: "Name of a policy to associate with this token. This can be " + |
| "specified multiple times to attach multiple policies.", |
| }) |
| |
| f.StringVar(&StringVar{ |
| Name: "entity-alias", |
| Target: &c.flagEntityAlias, |
| Default: "", |
| Usage: "Name of the entity alias to associate with during token creation. " + |
| "Only works in combination with -role argument and used entity alias " + |
| "must be listed in allowed_entity_aliases. If this has been specified, " + |
| "the entity will not be inherited from the parent.", |
| }) |
| |
| return set |
| } |
| |
| func (c *TokenCreateCommand) AutocompleteArgs() complete.Predictor { |
| return nil |
| } |
| |
| func (c *TokenCreateCommand) AutocompleteFlags() complete.Flags { |
| return c.Flags().Completions() |
| } |
| |
| func (c *TokenCreateCommand) 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) > 0 { |
| c.UI.Error(fmt.Sprintf("Too many arguments (expected 0, got %d)", len(args))) |
| return 1 |
| } |
| |
| if c.flagType == "batch" { |
| c.flagRenewable = false |
| } |
| |
| client, err := c.Client() |
| if err != nil { |
| c.UI.Error(err.Error()) |
| return 2 |
| } |
| |
| tcr := &api.TokenCreateRequest{ |
| ID: c.flagID, |
| Policies: c.flagPolicies, |
| Metadata: c.flagMetadata, |
| TTL: c.flagTTL.String(), |
| NoParent: c.flagOrphan, |
| NoDefaultPolicy: c.flagNoDefaultPolicy, |
| DisplayName: c.flagDisplayName, |
| NumUses: c.flagUseLimit, |
| Renewable: &c.flagRenewable, |
| ExplicitMaxTTL: c.flagExplicitMaxTTL.String(), |
| Period: c.flagPeriod.String(), |
| Type: c.flagType, |
| EntityAlias: c.flagEntityAlias, |
| } |
| |
| var secret *api.Secret |
| if c.flagRole != "" { |
| secret, err = client.Auth().Token().CreateWithRole(tcr, c.flagRole) |
| } else { |
| secret, err = client.Auth().Token().Create(tcr) |
| } |
| if err != nil { |
| c.UI.Error(fmt.Sprintf("Error creating token: %s", err)) |
| return 2 |
| } |
| |
| if c.flagField != "" { |
| return PrintRawField(c.UI, secret, c.flagField) |
| } |
| |
| return OutputSecret(c.UI, secret) |
| } |