@@ -34,7 +34,8 @@ func tokenCommand() cli.Command {
34
34
[**--sshpop-cert**=<file>] [**--sshpop-key**=<file>]
35
35
[**--cnf**=<fingerprint>] [**--cnf-file**=<file>]
36
36
[**--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>]` ,
38
39
Description : `**step ca token** command generates a one-time token granting access to the
39
40
certificates authority.
40
41
@@ -174,6 +175,18 @@ add the intermediate and the root in the provisioner configuration:
174
175
$ step ca token --kms yubikey:pin-value=123456 \
175
176
--x5c-cert yubikey:slot-id=82 --x5c-key yubikey:slot-id=82 \
176
177
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
177
190
'''` ,
178
191
Flags : []cli.Flag {
179
192
provisionerKidFlag ,
@@ -244,6 +257,8 @@ be invalid for any other API request.`,
244
257
flags .CaURL ,
245
258
flags .Root ,
246
259
flags .Context ,
260
+ flags .TemplateSet ,
261
+ flags .TemplateSetFile ,
247
262
},
248
263
}
249
264
}
@@ -350,11 +365,29 @@ func tokenAction(ctx *cli.Context) error {
350
365
tokenOpts = append (tokenOpts , cautils .WithConfirmationFingerprint (cnf ))
351
366
}
352
367
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
+
353
376
// --san and --type revoke are incompatible. Revocation tokens do not support SANs.
354
377
if typ == cautils .RevokeType && len (sans ) > 0 {
355
378
return errs .IncompatibleFlagWithFlag (ctx , "san" , "revoke" )
356
379
}
357
380
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
+
358
391
// parse times or durations
359
392
notBefore , ok := flags .ParseTimeOrDuration (ctx .String ("not-before" ))
360
393
if ! ok {
0 commit comments