nethsm_cli/cli/
key.rs

1use std::path::PathBuf;
2
3use clap::{Parser, Subcommand};
4use expression_format::ex_format;
5use nethsm::KeyId;
6use nethsm::{
7    DecryptMode,
8    EncryptMode,
9    KeyFormat,
10    KeyMechanism,
11    KeyType,
12    SignatureType,
13    UserRole::{Administrator, Operator},
14};
15use strum::IntoEnumIterator;
16
17use super::BIN_NAME;
18
19#[derive(Debug, Subcommand)]
20#[command(
21    about = "Operate on the keys of a device",
22    long_about = ex_format!("Operate on the keys of a device
23
24Supports all relevant cryptographic operations (decrypt, encrypt, sign), certificate handling, importing, generation and ACL management.
25
26Keys may exist in specific scopes: system-wide or in namespaces (see \"{BIN_NAME} namespace\").
27While system-wide users only have access to system-wide keys, namespaced users only have access to keys in their own namespace."
28    )
29)]
30pub enum KeyCommand {
31    #[command(subcommand)]
32    Cert(KeyCertCommand),
33    Csr(KeyCsrCommand),
34    Decrypt(KeyDecryptCommand),
35    Encrypt(KeyEncryptCommand),
36    Generate(KeyGenerateCommand),
37    Get(KeyGetCommand),
38    Import(KeyImportCommand),
39    List(KeyListCommand),
40    PublicKey(KeyPublicKeyCommand),
41    Remove(KeyRemoveCommand),
42    Sign(KeySignCommand),
43    Tag(KeyTagCommand),
44    Untag(KeyUntagCommand),
45}
46
47#[derive(Debug, Subcommand)]
48#[command(
49    about = "Operate on certificates for a key",
50    long_about = "Operate on certificates for a key
51
52Supports certificate retrieval, removal and import.
53
54System-wide users only have access to system-wide keys.
55Namespaced users only have access to keys in their own namespace.
56"
57)]
58pub enum KeyCertCommand {
59    Delete(KeyCertDeleteCommand),
60    Get(KeyCertGetCommand),
61    Import(KeyCertImportCommand),
62}
63
64#[derive(Debug, Parser)]
65#[command(
66    about = "Delete the certificate for a key",
67    long_about = ex_format!("Delete the certificate for a key
68
69System-wide users in the \"{Administrator}\" role can only delete certificates for system-wide keys.
70Namespaced users in the \"{Administrator}\" role can only delete certificates for keys in their own namespace.
71
72Requires authentication of a user in the \"{Administrator}\" role."
73)
74)]
75pub struct KeyCertDeleteCommand {
76    #[arg(
77        env = "NETHSM_KEY_ID",
78        help = "The ID of the key, for which to delete the certificate"
79    )]
80    pub key_id: KeyId,
81}
82
83#[derive(Debug, Parser)]
84#[command(
85    about = "Get the certificate for a key",
86    long_about = ex_format!("Get the certificate for a key
87
88System-wide users in the \"{Administrator}\" role can only get certificates for system-wide keys.
89Namespaced users in the \"{Administrator}\" role can only get certificates for keys in their own namespace.
90
91Unless a specific output file is specified, the certificate is written to stdout.
92
93Requires authentication of a user in the \"{Administrator}\" or \"{Operator}\" role (with access to the key - see \"{BIN_NAME} key tag\" and \"{BIN_NAME} user tag\")."
94    )
95)]
96pub struct KeyCertGetCommand {
97    #[arg(
98        env = "NETHSM_KEY_ID",
99        help = "The ID of the key, for which to retrieve the certificate"
100    )]
101    pub key_id: KeyId,
102
103    #[arg(
104        env = "NETHSM_FORCE",
105        help = "Write to output file even if it exists already",
106        long,
107        short
108    )]
109    pub force: bool,
110
111    #[arg(
112        env = "NETHSM_KEY_CERT_OUTPUT_FILE",
113        help = "The optional path to a specific output file",
114        long,
115        short
116    )]
117    pub output: Option<PathBuf>,
118}
119
120#[derive(Debug, Parser)]
121#[command(
122    about = "Import the certificate for a key",
123    long_about = ex_format!("Import the certificate for a key
124
125The NetHSM backend can store binary data up to 1 MiB in size as certificate.
126
127System-wide users in the \"{Administrator}\" role can only import certificates for system-wide keys.
128Namespaced users in the \"{Administrator}\" role can only import certificates for keys in their own namespace.
129
130Requires authentication of a user in the \"{Administrator}\" role."
131    )
132)]
133pub struct KeyCertImportCommand {
134    #[arg(
135        env = "NETHSM_KEY_ID",
136        help = "The ID of the key, for which to import the certificate"
137    )]
138    pub key_id: KeyId,
139
140    #[arg(
141        env = "NETHSM_KEY_CERT_FILE",
142        help = "The path to the certificate file to import"
143    )]
144    pub cert_file: PathBuf,
145}
146
147#[derive(Debug, Parser)]
148#[command(
149    about = "Get a Certificate Signing Request for a key",
150    long_about = ex_format!("Get a Certificate Signing Request for a key
151
152The PKCS#10 Certificate Signing Request (CSR) is returned in Privacy-enhanced Electronic Mail (PEM) format.
153Unless a specific output file is chosen, the certificate is returned on stdout.
154
155At a minimum, the \"Common Name\" (CN) attribute for the CSR has to be provided.
156
157System-wide users in the \"{Administrator}\" or \"{Operator}\" role can only create CSRs for system-wide keys.
158Namespaced users in the \"{Administrator}\" or \"{Operator}\" role can only create CSRs for keys in their own namespace.
159
160Requires authentication of a user in the \"{Administrator}\" or \"{Operator}\" role (with access to the key - see \"{BIN_NAME} key tag\" and \"{BIN_NAME} user tag\")."
161    )
162)]
163pub struct KeyCsrCommand {
164    #[arg(env = "NETHSM_KEY_ID", help = "The key ID for which to create a CSR")]
165    pub key_id: KeyId,
166
167    #[arg(
168        env = "NETHSM_KEY_CSR_COMMON_NAME",
169        help = "The mandatory \"Common Name\" (CN) attribute for the CSR",
170        long_help = "The mandatory \"Common Name\" (CN) attribute for the CSR
171
172A fully qualified domain name (FQDN) that should be secured using the CSR."
173    )]
174    pub common_name: String,
175
176    #[arg(
177        env = "NETHSM_KEY_CSR_ORG_NAME",
178        help = "The optional \"Organization Name\" (O) attribute for the CSR",
179        long_help = "The optional \"Organization Name\" (O) attribute for the CSR
180
181Usually the legal name of a company or entity and should include any suffixes such as Ltd., Inc., or Corp."
182    )]
183    pub org_name: Option<String>,
184
185    #[arg(
186        env = "NETHSM_KEY_CSR_ORG_UNIT",
187        help = "The optional \"Organizational Unit\" (OU) attribute for the CSR",
188        long_help = "The optional \"Organizational Unit\" (OU) attribute for the CSR
189
190Internal organization department/division name."
191    )]
192    pub org_unit: Option<String>,
193
194    #[arg(
195        env = "NETHSM_KEY_CSR_LOCALITY",
196        help = "The optional \"Locality\" (L) attribute for the CSR",
197        long_help = "The optional \"Locality\" (L) attribute for the CSR
198
199Name of town, city, village, etc."
200    )]
201    pub locality: Option<String>,
202
203    #[arg(
204        env = "NETHSM_KEY_CSR_STATE",
205        help = "The optional \"State\" (ST) attribute for the CSR",
206        long_help = "The optional \"State\" (ST) attribute for the CSR
207
208Province, region, county or state."
209    )]
210    pub state: Option<String>,
211
212    #[arg(
213        env = "NETHSM_KEY_CSR_COUNTRY",
214        help = "The optional \"Country\" (C) attribute for the CSR",
215        long_help = "The optional \"Country\" (C) attribute for the CSR
216
217The two-letter ISO code for the country where the \"Organization\" (O) is located."
218    )]
219    pub country: Option<String>,
220
221    #[arg(
222        env = "NETHSM_KEY_CSR_EMAIL",
223        help = "The optional \"Email Address\" (EMAIL) attribute for the CSR",
224        long_help = "The optional \"Email Address\" (EMAIL) attribute for the CSR
225
226The organization contact, usually of the certificate administrator or IT department."
227    )]
228    pub email: Option<String>,
229
230    #[arg(
231        env = "NETHSM_FORCE",
232        help = "Write to output file even if it exists already",
233        long,
234        short
235    )]
236    pub force: bool,
237
238    #[arg(
239        env = "NETHSM_KEY_CSR_OUTPUT_FILE",
240        help = "The optional path to a specific output file",
241        long,
242        short
243    )]
244    pub output: Option<PathBuf>,
245}
246
247#[derive(Debug, Parser)]
248#[command(
249    about = "Decrypt a message using a key",
250    long_about = ex_format!("Decrypt a message using a key
251
252The chosen decryption mode must match the targeted key and the initialization vector (if applicable) must be identical to the one used for encryption.
253
254System-wide users in the \"{Operator}\" role can only decrypt messages using system-wide keys.
255Namespaced users in the \"{Operator}\" role can only decrypt messages using keys in their own namespace.
256
257Requires authentication of a user in the \"{Operator}\" role that has access (see \"{BIN_NAME} key tag\" and \"{BIN_NAME} user tag\") to the targeted key."
258    )
259)]
260pub struct KeyDecryptCommand {
261    #[arg(
262        env = "NETHSM_KEY_ID",
263        help = "The ID of the key to use for decryption"
264    )]
265    pub key_id: KeyId,
266
267    #[arg(
268        env = "NETHSM_KEY_DECRYPT_MESSAGE",
269        help = "The path to an encrypted message to decrypt"
270    )]
271    pub message: PathBuf,
272
273    #[arg(
274        env = "NETHSM_KEY_DECRYPT_MODE",
275        help = "The decryption mode to use",
276        long_help = format!("The decryption mode to use
277
278One of {:?} (defaults to \"{:?}\").", DecryptMode::iter().map(Into::into).collect::<Vec<&'static str>>(), DecryptMode::default())
279    )]
280    pub decrypt_mode: Option<DecryptMode>,
281
282    #[arg(
283        env = "NETHSM_FORCE",
284        help = "Write to output file even if it exists already",
285        long,
286        short
287    )]
288    pub force: bool,
289
290    #[arg(
291        env = "NETHSM_KEY_DECRYPT_IV",
292        help = "The path to a file containing the initialization vector (IV) for symmetric decryption",
293        long_help = ex_format!("The path to a file containing the initialization vector (IV) for symmetric decryption
294
295The IV can only be used when choosing symmetric decryption (i.e. with \"{DecryptMode::AesCbc}\")"),
296        long,
297        short
298    )]
299    pub initialization_vector: Option<PathBuf>,
300
301    #[arg(
302        env = "NETHSM_KEY_DECRYPT_OUTPUT",
303        help = "The path to a specific file to write the decrypted message to",
304        long,
305        short
306    )]
307    pub output: Option<PathBuf>,
308}
309
310#[derive(Debug, Parser)]
311#[command(
312    about = "Encrypt a message using a key",
313    long_about = ex_format!("Encrypt a message using a key
314
315Only symmetric encryption is supported.
316
317System-wide users in the \"{Operator}\" role can only encrypt messages using system-wide keys.
318Namespaced users in the \"{Operator}\" role can only encrypt messages using keys in their own namespace.
319
320Requires authentication of a user in the \"{Operator}\" role that has access (see \"{BIN_NAME} key tag\" and \"{BIN_NAME} user tag\") to the targeted key."
321    )
322)]
323pub struct KeyEncryptCommand {
324    #[arg(
325        env = "NETHSM_KEY_ID",
326        help = "The ID of the key to use for encryption"
327    )]
328    pub key_id: KeyId,
329
330    #[arg(
331        env = "NETHSM_KEY_ENCRYPT_MESSAGE",
332        help = "The path to a message to encrypt"
333    )]
334    pub message: PathBuf,
335
336    #[arg(
337        env = "NETHSM_KEY_ENCRYPT_MODE",
338        help = "The encryption mode to use",
339        long_help = format!("The encryption mode to use
340
341One of {:?} (defaults to \"{:?}\").", EncryptMode::iter().map(Into::into).collect::<Vec<&'static str>>(), EncryptMode::default())
342    )]
343    pub encrypt_mode: Option<EncryptMode>,
344
345    #[arg(
346        env = "NETHSM_FORCE",
347        help = "Write to output file even if it exists already",
348        long,
349        short
350    )]
351    pub force: bool,
352
353    #[arg(
354        env = "NETHSM_KEY_ENCRYPT_IV",
355        help = "The path to a file containing the initialization vector (IV) for symmetric encryption",
356        long_help = ex_format!("The path to a file containing the initialization vector (IV) for symmetric encryption
357
358The IV can only be used when choosing symmetric encryption (i.e. with \"{EncryptMode::AesCbc}\")"),
359        long,
360        short
361    )]
362    pub initialization_vector: Option<PathBuf>,
363
364    #[arg(
365        env = "NETHSM_KEY_ENCRYPT_OUTPUT",
366        help = "The path to a specific file to write the encrypted message to",
367        long,
368        short
369    )]
370    pub output: Option<PathBuf>,
371}
372
373#[derive(Debug, Parser)]
374#[command(
375    about = "Generate a new key",
376    long_about = ex_format!("Generate a new key
377
378The provided key type and list of key mechanisms have to match:
379* \"{KeyType::Rsa}\" requires one of {:?KeyMechanism::rsa_mechanisms()}
380* \"{KeyType::Curve25519}\" requires one of {:?KeyMechanism::curve25519_mechanisms()}
381* \"{KeyType::EcP224}\", \"{KeyType::EcP256}\", \"{KeyType::EcP384}\" and \"{KeyType::EcP521}\" require one of {:?KeyMechanism::elliptic_curve_mechanisms()}
382* \"{KeyType::Generic}\" requires at least one of {:?KeyMechanism::generic_mechanisms()}
383
384System-wide users in the \"{Administrator}\" role generate system-wide keys.
385Namespaced users in the \"{Administrator}\" role generate keys in their own namespace.
386
387Note: Although assigning tags to the new key is optional, it is highly recommended as not doing so means that all users in the same scope have access to it!
388
389Requires authentication of a user in the \"{Administrator}\" role."
390    )
391)]
392pub struct KeyGenerateCommand {
393    #[arg(
394        env = "NETHSM_KEY_TYPE",
395        help = "The optional type of key to generate",
396        long_help = format!("The optional type of key to generate
397
398The key type must match the chosen key mechanisms!
399
400One of {:?} (defaults to \"{:?}\").",
401            KeyType::iter().map(Into::into).collect::<Vec<&'static str>>(),
402            KeyType::default()),
403    )]
404    pub key_type: Option<KeyType>,
405
406    #[arg(
407        env = "NETHSM_KEY_MECHANISMS",
408        help = "The mechanisms provided by the generated key",
409        long_help = format!("The mechanisms provided by the generated key
410
411The key mechanisms must match the chosen key type!
412
413At least one of {:?} (defaults to \"{:?}\").",
414            KeyMechanism::iter().map(Into::into).collect::<Vec<&'static str>>(),
415            KeyMechanism::default()),
416    )]
417    pub key_mechanisms: Vec<KeyMechanism>,
418
419    #[arg(
420        env = "NETHSM_KEY_BIT_LENGTH",
421        help = "The optional bit length of the generated key",
422        long_help = "The optional bit length of the generated key
423
424If none is provided, a default is chosen.",
425        long,
426        short = 'L'
427    )]
428    pub length: Option<u32>,
429
430    #[arg(
431        env = "NETHSM_KEY_ID",
432        help = "An optional unique ID that is assigned to the generated key",
433        long_help = "An optional unique ID that is assigned to the generated key
434
435If none is provided a generic one is generated for the key.",
436        long,
437        short
438    )]
439    pub key_id: Option<KeyId>,
440
441    #[arg(
442        env = "NETHSM_KEY_TAGS",
443        help = "An optional list of tags that are assigned to the generated key",
444        long_help = "An optional list of tags that are assigned to the generated key
445
446Tags on keys are used to grant access to those keys for users that carry the same tags.",
447        long,
448        short
449    )]
450    pub tags: Option<Vec<String>>,
451}
452
453#[derive(Debug, Parser)]
454#[command(
455    about = "Get information on a key",
456    long_about = ex_format!("Get information on a key
457
458Displays information on supported key mechanisms, the key type, which restrictions apply (i.e. which tags are set for the key), information on the public key part and how many operations have been done with the key.
459
460System-wide users in the \"{Administrator}\" or \"{Operator}\" role can only retrieve information on system-wide keys.
461Namespaced users in the \"{Administrator}\" or \"{Operator}\" role can only retrieve information on keys in their own namespace.
462
463Requires authentication of a user in the \"{Administrator}\" or \"{Operator}\" role (with access to the key - see \"{BIN_NAME} key tag\" and \"{BIN_NAME} user tag\")."
464    )
465)]
466pub struct KeyGetCommand {
467    #[arg(
468        env = "NETHSM_KEY_ID",
469        help = "The ID of the key, for which to show information for"
470    )]
471    pub key_id: KeyId,
472}
473
474#[derive(Debug, Parser)]
475#[command(
476    about = "Import a key",
477    long_about = ex_format!("Import a key
478
479The provided key data must be provided as PKCS#8 private key in ASN.1 Distinguished Encoding Rules (DER) encoded or Privacy-Enhanced Mail (PEM) format.
480The key data must match the provided key type.
481
482The provided key type and list of key mechanisms have to match:
483* \"{KeyType::Rsa}\" requires one of {:?KeyMechanism::rsa_mechanisms()}
484* \"{KeyType::Curve25519}\" requires one of {:?KeyMechanism::curve25519_mechanisms()}
485* \"{KeyType::EcP224}\", \"{KeyType::EcP256}\", \"{KeyType::EcP384}\" and \"{KeyType::EcP521}\" require one of {:?KeyMechanism::elliptic_curve_mechanisms()}
486* \"{KeyType::Generic}\" requires at least one of {:?KeyMechanism::generic_mechanisms()}
487
488System-wide users in the \"{Administrator}\" role import system-wide keys.
489Namespaced users in the \"{Administrator}\" role import keys in their own namespace.
490
491Note: Although assigning tags to the new key is optional, it is highly recommended as not doing so means that all users in the same scope have access to it!
492
493Requires authentication of a user in the \"{Administrator}\" role."
494    )
495)]
496pub struct KeyImportCommand {
497    #[arg(
498        env = "NETHSM_KEY_TYPE",
499        help = "The type of key to import",
500        long_help = format!("The type of key to import
501
502The key type must match the provided key data and chosen key mechanisms!
503
504One of {:?}.",
505            KeyMechanism::iter().map(Into::into).collect::<Vec<&'static str>>()),
506    )]
507    pub key_type: KeyType,
508
509    #[arg(
510        env = "NETHSM_KEY_FORMAT",
511        help = "The format of key to import",
512        default_value_t = KeyFormat::default(),
513        long,
514        long_help = format!("The format of key to import
515
516Keys can be imported in Distinguished Encoding Rules (DER) or Privacy-Enhanced Mail (PEM) format.
517
518One of {:?}.",
519            KeyFormat::iter().map(Into::into).collect::<Vec<&'static str>>()),
520    )]
521    pub format: KeyFormat,
522
523    #[arg(
524        env = "NETHSM_KEY_DATA",
525        help = "The path to a PKCS#8 private key in ASN.1 DER-encoded format",
526        long_help = "The path to a PKCS#8 private key in ASN.1 DER-encoded format
527
528The private key data must match the chosen key type."
529    )]
530    pub key_data: PathBuf,
531
532    #[arg(
533        env = "NETHSM_KEY_MECHANISMS",
534        help = "The mechanisms provided by the imported key",
535        long_help = format!("The mechanisms provided by the imported key
536
537The key mechanisms must match the chosen key type!
538
539At least one of {:?}.",
540            KeyMechanism::iter().map(Into::into).collect::<Vec<&'static str>>()),
541    )]
542    pub key_mechanisms: Vec<KeyMechanism>,
543
544    #[arg(
545        env = "NETHSM_KEY_ID",
546        help = "An optional unique ID that is assigned to the imported key",
547        long_help = "An optional unique ID that is assigned to the imported key
548
549If none is provided a generic one is generated for the key.",
550        long,
551        short
552    )]
553    pub key_id: Option<KeyId>,
554
555    #[arg(
556        env = "NETHSM_KEY_TAGS",
557        help = "An optional list of tags that are assigned to the imported key",
558        long_help = "An optional list of tags that are assigned to the imported key
559
560Tags on keys are used to grant access to those keys for users that carry the same tags.",
561        long,
562        short
563    )]
564    pub tags: Option<Vec<String>>,
565}
566
567#[derive(Debug, Parser)]
568#[command(
569    about = "List all key IDs",
570    long_about = ex_format!("List all key IDs
571
572Optionally filter the list of key IDs by a keyword.
573
574System-wide users in the \"{Administrator}\" or \"{Operator}\" role can only list system-wide keys.
575Namespaced users in the \"{Administrator}\" or \"{Operator}\" role can only list keys in their own namespace.
576
577Requires authentication of a user in the \"{Administrator}\" or \"{Operator}\" role (with access to the key - see \"{BIN_NAME} key tag\" and \"{BIN_NAME} user tag\")."
578    )
579)]
580pub struct KeyListCommand {
581    #[arg(
582        env = "NETHSM_KEY_ID_FILTER",
583        help = "A filter to apply to the list of key IDs"
584    )]
585    pub filter: Option<String>,
586}
587
588#[derive(Debug, Parser)]
589#[command(
590    about = "Get the public key for a key",
591    long_about = ex_format!("Get the public key for a key
592
593The public key is returned as X.509 public key certificate in Privacy-enhanced Electronic Mail (PEM) format.
594If no specific output file is chosen, the public key is emitted on stdout.
595
596Note: Keys of type \"{KeyType::Generic}\" do not have a public key and this command fails for them!
597
598System-wide users in the \"{Administrator}\" or \"{Operator}\" role can only get the public key for system-wide keys.
599Namespaced users in the \"{Administrator}\" or \"{Operator}\" role can only get the public key for keys in their own namespace.
600
601Requires authentication of a user in the \"{Administrator}\" or \"{Operator}\" role (with access to the key - see \"{BIN_NAME} key tag\" and \"{BIN_NAME} user tag\")."
602    )
603)]
604pub struct KeyPublicKeyCommand {
605    #[arg(
606        env = "NETHSM_KEY_ID",
607        help = "The ID of the key to get the public key for"
608    )]
609    pub key_id: KeyId,
610
611    #[arg(
612        env = "NETHSM_FORCE",
613        help = "Write to output file even if it exists already",
614        long,
615        short
616    )]
617    pub force: bool,
618
619    #[arg(
620        env = "NETHSM_KEY_PUBKEY_OUTPUT_FILE",
621        help = "The optional path to a specific output file",
622        long,
623        short
624    )]
625    pub output: Option<PathBuf>,
626}
627
628#[derive(Debug, Parser)]
629#[command(
630    about = "Remove a key",
631    long_about = ex_format!("Remove a key
632
633System-wide users in the \"{Administrator}\" role can only remove system-wide keys.
634Namespaced users in the \"{Administrator}\" role can only remove keys in their own namespace.
635
636Requires authentication of a user in the \"{Administrator}\" role."
637    )
638)]
639pub struct KeyRemoveCommand {
640    #[arg(env = "NETHSM_KEY_ID", help = "The ID of the key that is removed")]
641    pub key_id: KeyId,
642}
643
644#[derive(Debug, Parser)]
645#[command(
646    about = "Sign a message using a key",
647    long_about = ex_format!("Sign a message using a key
648
649The targeted key must be equipped with relevant key mechanisms for signing.
650The chosen signature type must match the target key type and key mechanisms.
651
652If no specific output file is chosen, the signature is written to stdout.
653
654System-wide users in the \"{Operator}\" role can only create signatures for messages using system-wide keys.
655Namespaced users in the \"{Operator}\" role can only create signatures for messages using keys in their own namespace.
656
657Requires authentication of a user in the \"{Operator}\" role with access (see \"{BIN_NAME} key tag\" and \"{BIN_NAME} user tag\") to the target key."
658    )
659)]
660pub struct KeySignCommand {
661    #[arg(
662        env = "NETHSM_KEY_ID",
663        help = "The ID of the key to use for signing the message"
664    )]
665    pub key_id: KeyId,
666
667    #[arg(
668        env = "NETHSM_KEY_SIGNATURE_TYPE",
669        help = "The signature type to use for the signature",
670        long_help = format!("The signature type to use for the signature
671
672One of {:?}", SignatureType::iter().map(Into::into).collect::<Vec<&'static str>>()),
673    )]
674    pub signature_type: SignatureType,
675
676    #[arg(
677        env = "NETHSM_KEY_SIGNATURE_MESSAGE",
678        help = "The path to a message for which to create a signature"
679    )]
680    pub message: PathBuf,
681
682    #[arg(
683        env = "NETHSM_FORCE",
684        help = "Write to output file even if it exists already",
685        long,
686        short
687    )]
688    pub force: bool,
689
690    #[arg(
691        env = "NETHSM_KEY_SIGNATURE_OUTPUT_FILE",
692        help = "The optional path to a specific file that the signature is written to",
693        long,
694        short
695    )]
696    pub output: Option<PathBuf>,
697}
698
699#[derive(Debug, Parser)]
700#[command(
701    about = "Tag a key",
702    long_about = ex_format!("Tag a key
703
704Tags are used to grant access to keys for users in the \"{Operator}\" role.
705If a user and a key are tagged with the same tag, the user gains access to that key.
706As keys exist either system-wide or in a namespace, users in the \"{Operator}\" role must be in the same scope as the key for this have effect!
707
708Note: Tags on keys must be created before creating tags on users.
709
710System-wide users in the \"{Administrator}\" role can only tag system-wide keys.
711Namespaced users in the \"{Administrator}\" role can only tag keys in their own namespace.
712
713Requires authentication of a user in the \"{Administrator}\" role."
714    )
715)]
716pub struct KeyTagCommand {
717    #[arg(
718        env = "NETHSM_KEY_ID",
719        help = "The ID of the key for which a tag is added"
720    )]
721    pub key_id: KeyId,
722
723    #[arg(env = "NETHSM_KEY_TAG", help = "The tag to add to the key")]
724    pub tag: String,
725}
726
727#[derive(Debug, Parser)]
728#[command(
729    about = "Untag a key",
730    long_about = ex_format!("Untag a key
731
732Removes access to any key for users in the \"{Operator}\" role that have the same tag.
733As keys exist either system-wide or in a namespace, users in the \"{Operator}\" role must be in the same scope as the key for this to have effect!
734
735System-wide users in the \"{Administrator}\" role can only untag system-wide keys.
736Namespaced users in the \"{Administrator}\" role can only untag keys in their own namespace.
737
738Requires authentication of a user in the \"{Administrator}\" role."
739    )
740)]
741pub struct KeyUntagCommand {
742    #[arg(
743        env = "NETHSM_KEY_ID",
744        help = "The ID of the key for which a tag is removed"
745    )]
746    pub key_id: KeyId,
747
748    #[arg(env = "NETHSM_KEY_TAG", help = "The tag to remove from the key")]
749    pub tag: String,
750}