From d735decfcc50d2285f89d320c371c0ac81a8ebad Mon Sep 17 00:00:00 2001 From: Simon Kowallik Date: Sun, 29 Dec 2024 12:54:59 +0100 Subject: [PATCH] feat: improved check cli interface --- README.md | 13 ++++++++++++- files/Dockerfile.apiserver | 15 ++++++++++++--- irulescan/Cargo.lock | 24 ++++++++++++------------ irulescan/src/main.rs | 13 +++++++++++-- tests/basic/dangerous.txt | 2 ++ tests/run-tests.sh | 8 ++++---- 6 files changed, 53 insertions(+), 22 deletions(-) create mode 100644 tests/basic/dangerous.txt diff --git a/README.md b/README.md index 761aec7..339f00b 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,17 @@ irulescan check --exclude-empty-findings ./tests/basic/ | jq > Please note the differences in `"filepath"` between the two invocation methods. > This is important to consider when comparing a new scan to existing results. > `--exclude-empty-findings` removes the entry for the file `"ok.tcl"` as it has no findings. +> `cd tests/basic; irulescan check . | jq` would have provided the same results as the docker command from the previous example. + +When specifying a file, irulescan will try to scan the file regardless of the file extension. + +```console +irulescan check --no-warn tests/basic/dangerous.txt +``` + +```json +[{"filepath":"tests/basic/dangerous.txt","warning":[],"dangerous":["Dangerous unquoted expr at `$one` in `expr 1 + $one`"]}] +``` ```console irulescan --help @@ -210,7 +221,7 @@ The irulescan container tag `:apiserver` provides a simple Swagger / OpenAPI ser Start the API server: ```shell -docker run -t --rm -p 80:80 simonkowallik/irulescan:apiserver +docker run -t --rm -p 8000:8000 simonkowallik/irulescan:apiserver ``` Scanning a single file / iRule code: diff --git a/files/Dockerfile.apiserver b/files/Dockerfile.apiserver index c5a8ccc..ce715d5 100644 --- a/files/Dockerfile.apiserver +++ b/files/Dockerfile.apiserver @@ -89,6 +89,15 @@ COPY --from=build-python /build/artifacts / COPY --from=build-python /home/nonroot/.local /home/nonroot/.local # python asyncio.create_subprocess_shell needs a shell -COPY --from=build-python /bin/busybox /bin/sh - -CMD ["/home/nonroot/.local/bin/uvicorn", "--app-dir", "/", "apiserver:app", "--host", "0.0.0.0", "--port", "80", "--no-server-header"] +COPY --from=build-python /bin/busybox /bin/busybox +# busybox command aliases +COPY --from=build-python /bin/sh /bin/sh +# busybox depends on libxcrypt +COPY --from=build-python /usr/lib/libcrypt.so* /usr/lib/ +# sbom +COPY --from=build-python /var/lib/db/sbom/busybox* /var/lib/db/sbom/ +COPY --from=build-python var/lib/db/sbom/libxcrypt* /var/lib/db/sbom/ + +EXPOSE 8000 + +CMD ["/home/nonroot/.local/bin/uvicorn", "--app-dir", "/", "apiserver:app", "--host", "0.0.0.0", "--port", "8000", "--no-server-header"] diff --git a/irulescan/Cargo.lock b/irulescan/Cargo.lock index a6e53c1..011df35 100644 --- a/irulescan/Cargo.lock +++ b/irulescan/Cargo.lock @@ -296,9 +296,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.167" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libloading" @@ -441,9 +441,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -500,18 +500,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -520,9 +520,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ "indexmap", "itoa", @@ -545,9 +545,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.90" +version = "2.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "70ae51629bf965c5c098cc9e87908a3df5301051a9e087d6f9bef5c9771ed126" dependencies = [ "proc-macro2", "quote", diff --git a/irulescan/src/main.rs b/irulescan/src/main.rs index 39c62b5..5fa8e1d 100644 --- a/irulescan/src/main.rs +++ b/irulescan/src/main.rs @@ -159,8 +159,14 @@ fn main() { let stdin_content = read_stdin(); is_stdin = true; script_ins.push(("STDIN".to_string(), stdin_content)); - } else { - // Normal directory/file handling + } else if dirpath.is_file() { + // If dirpath is a file, read the file regardless of the file extension + script_ins.push(( + dirpath.to_str().unwrap().trim_start_matches("./").to_string(), + read_file(&dirpath), + )); + } else if dirpath.is_dir() { + // If dirpath is a directory, read all files that match IRULE_FILE_EXTENSIONS for entry in walkdir::WalkDir::new(&dirpath) .into_iter() .filter_map(|e| e.ok()) @@ -177,6 +183,9 @@ fn main() { )); } } + } else { + eprintln!("ERROR: Invalid filepath: {:?}, not a file or directory", dirpath); + std::process::exit(1); } let mut preprocessed_scripts: Vec<(String, String)> = Vec::new(); diff --git a/tests/basic/dangerous.txt b/tests/basic/dangerous.txt new file mode 100644 index 0000000..d91fae8 --- /dev/null +++ b/tests/basic/dangerous.txt @@ -0,0 +1,2 @@ +set one 1 +expr 1 + $one diff --git a/tests/run-tests.sh b/tests/run-tests.sh index 7d18950..4a56491 100755 --- a/tests/run-tests.sh +++ b/tests/run-tests.sh @@ -12,7 +12,7 @@ function prepare-apiserver { docker image inspect irulescan:apiserver > /dev/null 2>&1 || build-container-apiserver if [ -z "$(docker ps -q --filter ancestor=irulescan:apiserver)" ]; then echo -n "starting API server: " - docker run --rm -p 8888:80 -d irulescan:apiserver + docker run -p 8000:8000 -d irulescan:apiserver sleep 5 fi } @@ -36,7 +36,7 @@ function test_scandir_multi_file { echo -n "test_scandir_multi_file: " docker run --rm -v ${PWD}/tests/basic:/scandir \ irulescan:latest > output.json - jd -mset output.json tests/basic/irulescan_exclude_empty.json || ( echo "fail" && exit 1 ) + jd -mset output.json tests/basic/irulescan.json || ( echo "fail" && exit 1 ) echo "OK" } @@ -44,7 +44,7 @@ function test_apiserver_multi_file { prepare-apiserver echo -n "test_apiserver_multi_file: " - curl -s http://localhost:8888/scanfiles/ \ + curl -s http://localhost:8000/scanfiles/ \ -F 'file=@tests/basic/ok.tcl' \ -F 'file=@tests/basic/warning.tcl' \ -F 'file=@tests/basic/dangerous.tcl' > output.json @@ -56,7 +56,7 @@ function test_apiserver_plain_code { prepare-apiserver echo -n "test_apiserver_plain_code: " - curl -s http://localhost:8888/scan/ \ + curl -s http://localhost:8000/scan/ \ --data-binary '@tests/basic/dangerous.tcl' > output.json jd -mset output.json tests/basic/dangerous.tcl.stdin.json || ( echo "fail" && exit 1 ) echo "OK"