nethsm_cli/cli/
openpgp.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
use std::path::PathBuf;

use chrono::{DateTime, Utc};
use clap::{Parser, Subcommand};
use expression_format::ex_format;
use nethsm::{
    KeyId,
    OpenPgpUserId,
    OpenPgpVersion,
    UserRole::{Administrator, Operator},
};
use strum::IntoEnumIterator;

use super::BIN_NAME;

#[derive(Debug, Subcommand)]
#[command(
    about = "OpenPGP operations",
    long_about = ex_format!("OpenPGP operations

Supports creating OpenPGP certificates for existing keys, as well as cryptographic operations using those keys.

Keys may exist in specific scopes: system-wide or in namespaces (see \"{BIN_NAME} namespace\").
While system-wide users only have access to system-wide keys, namespaced users only have access to keys in their own namespace.")
)]
pub enum OpenPgpCommand {
    Add(OpenPgpAddCommand),
    Import(OpenPgpImportCommand),
    Sign(OpenPgpSignCommand),
    SignState(OpenPgpSignStateCommand),
}

#[derive(Debug, Parser)]
#[command(
    about = "Add an OpenPGP certificate for a key",
    long_about = ex_format!("Add an OpenPGP certificate for a key

Creates an OpenPGP certificate for an existing key.
The created certificate is then added as the key's certificate (see \"{BIN_NAME} key cert import\").

System-wide users in the \"{Administrator}\" and \"{Operator}\" role can only add OpenPGP certificates for system-wide keys.
Namespaced users in the \"{Administrator}\" and \"{Operator}\" role can only add OpenPGP certificates for keys in their own namespace.

Requires authentication of a user in the \"{Operator}\" role, that has access to the targeted key (see \"{BIN_NAME} key tag\" and \"{BIN_NAME} user tag\").
Additionally, authentication of a user in the \"{Administrator}\" role is needed to import the certificate.")
)]
pub struct OpenPgpAddCommand {
    #[arg(env = "NETHSM_KEY_ID", help = "The ID of the key to use")]
    pub key_id: KeyId,

    #[arg(env = "NETHSM_OPENPGP_USERID", help = "The User ID to use for the key")]
    pub user_id: OpenPgpUserId,

    #[arg(
        env = "NETHSM_OPENPGP_CREATED_AT",
        help = "The optional creation time of the certificate (defaults to now)",
        long,
        short
    )]
    pub time: Option<DateTime<Utc>>,

    #[arg(
        env = "NETHSM_OPENPGP_VERSION",
        help = ex_format!("The OpenPGP version the certificate is created with (defaults to \"{OpenPgpVersion::default()}\")"),
        long_help = ex_format!(
            "The OpenPGP version the certificate is created with (defaults to \"{OpenPgpVersion::default()}\")

One of {:?OpenPgpVersion::iter().map(Into::into).collect::<Vec<&'static str>>()}."
        ),
        long,
        short
    )]
    pub version: Option<OpenPgpVersion>,

    #[arg(
        env = "NETHSM_OPENPGP_CERT_GENERATE_CAN_SIGN",
        help = "Sets the signing key flag (default to set)",
        long_help = "Sets the signing key flag (default to set)

If this option is used, the key is created with a component key that has the signing key flag set.",
        group = "sign-group",
        long,
        default_value_t = true
    )]
    pub can_sign: bool,

    #[arg(
        env = "NETHSM_OPENPGP_CERT_GENERATE_CANNOT_SIGN",
        help = "Clears the signing key flag",
        long_help = "Clears the signing key flag

If this option is used, the key is created without a component key that has the signing key flag set.",
        group = "sign-group",
        long
    )]
    pub cannot_sign: bool,
}

#[derive(Debug, Parser)]
#[command(
    about = "Create an OpenPGP signature for a message",
    long_about = ex_format!("Create an OpenPGP signature for a message

The signature is written to stdout, unless a specific path to a file is provided.

System-wide users in the \"{Operator}\" role can only create OpenPGP signatures for a message using system-wide keys.
Namespaced users in the \"{Operator}\" role can only create OpenPGP signatures for a message using keys in their own namespace.

Requires authentication of a user in the \"{Operator}\" role that has access to the targeted key (see \"{BIN_NAME} key tag\" and \"{BIN_NAME} user tag\").")
)]
pub struct OpenPgpSignCommand {
    #[arg(env = "NETHSM_KEY_ID", help = "The ID of the key to use")]
    pub key_id: KeyId,

    #[arg(
        env = "NETHSM_FORCE",
        help = "Write to output file even if it exists already",
        long,
        short
    )]
    pub force: bool,

    #[arg(
        env = "NETHSM_OPENPGP_SIGNATURE_MESSAGE",
        help = "The path to a message for which to create a signature"
    )]
    pub message: PathBuf,

    #[arg(
        env = "NETHSM_OPENPGP_SIGNATURE_OUTPUT_FILE",
        help = "The optional path to a specific output file",
        long,
        short
    )]
    pub output: Option<PathBuf>,
}

#[derive(Debug, Parser)]
#[command(
    about = "Create an OpenPGP signature for a hasher state",
    long_about = ex_format!("Create an OpenPGP signature for a hasher's state

Requires a valid hasher state payload on stdin as produced by the `signstar-request-signature` binary.

The signature is written to stdout, unless a specific path to a file is provided.

Requires authentication of a user in the \"{Operator}\" role that has access to the targeted key.")
)]
pub struct OpenPgpSignStateCommand {
    #[arg(env = "NETHSM_KEY_ID", help = "The ID of the key to use")]
    pub key_id: KeyId,

    #[arg(
        env = "NETHSM_OPENPGP_REQUEST_SIGNATURE_FILE",
        help = "The path to a valid signature request file"
    )]
    pub input: PathBuf,

    #[arg(
        env = "NETHSM_FORCE",
        help = "Write to output file even if it exists already",
        long,
        short
    )]
    pub force: bool,

    #[arg(
        env = "NETHSM_OPENPGP_SIGNATURE_OUTPUT_FILE",
        help = "The optional path to a specific output file",
        long,
        short
    )]
    pub output: Option<PathBuf>,
}

#[derive(Debug, Parser)]
#[command(
    about = "Import OpenPGP TSK-formatted private key",
    long_about = ex_format!("Import OpenPGP Transferable Secret Key (TSK) formatted private key

Only TSKs with a single component key are supported.

System-wide users in the \"{Administrator}\" role can only import TSKs as system-wide keys.
Namespaced users in the \"{Administrator}\" role can only import TSKs as keys in their own namespace.

Note: 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!

Requires authentication of a user in the \"{Administrator}\" role.")
)]
pub struct OpenPgpImportCommand {
    #[arg(
        env = "NETHSM_OPENPGP_TSK_FILE",
        help = "The path to the Transferable Secret Key file to import"
    )]
    pub tsk_file: PathBuf,

    #[arg(
        env = "NETHSM_OPENPGP_KEY_ID",
        help = "An optional unique ID that is assigned to the imported key",
        long_help = "An optional unique ID that is assigned to the imported key

If none is provided a generic one is generated for the key.",
        long,
        short
    )]
    pub key_id: Option<KeyId>,

    #[arg(
        env = "NETHSM_OPENPGP_KEY_TAGS",
        help = "An optional list of tags that are assigned to the imported key",
        long_help = "An optional list of tags that are assigned to the imported key

Tags on keys are used to grant access to those keys for users that carry the same tags.",
        long,
        short
    )]
    pub tags: Option<Vec<String>>,
}