aws-nitro-enclaves-cli 1.5.2

Command line tool to build and manage AWS Nitro Enclaves.
Documentation
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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
use lazy_static::lazy_static;

use std::collections::HashMap;

use crate::common::{NitroCliErrorEnum, NitroCliFailure};

lazy_static! {
    /// Structure mapping enum Errors to a specific error code.
    pub static ref ERROR_CODES: HashMap<NitroCliErrorEnum, &'static str> =
        [
            (NitroCliErrorEnum::UnspecifiedError, "E00"),
            (NitroCliErrorEnum::MissingArgument, "E01"),
            (NitroCliErrorEnum::ConflictingArgument, "E02"),
            (NitroCliErrorEnum::InvalidArgument, "E03"),
            (NitroCliErrorEnum::SocketPairCreationFailure, "E04"),
            (NitroCliErrorEnum::ProcessSpawnFailure, "E05"),
            (NitroCliErrorEnum::DaemonizeProcessFailure, "E06"),
            (NitroCliErrorEnum::ReadFromDiskFailure, "E07"),
            (NitroCliErrorEnum::UnusableConnectionError, "E08"),
            (NitroCliErrorEnum::SocketCloseError, "E09"),
            (NitroCliErrorEnum::SocketConnectTimeoutError, "E10"),
            (NitroCliErrorEnum::SocketError, "E11"),
            (NitroCliErrorEnum::EpollError, "E12"),
            (NitroCliErrorEnum::InotifyError, "E13"),
            (NitroCliErrorEnum::InvalidCommand, "E14"),
            (NitroCliErrorEnum::LockAcquireFailure, "E15"),
            (NitroCliErrorEnum::ThreadJoinFailure, "E16"),
            (NitroCliErrorEnum::SerdeError, "E17"),
            (NitroCliErrorEnum::FilePermissionsError, "E18"),
            (NitroCliErrorEnum::FileOperationFailure, "E19"),
            (NitroCliErrorEnum::InvalidCpuConfiguration, "E20"),
            (NitroCliErrorEnum::NoSuchCpuAvailableInPool, "E21"),
            (NitroCliErrorEnum::InsufficientCpus, "E22"),
            (NitroCliErrorEnum::MalformedCpuId, "E23"),
            (NitroCliErrorEnum::CpuError, "E24"),
            (NitroCliErrorEnum::NoSuchHugepageFlag, "E25"),
            (NitroCliErrorEnum::InsufficientMemoryRequested, "E26"),
            (NitroCliErrorEnum::InsufficientMemoryAvailable, "E27"),
            (NitroCliErrorEnum::InvalidEnclaveFd, "E28"),
            (NitroCliErrorEnum::IoctlFailure, "E29"),
            (NitroCliErrorEnum::IoctlImageLoadInfoFailure, "E30"),
            (NitroCliErrorEnum::IoctlSetMemoryRegionFailure, "E31"),
            (NitroCliErrorEnum::IoctlAddVcpuFailure, "E32"),
            (NitroCliErrorEnum::IoctlEnclaveStartFailure, "E33"),
            (NitroCliErrorEnum::MemoryOverflow, "E34"),
            (NitroCliErrorEnum::EifParsingError, "E35"),
            (NitroCliErrorEnum::EnclaveBootFailure, "E36"),
            (NitroCliErrorEnum::EnclaveEventWaitError, "E37"),
            (NitroCliErrorEnum::EnclaveProcessCommandNotExecuted, "E38"),
            (NitroCliErrorEnum::EnclaveProcessConnectionFailure, "E39"),
            (NitroCliErrorEnum::SocketPathNotFound, "E40"),
            (NitroCliErrorEnum::EnclaveProcessSendReplyFailure, "E41"),
            (NitroCliErrorEnum::EnclaveMmapError, "E42"),
            (NitroCliErrorEnum::EnclaveMunmapError, "E43"),
            (NitroCliErrorEnum::EnclaveConsoleConnectionFailure, "E44"),
            (NitroCliErrorEnum::EnclaveConsoleReadError, "E45"),
            (NitroCliErrorEnum::EnclaveConsoleWriteOutputError, "E46"),
            (NitroCliErrorEnum::IntegerParsingError, "E47"),
            (NitroCliErrorEnum::EifBuildingError, "E48"),
            (NitroCliErrorEnum::DockerImageBuildError, "E49"),
            (NitroCliErrorEnum::DockerImagePullError, "E50"),
            (NitroCliErrorEnum::ArtifactsPathNotSet, "E51"),
            (NitroCliErrorEnum::BlobsPathNotSet, "E52"),
            (NitroCliErrorEnum::ClockSkewError, "E53"),
            (NitroCliErrorEnum::SignalMaskingError, "E54"),
            (NitroCliErrorEnum::SignalUnmaskingError, "E55"),
            (NitroCliErrorEnum::LoggerError, "E56"),
            (NitroCliErrorEnum::HasherError, "E57"),
            (NitroCliErrorEnum::EnclaveNamingError, "E58"),
            (NitroCliErrorEnum::EIFSignatureCheckerError, "E59"),
            (NitroCliErrorEnum::EIFSigningError, "E60"),
        ].iter().cloned().collect();
}

