Skip to main content

nitro_cli/common/
document_errors.rs

1use lazy_static::lazy_static;
2
3use std::collections::HashMap;
4
5use crate::common::{NitroCliErrorEnum, NitroCliFailure};
6
7lazy_static! {
8    /// Structure mapping enum Errors to a specific error code.
9    pub static ref ERROR_CODES: HashMap<NitroCliErrorEnum, &'static str> =
10        [
11            (NitroCliErrorEnum::UnspecifiedError, "E00"),
12            (NitroCliErrorEnum::MissingArgument, "E01"),
13            (NitroCliErrorEnum::ConflictingArgument, "E02"),
14            (NitroCliErrorEnum::InvalidArgument, "E03"),
15            (NitroCliErrorEnum::SocketPairCreationFailure, "E04"),
16            (NitroCliErrorEnum::ProcessSpawnFailure, "E05"),
17            (NitroCliErrorEnum::DaemonizeProcessFailure, "E06"),
18            (NitroCliErrorEnum::ReadFromDiskFailure, "E07"),
19            (NitroCliErrorEnum::UnusableConnectionError, "E08"),
20            (NitroCliErrorEnum::SocketCloseError, "E09"),
21            (NitroCliErrorEnum::SocketConnectTimeoutError, "E10"),
22            (NitroCliErrorEnum::SocketError, "E11"),
23            (NitroCliErrorEnum::EpollError, "E12"),
24            (NitroCliErrorEnum::InotifyError, "E13"),
25            (NitroCliErrorEnum::InvalidCommand, "E14"),
26            (NitroCliErrorEnum::LockAcquireFailure, "E15"),
27            (NitroCliErrorEnum::ThreadJoinFailure, "E16"),
28            (NitroCliErrorEnum::SerdeError, "E17"),
29            (NitroCliErrorEnum::FilePermissionsError, "E18"),
30            (NitroCliErrorEnum::FileOperationFailure, "E19"),
31            (NitroCliErrorEnum::InvalidCpuConfiguration, "E20"),
32            (NitroCliErrorEnum::NoSuchCpuAvailableInPool, "E21"),
33            (NitroCliErrorEnum::InsufficientCpus, "E22"),
34            (NitroCliErrorEnum::MalformedCpuId, "E23"),
35            (NitroCliErrorEnum::CpuError, "E24"),
36            (NitroCliErrorEnum::NoSuchHugepageFlag, "E25"),
37            (NitroCliErrorEnum::InsufficientMemoryRequested, "E26"),
38            (NitroCliErrorEnum::InsufficientMemoryAvailable, "E27"),
39            (NitroCliErrorEnum::InvalidEnclaveFd, "E28"),
40            (NitroCliErrorEnum::IoctlFailure, "E29"),
41            (NitroCliErrorEnum::IoctlImageLoadInfoFailure, "E30"),
42            (NitroCliErrorEnum::IoctlSetMemoryRegionFailure, "E31"),
43            (NitroCliErrorEnum::IoctlAddVcpuFailure, "E32"),
44            (NitroCliErrorEnum::IoctlEnclaveStartFailure, "E33"),
45            (NitroCliErrorEnum::MemoryOverflow, "E34"),
46            (NitroCliErrorEnum::EifParsingError, "E35"),
47            (NitroCliErrorEnum::EnclaveBootFailure, "E36"),
48            (NitroCliErrorEnum::EnclaveEventWaitError, "E37"),
49            (NitroCliErrorEnum::EnclaveProcessCommandNotExecuted, "E38"),
50            (NitroCliErrorEnum::EnclaveProcessConnectionFailure, "E39"),
51            (NitroCliErrorEnum::SocketPathNotFound, "E40"),
52            (NitroCliErrorEnum::EnclaveProcessSendReplyFailure, "E41"),
53            (NitroCliErrorEnum::EnclaveMmapError, "E42"),
54            (NitroCliErrorEnum::EnclaveMunmapError, "E43"),
55            (NitroCliErrorEnum::EnclaveConsoleConnectionFailure, "E44"),
56            (NitroCliErrorEnum::EnclaveConsoleReadError, "E45"),
57            (NitroCliErrorEnum::EnclaveConsoleWriteOutputError, "E46"),
58            (NitroCliErrorEnum::IntegerParsingError, "E47"),
59            (NitroCliErrorEnum::EifBuildingError, "E48"),
60            (NitroCliErrorEnum::DockerImageBuildError, "E49"),
61            (NitroCliErrorEnum::DockerImagePullError, "E50"),
62            (NitroCliErrorEnum::ArtifactsPathNotSet, "E51"),
63            (NitroCliErrorEnum::BlobsPathNotSet, "E52"),
64            (NitroCliErrorEnum::ClockSkewError, "E53"),
65            (NitroCliErrorEnum::SignalMaskingError, "E54"),
66            (NitroCliErrorEnum::SignalUnmaskingError, "E55"),
67            (NitroCliErrorEnum::LoggerError, "E56"),
68            (NitroCliErrorEnum::HasherError, "E57"),
69            (NitroCliErrorEnum::EnclaveNamingError, "E58"),
70            (NitroCliErrorEnum::EIFSignatureCheckerError, "E59"),
71            (NitroCliErrorEnum::EIFSigningError, "E60"),
72        ].iter().cloned().collect();
73}
74
75/// Returns detailed error information based on supplied arguments.
76pub fn get_detailed_info(error_code_str: String, additional_info: &[String]) -> String {
77    let mut ret = format!("[ {error_code_str} ] ");
78    let info_placeholder = "MISSING_INFO".to_string();
79
80    match error_code_str.as_str() {
81        "E00" => {
82            ret.push_str("Unspecified error. This is used as a catch-all error and should not be used in the code.");
83        }
84        "E01" => {
85            ret.push_str(
86                format!(
87                    "Missing mandatory argument. User did not provide the `{}` argument.",
88                    additional_info.first().unwrap_or(&info_placeholder)
89                )
90                .as_str(),
91            );
92        }
93        "E02" => {
94            ret.push_str(
95                format!(
96                    "Conflicting arguments. User provided both `{}` and `{}`.",
97                    additional_info.first().unwrap_or(&info_placeholder),
98                    additional_info.get(1).unwrap_or(&info_placeholder)
99                )
100                .as_str(),
101            );
102        }
103        "E03" => {
104            ret.push_str(
105                format!(
106                    "Invalid argument provided. The parameter `{}` is not a valid integer (`{}`)",
107                    additional_info.first().unwrap_or(&info_placeholder),
108                    additional_info.get(1).unwrap_or(&info_placeholder)
109                )
110                .as_str(),
111            );
112        }
113        "E04" => {
114            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.");
115        }
116        "E05" => {
117            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.");
118        }
119        "E06" => {
120            ret.push_str("Daemonize process failure. Such error appears when the system fails to daemonize a newly spawned enclave process.");
121        }
122        "E07" => {
123            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.");
124        }
125        "E08" => {
126            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");
127        }
128        "E09" => {
129            ret.push_str("Socket close error. Such error appears when the system fails to successfully close a communication channel.");
130        }
131        "E10" => {
132            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.");
133        }
134        "E11" => {
135            ret.push_str("Socket error. This is used as an error for catching any other socket operation errors not covered by previous custom errors.");
136        }
137        "E12" => {
138            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.");
139        }
140        "E13" => {
141            ret.push_str("Inotify error. Such error appears when the system fails to configure a socket for monitorization.");
142        }
143        "E14" => {
144            ret.push_str("Invalid command. Such error appears when an unknown command and / or unknown arguments are sent through a socket.");
145        }
146        "E15" => {
147            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.");
148        }
149        "E16" => {
150            ret.push_str("Thread join failure. Such error appears when the system fails to successfully join a thread, after it finished executing.");
151        }
152        "E17" => {
153            ret.push_str("Serde error. Such error appears when serializing / deserializing a command or response fails.");
154        }
155        "E18" => {
156            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");
157        }
158        "E19" => {
159            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.");
160            if additional_info.len() >= 2 {
161                ret.push_str(
162                    format!(
163                        "\nFile: '{}', failing operation: '{}'.",
164                        additional_info.first().unwrap_or(&info_placeholder),
165                        additional_info.get(1).unwrap_or(&info_placeholder),
166                    )
167                    .as_str(),
168                );
169            }
170        }
171        "E20" => {
172            ret.push_str(
173                format!(
174                    "Invalid CPU configuration. User provided `{}` contains same CPU(s) (CPU(s) {}) multiple times.",
175                    additional_info.first().unwrap_or(&info_placeholder),
176                    additional_info.get(1).unwrap_or(&info_placeholder),
177                )
178                .as_str(),
179            );
180        }
181        "E21" => {
182            ret.push_str(
183                format!(
184                    "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.",
185                    additional_info.first().unwrap_or(&info_placeholder),
186                    additional_info.get(1).unwrap_or(&info_placeholder),
187                ).as_str(),
188            );
189        }
190        "E22" => {
191            ret.push_str(
192                format!(
193                    "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.",
194                    additional_info.first().unwrap_or(&info_placeholder),
195                    additional_info.get(1).unwrap_or(&info_placeholder),
196                ).as_str(),
197            );
198        }
199        "E23" => {
200            ret.push_str("Malformed CPU ID error. Such error appears when a `lscpu` line is malformed and reports an invalid online CPUs list.");
201        }
202        "E24" => {
203            ret.push_str("CPU error. Such error appears when a CPU line interval is invalid (for instance, 0-3-7)");
204        }
205        "E25" => {
206            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.");
207        }
208        "E26" => {
209            if additional_info.len() >= 3 {
210                ret.push_str(
211                    format!(
212                        "Insufficient memory requested. User provided `{}` is {} MB, but based on the EIF file size, the minimum memory should be {} MB",
213                        additional_info.first().unwrap_or(&info_placeholder),
214                        additional_info.get(1).unwrap_or(&info_placeholder),
215                        additional_info.get(2).unwrap_or(&info_placeholder)
216                    ).as_str(),
217                );
218            } else {
219                ret.push_str(
220                    format!(
221                        "Insufficient memory requested. User provided `{}` is {} MB, and memory should be greater than 0 MB.",
222                        additional_info.first().unwrap_or(&info_placeholder),
223                        additional_info.get(1).unwrap_or(&info_placeholder)
224                    ).as_str(),
225                );
226            }
227        }
228        "E27" => {
229            ret.push_str(
230                format!(
231                    "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.",
232                    additional_info.first().unwrap_or(&info_placeholder),
233                    additional_info.get(1).unwrap_or(&info_placeholder)
234                ).as_str(),
235            );
236        }
237        "E28" => {
238            ret.push_str("Invalid enclave descriptor. Such error appears when the NE_CREATE_VM ioctl returns with an error.");
239        }
240        "E29" => {
241            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.");
242        }
243        "E30" => {
244            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.");
245        }
246        "E31" => {
247            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.");
248        }
249        "E32" => {
250            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.");
251        }
252        "E33" => {
253            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.");
254        }
255        "E34" => {
256            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.");
257        }
258        "E35" => {
259            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.");
260        }
261        "E36" => {
262            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.");
263        }
264        "E37" => {
265            ret.push_str("Enclave event wait error. Such error appears when monitoring an enclave descriptor for events fails.");
266        }
267        "E38" => {
268            ret.push_str("Enclave process command not executed error. Such error appears when at least one enclave fails to provide the description information.");
269        }
270        "E39" => {
271            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.");
272        }
273        "E40" => {
274            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.");
275        }
276        "E41" => {
277            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.");
278        }
279        "E42" => {
280            ret.push_str(
281                "Enclave mmap error. Such error appears when allocating the enclave memory fails.",
282            );
283        }
284        "E43" => {
285            ret.push_str(
286                "Enclave munmap error. Such error appears when unmapping the enclave memory fails.",
287            );
288        }
289        "E44" => {
290            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.");
291        }
292        "E45" => {
293            ret.push_str("Enclave console read error. Such error appears when reading from a running enclave's console fails.");
294        }
295        "E46" => {
296            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.");
297        }
298        "E47" => {
299            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.");
300        }
301        "E48" => {
302            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.");
303        }
304        "E49" => {
305            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.");
306        }
307        "E50" => {
308            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.");
309        }
310        "E51" => {
311            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.");
312        }
313        "E52" => {
314            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.");
315        }
316        "E53" => {
317            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.");
318        }
319        "E54" => {
320            ret.push_str("Signal masking error. Such error appears if attempting to mask specific signals before creating an enclave process fails.");
321        }
322        "E55" => {
323            ret.push_str("Signal unmasking error. Such error appears if attempting to unmask specific signals after creating an enclave process fails.");
324        }
325        "E56" => {
326            ret.push_str("Logger error. Such error appears when attempting to initialize the underlying logging system fails.");
327        }
328        "E57" => {
329            ret.push_str("Hasher error. Such error appears when trying to initialize a hasher or write bytes to it, resulting in a IO error.");
330        }
331        "E58" => {
332            ret.push_str("Naming error. Such error appears when trying to perform an enclave operation using the enclave name and the name is invalid.");
333        }
334        "E59" => {
335            ret.push_str("EIF signature checker error. Such error appears when validation of the signing certificate fails.");
336        }
337        "E60" => {
338            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.");
339        }
340        _ => {
341            ret.push_str(format!("No such error code {error_code_str}").as_str());
342        }
343    }
344
345    ret
346}
347
348/// Returns a link with more detailed information regarding a specific error.
349pub fn construct_help_link(error_code_str: String) -> String {
350    format!("https://docs.aws.amazon.com/enclaves/latest/user/cli-errors.html#{error_code_str}")
351}
352
353/// Returns a string containing the backtrace recorded during propagating an error message
354pub fn construct_backtrace(failure_info: &NitroCliFailure) -> String {
355    let version = env!("CARGO_PKG_VERSION").to_string();
356
357    format!("  Action: {}\n  Subactions:{}\n  Root error file: {}\n  Root error line: {}\n  Version: {}",
358        failure_info.action,
359        failure_info.subactions.iter().rev().fold("".to_string(), |acc, x| {
360            format!("{acc}\n    {x}")
361        }),
362        failure_info.file,
363        failure_info.line,
364        version)
365}
366
367/// Detailed information based on user-provided error code.
368pub fn explain_error(error_code_str: String) {
369    match error_code_str.as_str() {
370        "E00" => {
371            eprintln!("Unspecified error. This is used as a catch-all error and should not be used in the code.");
372        }
373        "E01" => {
374            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.");
375        }
376        "E02" => {
377            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.");
378        }
379        "E03" => {
380            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." );
381        }
382        "E04" => {
383            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.");
384        }
385        "E05" => {
386            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.");
387        }
388        "E06" => {
389            eprintln!("Daemonize process failure. Such error appears when the system fails to daemonize the newly spawned enclave process.")
390        }
391        "E07" => {
392            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.");
393        }
394        "E08" => {
395            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");
396        }
397        "E09" => {
398            eprintln!("Socket close error. Such error appears when the system fails to successfully close a communication channel.");
399        }
400        "E10" => {
401            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.");
402        }
403        "E11" => {
404            eprintln!("Socket error. This is used as an error for catching any other socket operation errors not covered by previous custom errors.");
405        }
406        "E12" => {
407            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.");
408        }
409        "E13" => {
410            eprintln!("Inotify error. Such error appears when the system fails to configure a socket for monitorization.");
411        }
412        "E14" => {
413            eprintln!("Invalid command. Such error appears when an unknown command and / or unknown arguments are sent through a socket.");
414        }
415        "E15" => {
416            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.");
417        }
418        "E16" => {
419            eprintln!("Thread join failure. Such error appears when the system fails to successfully join a thread, after it finished executing.");
420        }
421        "E17" => {
422            eprintln!("Serde error. Such error appears when serializing / deserializing a command or response fails.");
423        }
424        "E18" => {
425            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");
426        }
427        "E19" => {
428            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.");
429        }
430        "E20" => {
431            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.");
432        }
433        "E21" => {
434            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.");
435        }
436        "E22" => {
437            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.");
438        }
439        "E23" => {
440            eprintln!("Malformed CPU ID error. Such error appears when a `lscpu` line is malformed and reports an invalid online CPUs list.");
441        }
442        "E24" => {
443            eprintln!(
444                "CPU error. Such error appears when a CPU line interval is invalid (as in 0-3-7)"
445            );
446        }
447        "E25" => {
448            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.");
449        }
450        "E26" => {
451            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.");
452        }
453        "E27" => {
454            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.");
455        }
456        "E28" => {
457            eprintln!("Invalid enclave descriptor. Such error appears when the NE_CREATE_VM ioctl returns with an error.");
458        }
459        "E29" => {
460            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.");
461        }
462        "E30" => {
463            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.");
464        }
465        "E31" => {
466            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.");
467        }
468        "E32" => {
469            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.");
470        }
471        "E33" => {
472            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.");
473        }
474        "E34" => {
475            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.");
476        }
477        "E35" => {
478            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.");
479        }
480        "E36" => {
481            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.");
482        }
483        "E37" => {
484            eprintln!("Enclave event wait error. Such error appears when monitoring an enclave descriptor for events fails.");
485        }
486        "E38" => {
487            eprintln!("Enclave process command not executed error. Such error appears when at least one enclave fails to provide the description information.");
488        }
489        "E39" => {
490            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.");
491        }
492        "E40" => {
493            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.");
494        }
495        "E41" => {
496            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.");
497        }
498        "E42" => {
499            eprintln!(
500                "Enclave mmap error. Such error appears when allocating the enclave memory fails."
501            );
502        }
503        "E43" => {
504            eprintln!(
505                "Enclave munmap error. Such error appears when unmapping the enclave memory fails."
506            );
507        }
508        "E44" => {
509            eprintln!("Enclave console connection failure. Such error appears when the Nitro CLI process fails to establish a connection to a running enclave's console.");
510        }
511        "E45" => {
512            eprintln!("Enclave console read error. Such error appears when reading from a running enclave's console fails.");
513        }
514        "E46" => {
515            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.");
516        }
517        "E47" => {
518            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.");
519        }
520        "E48" => {
521            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.");
522        }
523        "E49" => {
524            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.");
525        }
526        "E50" => {
527            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.");
528        }
529        "E51" => {
530            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.");
531        }
532        "E52" => {
533            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.");
534        }
535        "E53" => {
536            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.");
537        }
538        "E54" => {
539            eprintln!("Signal masking error. Such error appears if attempting to mask specific signals before creating an enclave process fails.");
540        }
541        "E55" => {
542            eprintln!("Signal unmasking error. Such error appears if attempting to unmask specific signals after creating an enclave process fails.");
543        }
544        "E56" => {
545            eprintln!("Logger error. Such error appears when attempting to initialize the underlying logging system fails.");
546        }
547        "E60" => {
548            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.");
549        }
550        _ => {
551            eprintln!("No such error code {error_code_str}");
552        }
553    }
554}
555
556#[cfg(test)]
557mod tests {
558    use super::NitroCliFailure;
559    use crate::common::document_errors::construct_backtrace;
560
561    #[test]
562    fn test_construct_backtrace() {
563        let failure = NitroCliFailure::new()
564            .set_action(String::from("ABCD"))
565            .add_subaction(String::from("EFGH"))
566            .add_subaction(String::from("IJKL"))
567            .set_file_and_line("/path/file.txt", 1234);
568        // "  Action: ABCD
569        //    Subactions:
570        //      IJKL
571        //      EFGH
572        //    Root error file: /path/file.txt
573        //    Root error line: 1234
574        //    Version: X.Y.Z"
575        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: {}",
576            env!("CARGO_PKG_VERSION"));
577        assert_eq!(expected, construct_backtrace(&failure));
578    }
579}