1use clap::{Parser, Subcommand};
2use expression_format::ex_format;
3use nethsm::{
4 SystemState::Operational,
5 UserId,
6 UserRole::{self, Administrator, Operator},
7};
8use strum::IntoEnumIterator;
9
10use super::BIN_NAME;
11use crate::passphrase_file::PassphraseFile;
12
13#[derive(Debug, Subcommand)]
15#[command(
16 about = "Operate on users of a device",
17 long_about = ex_format!("Operate on users of a device
18
19Allows to add and remove users, retrieve information about them, set their passphrases and set or unset tags for them.
20
21Users may exist in specific scopes: system-wide or in namespaces (see \"{BIN_NAME} namespace\").
22The use of a namespace is indicated by a prefix in the user name (e.g. the user name \"namespace1~user1\" indicates that the user is in \"namespace1\").
23Users in a namespace can only be administrated by users in the \"{Administrator}\" role in that same namespace.
24System-wide users can only be administratred by system-wide users in the \"{Administrator}\" role.")
25)]
26pub enum UserCommand {
27 Add(UserAddCommand),
29 Get(UserGetCommand),
31 List(UserListCommand),
33 Passphrase(UserPassphraseCommand),
35 Remove(UserRemoveCommand),
37 Tag(UserTagCommand),
39 Untag(UserUntagCommand),
41}
42
43#[derive(Debug, Parser)]
44#[command(
45 about = "Add a user",
46 long_about = ex_format!("Add a user
47
48Adds a new user by providing a real name and a user role.
49If no user name is provided specifically, a random one is generated automatically by the target device.
50If no passphrase is provided, it is prompted for interactively.
51
52New users inherit the scope of the user that created them.
53If a system-wide user in the \"{Administrator}\" role creates a new user (e.g. \"user1\"), then that new user is also a system-wide user.
54As exception to this rule, a system-wide user in the \"{Administrator}\" role can create namespaced users by providing a user name specifically (e.g. \"namespace1~user1\"), but only if the targeted namespace (i.e. \"namespace1\") does not yet exist (see \"{BIN_NAME} namespace add\").
55If a namespaced user in the \"{Administrator}\" role creates a new user, then that new user is also a user in that namespace.
56If a namespaced user in the \"{Administrator}\" role (e.g. \"namespace1~admin1\") provides a specific user name, it must be in that same namespace (e.g. \"namespace1~user1\", not \"namespace2~user1\")!
57
58The device must be in state \"{Operational}\".
59
60Requires authentication of a user in the \"{Administrator}\" role."),
61)]
62pub struct UserAddCommand {
63 #[arg(
64 env = "NETHSM_REAL_NAME",
65 help = "The real name of the user that is created",
66 long_help = "The real name of the user that is created
67
68This name is only used for further identification, but not for authentication!"
69 )]
70 pub real_name: String,
71
72 #[arg(
73 env = "NETHSM_USER_ROLE",
74 help = "The role of the user that is created",
75 long_help = format!("The role of the user that is created
76
77One of {:?} (defaults to \"{:?}\").", UserRole::iter().map(Into::into).collect::<Vec<&'static str>>(), UserRole::default())
78 )]
79 pub role: Option<UserRole>,
80
81 #[arg(
82 env = "NETHSM_USER_NAME",
83 help = "A unique name for the user that is created",
84 long_help = "A unique name for the user that is created
85
86This name must be unique as it is used for authentication!"
87 )]
88 pub name: Option<UserId>,
89
90 #[arg(
91 env = "NETHSM_PASSPHRASE_FILE",
92 help = "The path to a file containing the new user's passphrase",
93 long_help = "The path to a file containing the new user's passphrase
94
95The passphrase must be >= 10 and <= 200 characters long.",
96 long,
97 short
98 )]
99 pub passphrase_file: Option<PassphraseFile>,
100}
101
102#[derive(Debug, Parser)]
103#[command(
104 about = "Get information about a user",
105 long_about = ex_format!("Get information about a user
106
107Retrieves the real name and role of a user.
108If the user is in the \"{Operator}\" role, also displays tags that are assigned to the user.
109
110System-wide users in the \"{Administrator}\" role have access to information of system-wide and namespaced users.
111Namespaced users in the \"{Administrator}\" role only have access to information of users in the same namespace.
112
113The device must be in state \"{Operational}\".
114
115Requires authentication of a user in the \"{Administrator}\" role."),
116)]
117pub struct UserGetCommand {
118 #[arg(
119 env = "NETHSM_USER_NAME",
120 help = "The unique name of a user on the target device"
121 )]
122 pub name: UserId,
123}
124
125#[derive(Debug, Parser)]
126#[command(
127 about = "List all user names",
128 long_about = ex_format!("List all user names
129
130System-wide users in the \"{Administrator}\" role can list system-wide and namespaced users.
131Namespaced users in the \"{Administrator}\" role can only list users in the same namespace.
132
133The device must be in state \"{Operational}\".
134
135Requires authentication of a user in the \"{Administrator}\" role."),
136)]
137pub struct UserListCommand {}
138
139#[derive(Debug, Parser)]
140#[command(
141 about = "Set the passphrase for a user",
142 long_about = ex_format!("Set the passphrase for a user
143
144If no passphrase is provided specifically, it is prompted for interactively.
145
146System-wide users in the \"{Administrator}\" role can only set the passphrase for system-wide users.
147Namespaced users in the \"{Administrator}\" role can only set the passphrase for users in the same namespace.
148
149The device must be in state \"{Operational}\".
150
151Requires authentication of a user in the \"{Administrator}\" role."),
152)]
153pub struct UserPassphraseCommand {
154 #[arg(
155 env = "NETHSM_USER_NAME",
156 help = "The name of the user on the target device"
157 )]
158 pub name: UserId,
159
160 #[arg(
161 env = "NETHSM_PASSPHRASE_FILE",
162 help = "The path to a file containing the user's new passphrase",
163 long_help = "The path to a file containing the user's new passphrase
164
165The passphrase must be >= 10 and <= 200 characters long.",
166 long,
167 short
168 )]
169 pub passphrase_file: Option<PassphraseFile>,
170}
171
172#[derive(Debug, Parser)]
173#[command(
174 about = "Remove a user",
175 long_about = ex_format!("Remove a user
176
177System-wide users in the \"{Administrator}\" role can only remove system-wide users.
178As an exception to this rule, system-wide users in the \"{Administrator}\" role can delete users in a namespace, if the namespace is removed first (see \"{BIN_NAME} namespace remove\").
179Namespaced users in the \"{Administrator}\" role can only remove users in the same namespace.
180
181The device must be in state \"{Operational}\".
182
183Requires authentication of a user in the \"{Administrator}\" role."),
184)]
185pub struct UserRemoveCommand {
186 #[arg(env = "NETHSM_USER_NAME", help = "The name of the user to remove")]
187 pub name: UserId,
188}
189
190#[derive(Debug, Parser)]
191#[command(
192 about = "Add a tag to a user",
193 long_about = ex_format!("Add a tag to a user
194
195Tags provide access to keys for users.
196Keys that carry identical tags to that of a user, are accessible for the user.
197Tags on a key must exist (see \"{BIN_NAME} key tag\") before an identical tag can be added to a user.
198
199System-wide users in the \"{Administrator}\" role can only add tags for system-wide users in the \"{Operator}\" role.
200Namespaced users in the \"{Administrator}\" role can only add tags for users in the \"{Operator}\" role in the same namespace.
201
202The device must be in state \"{Operational}\".
203
204Requires authentication of a user in the \"{Administrator}\" role."),
205)]
206pub struct UserTagCommand {
207 #[arg(
208 env = "NETHSM_USER_NAME",
209 help = "The name of the user for which to add a tag"
210 )]
211 pub name: UserId,
212
213 #[arg(env = "NETHSM_USER_TAG", help = "The tag to add for a user")]
214 pub tag: String,
215}
216
217#[derive(Debug, Parser)]
218#[command(
219 about = "Remove a tag from a user",
220 long_about = ex_format!("Remove a tag from a user
221
222Tags provide access to keys for users.
223Removing a tag from a user removes its access to keys that carry identical tags.
224
225System-wide users in the \"{Administrator}\" role can only remove tags for system-wide users in the \"{Operator}\" role.
226Namespaced users in the \"{Administrator}\" role can only remove tags for users in the \"{Operator}\" role in the same namespace.
227
228The device must be in state \"{Operational}\".
229
230Requires authentication of a user in the \"{Administrator}\" role."),
231)]
232pub struct UserUntagCommand {
233 #[arg(
234 env = "NETHSM_USER_NAME",
235 help = "The name of the user from which to remove a tag"
236 )]
237 pub name: UserId,
238
239 #[arg(env = "NETHSM_USER_TAG", help = "The tag to remove from a user")]
240 pub tag: String,
241}