/// Returns detailed error information based on supplied arguments.
pub fn get_detailed_info(error_code_str: String, additional_info: &[String]) -> String {
    let mut ret = format!("[ {error_code_str} ] ");
    let info_placeholder = "MISSING_INFO".to_string();

    match error_code_str.as_str() {
        "E00" => {
            ret.push_str("Unspecified error. This is used as a catch-all error and should not be used in the code.");
        }
        "E01" => {
            ret.push_str(
                format!(
                    "Missing mandatory argument. User did not provide the `{}` argument.",
                    additional_info.first().unwrap_or(&info_placeholder)
                )
                .as_str(),
            );
        }
        "E02" => {
            ret.push_str(
                format!(
                    "Conflicting arguments. User provided both `{}` and `{}`.",
                    additional_info.first().unwrap_or(&info_placeholder),
                    additional_info.get(1).unwrap_or(&info_placeholder)
                )
                .as_str(),
            );
        }
        "E03" => {
            ret.push_str(
                format!(
                    "Invalid argument provided. The parameter `{}` is not a valid integer (`{}`)",
                    additional_info.first().unwrap_or(&info_placeholder),
                    additional_info.get(1).unwrap_or(&info_placeholder)
                )
                .as_str(),
            );
        }
        "E04" => {
            ret.push_str("Socket pair creation failure. Such error appears when the Nitro CLI process attempts to open a stream pair in order to send a command to the enclave process but the stream initialization fails.");
        }
        "E05" => {
            ret.push_str("Process spawn failure. Such error appears when the main Nitro CLI process fails to spawn the enclave process, in order to complete a `run-enclave` command.");
        }
        "E06" => {
            ret.push_str("Daemonize process failure. Such error appears when the system fails to daemonize a newly spawned enclave process.");
        }
        "E07" => {
            ret.push_str("Read from disk failure. Such error appears when the Nitro CLI process fails to read the content of the enclave sockets directory (usually '/run/nitro_enclaves/') in order to perform a `describe-enclave` operation. Check that the directory exists and it has proper permissions, or run the Nitro Enclaves configuration script in order to (re)configure the environment.");
        }
        "E08" => {
            ret.push_str("Unusable connection error. Such error appears when the Nitro CLI process attempts to open a connection to a non-existing or previously closed enclave descriptor");
        }
        "E09" => {
            ret.push_str("Socket close error. Such error appears when the system fails to successfully close a communication channel.");
        }
        "E10" => {
            ret.push_str("Socket connect set timeout error. Such error appears when the system fails to configure a specific timeout for a given socket. May arise when trying to connect to an enclave's console.");
        }
        "E11" => {
            ret.push_str("Socket error. This is used as an error for catching any other socket operation errors not covered by previous custom errors.");
        }
        "E12" => {
            ret.push_str("Epoll error. Such error appears, for instance, when the system fails to register a specific enclave descriptor with epoll in order to monitor events for it.");
        }
        "E13" => {
            ret.push_str("Inotify error. Such error appears when the system fails to configure a socket for monitorization.");
        }
        "E14" => {
            ret.push_str("Invalid command. Such error appears when an unknown command and / or unknown arguments are sent through a socket.");
        }
        "E15" => {
            ret.push_str("Lock acquire failure. Such error appears when the system fails to obtain the lock for an object with concurrent access, such as a structure containing information about a running enclave.");
        }
        "E16" => {
            ret.push_str("Thread join failure. Such error appears when the system fails to successfully join a thread, after it finished executing.");
        }
        "E17" => {
            ret.push_str("Serde error. Such error appears when serializing / deserializing a command or response fails.");
        }
        "E18" => {
            ret.push_str("File permissions error. Such error appears when a user other than the owner of the logging file (usually '/var/log/nitro_enclaves/nitro_enclaves.log') attempts to change the file permissions");
        }
        "E19" => {
            ret.push_str("File operation failure. Such error appears when the system fails to perform the requested file operations, such as opening the EIF file when launching an enclave, or seeking to a specific offset in the EIF file, or writing to the log file.");
            if additional_info.len() >= 2 {
                ret.push_str(
                    format!(
                        "\nFile: '{}', failing operation: '{}'.",
                        additional_info.first().unwrap_or(&info_placeholder),
                        additional_info.get(1).unwrap_or(&info_placeholder),
                    )
                    .as_str(),
                );
            }
        }
        "E20" => {
            ret.push_str(
                format!(
                    "Invalid CPU configuration. User provided `{}` contains same CPU(s) (CPU(s) {}) multiple times.",
                    additional_info.first().unwrap_or(&info_placeholder),
                    additional_info.get(1).unwrap_or(&info_placeholder),
                )
                .as_str(),
            );
        }
        "E21" => {
            ret.push_str(
                format!(
                    "No such CPU available in the pool. User provided `{}` contains CPU {}, which is not available in the pool.\nYou can add a specific CPU to the CPU pool by editing the `cpu_pool` value from '/etc/nitro_enclaves/allocator.yaml' and then enable the nitro-enclaves-allocator.service.",
                    additional_info.first().unwrap_or(&info_placeholder),
                    additional_info.get(1).unwrap_or(&info_placeholder),
                ).as_str(),
            );
        }
        "E22" => {
            ret.push_str(
                format!(
                    "Insufficient CPUs available in the pool. User provided `{}` is {}, which is more than the configured CPU pool size.\nYou can increase the CPU pool size by editing the `cpu_count` value from '/etc/nitro_enclaves/allocator.yaml' and then enable the nitro-enclaves-allocator.service.",
                    additional_info.first().unwrap_or(&info_placeholder),
                    additional_info.get(1).unwrap_or(&info_placeholder),
                ).as_str(),
            );
        }
        "E23" => {
            ret.push_str("Malformed CPU ID error. Such error appears when a `lscpu` line is malformed and reports an invalid online CPUs list.");
        }
        "E24" => {
            ret.push_str("CPU error. Such error appears when a CPU line interval is invalid (for instance, 0-3-7)");
        }
        "E25" => {
            ret.push_str("No such hugepage flag error. Such error appears when the enclave process attempts to use an invalid hugepage size (size other than the known hugepage sizes) for initializing the enclave memory.");
        }
        "E26" => {
            if additional_info.len() >= 3 {
                ret.push_str(
                    format!(
                        "Insufficient memory requested. User provided `{}` is {} MB, but based on the EIF file size, the minimum memory should be {} MB",
                        additional_info.first().unwrap_or(&info_placeholder),
                        additional_info.get(1).unwrap_or(&info_placeholder),
                        additional_info.get(2).unwrap_or(&info_placeholder)
                    ).as_str(),
                );
            } else {
                ret.push_str(
                    format!(
                        "Insufficient memory requested. User provided `{}` is {} MB, and memory should be greater than 0 MB.",
                        additional_info.first().unwrap_or(&info_placeholder),
                        additional_info.get(1).unwrap_or(&info_placeholder)
                    ).as_str(),
                );
            }
        }
        "E27" => {
            ret.push_str(
                format!(
                    "Insufficient memory available. User provided `{}` is {} MB, which is more than the available hugepage memory.\nYou can increase the available memory by editing the `memory_mib` value from '/etc/nitro_enclaves/allocator.yaml' and then restart the nitro-enclaves-allocator.service.",
                    additional_info.first().unwrap_or(&info_placeholder),
                    additional_info.get(1).unwrap_or(&info_placeholder)
                ).as_str(),
            );
        }
        "E28" => {
            ret.push_str("Invalid enclave descriptor. Such error appears when the NE_CREATE_VM ioctl returns with an error.");
        }
        "E29" => {
            ret.push_str("Ioctl failure. Such error is used as a general ioctl error and appears whenever an ioctl fails. In this case, the error backtrace provides detailed information on what specifically failed during the ioctl.");
        }
        "E30" => {
            ret.push_str("Ioctl image get load info failure. Such error appears when the ioctl used for getting the memory load information fails. In this case, the error backtrace provides detailed information on what specifically failed during the ioctl.");
        }
        "E31" => {
            ret.push_str("Ioctl set memory region failure. Such error appears when the ioctl used for setting a given memory region fails. In this case, the error backtrace provides detailed information on what specifically failed during the ioctl.");
        }
        "E32" => {
            ret.push_str("Ioctl add vCPU failure. Such error appears when the ioctl used for adding a vCPU fails. In this case, the error backtrace provides detailed information on what specifically failed during the ioctl.");
        }
        "E33" => {
            ret.push_str("Ioctl start enclave failure. Such error appears when the ioctl used for starting an enclave fails. In this case, the error backtrace provides details information on what specifically failed during the ioctl.");
        }
        "E34" => {
            ret.push_str("Memory overflow. Such error may appear during loading the EIF in the memory regions which will be conceded to the future enclave, if the regions offset plus the EIF file size exceeds the maximum address of the target platform.");
        }
        "E35" => {
            ret.push_str("EIF file parsing error. Such errors appear when attempting to fill a memory region with a section of the EIF file, but reading the entire section fails. This might indicate that the required hugepages are not available.");
        }
        "E36" => {
            ret.push_str("Enclave boot failure. Such error appears when attempting to receive the `ready` signal from a freshly booted enclave. It arises in several contexts, for instance, when the enclave is booted from an invalid EIF file and the enclave process immediately exits, failing to submit the `ready` signal. In this case, the error backtrace provides detailed information on what specifically failed during the enclave boot process.");
        }
        "E37" => {
            ret.push_str("Enclave event wait error. Such error appears when monitoring an enclave descriptor for events fails.");
        }
        "E38" => {
            ret.push_str("Enclave process command not executed error. Such error appears when at least one enclave fails to provide the description information.");
        }
        "E39" => {
            ret.push_str("Enclave process connection failure. Such error appears when the enclave manager fails to connect to at least one enclave process for retrieving the description information.");
        }
        "E40" => {
            ret.push_str("Socket path not found. Such error appears when the Nitro CLI process fails to build the corresponding socket path starting from a given enclave ID.");
        }
        "E41" => {
            ret.push_str("Enclave process send reply failure. Such error appears when the enclave process fails to submit the status code to the Nitro CLI process after performing a run / describe / terminate command.");
        }
        "E42" => {
            ret.push_str(
                "Enclave mmap error. Such error appears when allocating the enclave memory fails.",
            );
        }
        "E43" => {
            ret.push_str(
                "Enclave munmap error. Such error appears when unmapping the enclave memory fails.",
            );
        }
        "E44" => {
            ret.push_str("Enclave console connection failure. Such error appears when the Nitro CLI process fails to establish a connection to a running enclave's console.");
        }
        "E45" => {
            ret.push_str("Enclave console read error. Such error appears when reading from a running enclave's console fails.");
        }
        "E46" => {
            ret.push_str("Enclave console write output error. Such error appears when writing the information retrieved from a running enclave's console (to a given stream) fails.");
        }
        "E47" => {
            ret.push_str("Integer parsing error. Such error appears when trying to connect to a running enclave's console, but the enclave CID cannot be parsed correctly.");
        }
        "E48" => {
            ret.push_str("EIF building error. Such error appears when trying to build an EIF file. In this case, the error backtrace provides detailed information on the failure reason.");
        }
        "E49" => {
            ret.push_str("Docker image build error. Such error appears when trying to build and EIF file, but building the corresponding docker image fails. In this case, the error backtrace provides detailed information on the failure reason.");
        }
        "E50" => {
            ret.push_str("Docker image pull error. Such error appears when trying to build an EIF file, but pulling the corresponding docker image fails. In this case, the error backtrace provides detailed informatino on the failure reason.");
        }
        "E51" => {
            ret.push_str("Artifacts path environment variable not set. Such error appears when trying to build an EIF file, but the artifacts path environment variable is not set.");
        }
        "E52" => {
            ret.push_str("Blobs path environment variable not set. Such error appears when trying to build an EIF file, but the blobs path environment variable is not set.");
        }
        "E53" => {
            ret.push_str("Clock skew error. Such error appears when continuously reading from a running enclave's console, but measuring the time elapsed between consecutive reads failed.");
        }
        "E54" => {
            ret.push_str("Signal masking error. Such error appears if attempting to mask specific signals before creating an enclave process fails.");
        }
        "E55" => {
            ret.push_str("Signal unmasking error. Such error appears if attempting to unmask specific signals after creating an enclave process fails.");
        }
        "E56" => {
            ret.push_str("Logger error. Such error appears when attempting to initialize the underlying logging system fails.");
        }
        "E57" => {
            ret.push_str("Hasher error. Such error appears when trying to initialize a hasher or write bytes to it, resulting in a IO error.");
        }
        "E58" => {
            ret.push_str("Naming error. Such error appears when trying to perform an enclave operation using the enclave name and the name is invalid.");
        }
        "E59" => {
            ret.push_str("EIF signature checker error. Such error appears when validation of the signing certificate fails.");
        }
        "E60" => {
            ret.push_str("Signing error. Such error appears if incorrect key or certificate paths are provided, or when AWS credenrials need to be refreshed to use a KMS key.");
        }
        _ => {
            ret.push_str(format!("No such error code {error_code_str}").as_str());
        }
    }

    ret
}

