@@ -34,7 +34,8 @@ func tokenCommand() cli.Command {
3434[**--sshpop-cert**=<file>] [**--sshpop-key**=<file>]
3535[**--cnf**=<fingerprint>] [**--cnf-file**=<file>]
3636[**--ssh**] [**--host**] [**--principal**=<name>] [**--k8ssa-token-path**=<file>]
37- [**--ca-url**=<uri>] [**--root**=<file>] [**--context**=<name>]` ,
37+ [**--ca-url**=<uri>] [**--root**=<file>] [**--context**=<name>]
38+ [**--set**=<key=value>] [**--set-file**=<file>]` ,
3839 Description : `**step ca token** command generates a one-time token granting access to the
3940certificates authority.
4041
@@ -174,6 +175,18 @@ add the intermediate and the root in the provisioner configuration:
174175$ step ca token --kms yubikey:pin-value=123456 \
175176 --x5c-cert yubikey:slot-id=82 --x5c-key yubikey:slot-id=82 \
176177 internal.example.com
178+ '''
179+
180+ Generate a token with custom data in the "user" claim. The example below can be
181+ accessed in a template as **{{ .Token.user.field }}**, rendering to the string
182+ "value".
183+
184+ This is distinct from **.Insecure.User**: any attributes set using this option
185+ are added to a claim named "user" in the signed JWT produced by this command.
186+ This data may therefore be considered trusted (insofar as the token itself is
187+ trusted).
188+ '''
189+ $ step ca token --set field=value internal.example.com
177190'''` ,
178191 Flags : []cli.Flag {
179192 provisionerKidFlag ,
@@ -244,6 +257,8 @@ be invalid for any other API request.`,
244257 flags .CaURL ,
245258 flags .Root ,
246259 flags .Context ,
260+ flags .TemplateSet ,
261+ flags .TemplateSetFile ,
247262 },
248263 }
249264}
@@ -350,11 +365,29 @@ func tokenAction(ctx *cli.Context) error {
350365 tokenOpts = append (tokenOpts , cautils .WithConfirmationFingerprint (cnf ))
351366 }
352367
368+ templateData , err := flags .GetTemplateData (ctx )
369+ if err != nil {
370+ return err
371+ }
372+ if templateData != nil {
373+ tokenOpts = append (tokenOpts , cautils .WithCustomAttributes (templateData ))
374+ }
375+
353376 // --san and --type revoke are incompatible. Revocation tokens do not support SANs.
354377 if typ == cautils .RevokeType && len (sans ) > 0 {
355378 return errs .IncompatibleFlagWithFlag (ctx , "san" , "revoke" )
356379 }
357380
381+ // --offline doesn't support tokenOpts, so reject set/set-file
382+ if offline {
383+ if len (ctx .StringSlice ("set" )) > 0 {
384+ return errs .IncompatibleFlagWithFlag (ctx , "offline" , "set" )
385+ }
386+ if ctx .String ("set-file" ) != "" {
387+ return errs .IncompatibleFlagWithFlag (ctx , "offline" , "set-file" )
388+ }
389+ }
390+
358391 // parse times or durations
359392 notBefore , ok := flags .ParseTimeOrDuration (ctx .String ("not-before" ))
360393 if ! ok {
0 commit comments