Upgrade binary test fixtures management (#2444)

* test: strip fixtures of any execution permissions

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

* chore: add lint check for large files

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

* add helper script to capture binary snippets

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* chore: update scripts and add new dir output for snippets

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

* test: update erlang test to new generated format

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

* test: update memcached to new generator pattern

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

* test: update openjdk to named version

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

* test: move openjdk lts to versioned folder

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

* test: rename unversioned java to versioned folders

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

* test: migrate bash fixture to new snippet workflow

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

* test: update script to size 600 bytes

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

* test: update go classifier to new snippet workflow

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

* test: move haproxy new new snippet

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

* test: add flatter haproxy example

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

* test: update tests to new pattern

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

* test: final version of snippet script

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>

* [wip] download bin helpers

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* add manager for binary cataloger test fixtures

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* add remaining binary cataloger patterns and snippets

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* adjust gitignore to be more permissive to snippets

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* add rust darwin snippets

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* skip tests that are missing full binaries

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* address PR feedback

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* add tests for binary test fixture manager

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* highlight rows that do not have binaries or snippets

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* bump fixture limit to 1K (found exceptions when adding snippets)

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* add redis and postgres snippets

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* improve formating of fixture listing

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
Christopher Angelo Phillips 2024-01-05 16:40:03 -05:00 committed by GitHub
parent a16a4ad6c9
commit 7182f5b519
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
158 changed files with 3539 additions and 500 deletions

36
.github/scripts/check_binary_fixture_size.sh vendored Executable file
View file

@ -0,0 +1,36 @@
#!/bin/bash
# current limit for fixture size
size=1000
if [ $# -eq 0 ]; then
echo "Usage: $0 <directory>"
exit 1
fi
directory="$1"
# Remove trailing slash using parameter expansion
directory="${directory%/}"
if [ ! -d "$directory" ]; then
echo "Directory not found: $directory"
exit 1
fi
found_large_files=0
while IFS= read -r -d '' file; do
if [ $(wc -c < "$file") -gt $size ]; then
echo "File $file is greater than ${size} bytes."
found_large_files=1
fi
done < <(find "$directory" -type f -print0)
if [ "$found_large_files" -eq 1 ]; then
echo "Script failed: Some files are greater than ${size} bytes."
exit 1
else
echo "All files in $directory and its subdirectories are ${size} bytes or smaller. Check passed."
exit 0
fi

View file

@ -57,7 +57,7 @@ jobs:
- name: Restore binary cataloger test-fixture cache - name: Restore binary cataloger test-fixture cache
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2 uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
with: with:
path: syft/pkg/cataloger/binary/test-fixtures/classifiers/dynamic path: syft/pkg/cataloger/binary/test-fixtures/classifiers/bin
key: ${{ runner.os }}-unit-binary-cataloger-cache-${{ hashFiles( 'syft/pkg/cataloger/binary/test-fixtures/cache.fingerprint' ) }} key: ${{ runner.os }}-unit-binary-cataloger-cache-${{ hashFiles( 'syft/pkg/cataloger/binary/test-fixtures/cache.fingerprint' ) }}
- name: Restore Kernel test-fixture cache - name: Restore Kernel test-fixture cache

View file

@ -54,6 +54,7 @@ tasks:
- task: check-licenses - task: check-licenses
- task: lint - task: lint
- task: check-json-schema-drift - task: check-json-schema-drift
- task: check-binary-fixture-size
test: test:
desc: Run all levels of test desc: Run all levels of test
@ -169,6 +170,11 @@ tasks:
cmds: cmds:
- .github/scripts/json-schema-drift-check.sh - .github/scripts/json-schema-drift-check.sh
check-binary-fixture-size:
desc: Ensure that the binary test fixtures are not too large
cmds:
- .github/scripts/check_binary_fixture_size.sh syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets
## Testing tasks ################################# ## Testing tasks #################################

9
go.mod
View file

@ -76,6 +76,12 @@ require (
modernc.org/sqlite v1.28.0 modernc.org/sqlite v1.28.0
) )
require (
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
github.com/charmbracelet/bubbles v0.16.1
github.com/jedib0t/go-pretty/v6 v6.4.9
)
require ( require (
dario.cat/mergo v1.0.0 // indirect dario.cat/mergo v1.0.0 // indirect
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
@ -91,9 +97,9 @@ require (
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect github.com/andybalholm/brotli v1.0.4 // indirect
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492 // indirect github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492 // indirect
github.com/atotto/clipboard v0.1.4 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/becheran/wildmatch-go v1.0.0 // indirect github.com/becheran/wildmatch-go v1.0.0 // indirect
github.com/charmbracelet/bubbles v0.16.1 // indirect
github.com/charmbracelet/harmonica v0.2.0 // indirect github.com/charmbracelet/harmonica v0.2.0 // indirect
github.com/cloudflare/circl v1.3.3 // indirect github.com/cloudflare/circl v1.3.3 // indirect
github.com/containerd/cgroups v1.1.0 // indirect github.com/containerd/cgroups v1.1.0 // indirect
@ -180,6 +186,7 @@ require (
github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/sagikazarmark/locafero v0.3.0 // indirect github.com/sagikazarmark/locafero v0.3.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sahilm/fuzzy v0.1.0 // indirect
github.com/shopspring/decimal v1.2.0 // indirect github.com/shopspring/decimal v1.2.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect
github.com/skeema/knownhosts v1.2.1 // indirect github.com/skeema/knownhosts v1.2.1 // indirect

11
go.sum
View file

@ -127,6 +127,8 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/becheran/wildmatch-go v1.0.0 h1:mE3dGGkTmpKtT4Z+88t8RStG40yN9T+kFEGj2PZFSzA= github.com/becheran/wildmatch-go v1.0.0 h1:mE3dGGkTmpKtT4Z+88t8RStG40yN9T+kFEGj2PZFSzA=
@ -464,6 +466,8 @@ github.com/invopop/jsonschema v0.7.0 h1:2vgQcBz1n256N+FpX3Jq7Y17AjYt46Ig3zIWyy77
github.com/invopop/jsonschema v0.7.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0= github.com/invopop/jsonschema v0.7.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jedib0t/go-pretty/v6 v6.4.9 h1:vZ6bjGg2eBSrJn365qlxGcaWu09Id+LHtrfDWlB2Usc=
github.com/jedib0t/go-pretty/v6 v6.4.9/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs=
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@ -503,6 +507,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs= github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs=
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
@ -533,6 +539,7 @@ github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 h1:P8UmIzZ
github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
@ -629,6 +636,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA=
github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
@ -673,6 +681,8 @@ github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9c
github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U= github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA= github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA=
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
@ -738,6 +748,7 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=

View file

@ -0,0 +1,122 @@
# Adding tests for the Binary cataloger
> [!TIP]
> **TL;DR** to add a test for a new classifier:
> 1. head to the correct directory: `cd test-fixtures`
> 2. add a new entry to `config.yaml` to track where to get the binary from (verify the entry with `make list`)
> 3. run `make download` to get the binary
> 4. run `make add-snippet` and follow the prompts (use `/` to search)
> 5. add a new test case to `Test_Cataloger_PositiveCases` in `../cataloger_test.go`
To test the binary cataloger we run it against a set of files ("test fixtures"). There are two kinds of test fixtures:
- **Full binaries**: files downloaded and cached at test runtime
- **Snippets**: ~100 byte files checked into the repo
The upside with snippets is that they live with the test, don't necessarily require network access or hosting concerns, and are easy to add. The downside is that they are not the entire real binary so modifications may require recreating the snippet entirely.
The upside with full binaries is that they are the "Real McCoy" and allows the business logic to change without needing to update the fixture. The downside is that they require network access and take up a lot of space. For instance, downloading all binaries for testing today requires downloading ~15GB of container images and ends up being ~500MB of disk space.
You can find the test fixtures at the following locations:
```
syft/pkg/cataloger/binary/test-fixtures/
└── classifiers/
├── bin/ # full binaries
├── ...
└── snippets/ # snippets
```
And use tooling to list and manage the fixtures:
- `make list` - list all fixtures
- `make download` - download binaries that are not covered by a snippet
- `make download-all` - download all binaries
- `go run ./manager add-snippet` - add a new snippet based off of a configured binary
- `capture-snippet.sh` - add a new snippet based off of a binary on your local machine (not recommended, but allowed)
There is a `config.yaml` that tracks all binaries that the tests can use. This makes it possible to download it at any time from a hosted source. Today the only method allowed is to download a container image and extract files out.
Here is an example entry in `config.yaml` for a binary reference from a container image:
```yaml
from-images:
# note the group-name is assumed from the single binary name extracted: "redis-server"
- version: 7.2.3
images:
# note we're pulling the same binary from multiple images (representing different architectures)
- ref: redis:7.2.3@sha256:d4c84914b872521e215f77d8845914c2268a96b0e35bacd5691e1f5e1f88b500
platform: linux/amd64
- ref: redis:7.2.3@sha256:a0a0c38b31011b813cddf78d997f8ccba13019c27efd386984b0cfc1e4b618ff
platform: linux/arm64
# the paths to extract from the binary...
paths:
- /usr/local/bin/redis-server
# since there are multiple binaries in the image, we need to specify the group-name
- name: ruby-bullseye-shared-libs
version: 2.7.7
images:
- ref: ruby:2.7.7-bullseye@sha256:055191740a063f33fef1f09423e5ed8f91143aae62a3772a90910118464c5120
platform: linux/amd64
paths:
- /usr/local/bin/ruby
- /usr/local/lib/libruby.so.2.7.7
- /usr/local/lib/libruby.so.2.7
```
> [!NOTE]
> You will need a system with `go`, `bash`, `strings`, and `xxd` installed to capture test snippets.
## Testing
The test cases have been setup to allow testing against full binaries or a mix of both (default).
To force running only against full binaries run with:
```bash
go test -must-use-full-binaries ./syft/pkg/cataloger/binary/test-fixtures/...
```
## Adding a new test fixture
### Adding a snippet (recommended)
Even if you are adding a snippet, it is best practice to:
- create that snippet from a full binary (not craft a snippet by hand)
- track where the binary is from and how to download it in `config.yaml`
1. Follow the steps above to [add a full binary](#adding-a-full-binary)
2. Run `go run ./manager add-snippet` and follow the prompts to create a new snippet
- you should see your binary in the list of binaries to choose from. If not, check step 2
- if the search results in no matching snippets, you can specify your own search with `--search-for <grep-pattern>`
- you should see a new snippet file created in `snippets/`
3. Write a test that references your new snippet by `<name>/<version>/<architecture>`
- `<name>` is the name of the binary (e.g. `curl`) or the name in `config.yaml` if specified
- note that your test does not know about if it's running against a snippet or a full binary
### Adding a full binary
1. Add a new entry to `config.yaml` with the following fields
- if you are adding a single binary, the `name` field does not need to be specified
- the `name` field is useful for distinguishing a quality about the binary (e.g. `java` vs `java-jre-ibm`)
2. Run `make download` and ensure your new binary is downloaded
### Adding a custom snippet
If you need to add a snippet that is not based off of a full binary, you can use the `capture-snippet.sh` script.
```bash
./capture-snippet.sh <binary-path> <version> [--search-for <pattern>] [--length <length>] [--prefix-length <prefix_length>] [--group <name>]
```
This is **not** recommended because it is not reproducible and does not allow for the test to be run against a full binary.

View file

@ -2,6 +2,7 @@ package binary
import ( import (
"errors" "errors"
"flag"
"fmt" "fmt"
"io" "io"
"strings" "strings"
@ -15,18 +16,24 @@ import (
"github.com/anchore/stereoscope/pkg/imagetest" "github.com/anchore/stereoscope/pkg/imagetest"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/binary/test-fixtures/manager/testutil"
"github.com/anchore/syft/syft/source" "github.com/anchore/syft/syft/source"
) )
func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) { var mustUseOriginalBinaries = flag.Bool("must-use-original-binaries", false, "force the use of binaries for testing (instead of snippets)")
func Test_Cataloger_PositiveCases(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
fixtureDir string // logicalFixture is the logical path to the full binary or snippet. This is relative to the test-fixtures/classifiers/snippets
// or test-fixtures/classifiers/bin directory . Snippets are searched for first, and if not found, then existing binaries are
// used. If no binary or snippet is found the test will fail. If '-must-use-original-binaries' is used the only
// full binaries are tested (no snippets), and if no binary is found the test will be skipped.
logicalFixture string
expected pkg.Package expected pkg.Package
}{ }{
{ {
name: "positive-postgresql-15beta4", logicalFixture: "postgres/15beta4/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/postgresql-15beta4",
expected: pkg.Package{ expected: pkg.Package{
Name: "postgresql", Name: "postgresql",
Version: "15beta4", Version: "15beta4",
@ -37,8 +44,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-postgresql-15.1", logicalFixture: "postgres/15.1/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/postgresql-15.1",
expected: pkg.Package{ expected: pkg.Package{
Name: "postgresql", Name: "postgresql",
Version: "15.1", Version: "15.1",
@ -49,8 +55,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-postgresql-9.6.24", logicalFixture: "postgres/9.6.24/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/postgresql-9.6.24",
expected: pkg.Package{ expected: pkg.Package{
Name: "postgresql", Name: "postgresql",
Version: "9.6.24", Version: "9.6.24",
@ -61,8 +66,9 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-postgresql-9.5alpha1", // TODO: find original binary...
fixtureDir: "test-fixtures/classifiers/positive/postgresql-9.5alpha1", // note: cannot find the original binary, using a custom snippet based on the original snippet in the repo
logicalFixture: "postgres/9.5alpha1/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "postgresql", Name: "postgresql",
Version: "9.5alpha1", Version: "9.5alpha1",
@ -73,8 +79,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-mysql-8.0.34", logicalFixture: "mysql/8.0.34/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/mysql-8.0.34",
expected: pkg.Package{ expected: pkg.Package{
Name: "mysql", Name: "mysql",
Version: "8.0.34", Version: "8.0.34",
@ -85,8 +90,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-mysql-5.6.51", logicalFixture: "mysql/5.6.51/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/mysql-5.6.51",
expected: pkg.Package{ expected: pkg.Package{
Name: "mysql", Name: "mysql",
Version: "5.6.51", Version: "5.6.51",
@ -97,8 +101,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-mariadb-10.6.15", logicalFixture: "mariadb/10.6.15/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/mariadb-10.6.15",
expected: pkg.Package{ expected: pkg.Package{
Name: "mariadb", Name: "mariadb",
Version: "10.6.15", Version: "10.6.15",
@ -109,20 +112,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-traefik-2.9.6", logicalFixture: "traefik/1.7.34/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/traefik-2.9.6",
expected: pkg.Package{
Name: "traefik",
Version: "2.9.6",
Type: "binary",
PURL: "pkg:generic/traefik@2.9.6",
Locations: locations("traefik"),
Metadata: metadata("traefik-binary"),
},
},
{
name: "positive-traefik-1.7.34",
fixtureDir: "test-fixtures/classifiers/positive/traefik-1.7.34",
expected: pkg.Package{ expected: pkg.Package{
Name: "traefik", Name: "traefik",
Version: "1.7.34", Version: "1.7.34",
@ -133,8 +123,18 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-memcached-1.6.18", logicalFixture: "traefik/2.9.6/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/memcached-1.6.18", expected: pkg.Package{
Name: "traefik",
Version: "2.9.6",
Type: "binary",
PURL: "pkg:generic/traefik@2.9.6",
Locations: locations("traefik"),
Metadata: metadata("traefik-binary"),
},
},
{
logicalFixture: "memcached/1.6.18/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "memcached", Name: "memcached",
Version: "1.6.18", Version: "1.6.18",
@ -145,8 +145,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-httpd-2.4.54", logicalFixture: "httpd/2.4.54/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/httpd-2.4.54",
expected: pkg.Package{ expected: pkg.Package{
Name: "httpd", Name: "httpd",
Version: "2.4.54", Version: "2.4.54",
@ -157,8 +156,9 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-php-cli-8.2.1", // TODO: find original binary...
fixtureDir: "test-fixtures/classifiers/positive/php-cli-8.2.1", // note: cannot find the original binary, using a custom snippet based on the original snippet in the repo
logicalFixture: "php-cli/8.2.1/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "php-cli", Name: "php-cli",
Version: "8.2.1", Version: "8.2.1",
@ -169,8 +169,9 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-php-fpm-8.2.1", // TODO: find original binary...
fixtureDir: "test-fixtures/classifiers/positive/php-fpm-8.2.1", // note: cannot find the original binary, using a custom snippet based on the original snippet in the repo
logicalFixture: "php-fpm/8.2.1/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "php-fpm", Name: "php-fpm",
Version: "8.2.1", Version: "8.2.1",
@ -181,8 +182,9 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-php-apache-8.2.1", // TODO: find original binary...
fixtureDir: "test-fixtures/classifiers/positive/php-apache-8.2.1", // note: cannot find the original binary, using a custom snippet based on the original snippet in the repo
logicalFixture: "php-apache/8.2.1/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "libphp", Name: "libphp",
Version: "8.2.1", Version: "8.2.1",
@ -193,8 +195,9 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-perl-5.12.5", // TODO: original binary is different than whats in config.yaml
fixtureDir: "test-fixtures/classifiers/positive/perl-5.12.5", // note: cannot find the original binary, using a custom snippet based on the original snippet in the repo
logicalFixture: "perl/5.12.5/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "perl", Name: "perl",
Version: "5.12.5", Version: "5.12.5",
@ -205,8 +208,9 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-perl-5.20.0", // TODO: original binary is different than whats in config.yaml
fixtureDir: "test-fixtures/classifiers/positive/perl-5.20.0", // note: cannot find the original binary, using a custom snippet based on the original snippet in the repo
logicalFixture: "perl/5.20.0/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "perl", Name: "perl",
Version: "5.20.0", Version: "5.20.0",
@ -217,8 +221,9 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-perl-5.37.8", // TODO: original binary is different than whats in config.yaml
fixtureDir: "test-fixtures/classifiers/positive/perl-5.37.8", // note: cannot find the original binary, using a custom snippet based on the original snippet in the repo
logicalFixture: "perl/5.37.8/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "perl", Name: "perl",
Version: "5.37.8", Version: "5.37.8",
@ -229,8 +234,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-haproxy-1.5.14", logicalFixture: "haproxy/1.5.14/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/haproxy-1.5.14",
expected: pkg.Package{ expected: pkg.Package{
Name: "haproxy", Name: "haproxy",
Version: "1.5.14", Version: "1.5.14",
@ -241,8 +245,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-haproxy-1.8.22", logicalFixture: "haproxy/1.8.22/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/haproxy-1.8.22",
expected: pkg.Package{ expected: pkg.Package{
Name: "haproxy", Name: "haproxy",
Version: "1.8.22", Version: "1.8.22",
@ -253,8 +256,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-haproxy-2.7.3", logicalFixture: "haproxy/2.7.3/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/haproxy-2.7.3",
expected: pkg.Package{ expected: pkg.Package{
Name: "haproxy", Name: "haproxy",
Version: "2.7.3", Version: "2.7.3",
@ -264,21 +266,9 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
Metadata: metadata("haproxy-binary"), Metadata: metadata("haproxy-binary"),
}, },
}, },
{ {
name: "positive-redis-2.8.23", logicalFixture: "helm/3.11.1/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/redis-server-2.8.23",
expected: pkg.Package{
Name: "redis",
Version: "2.8.23",
Type: "binary",
PURL: "pkg:generic/redis@2.8.23",
Locations: locations("redis-server"),
Metadata: metadata("redis-binary"),
},
},
{
name: "positive-helm-3.11.1",
fixtureDir: "test-fixtures/classifiers/dynamic/helm-3.11.1",
expected: pkg.Package{ expected: pkg.Package{
Name: "helm", Name: "helm",
Version: "3.11.1", Version: "3.11.1",
@ -289,8 +279,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-helm-3.10.3", logicalFixture: "helm/3.10.3/linux-amd64",
fixtureDir: "test-fixtures/classifiers/dynamic/helm-3.10.3",
expected: pkg.Package{ expected: pkg.Package{
Name: "helm", Name: "helm",
Version: "3.10.3", Version: "3.10.3",
@ -300,9 +289,22 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
Metadata: metadata("helm"), Metadata: metadata("helm"),
}, },
}, },
{ {
name: "positive-redis-4.0.11", // note: dynamic (non-snippet) test case
fixtureDir: "test-fixtures/classifiers/positive/redis-server-4.0.11", logicalFixture: "redis-server/2.8.23/linux-amd64",
expected: pkg.Package{
Name: "redis",
Version: "2.8.23",
Type: "binary",
PURL: "pkg:generic/redis@2.8.23",
Locations: locations("redis-server"),
Metadata: metadata("redis-binary"),
},
},
{
// note: dynamic (non-snippet) test case
logicalFixture: "redis-server/4.0.11/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "redis", Name: "redis",
Version: "4.0.11", Version: "4.0.11",
@ -313,8 +315,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-redis-5.0.0", logicalFixture: "redis-server/5.0.0/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/redis-server-5.0.0",
expected: pkg.Package{ expected: pkg.Package{
Name: "redis", Name: "redis",
Version: "5.0.0", Version: "5.0.0",
@ -325,8 +326,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-redis-6.0.16", logicalFixture: "redis-server/6.0.16/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/redis-server-6.0.16",
expected: pkg.Package{ expected: pkg.Package{
Name: "redis", Name: "redis",
Version: "6.0.16", Version: "6.0.16",
@ -337,8 +337,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-redis-7.0.0", logicalFixture: "redis-server/7.0.0/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/redis-server-7.0.0",
expected: pkg.Package{ expected: pkg.Package{
Name: "redis", Name: "redis",
Version: "7.0.0", Version: "7.0.0",
@ -349,8 +348,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-redis-7.0.14", logicalFixture: "redis-server/7.0.14/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/redis-server-7.0.14",
expected: pkg.Package{ expected: pkg.Package{
Name: "redis", Name: "redis",
Version: "7.0.14", Version: "7.0.14",
@ -361,8 +359,8 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-redis-7.2.3-amd64", // note: dynamic (non-snippet) test case
fixtureDir: "test-fixtures/classifiers/positive/redis-server-7.2.3-amd64", logicalFixture: "redis-server/7.2.3/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "redis", Name: "redis",
Version: "7.2.3", Version: "7.2.3",
@ -373,8 +371,8 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-redis-7.2.3-arm64", // note: dynamic (non-snippet) test case
fixtureDir: "test-fixtures/classifiers/positive/redis-server-7.2.3-arm64", logicalFixture: "redis-server/7.2.3/linux-arm64",
expected: pkg.Package{ expected: pkg.Package{
Name: "redis", Name: "redis",
Version: "7.2.3", Version: "7.2.3",
@ -385,27 +383,27 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-libpython3.7.so", logicalFixture: "python-shared-lib/3.7.4/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/python-binary-lib-3.7",
expected: pkg.Package{ expected: pkg.Package{
Name: "python", Name: "python",
Version: "3.7.4", Version: "3.7.4",
PURL: "pkg:generic/python@3.7.4", PURL: "pkg:generic/python@3.7.4",
Locations: locations("libpython3.7.so"), Locations: locations("libpython3.7m.so.1.0"),
Metadata: metadata("python-binary-lib"), Metadata: metadata("python-binary-lib"),
}, },
}, },
{ {
name: "positive-python-3.11.2-from-shared-lib", // note: dynamic (non-snippet) test case
fixtureDir: "test-fixtures/classifiers/dynamic/python-binary-shared-lib-3.11", logicalFixture: "python-slim-shared-libs/3.11/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "python", Name: "python",
Version: "3.11.2", Version: "3.11.2",
PURL: "pkg:generic/python@3.11.2", PURL: "pkg:generic/python@3.11.2",
Locations: locations("python3", "libpython3.11.so.1.0"), Locations: locations("python3.11", "libpython3.11.so.1.0"),
Metadata: pkg.BinarySignature{ Metadata: pkg.BinarySignature{
Matches: []pkg.ClassifierMatch{ Matches: []pkg.ClassifierMatch{
match("python-binary", "python3"), match("python-binary", "python3.11"),
match("python-binary", "libpython3.11.so.1.0"), match("python-binary", "libpython3.11.so.1.0"),
match("python-binary-lib", "libpython3.11.so.1.0"), match("python-binary-lib", "libpython3.11.so.1.0"),
}, },
@ -413,8 +411,8 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-python-3.9-from-shared-redhat-lib", // note: dynamic (non-snippet) test case
fixtureDir: "test-fixtures/classifiers/dynamic/python-binary-shared-lib-redhat-3.9", logicalFixture: "python-rhel-shared-libs/3.9/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "python", Name: "python",
Version: "3.9.13", Version: "3.9.13",
@ -430,8 +428,8 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-python-binary-with-version-3.9", // note: dynamic (non-snippet) test case
fixtureDir: "test-fixtures/classifiers/dynamic/python-binary-with-version-3.9", logicalFixture: "python3.9/3.9.16/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "python", Name: "python",
Version: "3.9.2", Version: "3.9.2",
@ -445,8 +443,8 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-python-binary-3.4-alpine", // note: dynamic (non-snippet) test case
fixtureDir: "test-fixtures/classifiers/dynamic/python-binary-3.4-alpine", logicalFixture: "python-alpine-shared-libs/3.4/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "python", Name: "python",
Version: "3.4.10", Version: "3.4.10",
@ -462,8 +460,9 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-python-3.5-with-incorrect-match", // TODO: find original binary...
fixtureDir: "test-fixtures/classifiers/positive/python-3.5-with-incorrect-match", // note: cannot find the original binary, using a custom snippet based on the original snippet in the repo
logicalFixture: "python-with-incorrect-match/3.5.3/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "python", Name: "python",
Version: "3.5.3", Version: "3.5.3",
@ -473,8 +472,9 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-python3.6", // TODO: find original binary...
fixtureDir: "test-fixtures/classifiers/positive/python-binary-3.6", // note: cannot find the original binary, using a custom snippet based on the original snippet in the repo
logicalFixture: "python/3.6.3/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "python", Name: "python",
Version: "3.6.3", Version: "3.6.3",
@ -484,8 +484,9 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-python-duplicates", // TODO: find original binary...
fixtureDir: "test-fixtures/classifiers/positive/python-duplicates", // note: cannot find the original binary, using a custom snippet based on the original snippet in the repo
logicalFixture: "python-duplicates/3.8.16/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "python", Name: "python",
Version: "3.8.16", Version: "3.8.16",
@ -502,30 +503,29 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-go", logicalFixture: "go/1.21.3/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/go-1.14",
expected: pkg.Package{ expected: pkg.Package{
Name: "go", Name: "go",
Version: "1.14", Version: "1.21.3",
PURL: "pkg:generic/go@1.14", PURL: "pkg:generic/go@1.21.3",
Locations: locations("go"), Locations: locations("go"),
Metadata: metadata("go-binary"), Metadata: metadata("go-binary"),
}, },
}, },
{ {
name: "positive-node", logicalFixture: "node/19.2.0/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/node-19.2.1",
expected: pkg.Package{ expected: pkg.Package{
Name: "node", Name: "node",
Version: "19.2.1", Version: "19.2.0",
PURL: "pkg:generic/node@19.2.1", PURL: "pkg:generic/node@19.2.0",
Locations: locations("node"), Locations: locations("node"),
Metadata: metadata("nodejs-binary"), Metadata: metadata("nodejs-binary"),
}, },
}, },
{ {
name: "positive-go-hint", // TODO: find original binary...
fixtureDir: "test-fixtures/classifiers/positive/go-hint-1.15", // note: cannot find the original binary, using a custom snippet based on the original snippet in the repo
logicalFixture: "go-version-hint/1.15/any",
expected: pkg.Package{ expected: pkg.Package{
Name: "go", Name: "go",
Version: "1.15", Version: "1.15",
@ -535,19 +535,19 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-busybox", // note: this is testing BUSYBOX which is typically through a link to "[" (in this case a symlink but in
fixtureDir: "test-fixtures/classifiers/positive/busybox-3.33.3", // practice this is often a hard link).
logicalFixture: `busybox/1.36.1/linux-amd64`,
expected: pkg.Package{ expected: pkg.Package{
Name: "busybox", Name: "busybox",
Version: "3.33.3", Version: "1.36.1",
PURL: "pkg:generic/busybox@3.33.3", PURL: "pkg:generic/busybox@1.36.1",
Locations: locations("["), // note: busybox is a link to [ Locations: locations("["), // note: busybox is a link to [
Metadata: metadata("busybox-binary", "[", "busybox"), Metadata: metadata("busybox-binary", "[", "busybox"),
}, },
}, },
{ {
name: "positive-java-openjdk", logicalFixture: "java-jre-openjdk/1.8.0_352-b08/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/openjdk",
expected: pkg.Package{ expected: pkg.Package{
Name: "java", Name: "java",
Version: "1.8.0_352-b08", Version: "1.8.0_352-b08",
@ -558,8 +558,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-java-openjdk-lts", logicalFixture: "java-jre-openjdk/11.0.17/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/openjdk-lts",
expected: pkg.Package{ expected: pkg.Package{
Name: "java", Name: "java",
Version: "11.0.17+8-LTS", Version: "11.0.17+8-LTS",
@ -570,8 +569,9 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-java-oracle", // TODO: find original binary...
fixtureDir: "test-fixtures/classifiers/positive/oracle", // note: cannot find the original binary, using a custom snippet based on the original snippet in the repo
logicalFixture: "java-jre-oracle/19.0.1/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "java", Name: "java",
Version: "19.0.1+10-21", Version: "19.0.1+10-21",
@ -582,8 +582,9 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-java-oracle-macos", // TODO: find original binary...
fixtureDir: "test-fixtures/classifiers/positive/oracle-macos", // note: cannot find the original binary, using a custom snippet based on the original snippet in the repo
logicalFixture: "java-jre-oracle/19.0.1/darwin",
expected: pkg.Package{ expected: pkg.Package{
Name: "java", Name: "java",
Version: "19.0.1+10-21", Version: "19.0.1+10-21",
@ -594,56 +595,80 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-java-ibm", logicalFixture: "java-jre-ibm/1.8.0_391/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/ibm",
expected: pkg.Package{ expected: pkg.Package{
Name: "java", Name: "java",
Version: "1.8.0-foreman_2022_09_22_15_30-b00", Version: "1.8.0-foreman_2023_10_12_13_27-b00",
Type: "binary", Type: "binary",
PURL: "pkg:generic/java@1.8.0-foreman_2022_09_22_15_30-b00", PURL: "pkg:generic/java@1.8.0-foreman_2023_10_12_13_27-b00",
Locations: locations("java"), Locations: locations("java"),
Metadata: metadata("java-binary-ibm", "java"), Metadata: metadata("java-binary-ibm", "java"),
}, },
}, },
{ {
name: "positive-rust-1.50.0-macos", logicalFixture: "rust-libstd/1.50.0/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/rust-1.50.0",
expected: pkg.Package{ expected: pkg.Package{
Name: "rust", Name: "rust",
Version: "1.50.0", Version: "1.50.0",
Type: "binary", Type: "binary",
PURL: "pkg:generic/rust@1.50.0", PURL: "pkg:generic/rust@1.50.0",
Locations: locations("lib/rustlib/aarch64-apple-darwin/lib/libstd-f6f9eec1635e636a.dylib"), Locations: locations("libstd-6f77337c1826707d.so"),
Metadata: metadata("rust-standard-library-macos"),
},
},
{
name: "positive-rust-1.67.1-macos",
fixtureDir: "test-fixtures/classifiers/positive/rust-1.67.1/toolchains/stable-aarch64-apple-darwin",
expected: pkg.Package{
Name: "rust",
Version: "1.67.1",
Type: "binary",
PURL: "pkg:generic/rust@1.67.1",
Locations: locations("lib/libstd-16f2b65e77054c42.dylib"),
Metadata: metadata("rust-standard-library-macos"),
},
},
{
name: "positive-rust-1.67.1-linux",
fixtureDir: "test-fixtures/classifiers/positive/rust-1.67.1/toolchains/stable-x86_64-unknown-linux-musl",
expected: pkg.Package{
Name: "rust",
Version: "1.67.1",
Type: "binary",
PURL: "pkg:generic/rust@1.67.1",
Locations: locations("lib/libstd-86aefecbddda356d.so"),
Metadata: metadata("rust-standard-library-linux"), Metadata: metadata("rust-standard-library-linux"),
}, },
}, },
{ {
// TODO: find original binary...
// note: cannot find the original binary, using a custom snippet based on the original snippet in the repo
logicalFixture: "rust-libstd/1.50.0/darwin",
expected: pkg.Package{
Name: "rust",
Version: "1.50.0",
Type: "binary",
PURL: "pkg:generic/rust@1.50.0",
Locations: locations("libstd-f6f9eec1635e636a.dylib"),
Metadata: metadata("rust-standard-library-macos"),
},
},
{
// TODO: find original binary...
// note: cannot find the original binary, using a custom snippet based on the original snippet in the repo
logicalFixture: "rust-libstd/1.67.1/darwin",
expected: pkg.Package{
Name: "rust",
Version: "1.67.1",
Type: "binary",
PURL: "pkg:generic/rust@1.67.1",
Locations: locations("libstd-16f2b65e77054c42.dylib"),
Metadata: metadata("rust-standard-library-macos"),
},
},
{
logicalFixture: "rust-libstd-musl/1.67.1/linux-amd64",
expected: pkg.Package{
Name: "rust",
Version: "1.67.1",
Type: "binary",
PURL: "pkg:generic/rust@1.67.1",
Locations: locations("libstd-86aefecbddda356d.so"),
Metadata: metadata("rust-standard-library-linux"),
},
},
{
logicalFixture: "rust-libstd/1.67.1/linux-amd64",
expected: pkg.Package{
Name: "rust",
Version: "1.67.1",
Type: "binary",
PURL: "pkg:generic/rust@1.67.1",
Locations: locations("libstd-c6192dd4c4d410ac.so"),
Metadata: metadata("rust-standard-library-linux"),
},
},
{
// note: dynamic (non-snippet) test case
name: "positive-ruby-3.2.1", name: "positive-ruby-3.2.1",
fixtureDir: "test-fixtures/classifiers/dynamic/ruby-library-3.2.1", logicalFixture: "ruby-bullseye-shared-libs/3.2.1/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "ruby", Name: "ruby",
Version: "3.2.1", Version: "3.2.1",
@ -659,8 +684,8 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-ruby-2.7.7", // note: dynamic (non-snippet) test case
fixtureDir: "test-fixtures/classifiers/dynamic/ruby-library-2.7.7", logicalFixture: "ruby-bullseye-shared-libs/2.7.7/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "ruby", Name: "ruby",
Version: "2.7.7p221", Version: "2.7.7p221",
@ -676,8 +701,8 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-ruby-2.6.10", // note: dynamic (non-snippet) test case
fixtureDir: "test-fixtures/classifiers/dynamic/ruby-library-2.6.10", logicalFixture: "ruby-shared-libs/2.6.10/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "ruby", Name: "ruby",
Version: "2.6.10p210", Version: "2.6.10p210",
@ -693,8 +718,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-ruby-1.9.3p551", logicalFixture: "ruby/1.9.3p551/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/ruby-1.9.3p551",
expected: pkg.Package{ expected: pkg.Package{
Name: "ruby", Name: "ruby",
Version: "1.9.3p551", Version: "1.9.3p551",
@ -705,8 +729,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-consul-1.15.2", logicalFixture: "consul/1.15.2/linux-amd64",
fixtureDir: "test-fixtures/classifiers/dynamic/consul-1.15.2",
expected: pkg.Package{ expected: pkg.Package{
Name: "consul", Name: "consul",
Version: "1.15.2", Version: "1.15.2",
@ -717,20 +740,29 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-erlang-25.3.2.7", logicalFixture: "erlexec/25.3.2.6/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/erlang-25.3.2.7",
expected: pkg.Package{ expected: pkg.Package{
Name: "erlang", Name: "erlang",
Version: "25.3.2.7", Version: "25.3.2.6",
Type: "binary", Type: "binary",
PURL: "pkg:generic/erlang@25.3.2.7", PURL: "pkg:generic/erlang@25.3.2.6",
Locations: locations("erlexec"), Locations: locations("erlexec"),
Metadata: metadata("erlang-binary"), Metadata: metadata("erlang-binary"),
}, },
}, },
{ {
name: "positive-nginx-1.25.1", logicalFixture: "erlexec/26.2.0.0/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/nginx-1.25.1", expected: pkg.Package{
Name: "erlang",
Version: "26.2",
Type: "binary",
PURL: "pkg:generic/erlang@26.2",
Locations: locations("erlexec"),
Metadata: metadata("erlang-binary"),
},
},
{
logicalFixture: "nginx/1.25.1/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
Name: "nginx", Name: "nginx",
Version: "1.25.1", Version: "1.25.1",
@ -741,8 +773,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-nginx-openresty-1.21.4.2", logicalFixture: "nginx-openresty/1.21.4.3/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/nginx-openresty-1.21.4.2",
expected: pkg.Package{ expected: pkg.Package{
Name: "nginx", Name: "nginx",
Version: "1.21.4", Version: "1.21.4",
@ -753,20 +784,18 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
}, },
}, },
{ {
name: "positive-bash-5.2.15", logicalFixture: "bash/5.1.16/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/bash-5.2.15",
expected: pkg.Package{ expected: pkg.Package{
Name: "bash", Name: "bash",
Version: "5.2.15", Version: "5.1.16",
Type: "binary", Type: "binary",
PURL: "pkg:generic/bash@5.2.15", PURL: "pkg:generic/bash@5.1.16",
Locations: locations("bash"), Locations: locations("bash"),
Metadata: metadata("bash-binary"), Metadata: metadata("bash-binary"),
}, },
}, },
{ {
name: "positive-openssl-3.1.4", logicalFixture: "openssl/3.1.4/linux-amd64",
fixtureDir: "test-fixtures/classifiers/positive/openssl-3.1.4",
expected: pkg.Package{ expected: pkg.Package{
Name: "openssl", Name: "openssl",
Version: "3.1.4", Version: "3.1.4",
@ -779,10 +808,16 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.logicalFixture, func(t *testing.T) {
c := NewCataloger(DefaultCatalogerConfig()) c := NewCataloger(DefaultCatalogerConfig())
src, err := source.NewFromDirectoryPath(test.fixtureDir) // logicalFixture is the logical path to the full binary or snippet. This is relative to the test-fixtures/classifiers/snippets
// or test-fixtures/classifiers/bin directory . Snippets are searched for first, and if not found, then existing binaries are
// used. If no binary or snippet is found the test will fail. If '-must-use-original-binaries' is used the only
// full binaries are tested (no snippets), and if no binary is found the test will be skipped.
path := testutil.SnippetOrBinary(t, test.logicalFixture, *mustUseOriginalBinaries)
src, err := source.NewFromDirectoryPath(path)
require.NoError(t, err) require.NoError(t, err)
resolver, err := src.FileResolver(source.SquashedScope) resolver, err := src.FileResolver(source.SquashedScope)
@ -791,7 +826,7 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases(t *testing.T) {
packages, _, err := c.Catalog(resolver) packages, _, err := c.Catalog(resolver)
require.NoError(t, err) require.NoError(t, err)
require.Len(t, packages, 1) require.Len(t, packages, 1, "mismatched package count")
assertPackagesAreEqual(t, test.expected, packages[0]) assertPackagesAreEqual(t, test.expected, packages[0])
}) })
@ -901,7 +936,7 @@ func Test_Cataloger_CustomClassifiers(t *testing.T) {
config: CatalogerConfig{ config: CatalogerConfig{
Classifiers: []Classifier{}, Classifiers: []Classifier{},
}, },
fixtureDir: "test-fixtures/classifiers/positive/go-1.14", fixtureDir: "test-fixtures/custom/go-1.14",
expected: nil, expected: nil,
}, },
{ {
@ -909,7 +944,7 @@ func Test_Cataloger_CustomClassifiers(t *testing.T) {
config: CatalogerConfig{ config: CatalogerConfig{
Classifiers: defaultClassifers, Classifiers: defaultClassifers,
}, },
fixtureDir: "test-fixtures/classifiers/positive/go-1.14", fixtureDir: "test-fixtures/custom/go-1.14",
expected: &golangExpected, expected: &golangExpected,
}, },
{ {
@ -917,7 +952,7 @@ func Test_Cataloger_CustomClassifiers(t *testing.T) {
config: CatalogerConfig{ config: CatalogerConfig{
Classifiers: []Classifier{fooClassifier}, Classifiers: []Classifier{fooClassifier},
}, },
fixtureDir: "test-fixtures/classifiers/positive/go-1.14", fixtureDir: "test-fixtures/custom/go-1.14",
expected: nil, expected: nil,
}, },
{ {
@ -928,11 +963,11 @@ func Test_Cataloger_CustomClassifiers(t *testing.T) {
fooClassifier, fooClassifier,
), ),
}, },
fixtureDir: "test-fixtures/classifiers/positive/go-1.14", fixtureDir: "test-fixtures/custom/go-1.14",
expected: &golangExpected, expected: &golangExpected,
}, },
{ {
name: "default-cutsom-negative", name: "default-custom-negative",
config: CatalogerConfig{ config: CatalogerConfig{
Classifiers: append( Classifiers: append(
@ -947,7 +982,7 @@ func Test_Cataloger_CustomClassifiers(t *testing.T) {
}, },
), ),
}, },
fixtureDir: "test-fixtures/classifiers/positive/custom", fixtureDir: "test-fixtures/custom/extra",
expected: nil, expected: nil,
}, },
{ {
@ -958,7 +993,7 @@ func Test_Cataloger_CustomClassifiers(t *testing.T) {
fooClassifier, fooClassifier,
), ),
}, },
fixtureDir: "test-fixtures/classifiers/positive/custom", fixtureDir: "test-fixtures/custom/extra",
expected: &customExpected, expected: &customExpected,
}, },
} }
@ -1050,14 +1085,6 @@ func assertPackagesAreEqual(t *testing.T, expected pkg.Package, p pkg.Package) {
matches = false matches = false
break break
} }
if m1.Location.RealPath != "" && m1.Location.RealPath != m2.Location.RealPath {
matches = false
break
}
if m1.Location.AccessPath != "" && m1.Location.AccessPath != m2.Location.AccessPath {
matches = false
break
}
} }
} else { } else {
matches = false matches = false
@ -1080,7 +1107,8 @@ func assertPackagesAreEqual(t *testing.T, expected pkg.Package, p pkg.Package) {
}), }),
cmpopts.IgnoreUnexported(pkg.Package{}, file.LocationData{}), cmpopts.IgnoreUnexported(pkg.Package{}, file.LocationData{}),
cmpopts.IgnoreFields(pkg.Package{}, "CPEs", "FoundBy", "Type", "Locations", "Licenses"), cmpopts.IgnoreFields(pkg.Package{}, "CPEs", "FoundBy", "Type", "Locations", "Licenses"),
)) ),
)
} }
} }

View file

@ -234,8 +234,6 @@ func DefaultClassifiers() []Classifier {
Class: "mysql-binary", Class: "mysql-binary",
FileGlob: "**/mysql", FileGlob: "**/mysql",
EvidenceMatcher: FileContentsVersionMatcher( EvidenceMatcher: FileContentsVersionMatcher(
// ../../mysql-8.0.34
// /mysql-5.6.51/bld/client
`(?m).*/mysql-(?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)`), `(?m).*/mysql-(?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)`),
Package: "mysql", Package: "mysql",
PURL: mustPURL("pkg:generic/mysql@version"), PURL: mustPURL("pkg:generic/mysql@version"),
@ -287,9 +285,15 @@ func DefaultClassifiers() []Classifier {
{ {
Class: "erlang-binary", Class: "erlang-binary",
FileGlob: "**/erlexec", FileGlob: "**/erlexec",
EvidenceMatcher: FileContentsVersionMatcher( EvidenceMatcher: evidenceMatchers(
FileContentsVersionMatcher(
// <artificial>[NUL]/usr/src/otp_src_25.3.2.6/erts/
`(?m)/src/otp_src_(?P<version>[0-9]+\.[0-9]+(\.[0-9]+\.[0-9]+)?)/erts/`,
),
FileContentsVersionMatcher(
// <artificial>[NUL]/usr/local/src/otp-25.3.2.7/erts/ // <artificial>[NUL]/usr/local/src/otp-25.3.2.7/erts/
`(?m)\<artificial\>\x00/usr/local/src/otp-(?P<version>[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+?)/erts/`, `(?m)/usr/local/src/otp-(?P<version>[0-9]+\.[0-9]+(\.[0-9]+\.[0-9]+)?)/erts/`,
),
), ),
Package: "erlang", Package: "erlang",
PURL: mustPURL("pkg:generic/erlang@version"), PURL: mustPURL("pkg:generic/erlang@version"),

View file

@ -1 +1,10 @@
classifiers/dynamic classifiers/dynamic
classifiers/bin
cache.fingerprint
# allow for lb patterns (rust, pytho, php and more)
!lib*.so
!lib*.dylib
# allow for go-hint file
!VERSION*

View file

@ -1,110 +1,29 @@
.PHONY: all .PHONY: default list download download-all cache.fingerprint
all: \
classifiers/dynamic/python-binary-shared-lib-3.11 \
classifiers/dynamic/python-binary-shared-lib-redhat-3.9 \
classifiers/dynamic/python-binary-with-version-3.9 \
classifiers/dynamic/python-binary-3.4-alpine \
classifiers/dynamic/ruby-library-3.2.1 \
classifiers/dynamic/ruby-library-2.7.7 \
classifiers/dynamic/ruby-library-2.6.10 \
classifiers/dynamic/helm-3.11.1 \
classifiers/dynamic/helm-3.10.3 \
classifiers/dynamic/consul-1.15.2
.DEFAULT_GOAL := default
default: download
classifiers/dynamic/python-binary-shared-lib-3.11: list: ## list all managed binaries and snippets
$(eval $@_image := "python:3.11-slim@sha256:0b106e1d2bf485c2a41474bc9cd5103e9eea4e179f40f10741b53b127059221e") go run ./manager list
./get-image-file.sh $($@_image) \
/usr/local/bin/python3.11 \
$@/python3
./get-image-file.sh $($@_image) \
/usr/local/lib/libpython3.11.so.1.0 \
$@/libpython3.11.so.1.0
classifiers/dynamic/python-binary-shared-lib-redhat-3.9: download: ## download only binaries that are not covered by a snippet
$(eval $@_image := "registry.access.redhat.com/ubi8/python-39@sha256:f3cf958b96ce016b63e3e163e488f52e42891304dafef5a0811563f22e3cbad0") go run ./manager download $(name) --skip-if-covered-by-snippet
./get-image-file.sh $($@_image) \
/usr/bin/python3.9 \
$@/python3.9
./get-image-file.sh $($@_image) \
/usr/lib64/libpython3.9.so.1.0 \
$@/libpython3.9.so.1.0
classifiers/dynamic/python-binary-with-version-3.9: download-all: ## download all managed binaries
$(eval $@_image := "python:3.9.16-bullseye@sha256:93fb93c461a2e47a2176706fad1f39eaacd5dd40e19c0b018699a28c03eb2e2a") go run ./manager download
./get-image-file.sh $($@_image) \
/usr/bin/python3.9 \
$@/python3.9
classifiers/dynamic/python-binary-3.4-alpine: add-snippet: ## add a new snippet from an existing binary
$(eval $@_image := "python:3.4-alpine@sha256:c210b660e2ea553a7afa23b41a6ed112f85dbce25cbcb567c75dfe05342a4c4b") go run ./manager add-snippet
./get-image-file.sh $($@_image) \
/usr/local/bin/python3.4 \
$@/python3.4
./get-image-file.sh $($@_image) \
/usr/local/lib/libpython3.4m.so.1.0 \
$@/libpython3.4m.so.1.0
classifiers/dynamic/ruby-library-3.2.1: cache.fingerprint: ## prints the sha256sum of the any input to the download command (to determine if there is a cache miss)
$(eval $@_image := "ruby:3.2.1-bullseye@sha256:b4a140656b0c5d26c0a80559b228b4d343f3fdbf56682fcbe88f6db1fa9afa6b") @cat ./config.yaml | sha256sum | awk '{print $$1}' | tee cache.fingerprint
./get-image-file.sh $($@_image) \
/usr/local/bin/ruby \
$@/ruby
./get-image-file.sh $($@_image) \
/usr/local/lib/libruby.so.3.2.1 \
$@/libruby.so.3.2.1
./get-image-file.sh $($@_image) \
/usr/local/lib/libruby.so.3.2 \
$@/libruby.so.3.2
classifiers/dynamic/ruby-library-2.7.7: clean: ## clean up all downloaded binaries
$(eval $@_image := "ruby:2.7.7-bullseye@sha256:055191740a063f33fef1f09423e5ed8f91143aae62a3772a90910118464c5120") rm -rf ./classifiers/bin
./get-image-file.sh $($@_image) \
/usr/local/bin/ruby \
$@/ruby
./get-image-file.sh $($@_image) \
/usr/local/lib/libruby.so.2.7.7 \
$@/libruby.so.2.7.7
./get-image-file.sh $($@_image) \
/usr/local/lib/libruby.so.2.7 \
$@/libruby.so.2.7
classifiers/dynamic/ruby-library-2.6.10: ## Halp! #################################
$(eval $@_image := "ruby:2.6.10@sha256:771a810704167e55da8a19970c5dfa6eb795dfee32547adffa29ea72703f7243")
./get-image-file.sh $($@_image) \
/usr/local/bin/ruby \
$@/ruby
./get-image-file.sh $($@_image) \
/usr/local/lib/libruby.so.2.6.10 \
$@/libruby.so.2.6.10
./get-image-file.sh $($@_image) \
/usr/local/lib/libruby.so.2.6 \
$@/libruby.so.2.6
classifiers/dynamic/helm-3.11.1: .PHONY: help
$(eval $@_image := "alpine/helm:3.11.1@sha256:8628e3695fb743a8b9de89626f1b7a221280c2152c0e288c2504e59b68233e8b") help:
./get-image-file.sh $($@_image) \ @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "$(BOLD)$(CYAN)%-25s$(RESET)%s\n", $$1, $$2}'
/usr/bin/helm \
$@/helm
classifiers/dynamic/helm-3.10.3:
$(eval $@_image := "argoproj/argocd:v2.6.4@sha256:61fcbba187ff53c00696cb580edf70cada59c45cf399d8477631acf43cf522ee")
./get-image-file.sh $($@_image) \
/usr/local/bin/helm \
$@/helm
classifiers/dynamic/consul-1.15.2:
$(eval $@_image := "hashicorp/consul:1.15.2@sha256:c2169f3bb18dd947ae8eb5f6766896695c71fb439f050a3343e0007d895615b8")
./get-image-file.sh $($@_image) \
/bin/consul \
$@/consul
.PHONY: clean
clean:
rm -rf classifiers/dynamic
.PHONY: cache.fingerprint
cache.fingerprint: # for CI
$(title,Install test fixture fingerprint)
@find ./classifiers/dynamic/* -type f -exec md5sum {} + | awk '{print $1}' | sort | tee /dev/stderr | md5sum | tee cache.fingerprint >> cache.fingerprint

View file

@ -0,0 +1,149 @@
#!/bin/bash
# Default values for length and prefix length
LENGTH=100
PREFIX_LENGTH=20
SEARCH_FOR=''
GROUP_NAME=''
# Function to show usage
usage() {
echo "Usage: $0 <path-to-binary> <version> [--search-for <pattern>] [--length <length>] [--prefix-length <prefix_length>] [--group <name>]"
exit 1
}
# Parse arguments
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
--search-for)
SEARCH_FOR="$2"
shift # past argument
shift # past value
;;
--length)
LENGTH="$2"
shift # past argument
shift # past value
;;
--group)
GROUP_NAME="$2"
shift # past argument
shift # past value
;;
--prefix-length)
PREFIX_LENGTH="$2"
shift # past argument
shift # past value
;;
*)
if [ -z "$BINARY_FILE" ]; then
BINARY_FILE="$1"
elif [ -z "$VERSION" ]; then
VERSION="$1"
else
echo "Unknown option: $1"
usage
fi
shift # past argument
;;
esac
done
LENGTH=$(expr "$LENGTH" + "$PREFIX_LENGTH")
# check if binary file and pattern are provided
if [ -z "$BINARY_FILE" ] || [ -z "$VERSION" ]; then
usage
fi
# if group name is empty use the binary filename
if [ -z "$GROUP_NAME" ]; then
GROUP_NAME=$(basename "$BINARY_FILE")
fi
# check if xxd is even installed
if ! command -v xxd &> /dev/null; then
echo "xxd not found. Please install xxd."
exit 1
fi
PATTERN=${SEARCH_FOR:-$VERSION}
echo "Using binary file: $BINARY_FILE"
echo "Searching for pattern: $PATTERN"
echo "Capture length: $LENGTH bytes"
echo "Capture prefix length: $PREFIX_LENGTH bytes"
PATTERN_RESULTS=$(strings -t d "$BINARY_FILE" | grep "$PATTERN")
RESULT_COUNT=$(echo "$PATTERN_RESULTS" | wc -l)
CONTINUE_LOOP=true
while $CONTINUE_LOOP; do
# if there are multiple matches, prompt the user to select one
if [ $RESULT_COUNT -gt 1 ]; then
echo "Multiple string matches found in the binary:"
echo ""
# show result lines one at a time (in a numbered list)
# but only show everything after the first field (not the offset)
echo "$PATTERN_RESULTS" | cut -d ' ' -f 2- | nl -w 1 -s ') '
echo ""
read -p "Please select a match: " SELECTION
# if the selection is not a number, exit
if ! [[ "$SELECTION" =~ ^[0-9]+$ ]]; then
echo "Invalid selection."
exit 1
fi
# if the selection is out of bounds, exit
if [ "$SELECTION" -gt $(echo "$PATTERN_RESULTS" | wc -l) ]; then
echo "Invalid selection."
exit 1
fi
# select the line from the results
SELECTED_RESULT=$(echo "$PATTERN_RESULTS" | sed -n "${SELECTION}p")
else
SELECTED_RESULT="$PATTERN_RESULTS"
fi
# search for the pattern in the binary file and capture the offset
OFFSET=$(echo "${SELECTED_RESULT}" | cut -d ' ' -f 1)
if [ -z "$OFFSET" ]; then
echo "Pattern not found."
exit 1
fi
# adjust the offset to capture prefix length before the match
OFFSET=$(expr "$OFFSET" - "$PREFIX_LENGTH")
# use xxd to capture the specified length from the calculated offset
SNIPPET=$(xxd -l "$LENGTH" -s "$OFFSET" "$BINARY_FILE")
# display the output and prompt the user
echo ""
echo "$SNIPPET"
echo ""
read -p "Does this snippet capture what you need? (Y/n/q) " RESPONSE
RESPONSE=${RESPONSE:-y}
if [ "$RESPONSE" == "y" ]; then
CONTINUE_LOOP=false
elif [ $RESULT_COUNT -eq 1 ] || [ "$RESPONSE" == "q" ]; then
echo "Exiting with no action taken."
exit 0
fi
done
go run ./manager write-snippet "$BINARY_FILE" --offset "$OFFSET" --length "$LENGTH" --name "$GROUP_NAME" --version "$VERSION"

View file

@ -1,2 +0,0 @@
!*.so
!VERSION

View file

@ -1 +0,0 @@
@(#)Bash version 5.2.15(1) release GNU

View file

@ -1,3 +0,0 @@
# note: this SHOULD match as busybox 3.33.3
noise!BusyBox v3.33.3!noise

View file

@ -1 +0,0 @@
HA-Proxy version 1.5.14 2015/07/02Copyright 2000-2015 Willy Tarreau <willy@haproxy.org>

View file

@ -1,18 +0,0 @@
<Directory "
mailto:
Apache/2.4.54
Server at <a href="
<address>
--
</a> Port
Server at
Apache/2.4.54 (Unix)
ap_logio_add_bytes_out
ap_ident_lookup
--
access_compat_ap_satisfies
Apache
Apache/2.4
Apache/2
<VirtualHost
<Limit

View file

@ -1,31 +0,0 @@
The binary snippet was gathered with:
```bash
$ cat ./original-mariadb | strings | grep '-MariaDB'
# assert you can see the value
$ xxd ./original-mariadb | grep '\-MariaDB'
# get the address...
$ xxd -s 0x003dd5c0 -l 40 ./original-mariadb
003dd5c0: 2900 4c69 6e75 7800 3130 2e36 2e31 352d ).Linux.10.6.15-
003dd5d0: 4d61 7269 6144 4200 7265 6164 6c69 6e65 MariaDB.readline
003dd5e0: 0078 3836 5f36 3400 .x86_64.
$ dd if=./original-mariadb of=mariadb bs=1 skip=$((0x003dd5c0)) count=40
40+0 records in
40+0 records out
40 bytes transferred in 0.000264 secs (151515 bytes/sec)
$ xxd mariadb
00000000: 2900 4c69 6e75 7800 3130 2e36 2e31 352d ).Linux.10.6.15-
00000010: 4d61 7269 6144 4200 7265 6164 6c69 6e65 MariaDB.readline
00000020: 0078 3836 5f36 3400 .x86_64.
```

View file

@ -1,13 +0,0 @@
secs_since_last_cmd
listen
memcached 1.6.18
udp-port
memcached 1.6.18
Failed to allocate memory
%s,%s
--
bget
flush_all
VERSION 1.6.18
quit
BADCLASS invalid class id

View file

@ -1,39 +0,0 @@
The binary snippet was gathered with:
```bash
$ cat ./original-mysql | strings | grep '5.6.51'
# assert you can see the value
$ xxd ./original-mysql | grep '5.6.51'
# get the address...
$ xxd -s 0x008f13d0 -l 100 original-mysql
008f13d0: 2d62 6163 6b75 702d 7265 7374 6f72 6572 -backup-restorer
008f13e0: 2d6d 7973 716c 2d35 2e36 2f6d 7973 716c -mysql-5.6/mysql
008f13f0: 2d35 2e36 2e35 312f 636c 6965 6e74 2f63 -5.6.51/client/c
008f1400: 6f6d 706c 6574 696f 6e5f 6861 7368 2e63 ompletion_hash.c
008f1410: 6300 2f76 6172 2f76 6361 702f 6461 7461 c./var/vcap/data
008f1420: 2f63 6f6d 7069 6c65 2f64 6174 6162 6173 /compile/databas
008f1430: 652d 6261 e-ba
$ dd if=./original-mysql of=mysql bs=1 skip=$((0x008f13d0)) count=100
100+0 records in
100+0 records out
100 bytes transferred in 0.000642 secs (155763 bytes/sec)
$ xxd mysql
00000000: 2d62 6163 6b75 702d 7265 7374 6f72 6572 -backup-restorer
00000010: 2d6d 7973 716c 2d35 2e36 2f6d 7973 716c -mysql-5.6/mysql
00000020: 2d35 2e36 2e35 312f 636c 6965 6e74 2f63 -5.6.51/client/c
00000030: 6f6d 706c 6574 696f 6e5f 6861 7368 2e63 ompletion_hash.c
00000040: 6300 2f76 6172 2f76 6361 702f 6461 7461 c./var/vcap/data
00000050: 2f63 6f6d 7069 6c65 2f64 6174 6162 6173 /compile/databas
00000060: 652d 6261 e-ba
```

View file

@ -1,40 +0,0 @@
The binary snippet was gathered with:
```bash
$ cat ./original-mysql | strings | grep '8.0.34'
# assert you can see the value
$ xxd ./original-mysql | grep '8.0.34'
# get the address...
$ xxd -s 0x0014cd20 -l 100 original-mysql
0014cd20: 2069 7320 616c 7265 6164 7920 6c6f 6164 is already load
0014cd30: 6564 0000 0000 0000 2e2e 2f2e 2e2f 6d79 ed......../../my
0014cd40: 7371 6c2d 382e 302e 3334 2f73 716c 2d63 sql-8.0.34/sql-c
0014cd50: 6f6d 6d6f 6e2f 636c 6965 6e74 5f70 6c75 ommon/client_plu
0014cd60: 6769 6e2e 6363 002f 7573 722f 6c6f 6361 gin.cc./usr/loca
0014cd70: 6c2f 6d79 7371 6c2f 6c69 622f 706c 7567 l/mysql/lib/plug
0014cd80: 696e 0049 in.I
$ dd if=./original-mysql of=mysql bs=1 skip=$((0x0014cd20)) count=100
100+0 records in
100+0 records out
100 bytes transferred in 0.000519 secs (192678 bytes/sec)
$ xxd mysql
00000000: 2069 7320 616c 7265 6164 7920 6c6f 6164 is already load
00000010: 6564 0000 0000 0000 2e2e 2f2e 2e2f 6d79 ed......../../my
00000020: 7371 6c2d 382e 302e 3334 2f73 716c 2d63 sql-8.0.34/sql-c
00000030: 6f6d 6d6f 6e2f 636c 6965 6e74 5f70 6c75 ommon/client_plu
00000040: 6769 6e2e 6363 002f 7573 722f 6c6f 6361 gin.cc./usr/loca
00000050: 6c2f 6d79 7371 6c2f 6c69 622f 706c 7567 l/mysql/lib/plug
00000060: 696e 0049 in.I
```

View file

@ -1,2 +0,0 @@
# this should match node 19.2.1
node.js/v19.2.1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 B

View file

@ -1,5 +0,0 @@
[null] Script: '%s'
%s,%s
X-Powered-By: PHP/8.2.1
index pointer
PHP_VERSION

View file

@ -1,5 +0,0 @@
[null] Script: '%s'
%s,%s
X-Powered-By: PHP/8.2.1
index pointer
PHP_VERSION

View file

@ -1,5 +0,0 @@
[null] Script: '%s'
%s,%s
X-Powered-By: PHP/8.2.1
index pointer
PHP_VERSION

View file

@ -1,5 +0,0 @@
byteaout
byteain
?PostgreSQL 9.5alpha1 on x86_64-unknown-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit
/tmp/buildd/postgresql-9.5-9.5~alpha1/build/../src/backend/utils/adt/windowfuncs.c
argument of ntile must be greater than zero

View file

@ -1,9 +0,0 @@
super from singleton method that is defined to multiple classes is not supported; this will be fixed in 1.9.3 or later
/usr/local/lib/ruby/site_ruby/1.9.1
/usr/local/lib/ruby/site_ruby/1.9.1/x86_64-linux
/usr/local/lib/ruby/vendor_ruby/1.9.1
/usr/local/lib/ruby/vendor_ruby/1.9.1/x86_64-linux
/usr/local/lib/ruby/1.9.1
/usr/local/lib/ruby/1.9.1/x86_64-linux
ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-linux]
1.9.3

View file

@ -0,0 +1,12 @@
name: consul
offset: 57272433
length: 100
snippetSha256: a4a955b180d6df471797a9f17f5ebf6f23b92d688d40532712683922e119dac0
fileSha256: 5c5fed218247eaf43c3b54008b6a4c5d5cfa1b38539d6e7bfc09ac04623389fc
### byte snippet to follow ###
e%7D" />
<!-- CONSUL_VERSION: 1.15.2
-->
<link rel="icon" href="{{.ContentPath}}assets/favicon

View file

@ -0,0 +1,8 @@
name: mysql
offset: 1377134
length: 100
snippetSha256: f18b2e276e188db350b2d5e580085db8f8d5ae28f1eb9413523a8ea5948cb981
fileSha256: 38ba0547af106c7ccd78e98233499530d50eaa0c1aaea0f46002b03f28992beb
### byte snippet to follow ###
íÿ`íÿz íÿ/var/lib/pb2/sb_1-11875240-1687434163.06/rpm/BUILD/mysql-8.0.34/mysql-8.0.34/sql-common/cl

View file

@ -0,0 +1,12 @@
name: libphp.so
offset: unknown
length: unknown
snippetSha256: d39ac8dadf5ba868455c487f1d0bb4c8bec64006fd7e5d76e3e27a26e47e637f
fileSha256: unknown
### byte snippet to follow ###
%s'
%s,%s
X-Powered-By: PHP/8.2.1
index pointer
PHP_VERSION

View file

@ -0,0 +1,12 @@
name: php
offset: unknown
length: unknown
snippetSha256: d39ac8dadf5ba868455c487f1d0bb4c8bec64006fd7e5d76e3e27a26e47e637f
fileSha256: unknown
### byte snippet to follow ###
%s'
%s,%s
X-Powered-By: PHP/8.2.1
index pointer
PHP_VERSION

View file

@ -0,0 +1,12 @@
name: php-fpm
offset: unknown
length: unknown
snippetSha256: d39ac8dadf5ba868455c487f1d0bb4c8bec64006fd7e5d76e3e27a26e47e637f
fileSha256: unknown
### byte snippet to follow ###
%s'
%s,%s
X-Powered-By: PHP/8.2.1
index pointer
PHP_VERSION

View file

@ -0,0 +1,10 @@
name: postgres
offset: unknown
length: unknown
snippetSha256: 8f8323161ded8fd737ba7157b36b794c55354e8a9b8b6c5aa07dab9c3468886c
fileSha256: unknown
### byte snippet to follow ###
t
byteain
?PostgreSQL 9.5alpha1 on x86_64-unknown-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2

Some files were not shown because too many files have changed in this diff Show more