/// Returns a link with more detailed information regarding a specific error.
pub fn construct_help_link(error_code_str: String) -> String {
    format!("https://docs.aws.amazon.com/enclaves/latest/user/cli-errors.html#{error_code_str}")
}

/// Returns a string containing the backtrace recorded during propagating an error message
pub fn construct_backtrace(failure_info: &NitroCliFailure) -> String {
    let version = env!("CARGO_PKG_VERSION").to_string();

    format!("  Action: {}\n  Subactions:{}\n  Root error file: {}\n  Root error line: {}\n  Version: {}",
        failure_info.action,
        failure_info.subactions.iter().rev().fold("".to_string(), |acc, x| {
            format!("{acc}\n    {x}")
        }),
        failure_info.file,
        failure_info.line,
        version)
}

/// Detailed information based on user-provided error code.
pub fn explain_error(error_code_str: String) {
    match error_code_str.as_str() {
        "E00" => {
            eprintln!("Unspecified error. This is used as a catch-all error and should not be used in the code.");
        }
        "E01" => {
            eprintln!("Missing mandatory argument. Such error appears when the Nitro CLI is requested to perform an operation, but not all of the mandatory arguments were supplied.\n\tExample: `nitro-cli run-enclave --cpu-count 2 --eif-path /path/to/my/eif`. Note that in this case, the mandatory parameter `--memory` is missing a value.");
        }
        "E02" => {
            eprintln!("CLI conflicting arguments. Such error appears when the Nitro CLI is supplied two contradicting arguments at the same time, such as `--cpu-count` and `--cpu-ids`.\nIn this case, only one of the parameters should be supplied.");
        }
        "E03" => {
            eprintln!("Invalid argument provided. Such error appears when the type of at least one of the arguments provided to the Nitro CLI does not match the expected type of that parameter.\n\tExample: `nitro-cli run-enclave --cpu-count 1z --memory 80 --eif-path /path/to/my/eif`. In this case, `cpu-count` is not a valid integer value." );
        }
        "E04" => {
            eprintln!("Socket pair creation failure. Such error apears when the Nitro CLI process attempts to open a stream pair in order to send a command to the enclave process, but the stream initialization fails.");
        }
        "E05" => {
            eprintln!("Process spawn failure. Such error appears when the main Nitro CLI process failed to spawn the enclave process, in order to complete a `run-enclave` command.");
        }
        "E06" => {
            eprintln!("Daemonize process failure. Such error appears when the system fails to daemonize the newly spawned enclave process.")
        }
        "E07" => {
            eprintln!("Read from disk failure. Such error appears when the Nitro CLI process fails to read the content of the enclave sockets directory (usually '/run/nitro_enclaves/') in order to perform a `describe-enclave` operation. Check that the directory exists and it has proper permissions, or run the Nitro Enclaves configuration script in order to (re)configure the environment.");
        }
        "E08" => {
            eprintln!("Unusable connection error. Such error appears when the Nitro CLI process attempts to open a connection to a non-existing or previously closed enclave descriptor");
        }
        "E09" => {
            eprintln!("Socket close error. Such error appears when the system fails to successfully close a communication channel.");
        }
        "E10" => {
            eprintln!("Socket connect set timeout error. Such error appears when the system fails to configure a specific timeout for a given socket. May arise when trying to connect to an enclave's console.");
        }
        "E11" => {
            eprintln!("Socket error. This is used as an error for catching any other socket operation errors not covered by previous custom errors.");
        }
        "E12" => {
            eprintln!("Epoll error. Such error appears, for instance, when the system fails to register a specific enclave descriptor with epoll in order to monitor events for it.");
        }
        "E13" => {
            eprintln!("Inotify error. Such error appears when the system fails to configure a socket for monitorization.");
        }
        "E14" => {
            eprintln!("Invalid command. Such error appears when an unknown command and / or unknown arguments are sent through a socket.");
        }
        "E15" => {
            eprintln!("Lock acquire failure. Such error appears when the system fails to obtain the lock for an object with concurrent access, such as a structure containing information about a running enclave.");
        }
        "E16" => {
            eprintln!("Thread join failure. Such error appears when the system fails to successfully join a thread, after it finished executing.");
        }
        "E17" => {
            eprintln!("Serde error. Such error appears when serializing / deserializing a command or response fails.");
        }
        "E18" => {
            eprintln!("File permissions error. Such error appears when a user other than the owner of the logging file (usually '/var/log/nitro_enclaves/nitro_enclaves.log') attempts to change the file permissions");
        }
        "E19" => {
            eprintln!("File operation failure. Such error appears when the system fails to perform the requested file operations, such as opening the EIF file when launching an enclave, or seeking to a specific offset in the EIF file, or writing to the log file.");
        }
        "E20" => {
            eprintln!("Invalid CPU configuration. Such error appears when the user supplies the same CPU ID multiple times.\n\tExample: `nitro-cli run-enclave --cpu-ids 1 1 --memory 80 --eif-path /path/to/my/eif`. In this case, CPU ID `1` has been selected twice.");
        }
        "E21" => {
            eprintln!("No such CPU available in the pool. Such error appears when the user requests to run an enclave with at least one CPU ID which does not exist in the CPU pool.\n\tExample: (configured CPU pool: [1,9]) `nitro-cli run-enclave --cpu-ids 1 2 --memory 80 --eif-path /path/to/my/eif`. In this case, CPU 2 is not in the configured CPU pool.");
        }
        "E22" => {
            eprintln!("Insufficient CPUs available in the pool. Such error appears when the user requests to run an enclave with more CPUs that available in the CPU pool.\n\tExample: (configured CPU pool: [1,9]) `nitro-cli run-enclave --cpu-count 4 --memory 80 --eif-path /path/to/my/eif`. In this case, the user requested 4 CPUs, but the CPU pool contains only 2.");
        }
        "E23" => {
            eprintln!("Malformed CPU ID error. Such error appears when a `lscpu` line is malformed and reports an invalid online CPUs list.");
        }
        "E24" => {
            eprintln!(
                "CPU error. Such error appears when a CPU line interval is invalid (as in 0-3-7)"
            );
        }
        "E25" => {
            eprintln!("No such hugepage flag error. Such error appears when the enclave process attempts to use an invalid hugepage size (size other than the known hugepage sizes) for initializing the enclave memory.");
        }
        "E26" => {
            eprintln!("Insufficient memory requested. Such error appears when the user requests to launch an enclave with not enough memory. The enclave memory should be at least equal to the size of the EIF file used for launching the enclave.\n\tExample: (EIF file size: 11MB) `nitro-cli run-enclave --cpu-count 2 --memory 5 --eif-path /path/to/my/eif`. In this case, the user requested to run an enclave with only 5MB of memory, whereas the EIF file alone requires 11MB.");
        }
        "E27" => {
            eprintln!("Insufficient memory available. Such error appears when the user requests to launch an enclave with more memory than available. The enclave memory should be at most equal to the size of the configured hugepage memory.\n\tExample: (previously configured 80MB of hugepage memory) `nitro-cli run-enclave --cpu-count 2 --memory 100 --eif-path /path/to/my/eif`. In this case, the user requested to run an enclave with 100MB of memory, whereas the system has only 80MB available for enclaves. As a solution, (re)configure the Nitro Enclaves environment, specifying a higher value for the available memory.");
        }
        "E28" => {
            eprintln!("Invalid enclave descriptor. Such error appears when the NE_CREATE_VM ioctl returns with an error.");
        }
        "E29" => {
            eprintln!("Ioctl failure. Such error is used as a general ioctl error and appears whenever an ioctl fails. In this case, the error backtrace provides detailed information on what specifically failed during the ioctl.");
        }
        "E30" => {
            eprintln!("Ioctl image get load info failure. Such error appears when the ioctl used for getting the memory load information fails. In this case, the error backtrace provides detailed information on what specifically failed during the ioctl.");
        }
        "E31" => {
            eprintln!("Ioctl set memory region failure. Such error appears when the ioctl used for setting a given memory region fails. In this case, the error backtrace provides detailed information on what specifically failed during the ioctl.");
        }
        "E32" => {
            eprintln!("Ioctl add vCPU failure. Such error appears when the ioctl used for adding a vCPU fails. In this case, the error backtrace provides detailed information on what specifically failed during the ioctl.");
        }
        "E33" => {
            eprintln!("Ioctl start enclave failure. Such error appears when the ioctl used for starting an enclave fails. In this case, the error backtrace provides details information on what specifically failed during the ioctl.");
        }
        "E34" => {
            eprintln!("Memory overflow. Such error may appear during loading the EIF in the memory regions which will be conceded to the future enclave, if the regions offset plus the EIF file size exceeds the maximum address of the target platform.");
        }
        "E35" => {
            eprintln!("EIF file parsing error. Such errors appear when attempting to fill a memory region with a section of the EIF file, but reading the entire section fails. This might indicate that the required hugepages are not available.");
        }
        "E36" => {
            eprintln!("Enclave boot failure. Such error appears when attempting to receive the `ready` signal from a freshly booted enclave. It arises in several contexts, for instance, when the enclave is booted from an invalid EIF file and the enclave process immediately exits, failing to submit the `ready` signal. In this case, the error backtrace provides detailed information on what specifically failed during the enclave boot process.");
        }
        "E37" => {
            eprintln!("Enclave event wait error. Such error appears when monitoring an enclave descriptor for events fails.");
        }
        "E38" => {
            eprintln!("Enclave process command not executed error. Such error appears when at least one enclave fails to provide the description information.");
        }
        "E39" => {
            eprintln!("Enclave process connection failure. Such error appears when the enclave manager fails to connect to at least one enclave process for retrieving the description information.");
        }
        "E40" => {
            eprintln!("Socket path not found. Such error appears when the Nitro CLI process fails to build the corresponding socket path starting from a given enclave ID.");
        }
        "E41" => {
            eprintln!("Enclave process send reply failure. Such error appears when the enclave process fails to submit the status code to the Nitro CLI process after performing a run / describe / terminate command.");
        }
        "E42" => {
            eprintln!(
                "Enclave mmap error. Such error appears when allocating the enclave memory fails."
            );
        }
        "E43" => {
            eprintln!(
                "Enclave munmap error. Such error appears when unmapping the enclave memory fails."
            );
        }
        "E44" => {
            eprintln!("Enclave console connection failure. Such error appears when the Nitro CLI process fails to establish a connection to a running enclave's console.");
        }
        "E45" => {
            eprintln!("Enclave console read error. Such error appears when reading from a running enclave's console fails.");
        }
        "E46" => {
            eprintln!("Enclave console write output error. Such error appears when writing the information retrieved from a running enclave's console (to a given stream) fails.");
        }
        "E47" => {
            eprintln!("Integer parsing error. Such error appears when trying to connect to a running enclave's console, but the enclave CID cannot be parsed correctly.");
        }
        "E48" => {
            eprintln!("EIF building error. Such error appears when trying to build an EIF file. In this case, the error backtrace provides detailed information on the failure reason.");
        }
        "E49" => {
            eprintln!("Docker image build error. Such error appears when trying to build and EIF file, but building the corresponding docker image fails. In this case, the error backtrace provides detailed information on the failure reason.");
        }
        "E50" => {
            eprintln!("Docker image pull error. Such error appears when trying to build an EIF file, but pulling the corresponding docker image fails. In this case, the error backtrace provides detailed informatino on the failure reason.");
        }
        "E51" => {
            eprintln!("Artifacts path environment variable not set. Such error appears when trying to build an EIF file, but the artifacts path environment variable is not set.");
        }
        "E52" => {
            eprintln!("Blobs path environment variable not set. Such error appears when trying to build an EIF file, but the blobs path environment variable is not set.");
        }
        "E53" => {
            eprintln!("Clock skew error. Such error appears when continuously reading from a running enclave's console, but measuring the time elapsed between consecutive reads failed.");
        }
        "E54" => {
            eprintln!("Signal masking error. Such error appears if attempting to mask specific signals before creating an enclave process fails.");
        }
        "E55" => {
            eprintln!("Signal unmasking error. Such error appears if attempting to unmask specific signals after creating an enclave process fails.");
        }
        "E56" => {
            eprintln!("Logger error. Such error appears when attempting to initialize the underlying logging system fails.");
        }
        "E60" => {
            eprintln!("Signing error. Such error appears if incorrect key or certificate paths are provided, or when AWS credenrials need to be refreshed to use a KMS key.");
        }
        _ => {
            eprintln!("No such error code {error_code_str}");
        }
    }
}

#[cfg(test)]
mod tests {
    use super::NitroCliFailure;
    use crate::common::document_errors::construct_backtrace;

    #[test]
    fn test_construct_backtrace() {
        let failure = NitroCliFailure::new()
            .set_action(String::from("ABCD"))
            .add_subaction(String::from("EFGH"))
            .add_subaction(String::from("IJKL"))
            .set_file_and_line("/path/file.txt", 1234);
        // "  Action: ABCD
        //    Subactions:
        //      IJKL
        //      EFGH
        //    Root error file: /path/file.txt
        //    Root error line: 1234
        //    Version: X.Y.Z"
        let expected = format!("  Action: ABCD\n  Subactions:\n    IJKL\n    EFGH\n  Root error file: /path/file.txt\n  Root error line: 1234\n  Version: {}",
            env!("CARGO_PKG_VERSION"));
        assert_eq!(expected, construct_backtrace(&failure));
    }
}