nethsm_cli/cli/
system.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
use std::path::PathBuf;

use chrono::{DateTime, Utc};
use clap::{Parser, Subcommand};
use expression_format::ex_format;
use nethsm::{
    SystemState::{Locked, Operational, Unprovisioned},
    UserRole::{Administrator, Backup},
};

use super::BIN_NAME;
use crate::passphrase_file::PassphraseFile;

#[derive(Debug, Subcommand)]
#[command(about = "Do system actions for a device")]
pub enum SystemCommand {
    Backup(SystemBackupCommand),
    FactoryReset(SystemFactoryResetCommand),
    Info(SystemInfoCommand),
    Reboot(SystemRebootCommand),
    Restore(SystemRestoreCommand),
    Shutdown(SystemShutdownCommand),
    UploadUpdate(SystemUploadUpdateCommand),
    CancelUpdate(SystemCancelUpdateCommand),
    CommitUpdate(SystemCommitUpdateCommand),
    ValidateBackup(SystemValidateBackupCommand),
}

#[derive(Debug, Parser)]
#[command(
    about = "Backup the key store of a device",
    long_about = ex_format!("Backup the key store of a device

Writes an encrypted backup to a file in the current working directory, named after the device label in the configuration file and the current time.
Optionally, a specific output file can be provided.

Note: Requires setting the backup passphrase using \"{BIN_NAME} config set backup-passphrase\" first!

Requires authentication of a system-wide user in the \"{Backup}\" role.")
)]
pub struct SystemBackupCommand {
    #[arg(
        env = "NETHSM_FORCE",
        help = "Write to output file even if it exists already",
        long,
        short
    )]
    pub force: bool,

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

#[derive(Debug, Parser)]
#[command(
    about = "Reset the device to factory settings",
    long_about = ex_format!("Reset the device to factory settings

Triggers a factory reset for the device.

**WARNING**: This action deletes all user and system data! Make sure to create a backup using \"{BIN_NAME} system backup\" first!

Requires authentication of a system-wide user in the \"{Administrator}\" role.")
)]
pub struct SystemFactoryResetCommand {}

#[derive(Debug, Parser)]
#[command(
    about = "Retrieve system information of a device",
    long_about = ex_format!("Retrieve system information of a device

Provides information on software version, software build, firmware version, hardware version, device ID and information related to TPM and PCR.

Requires authentication of a system-wide user in the \"{Administrator}\" role.")
)]
pub struct SystemInfoCommand {}

#[derive(Debug, Parser)]
#[command(
    about = "Reboot the device",
    long_about = ex_format!("Reboot the device

Requires authentication of a user in the \"{Administrator}\" role.")
)]
pub struct SystemRebootCommand {}

#[derive(Debug, Parser)]
#[command(
    about = "Restore the device from a backup",
    long_about = ex_format!("Restore the device from a backup

The device may be in state \"{Operational}\" or \"{Unprovisioned}\".
In both cases, the users and keys from the backup replace those on the device (if any).

If the device is in state \"{Unprovisioned}\", any credentials provided for authentication are ignored, the system configuration
(e.g. TLS certificate, unlock passphrase, etc.) from the backup is used as well, the device is rebooted and ends up in
\"{Locked}\" state.

If no new system time is provided, it is derived from the caller's system time.
If no backup passphrase is provided specifically, it is prompted for interactively.

Requires authentication of a system-wide user in the \"{Administrator}\" role only if the device is in \"{Operational}\" state.")
)]
pub struct SystemRestoreCommand {
    #[arg(
        env = "NETHSM_BACKUP_FILE",
        help = "The path to a valid NetHSM backup file"
    )]
    pub input: PathBuf,

    #[arg(
        env = "NETHSM_BACKUP_PASSPHRASE_FILE",
        help = "The path to a file containing the backup passphrase",
        long,
        short
    )]
    pub backup_passphrase_file: Option<PassphraseFile>,

    #[arg(
        env = "NETHSM_SYSTEM_TIME",
        help = "The new system time for the device",
        long_help = "The new system time for the device

Must be provided as an ISO 8601 formatted UTC timestamp.",
        long,
        short
    )]
    pub system_time: Option<DateTime<Utc>>,
}

#[derive(Debug, Parser)]
#[command(
    about = "Shut down the device",
    long_about = ex_format!("Shut down the device

The device must be in state \"{Operational}\".

Requires authentication of a system-wide user in the \"{Administrator}\" role.")
)]
pub struct SystemShutdownCommand {}

#[derive(Debug, Parser)]
#[command(
    about = "Upload an update to the device",
    long_about = ex_format!("Upload an update to the device

Requires authentication of a user in the \"{Administrator}\" role.")
)]
pub struct SystemUploadUpdateCommand {
    #[arg(env = "NETHSM_UPDATE_FILE", help = "The path to an update file")]
    pub input: PathBuf,
}

#[derive(Debug, Parser)]
#[command(
    about = "Cancel an uploaded update on the device",
    long_about = ex_format!("Cancel an uploaded update on the device

The device must be in state \"{Operational}\" and an update file must have been uploaded first!

Requires authentication of a system-wide user in the \"{Administrator}\" role.")
)]
pub struct SystemCancelUpdateCommand {}

#[derive(Debug, Parser)]
#[command(
    about = "Commit an uploaded update on the device",
    long_about = ex_format!("Commit an uploaded update on the device

The device must be in state \"{Operational}\" and an update file must have been uploaded first!

Requires authentication of a system-wide user in the \"{Administrator}\" role.")
)]
pub struct SystemCommitUpdateCommand {}

#[derive(Debug, Parser)]
#[command(
    about = "Validate a backup file",
    long_about = ex_format!("Validate a backup file

Parse an encrypted backup file to ensure general properties.
If a passphrase is provided, decrypting the backup file and validating its version number is attempted.
This command exits with a non-zero exit code, if the file is corrupted, decryption or validation fails.

Note: Backups are created using \"{BIN_NAME} system backup\"")
)]
pub struct SystemValidateBackupCommand {
    #[arg(
        env = "NETHSM_VALIDATE_BACKUP_PASSPHRASE_FILE",
        help = "The path to a file containing the backup passphrase",
        long,
        short
    )]
    pub backup_passphrase_file: Option<PassphraseFile>,

    #[arg(
        env = "NETHSM_VALIDATE_BACKUP_FILE",
        help = "The path to the backup file to validate"
    )]
    pub input: PathBuf,
}