Closed ogarrett closed 2 years ago
@ogarrett I think it is ok to be verbose in stdout. Many tools are like that and they provide an option to save the output as a json/csv file which is machine readable.
$ syft .
✔ Indexed .
✔ Cataloged packages [1217 packages]
NAME VERSION TYPE
@ampproject/remapping 2.1.2 npm
@babel/code-frame 7.12.11 npm
syft --help
--file string file to write the default report output to (default is STDOUT)
--output stringArray report output format, options=[json text table cyclonedx cyclonedx-json spdx-tag-value spdx-json] (default [table])
IOC Scanner also has this option https://github.com/deepfence/IOCScanner/issues/6
It's OK to be verbose when the tool is used interactively (at a terminal), but we should also support non-interactive use. Non-interactive use includes running in a pipe in a terminal, or running from a script.
For example, I might want to do something like:
IOCScanner | jq <jq expression> | <additional processing>
... either in a terminal or in a script.
The typical unix behaviour that enables this is:
Note that syft
does this correctly. The pretty animations and diagnostics messages are written to stderr, and the regular output goes to stdout. You can verify this by running syft . > /tmp/output.txt
.
By all means, we can implement a --output
option to configure where to write output to in addition to defaulting to stdout for output.
BTW - diagnostic messages don't have to be prefixed by <SEVERITY> [<TIMESTAMP>]
. This is common for persistent daemon services where the events are processed by (for example) syslog, but is not common practice for single-operation tools.
Let's be consistent - either use them everywhere, or nowhere.
Update, after further investigation:
The YaRadare binary, using logrus, functions correctly with respect to logging, and writes logs to STDERR. However, when running in docker with a pseudo-tty, it merges STDOUT and STDERR into a single output stream (STDOUT), so logs and output are conflated.
The solution is to run the docker container without allocating a tty, as:
$ docker run -i --rm --name=deepfence-yaradare -v /var/run/docker.sock:/var/run/docker.sock deepfenceio/deepfence-yaradare:latest --image-name node:latest > /tmp/docker-no-t.txt
time="2022-07-08 13:16:23" level=info msg="trying to connect to endpoint 'unix:///var/run/docker.sock' with timeout '10s'"
time="2022-07-08 13:16:23" level=info msg="connected successfully using endpoint: unix:///var/run/docker.sock"
time="2022-07-08 13:16:23" level=info msg="trying to connect to endpoint 'unix:///run/containerd/containerd.sock' with timeout '10s'"
time="2022-07-08 13:16:33" level=warning msg="could not connect to endpoint 'unix:///run/containerd/containerd.sock': context deadline exceeded"
time="2022-07-08 13:16:33" level=info msg="trying to connect to endpoint 'unix:///run/k3s/containerd/containerd.sock' with timeout '10s'"
time="2022-07-08 13:16:43" level=warning msg="could not connect to endpoint 'unix:///run/k3s/containerd/containerd.sock': context deadline exceeded"
time="2022-07-08 13:16:43" level=info msg="container runtime detected: docker\n"
logrus uses a different output format in this case, but it's still usable.
The output is still untidy and not well-formatted JSON. Now that we've determined the STDOUT/STDERR problem and workaround/solution, I'll raise a separate issue concerning the output.
The default output from IOCScanner should be easily machine-readable.
The current output is written to stdout, and resembles the following:
Recommendations
Scan results must go to STDOUT, and be a single JSON document Diagnostic output (INFO and the like) must go to STDERR All diagnostic messages should be prefixed by INFO/WARN etc and a timestamp
Default log level should be ERROR, so no messages are sent to STDERR on a successful scan
Rationale
This: