mirror of
https://github.com/anchore/syft.git
synced 2026-10-12 14:17:20 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4e985b9b0 | ||
|
|
14355aac21 | ||
|
|
e38825a0a2 | ||
|
|
5a37b4a996 | ||
|
|
56dbb342ef | ||
|
|
3267545097 | ||
|
|
7adbdfe624 | ||
|
|
f2646d0156 | ||
|
|
5b9601d9c6 | ||
|
|
80c8bc1afb | ||
|
|
d7194bb00f | ||
|
|
754cebee64 | ||
|
|
138c6e3420 | ||
|
|
5c0df6386f | ||
|
|
7c69367b65 | ||
|
|
39146aaf62 | ||
|
|
67faca4208 | ||
|
|
f6e5405eb8 | ||
|
|
e962c10da7 | ||
|
|
8095f7b8c1 | ||
|
|
84877369e5 | ||
|
|
6124d72a29 | ||
|
|
c2c8c793d2 | ||
|
|
fbff87fc6d | ||
|
|
0c71bf23c5 | ||
|
|
b62b0cb800 | ||
|
|
223a52d07e | ||
|
|
5d068f30c0 | ||
|
|
5d165e0230 | ||
|
|
56ed131247 | ||
|
|
37c179b530 | ||
|
|
ccbee94b87 | ||
|
|
4d7ed9f749 | ||
|
|
4c4e5cb06c | ||
|
|
8b6159dbd8 | ||
|
|
7b30ce15d7 | ||
|
|
27ee203495 | ||
|
|
3b9c55d28b | ||
|
|
25f5c6729f | ||
|
|
0d457142cc | ||
|
|
fc8457418a | ||
|
|
13c6876906 | ||
|
|
770fdc53ea | ||
|
|
32c0d1e673 | ||
|
|
263ea6b1bb | ||
|
|
cc4f62b3d4 | ||
|
|
dbad17de9e | ||
|
|
93beceb4a2 | ||
|
|
9b242b0309 | ||
|
|
f5f8005fe0 | ||
|
|
2a3d171c10 | ||
|
|
1a746b2c05 | ||
|
|
e37c4686c2 | ||
|
|
5393cd5dec | ||
|
|
f9ef9cf1dc | ||
|
|
16122eb32d | ||
|
|
39b2bf5518 | ||
|
|
d7005d7d8c | ||
|
|
92c1ddec5a | ||
|
|
01de99b253 | ||
|
|
7815d8e4d9 | ||
|
|
963ea594c8 | ||
|
|
60bbd24031 | ||
|
|
7c12e3f3b3 | ||
|
|
9b5cf1db51 | ||
|
|
a08ea86aa6 | ||
|
|
98c96ce361 | ||
|
|
6a95a5f2ed | ||
|
|
cb0de97bc3 | ||
|
|
50016c3172 | ||
|
|
a2f12fef0c | ||
|
|
7934696463 | ||
|
|
b9efac4d78 | ||
|
|
48c1c45d12 | ||
|
|
9cc3641ac6 | ||
|
|
7b4feb7c16 | ||
|
|
41e9630409 | ||
|
|
58100fec9f | ||
|
|
834027e32d | ||
|
|
2b4d5c275f | ||
|
|
38e51f16ec | ||
|
|
1b863268df | ||
|
|
fcd5ec951d | ||
|
|
61a9fde01c | ||
|
|
c33a51d3d8 | ||
|
|
dbc4238f63 | ||
|
|
fce14fd537 | ||
|
|
98bd4e99b6 | ||
|
|
9c2799e379 | ||
|
|
dafc6ad034 | ||
|
|
16f89840fd | ||
|
|
2475f7f696 | ||
|
|
f735a428eb | ||
|
|
ba7bf6b85e | ||
|
|
b153b1d594 | ||
|
|
0a3f513f92 | ||
|
|
deabd4115a | ||
|
|
ff0bae67bd | ||
|
|
a343825685 | ||
|
|
7c96a10cbe | ||
|
|
8c690d000d | ||
|
|
8ade391658 | ||
|
|
e299a95120 | ||
|
|
f2caf45695 | ||
|
|
731fc77641 | ||
|
|
3499d92c6d | ||
|
|
19d2735aff | ||
|
|
11d77b4a94 | ||
|
|
2c25f81b68 | ||
|
|
04e3371cce | ||
|
|
5ab43bafec | ||
|
|
e9a8c27be1 | ||
|
|
4ee6c179f8 | ||
|
|
99be365f62 | ||
|
|
cf9bb13f2b | ||
|
|
0cd6185716 | ||
|
|
6549ec9831 | ||
|
|
b6b5c8e308 | ||
|
|
dad253785e | ||
|
|
cff9d494df | ||
|
|
9ab3de1819 | ||
|
|
6f0230879a | ||
|
|
691f34ce27 | ||
|
|
ac977246c9 | ||
|
|
78d48b4209 | ||
|
|
bd80eeafac | ||
|
|
73b9d5aa42 | ||
|
|
f786233e97 | ||
|
|
95b4a88256 | ||
|
|
511cc9c2d5 | ||
|
|
360983f75b | ||
|
|
4b7ae0ed3b | ||
|
|
4ff60ee837 | ||
|
|
965000dcbb | ||
|
|
a447884084 | ||
|
|
cd3b828905 | ||
|
|
3161e1847e | ||
|
|
df1e5b57fe | ||
|
|
d2b33f1acb | ||
|
|
91cf066db6 | ||
|
|
c19cf626ab | ||
|
|
cf85450e08 | ||
|
|
49d4e32241 | ||
|
|
19cc664cf8 | ||
|
|
64a9ecbf7a | ||
|
|
6267d69930 | ||
|
|
1fb47d908e | ||
|
|
2339743c8c | ||
|
|
9031592649 | ||
|
|
47d192d79b | ||
|
|
040b683da8 | ||
|
|
dcd87d1fef | ||
|
|
214a0498e0 | ||
|
|
0f9df805c1 | ||
|
|
703330abd0 | ||
|
|
9d40d1152e | ||
|
|
cc15edca62 | ||
|
|
623532e3ed | ||
|
|
48f1e975f0 | ||
|
|
c84cb2cf84 | ||
|
|
05a10e8bed | ||
|
|
92d63df6f5 | ||
|
|
a4b5dcd0df | ||
|
|
06526e2931 | ||
|
|
a2042e629c | ||
|
|
a35e410c75 | ||
|
|
8dd7c9c0b9 | ||
|
|
490e05adb2 | ||
|
|
1cd75b7d68 | ||
|
|
4882d2e8ce | ||
|
|
b3848f780f | ||
|
|
36f95d6828 | ||
|
|
68b96ae444 | ||
|
|
3917989f86 | ||
|
|
741c8fb9bd | ||
|
|
9573f557d1 | ||
|
|
ca945d16e0 | ||
|
|
fe7c5a7174 | ||
|
|
125c787e40 | ||
|
|
bfe6f5204a | ||
|
|
aead40e1de | ||
|
|
536611fa25 | ||
|
|
d0a7d4c43e | ||
|
|
0c53a087f0 | ||
|
|
b263b1ec1f | ||
|
|
034a98f029 | ||
|
|
69031b0646 | ||
|
|
761a161e7f | ||
|
|
ba31c2f1ae | ||
|
|
5d729a5e9e | ||
|
|
276df95768 | ||
|
|
cca9a06a64 | ||
|
|
4d23990dd4 | ||
|
|
d4fa61e0a2 | ||
|
|
d4d4e003e9 | ||
|
|
6bf91a410d | ||
|
|
77c300d617 | ||
|
|
75902b0540 | ||
|
|
278b72d39b | ||
|
|
37245a21cc | ||
|
|
e2fe955262 | ||
|
|
4e09908ba1 | ||
|
|
863793a3cc | ||
|
|
f7ffcc534f | ||
|
|
b101f44aba | ||
|
|
de3313cfb6 | ||
|
|
b2f9904d74 | ||
|
|
13d01ecaff | ||
|
|
7dc1b1ce27 | ||
|
|
b8dce675fe | ||
|
|
6dda9edd7c | ||
|
|
04c861bf77 | ||
|
|
573440b7cf | ||
|
|
c816039e91 | ||
|
|
7f3ca65cf6 | ||
|
|
43e5b1b45f | ||
|
|
a876aaccb2 | ||
|
|
875669bfd1 | ||
|
|
5283c4687a | ||
|
|
4d48adfa3f | ||
|
|
c8b449c92b | ||
|
|
ceced5eb27 | ||
|
|
7da15890eb | ||
|
|
580c09b01c | ||
|
|
0dce67872e | ||
|
|
1eae9333a9 | ||
|
|
863891f325 | ||
|
|
bd1c1d260c | ||
|
|
f5a917a5a2 | ||
|
|
ae0683074e | ||
|
|
9b178174a7 | ||
|
|
e947779886 | ||
|
|
7a35de04ee | ||
|
|
246df97ae7 | ||
|
|
750d37f075 | ||
|
|
5061b905dc | ||
|
|
ed3774afa7 | ||
|
|
22d5731482 | ||
|
|
af3aaa0397 | ||
|
|
70098e20bb | ||
|
|
784b17f66c | ||
|
|
d5cd5f6091 | ||
|
|
749ccc59c1 | ||
|
|
273e31e806 | ||
|
|
9beaec2e97 | ||
|
|
ca0cc52d47 | ||
|
|
dd723bb3c5 | ||
|
|
fb68489590 | ||
|
|
5590d5c1ce | ||
|
|
0956753409 | ||
|
|
f966bcfd03 | ||
|
|
c43f4fb416 | ||
|
|
db0c33481e | ||
|
|
a658cc7402 | ||
|
|
254a562b4e | ||
|
|
bc20e66d08 | ||
|
|
6e16396d18 | ||
|
|
5cdc0845fb | ||
|
|
baca15f186 | ||
|
|
b608ab77e1 | ||
|
|
f4c941f08d | ||
|
|
2d5760145c | ||
|
|
f11bb95c1e | ||
|
|
d2fa5ed41c | ||
|
|
7508d75b2b | ||
|
|
3472b48177 | ||
|
|
4bdbd1aa2a | ||
|
|
557ad73ee6 | ||
|
|
cb09dd9e19 | ||
|
|
2f39322f81 | ||
|
|
fe0b78b7fe | ||
|
|
8a7f08e2c8 | ||
|
|
29d601d1f1 | ||
|
|
3ac95bfbd0 | ||
|
|
24262b9e31 | ||
|
|
b04bc0fbfe | ||
|
|
aafa161ff6 | ||
|
|
eeb4193d4a | ||
|
|
5cf8cc9bc3 | ||
|
|
f4a69e6d35 | ||
|
|
ac34808b9c | ||
|
|
2b70ea3fc2 | ||
|
|
5eb1e7115f | ||
|
|
774602f0d8 | ||
|
|
c314e05aae | ||
|
|
05e8ba948d | ||
|
|
64e11d53e9 | ||
|
|
b51252dbdb | ||
|
|
77b3f66404 | ||
|
|
1c37bab2b2 | ||
|
|
7071f1e498 | ||
|
|
3875e4a67d | ||
|
|
a0f0332e30 | ||
|
|
ea50c6153d | ||
|
|
b41d5cced5 | ||
|
|
68daa42f86 | ||
|
|
2356787053 | ||
|
|
2d318cffaa | ||
|
|
49c458b113 | ||
|
|
1144407591 | ||
|
|
15808fbd04 | ||
|
|
13ae56e3ef | ||
|
|
1bec1fc5d3 | ||
|
|
15c9fe092a | ||
|
|
338ce51fd8 | ||
|
|
048df17e3d | ||
|
|
7ad7627d5d | ||
|
|
e767bcff4b | ||
|
|
4a18895545 | ||
|
|
fae6f5d372 | ||
|
|
ee75aafa37 | ||
|
|
c200896a96 | ||
|
|
4194a2cd34 | ||
|
|
74b01a1c38 | ||
|
|
b2ca5fbf89 | ||
|
|
1892f24002 | ||
|
|
88aaab2841 | ||
|
|
5044f48cd6 | ||
|
|
6c2e8c8c4b | ||
|
|
ada8f009d2 | ||
|
|
e7b6284039 | ||
|
|
78625164c6 | ||
|
|
c0635a77a9 | ||
|
|
3713d97b7b | ||
|
|
430c55a5b0 | ||
|
|
49e93646eb | ||
|
|
5ca26ed3ca | ||
|
|
e353214ef8 | ||
|
|
a56eff90d6 | ||
|
|
00ff3ffda9 | ||
|
|
9de533996e | ||
|
|
7aae7470e2 | ||
|
|
d6604adaaf | ||
|
|
34ca9a8412 | ||
|
|
f51b39ca04 | ||
|
|
9bbb42620a | ||
|
|
0b4de3d0c7 | ||
|
|
80d196a8c9 | ||
|
|
ed40833b30 | ||
|
|
93a7d2ee27 | ||
|
|
93a99e36c2 | ||
|
|
b0c88ddea9 | ||
|
|
047e31a969 | ||
|
|
25b55e1704 | ||
|
|
02dc2dfa9b | ||
|
|
5b03788300 | ||
|
|
9901ea8fe9 | ||
|
|
87cd6c8c48 | ||
|
|
d3310a1830 | ||
|
|
8640f978ba | ||
|
|
13b06dad45 | ||
|
|
9604e3dc9c | ||
|
|
f2fc10aa86 | ||
|
|
21b22555d2 | ||
|
|
5326efcef1 | ||
|
|
b90e7f9437 | ||
|
|
fbdd4ee015 | ||
|
|
f154bf570d | ||
|
|
99b58db497 | ||
|
|
8d960e62c6 | ||
|
|
27a8a1be03 | ||
|
|
4ccbd17255 | ||
|
|
891e61a2ef | ||
|
|
f7d3d552ce | ||
|
|
12ea9912b4 | ||
|
|
cf6f92f2c8 | ||
|
|
6440f26b5a | ||
|
|
f2633800ce | ||
|
|
4f227bf447 | ||
|
|
d70eb3d04b | ||
|
|
fe4819bc08 | ||
|
|
b26b38d6c5 | ||
|
|
31969136e3 | ||
|
|
f6845474bd | ||
|
|
e1cadead1d | ||
|
|
3e71f46fc8 | ||
|
|
3b01e13f92 | ||
|
|
25c2e60358 | ||
|
|
dc7fa21980 | ||
|
|
587690b875 | ||
|
|
21eaa5c82b | ||
|
|
081ec04b3f |
+24
-8
@@ -2,7 +2,7 @@ tools:
|
||||
# we want to use a pinned version of binny to manage the toolchain (so binny manages itself!)
|
||||
- name: binny
|
||||
version:
|
||||
want: v0.7.0
|
||||
want: v0.8.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: anchore/binny
|
||||
@@ -18,7 +18,7 @@ tools:
|
||||
# used to sign mac binaries at release
|
||||
- name: quill
|
||||
version:
|
||||
want: v0.4.1
|
||||
want: v0.4.2
|
||||
method: github-release
|
||||
with:
|
||||
repo: anchore/quill
|
||||
@@ -26,7 +26,7 @@ tools:
|
||||
# used for linting
|
||||
- name: golangci-lint
|
||||
version:
|
||||
want: v1.57.2
|
||||
want: v1.61.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: golangci/golangci-lint
|
||||
@@ -34,7 +34,7 @@ tools:
|
||||
# used for showing the changelog at release
|
||||
- name: glow
|
||||
version:
|
||||
want: v1.5.1
|
||||
want: v2.0.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: charmbracelet/glow
|
||||
@@ -42,7 +42,7 @@ tools:
|
||||
# used for signing the checksums file at release
|
||||
- name: cosign
|
||||
version:
|
||||
want: v2.2.4
|
||||
want: v2.4.1
|
||||
method: github-release
|
||||
with:
|
||||
repo: sigstore/cosign
|
||||
@@ -58,7 +58,7 @@ tools:
|
||||
# used to release all artifacts
|
||||
- name: goreleaser
|
||||
version:
|
||||
want: v1.25.1
|
||||
want: v2.3.2
|
||||
method: github-release
|
||||
with:
|
||||
repo: goreleaser/goreleaser
|
||||
@@ -103,7 +103,7 @@ tools:
|
||||
# used for running all local and CI tasks
|
||||
- name: task
|
||||
version:
|
||||
want: v3.36.0
|
||||
want: v3.39.2
|
||||
method: github-release
|
||||
with:
|
||||
repo: go-task/task
|
||||
@@ -111,7 +111,23 @@ tools:
|
||||
# used for triggering a release
|
||||
- name: gh
|
||||
version:
|
||||
want: v2.47.0
|
||||
want: v2.59.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: cli/cli
|
||||
|
||||
# used to upload test fixture cache
|
||||
- name: oras
|
||||
version:
|
||||
want: v1.2.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: oras-project/oras
|
||||
|
||||
# used to upload test fixture cache
|
||||
- name: yq
|
||||
version:
|
||||
want: v4.44.3
|
||||
method: github-release
|
||||
with:
|
||||
repo: mikefarah/yq
|
||||
|
||||
@@ -6,6 +6,7 @@ permit:
|
||||
- MPL.*
|
||||
- ISC
|
||||
- WTFPL
|
||||
- Unlicense
|
||||
|
||||
ignore-packages:
|
||||
# packageurl-go is released under the MIT license located in the root of the repo at /mit.LICENSE
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
contact_links:
|
||||
|
||||
- name: Join the Slack community 💬
|
||||
# link to our community Slack registration page
|
||||
url: https://anchore.com/slack
|
||||
- name: Join our Discourse community 💬
|
||||
# link to our community Discourse site
|
||||
url: https://anchore.com/discourse
|
||||
about: 'Come chat with us! Ask for help, join our software development efforts, or just give us feedback!'
|
||||
|
||||
@@ -5,7 +5,7 @@ inputs:
|
||||
go-version:
|
||||
description: "Go version to install"
|
||||
required: true
|
||||
default: "1.21.x"
|
||||
default: "1.22.x"
|
||||
go-dependencies:
|
||||
description: "Download go dependencies"
|
||||
required: true
|
||||
@@ -13,28 +13,27 @@ inputs:
|
||||
cache-key-prefix:
|
||||
description: "Prefix all cache keys with this value"
|
||||
required: true
|
||||
default: "1ac8281053"
|
||||
compute-fingerprints:
|
||||
description: "Compute test fixture fingerprints"
|
||||
default: "181053ac82"
|
||||
download-test-fixture-cache:
|
||||
description: "Download test fixture cache from OCI and github actions"
|
||||
required: true
|
||||
default: "true"
|
||||
default: "false"
|
||||
bootstrap-apt-packages:
|
||||
description: "Space delimited list of tools to install via apt"
|
||||
default: "libxml2-utils"
|
||||
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
# note: go mod and build is automatically cached on default with v4+
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe #v4.1.0
|
||||
- uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
if: inputs.go-version != ''
|
||||
with:
|
||||
go-version: ${{ inputs.go-version }}
|
||||
|
||||
- name: Restore tool cache
|
||||
id: tool-cache
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ${{ github.workspace }}/.tool
|
||||
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('.binny.yaml') }}
|
||||
@@ -54,8 +53,14 @@ runs:
|
||||
run: |
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt update && sudo -E apt install -y ${{ inputs.bootstrap-apt-packages }}
|
||||
|
||||
- name: Create all cache fingerprints
|
||||
if: inputs.compute-fingerprints == 'true'
|
||||
shell: bash
|
||||
run: make fingerprints
|
||||
- name: Restore ORAS cache from github actions
|
||||
if: inputs.download-test-fixture-cache == 'true'
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ${{ github.workspace }}/.tmp/oras-cache
|
||||
key: ${{ inputs.cache-key-prefix }}-oras-cache
|
||||
|
||||
- name: Download test fixture cache
|
||||
if: inputs.download-test-fixture-cache == 'true'
|
||||
shell: bash
|
||||
run: make download-test-fixture-cache
|
||||
|
||||
@@ -17,3 +17,11 @@ updates:
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "dependencies"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/.github/actions/boostrap"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
open-pull-requests-limit: 10
|
||||
labels:
|
||||
- "dependencies"
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# Description
|
||||
|
||||
Please include a summary of the changes along with any relevant motivation and context,
|
||||
or link to an issue where this is explained.
|
||||
|
||||
<!-- If this completes an issue, please include: -->
|
||||
|
||||
- Fixes #
|
||||
|
||||
## Type of change
|
||||
|
||||
<!-- Delete any that are not relevant -->
|
||||
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (please discuss with the team first; Syft is 1.0 software and we won't accept breaking changes without going to 2.0)
|
||||
- [ ] Documentation (updates the documentation)
|
||||
- [ ] Chore (improve the developer experience, fix a test flake, etc, without changing the visible behavior of Syft)
|
||||
- [ ] Performance (make Syft run faster or use less memory, without changing visible behavior much)
|
||||
|
||||
# Checklist:
|
||||
|
||||
- [ ] I have added unit tests that cover changed behavior
|
||||
- [ ] I have tested my code in common scenarios and confirmed there are no regressions
|
||||
- [ ] I have added comments to my code, particularly in hard-to-understand sections
|
||||
Executable
+135
@@ -0,0 +1,135 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import glob
|
||||
import sys
|
||||
import json
|
||||
import hashlib
|
||||
|
||||
|
||||
IGNORED_PREFIXES = []
|
||||
|
||||
|
||||
def find_fingerprints_and_check_dirs(base_dir):
|
||||
all_fingerprints = set(glob.glob(os.path.join(base_dir, '**', 'test*', '**', '*.fingerprint'), recursive=True))
|
||||
|
||||
all_fingerprints = {os.path.relpath(fp) for fp in all_fingerprints
|
||||
if not any(fp.startswith(prefix) for prefix in IGNORED_PREFIXES)}
|
||||
|
||||
if not all_fingerprints:
|
||||
show("No .fingerprint files or cache directories found.")
|
||||
exit(1)
|
||||
|
||||
missing_content = []
|
||||
valid_paths = set()
|
||||
fingerprint_contents = []
|
||||
|
||||
for fingerprint in all_fingerprints:
|
||||
path = fingerprint.replace('.fingerprint', '')
|
||||
|
||||
if not os.path.exists(path):
|
||||
missing_content.append(path)
|
||||
continue
|
||||
|
||||
if not os.path.isdir(path):
|
||||
valid_paths.add(path)
|
||||
continue
|
||||
|
||||
if os.listdir(path):
|
||||
valid_paths.add(path)
|
||||
else:
|
||||
missing_content.append(path)
|
||||
|
||||
with open(fingerprint, 'r') as f:
|
||||
content = f.read().strip()
|
||||
fingerprint_contents.append((fingerprint, content))
|
||||
|
||||
return sorted(valid_paths), missing_content, fingerprint_contents
|
||||
|
||||
|
||||
def parse_fingerprint_contents(fingerprint_content):
|
||||
input_map = {}
|
||||
for line in fingerprint_content.splitlines():
|
||||
digest, path = line.split()
|
||||
input_map[path] = digest
|
||||
return input_map
|
||||
|
||||
|
||||
def calculate_sha256(fingerprint_contents):
|
||||
sorted_fingerprint_contents = sorted(fingerprint_contents, key=lambda x: x[0])
|
||||
|
||||
concatenated_contents = ''.join(content for _, content in sorted_fingerprint_contents)
|
||||
|
||||
sha256_hash = hashlib.sha256(concatenated_contents.encode()).hexdigest()
|
||||
|
||||
return sha256_hash
|
||||
|
||||
|
||||
def calculate_file_sha256(file_path):
|
||||
sha256_hash = hashlib.sha256()
|
||||
with open(file_path, 'rb') as f:
|
||||
for byte_block in iter(lambda: f.read(4096), b""):
|
||||
sha256_hash.update(byte_block)
|
||||
return sha256_hash.hexdigest()
|
||||
|
||||
|
||||
def show(*s: str):
|
||||
print(*s, file=sys.stderr)
|
||||
|
||||
|
||||
def main(file_path: str | None):
|
||||
base_dir = '.'
|
||||
valid_paths, missing_content, fingerprint_contents = find_fingerprints_and_check_dirs(base_dir)
|
||||
|
||||
if missing_content:
|
||||
show("The following paths are missing or have no content, but have corresponding .fingerprint files:")
|
||||
for path in sorted(missing_content):
|
||||
show(f"- {path}")
|
||||
show("Please ensure these paths exist and have content if they are directories.")
|
||||
exit(1)
|
||||
|
||||
sha256_hash = calculate_sha256(fingerprint_contents)
|
||||
|
||||
paths_with_digests = []
|
||||
for path in sorted(valid_paths):
|
||||
fingerprint_file = f"{path}.fingerprint"
|
||||
try:
|
||||
if os.path.exists(fingerprint_file):
|
||||
file_digest = calculate_file_sha256(fingerprint_file)
|
||||
|
||||
# Parse the fingerprint file to get the digest/path tuples
|
||||
with open(fingerprint_file, 'r') as f:
|
||||
fingerprint_content = f.read().strip()
|
||||
input_map = parse_fingerprint_contents(fingerprint_content)
|
||||
|
||||
paths_with_digests.append({
|
||||
"path": path,
|
||||
"digest": file_digest,
|
||||
"input": input_map
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
show(f"Error processing {fingerprint_file}: {e}")
|
||||
raise e
|
||||
|
||||
|
||||
output = {
|
||||
"digest": sha256_hash,
|
||||
"paths": paths_with_digests
|
||||
}
|
||||
|
||||
content = json.dumps(output, indent=2, sort_keys=True)
|
||||
|
||||
if file_path:
|
||||
with open(file_path, 'w') as f:
|
||||
f.write(content)
|
||||
|
||||
print(content)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
file_path = None
|
||||
if len(sys.argv) > 1:
|
||||
file_path = sys.argv[1]
|
||||
main(file_path)
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import hashlib
|
||||
|
||||
BOLD = '\033[1m'
|
||||
YELLOW = '\033[0;33m'
|
||||
RESET = '\033[0m'
|
||||
|
||||
|
||||
def print_message(message):
|
||||
print(f"{YELLOW}{message}{RESET}")
|
||||
|
||||
|
||||
def sha256sum(filepath):
|
||||
h = hashlib.sha256()
|
||||
with open(filepath, 'rb') as f:
|
||||
for chunk in iter(lambda: f.read(4096), b""):
|
||||
h.update(chunk)
|
||||
return h.hexdigest()
|
||||
|
||||
|
||||
def is_git_tracked_or_untracked(directory):
|
||||
"""Returns a sorted list of files in the directory that are tracked or not ignored by Git."""
|
||||
result = subprocess.run(
|
||||
["git", "ls-files", "--cached", "--others", "--exclude-standard"],
|
||||
cwd=directory,
|
||||
stdout=subprocess.PIPE,
|
||||
text=True
|
||||
)
|
||||
return sorted(result.stdout.strip().splitlines())
|
||||
|
||||
|
||||
def find_test_fixture_dirs_with_images(base_dir):
|
||||
"""Find directories that contain 'test-fixtures' and at least one 'image-*' directory."""
|
||||
for root, dirs, files in os.walk(base_dir):
|
||||
if 'test-fixtures' in root:
|
||||
image_dirs = [d for d in dirs if d.startswith('image-')]
|
||||
if image_dirs:
|
||||
yield os.path.realpath(root)
|
||||
|
||||
|
||||
def generate_fingerprints():
|
||||
print_message("creating fingerprint files for docker fixtures...")
|
||||
|
||||
for test_fixture_dir in find_test_fixture_dirs_with_images('.'):
|
||||
cache_fingerprint_path = os.path.join(test_fixture_dir, 'cache.fingerprint')
|
||||
|
||||
with open(cache_fingerprint_path, 'w') as fingerprint_file:
|
||||
for image_dir in find_image_dirs(test_fixture_dir):
|
||||
for file in is_git_tracked_or_untracked(image_dir):
|
||||
file_path = os.path.join(image_dir, file)
|
||||
checksum = sha256sum(file_path)
|
||||
path_from_fixture_dir = os.path.relpath(file_path, test_fixture_dir)
|
||||
fingerprint_file.write(f"{checksum} {path_from_fixture_dir}\n")
|
||||
|
||||
|
||||
def find_image_dirs(test_fixture_dir):
|
||||
"""Find all 'image-*' directories inside a given test-fixture directory."""
|
||||
result = []
|
||||
for root, dirs, files in os.walk(test_fixture_dir):
|
||||
for dir_name in dirs:
|
||||
if dir_name.startswith('image-'):
|
||||
result.append(os.path.join(root, dir_name))
|
||||
return sorted(result)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_fingerprints()
|
||||
Regular → Executable
+21
-4
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
@@ -56,6 +58,8 @@ def main(changed_files: str | None = None, merge_base_schema_files: str | None =
|
||||
|
||||
pr_json_schema_files = filter_to_schema_files(pr_changed_files)
|
||||
|
||||
pr_labels = get_pr_labels(pr_number)
|
||||
|
||||
# print("schema files in pr: ", summarize_schema_files(pr_json_schema_files))
|
||||
# print("og schema files: ", summarize_schema_files(og_json_schema_files))
|
||||
|
||||
@@ -76,7 +80,8 @@ def main(changed_files: str | None = None, merge_base_schema_files: str | None =
|
||||
add_label(pr_number, JSON_SCHEMA_LABEL)
|
||||
|
||||
else:
|
||||
remove_label(pr_number, JSON_SCHEMA_LABEL)
|
||||
if JSON_SCHEMA_LABEL in pr_labels:
|
||||
remove_label(pr_number, JSON_SCHEMA_LABEL)
|
||||
|
||||
# new schema files should be scrutinized, comparing the latest and added versions to see if it's a breaking
|
||||
# change (major version bump). Warn about it on the PR via adding a breaking-change label...
|
||||
@@ -84,7 +89,8 @@ def main(changed_files: str | None = None, merge_base_schema_files: str | None =
|
||||
print("\nBreaking change detected...")
|
||||
add_label(pr_number, BREAKING_CHANGE_LABEL)
|
||||
else:
|
||||
remove_label(pr_number, BREAKING_CHANGE_LABEL)
|
||||
if BREAKING_CHANGE_LABEL in pr_labels:
|
||||
remove_label(pr_number, BREAKING_CHANGE_LABEL)
|
||||
|
||||
# modifying an existing schema could be a breaking change, we should warn about it on the PR via a comment...
|
||||
# removing schema files should never be allowed, we should warn about it on the PR via a comment...
|
||||
@@ -119,7 +125,7 @@ def add_label(pr_number: str, label: str):
|
||||
# run "gh pr edit --add-label <label>"
|
||||
result = run(f"gh pr edit {pr_number} --add-label {label}", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
if result.returncode != 0:
|
||||
print(f"Unable to add {label!r} label to PR with")
|
||||
print(f"Unable to add '{label!r}' label to PR, error:")
|
||||
print(str(result.stderr))
|
||||
sys.exit(1)
|
||||
|
||||
@@ -128,7 +134,7 @@ def remove_label(pr_number: str, label: str):
|
||||
# run "gh pr edit --remove-label <label>"
|
||||
result = run(f"gh pr edit {pr_number} --remove-label {label}", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
if result.returncode != 0:
|
||||
print(f"Unable to label PR with {label!r}")
|
||||
print(f"Unable to remove '{label!r}' label from PR, error:")
|
||||
print(str(result.stderr))
|
||||
sys.exit(1)
|
||||
|
||||
@@ -165,6 +171,17 @@ def get_pr_changed_files(pr_number: str) -> list[str]:
|
||||
return list_of_files
|
||||
|
||||
|
||||
def get_pr_labels(pr_number: str) -> list[str]:
|
||||
result = run(f"gh pr view {pr_number} --json labels --jq '.labels[].name'", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
if result.returncode != 0:
|
||||
print("Unable to get list of labels on PR")
|
||||
print(str(result.stderr))
|
||||
sys.exit(1)
|
||||
|
||||
list_of_labels = result.stdout.splitlines()
|
||||
return list_of_labels
|
||||
|
||||
|
||||
def filter_to_schema_files(list_of_files: list[str]) -> list[str]:
|
||||
# get files matching "schema/json/schema-*.json"
|
||||
files = []
|
||||
|
||||
Regular → Executable
+2
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
import subprocess
|
||||
|
||||
@@ -4,12 +4,19 @@ set -eu
|
||||
bold=$(tput bold)
|
||||
normal=$(tput sgr0)
|
||||
|
||||
if ! [ -x "$(command -v gh)" ]; then
|
||||
echo "The GitHub CLI could not be found. To continue follow the instructions at https://github.com/cli/cli#installation"
|
||||
GH_CLI=.tool/gh
|
||||
|
||||
if ! [ -x "$(command -v $GH_CLI)" ]; then
|
||||
echo "The GitHub CLI could not be found. run: make bootstrap"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
gh auth status
|
||||
$GH_CLI auth status
|
||||
|
||||
# set the default repo in cases where multiple remotes are defined
|
||||
$GH_CLI repo set-default anchore/syft
|
||||
|
||||
export GITHUB_TOKEN="${GITHUB_TOKEN-"$($GH_CLI auth token)"}"
|
||||
|
||||
# we need all of the git state to determine the next version. Since tagging is done by
|
||||
# the release pipeline it is possible to not have all of the tags from previous releases.
|
||||
@@ -37,7 +44,7 @@ done
|
||||
|
||||
echo "${bold}Kicking off release for ${NEXT_VERSION}${normal}..."
|
||||
echo
|
||||
gh workflow run release.yaml -f version=${NEXT_VERSION}
|
||||
$GH_CLI workflow run release.yaml -f version=${NEXT_VERSION}
|
||||
|
||||
echo
|
||||
echo "${bold}Waiting for release to start...${normal}"
|
||||
@@ -45,6 +52,6 @@ sleep 10
|
||||
|
||||
set +e
|
||||
|
||||
echo "${bold}Head to the release workflow to monitor the release:${normal} $(gh run list --workflow=release.yaml --limit=1 --json url --jq '.[].url')"
|
||||
id=$(gh run list --workflow=release.yaml --limit=1 --json databaseId --jq '.[].databaseId')
|
||||
gh run watch $id --exit-status || (echo ; echo "${bold}Logs of failed step:${normal}" && GH_PAGER="" gh run view $id --log-failed)
|
||||
echo "${bold}Head to the release workflow to monitor the release:${normal} $($GH_CLI run list --workflow=release.yaml --limit=1 --json url --jq '.[].url')"
|
||||
id=$($GH_CLI run list --workflow=release.yaml --limit=1 --json databaseId --jq '.[].databaseId')
|
||||
$GH_CLI run watch $id --exit-status || (echo ; echo "${bold}Logs of failed step:${normal}" && GH_PAGER="" $GH_CLI run view $id --log-failed)
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
set -ue
|
||||
|
||||
BIN="syft"
|
||||
DISTDIR=$1
|
||||
VERSION=$2
|
||||
VERSION_FILE="VERSION"
|
||||
VERSION=$1
|
||||
|
||||
# the source of truth as to whether we want to notify users of an update is if the release just created is NOT
|
||||
# flagged as a pre-release on github
|
||||
@@ -12,10 +12,9 @@ if [[ "$(curl -SsL https://api.github.com/repos/anchore/${BIN}/releases/tags/${V
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "creating and publishing version file"
|
||||
echo "creating and publishing version file (${VERSION})"
|
||||
|
||||
# create a version file for version-update checks
|
||||
VERSION_FILE="${DISTDIR}/VERSION"
|
||||
echo "${VERSION}" | tee "${VERSION_FILE}"
|
||||
|
||||
# upload the version file that supports the application version update check
|
||||
|
||||
@@ -17,13 +17,13 @@ jobs:
|
||||
# the job by event.
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Restore base benchmark result
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 #v4.1.1
|
||||
with:
|
||||
path: test/results/benchmark-main.txt
|
||||
# use base sha for PR or new commit hash for main push in benchmark result key
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
OUTPUT="${OUTPUT//$'\r'/'%0D'}" # URL encode all '\r' characters
|
||||
echo "result=$OUTPUT" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: benchmark-test-results
|
||||
path: test/results/**/*
|
||||
|
||||
@@ -36,16 +36,16 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 #v5.0.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 #v5.0.2
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@4355270be187e1b672a7a1c7c7bae5afdc1ab94a #v3.24.10
|
||||
uses: github/codeql-action/init@f779452ac5af1c261dce0346a8f964149f49322b #v3.26.13
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@4355270be187e1b672a7a1c7c7bae5afdc1ab94a #v3.24.10
|
||||
uses: github/codeql-action/autobuild@f779452ac5af1c261dce0346a8f964149f49322b #v3.26.13
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -70,4 +70,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@4355270be187e1b672a7a1c7c7bae5afdc1ab94a #v3.24.10
|
||||
uses: github/codeql-action/analyze@f779452ac5af1c261dce0346a8f964149f49322b #v3.26.13
|
||||
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
|
||||
- run: python .github/scripts/labeler.py
|
||||
env:
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
name: "Release Homebrew"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types:
|
||||
- released
|
||||
|
||||
jobs:
|
||||
homebrew:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
|
||||
with:
|
||||
# we need to be able to get the commit for a tag
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get release info
|
||||
id: release_info
|
||||
run: |
|
||||
echo -n "tag_name=$(gh release view --json tagName --jq '.tagName')" | tee -a $GITHUB_OUTPUT
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get commit info
|
||||
id: git_info
|
||||
run: |
|
||||
git checkout ${{ steps.release_info.outputs.tag_name }}
|
||||
echo -n "commit=$(git rev-parse HEAD)" | tee -a $GITHUB_OUTPUT
|
||||
|
||||
- name: Update Homebrew formula
|
||||
uses: dawidd6/action-homebrew-bump-formula@baf2b60c51fc1f8453c884b0c61052668a71bd1d # v3.11.0
|
||||
with:
|
||||
token: ${{ secrets.HOMEBREW_TOKEN }}
|
||||
org: anchore
|
||||
formula: syft
|
||||
tag: ${{ steps.release_info.outputs.tag_name }}
|
||||
revision: ${{ steps.git_info.outputs.commit }}
|
||||
|
||||
- uses: 8398a7/action-slack@28ba43ae48961b90635b50953d216767a6bea486 #v3.16.2
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
fields: repo,workflow,action,eventName
|
||||
text: "Post-release homebrew publish workflow has failed: https://github.com/anchore/syft/actions/workflows/release-homebrew.yaml"
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}
|
||||
@@ -0,0 +1,31 @@
|
||||
name: "Release: version file"
|
||||
|
||||
on:
|
||||
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: release version to update the version file with (prefixed with v)
|
||||
required: true
|
||||
|
||||
workflow_call:
|
||||
inputs:
|
||||
version:
|
||||
type: string
|
||||
description: release version to update the version file with (prefixed with v)
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
|
||||
release:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
|
||||
- name: Update version file
|
||||
run: make ci-release-version-file
|
||||
env:
|
||||
RELEASE_VERSION: ${{ github.event.inputs.version }}
|
||||
# for updating the VERSION file in S3...
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.TOOLBOX_AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.TOOLBOX_AWS_SECRET_ACCESS_KEY }}
|
||||
@@ -15,7 +15,15 @@ jobs:
|
||||
environment: release
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
|
||||
- name: Check if running on main
|
||||
if: github.ref != 'refs/heads/main'
|
||||
# we are using the following flag when running `cosign blob-verify` for checksum signature verification:
|
||||
# --certificate-identity-regexp "https://github.com/anchore/.github/workflows/release.yaml@refs/heads/main"
|
||||
# if we are not on the main branch, the signature will not be verifiable since the suffix requires the main branch
|
||||
# at the time of when the OIDC token was issued on the Github Actions runner.
|
||||
run: echo "This can only be run on the main branch otherwise releases produced will not be verifiable with cosign" && exit 1
|
||||
|
||||
- name: Check if tag already exists
|
||||
# note: this will fail if the tag already exists
|
||||
@@ -97,7 +105,7 @@ jobs:
|
||||
# required for goreleaser signs section with cosign
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -105,13 +113,13 @@ jobs:
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 #v3.1.0
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 #v3.3.0
|
||||
with:
|
||||
username: ${{ secrets.ANCHOREOSSWRITE_DH_USERNAME }}
|
||||
password: ${{ secrets.ANCHOREOSSWRITE_DH_PAT }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 #v3.1.0
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 #v3.3.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
@@ -139,11 +147,8 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# for updating brew formula in anchore/homebrew-syft
|
||||
GITHUB_BREW_TOKEN: ${{ secrets.ANCHOREOPS_GITHUB_OSS_WRITE_TOKEN }}
|
||||
# for updating the VERSION file in S3...
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.TOOLBOX_AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.TOOLBOX_AWS_SECRET_ACCESS_KEY }}
|
||||
|
||||
- uses: anchore/sbom-action@ab5d7b5f48981941c4c5d6bf33aeb98fe3bae38c #v0.15.10
|
||||
- uses: anchore/sbom-action@8d0a6505bf28ced3e85154d13dc6af83299e13f1 #v0.17.4
|
||||
continue-on-error: true
|
||||
with:
|
||||
artifact-name: sbom.spdx.json
|
||||
@@ -157,3 +162,10 @@ jobs:
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}
|
||||
if: ${{ success() }}
|
||||
|
||||
release-version-file:
|
||||
needs: [release]
|
||||
uses: ./.github/workflows/release-version-file.yaml
|
||||
with:
|
||||
version: ${{ github.event.inputs.version }}
|
||||
secrets: inherit
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
name: "Manage Awaiting Response Label"
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
run:
|
||||
uses: "anchore/workflows/.github/workflows/remove-awaiting-response-label.yaml@main"
|
||||
secrets:
|
||||
token: ${{ secrets.OSS_PROJECT_GH_TOKEN }}
|
||||
@@ -0,0 +1,39 @@
|
||||
name: "Test fixture cache: publish"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# run nightly at 4AM UTC
|
||||
- cron: "0 4 * * *"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
|
||||
Publish:
|
||||
name: "Publish test fixture image cache"
|
||||
# we use this runner to get enough storage space for docker images and fixture cache
|
||||
runs-on: ubuntu-22.04-4core-16gb
|
||||
permissions:
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
with:
|
||||
# we want to rebuild the cache with no previous state
|
||||
download-test-fixture-cache: false
|
||||
|
||||
- name: Run all tests
|
||||
run: make test
|
||||
env:
|
||||
# we want to rebuild the cache with no previous state
|
||||
DOWNLOAD_TEST_FIXTURE_CACHE: "false"
|
||||
|
||||
- name: Login to GitHub Container Registry (ORAS)
|
||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | .tool/oras login ghcr.io -u ${{ github.actor }} --password-stdin
|
||||
|
||||
- name: Publish test fixture cache
|
||||
run: make upload-test-fixture-cache
|
||||
@@ -13,13 +13,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'anchore/syft' # only run for main repo
|
||||
steps:
|
||||
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
with:
|
||||
bootstrap-apt-packages: ""
|
||||
compute-fingerprints: "false"
|
||||
go-dependencies: false
|
||||
|
||||
- name: "Update tool versions"
|
||||
@@ -50,7 +49,7 @@ jobs:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@70a41aba780001da0a30141984ae2a0c95d8704e #v6.0.2
|
||||
- uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f #v7.0.5
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'anchore/syft' # only run for main repo
|
||||
steps:
|
||||
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@70a41aba780001da0a30141984ae2a0c95d8704e #v6.0.2
|
||||
- uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f #v7.0.5
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
|
||||
@@ -17,9 +17,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'anchore/syft' # only run for main repo
|
||||
steps:
|
||||
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
|
||||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 #v5.0.0
|
||||
- uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 #v5.0.2
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
stable: ${{ env.GO_STABLE_VERSION }}
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@70a41aba780001da0a30141984ae2a0c95d8704e #v6.0.2
|
||||
- uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f #v7.0.5
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
name: "Static analysis"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
@@ -31,52 +31,12 @@ jobs:
|
||||
name: "Unit tests"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Restore file executable test-fixture cache
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
with:
|
||||
path: syft/file/cataloger/executable/test-fixtures/elf/bin
|
||||
key: ${{ runner.os }}-unit-file-executable-elf-cache-${{ hashFiles( 'syft/file/cataloger/executable/test-fixtures/elf/cache.fingerprint' ) }}
|
||||
|
||||
- name: Restore file executable shared-info test-fixture cache
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
with:
|
||||
path: syft/file/cataloger/executable/test-fixtures/shared-info/bin
|
||||
key: ${{ runner.os }}-unit-file-executable-shared-info-cache-${{ hashFiles( 'syft/file/cataloger/executable/test-fixtures/shared-info/cache.fingerprint' ) }}
|
||||
|
||||
- name: Restore Java test-fixture cache
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
with:
|
||||
path: syft/pkg/cataloger/java/test-fixtures/java-builds/packages
|
||||
key: ${{ runner.os }}-unit-java-cache-${{ hashFiles( 'syft/pkg/cataloger/java/test-fixtures/java-builds/cache.fingerprint' ) }}
|
||||
|
||||
- name: Restore RPM test-fixture cache
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
with:
|
||||
path: syft/pkg/cataloger/redhat/test-fixtures/rpms
|
||||
key: ${{ runner.os }}-unit-rpm-cache-${{ hashFiles( 'syft/pkg/cataloger/redhat/test-fixtures/rpms.fingerprint' ) }}
|
||||
|
||||
- name: Restore go binary test-fixture cache
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
with:
|
||||
path: syft/pkg/cataloger/golang/test-fixtures/archs/binaries
|
||||
key: ${{ runner.os }}-unit-go-binaries-cache-${{ hashFiles( 'syft/pkg/cataloger/golang/test-fixtures/archs/binaries.fingerprint' ) }}
|
||||
|
||||
- name: Restore binary cataloger test-fixture cache
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
with:
|
||||
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' ) }}
|
||||
|
||||
- name: Restore Kernel test-fixture cache
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
with:
|
||||
path: syft/pkg/cataloger/kernel/test-fixtures/cache
|
||||
key: ${{ runner.os }}-unit-kernel-cache-${{ hashFiles( 'syft/pkg/cataloger/kernel/test-fixtures/cache.fingerprint' ) }}
|
||||
download-test-fixture-cache: true
|
||||
|
||||
- name: Run unit tests
|
||||
run: make unit
|
||||
@@ -87,20 +47,16 @@ jobs:
|
||||
name: "Integration tests"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
with:
|
||||
download-test-fixture-cache: true
|
||||
|
||||
- name: Validate syft output against the CycloneDX schema
|
||||
run: make validate-cyclonedx-schema
|
||||
|
||||
- name: Restore integration test cache
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
with:
|
||||
path: ${{ github.workspace }}/cmd/syft/internal/test/integration/test-fixtures/cache
|
||||
key: ${{ runner.os }}-integration-test-cache-${{ hashFiles('/cmd/syft/internal/test/integration/test-fixtures/cache.fingerprint') }}
|
||||
|
||||
- name: Run integration tests
|
||||
run: make integration
|
||||
|
||||
@@ -109,7 +65,7 @@ jobs:
|
||||
name: "Build snapshot artifacts"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
@@ -122,7 +78,7 @@ jobs:
|
||||
# why not use actions/upload-artifact? It is very slow (3 minutes to upload ~600MB of data, vs 10 seconds with this approach).
|
||||
# see https://github.com/actions/upload-artifact/issues/199 for more info
|
||||
- name: Upload snapshot artifacts
|
||||
uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
uses: actions/cache/save@3624ceb22c1c5a301c8db4169662070a689d9ea8 #v4.1.1
|
||||
with:
|
||||
# we need to preserve the snapshot data itself as well as the task data that confirms if the
|
||||
# snapshot build is stale or not. Otherwise the downstream jobs will attempt to rebuild the snapshot
|
||||
@@ -139,14 +95,16 @@ jobs:
|
||||
needs: [Build-Snapshot-Artifacts]
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
with:
|
||||
download-test-fixture-cache: true
|
||||
|
||||
- name: Download snapshot build
|
||||
id: snapshot-cache
|
||||
uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
uses: actions/cache/restore@3624ceb22c1c5a301c8db4169662070a689d9ea8 #v4.1.1
|
||||
with:
|
||||
path: |
|
||||
snapshot
|
||||
@@ -162,13 +120,6 @@ jobs:
|
||||
- name: Run comparison tests (Linux)
|
||||
run: make compare-linux
|
||||
|
||||
- name: Restore install.sh test image cache
|
||||
id: install-test-image-cache
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
with:
|
||||
path: ${{ github.workspace }}/test/install/cache
|
||||
key: ${{ runner.os }}-install-test-image-cache-${{ hashFiles('test/install/cache.fingerprint') }}
|
||||
|
||||
- name: Load test image cache
|
||||
if: steps.install-test-image-cache.outputs.cache-hit == 'true'
|
||||
run: make install-test-cache-load
|
||||
@@ -187,19 +138,21 @@ jobs:
|
||||
needs: [Build-Snapshot-Artifacts]
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
|
||||
- name: Install Cosign
|
||||
uses: sigstore/cosign-installer@v3.7.0
|
||||
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
with:
|
||||
bootstrap-apt-packages: ""
|
||||
compute-fingerprints: "false"
|
||||
go-dependencies: false
|
||||
go-version: ""
|
||||
download-test-fixture-cache: true
|
||||
|
||||
- name: Download snapshot build
|
||||
id: snapshot-cache
|
||||
uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
uses: actions/cache/restore@3624ceb22c1c5a301c8db4169662070a689d9ea8 #v4.1.1
|
||||
with:
|
||||
path: |
|
||||
snapshot
|
||||
@@ -212,13 +165,6 @@ jobs:
|
||||
if: steps.snapshot-cache.outputs.cache-hit != 'true'
|
||||
run: echo "unable to download snapshots from previous job" && false
|
||||
|
||||
- name: Restore docker image cache for compare testing
|
||||
id: mac-compare-testing-cache
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
with:
|
||||
path: image.tar
|
||||
key: ${{ runner.os }}-${{ hashFiles('test/compare/mac.sh') }}
|
||||
|
||||
- name: Run comparison tests (Mac)
|
||||
run: make compare-mac
|
||||
|
||||
@@ -232,20 +178,16 @@ jobs:
|
||||
needs: [Build-Snapshot-Artifacts]
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 #v4.1.2
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Restore CLI test-fixture cache
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
with:
|
||||
path: ${{ github.workspace }}/test/cli/test-fixtures/cache
|
||||
key: ${{ runner.os }}-cli-test-cache-${{ hashFiles('test/cli/test-fixtures/cache.fingerprint') }}
|
||||
download-test-fixture-cache: true
|
||||
|
||||
- name: Download snapshot build
|
||||
id: snapshot-cache
|
||||
uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
uses: actions/cache/restore@3624ceb22c1c5a301c8db4169662070a689d9ea8 #v4.1.1
|
||||
with:
|
||||
path: |
|
||||
snapshot
|
||||
@@ -260,3 +202,22 @@ jobs:
|
||||
|
||||
- name: Run CLI Tests (Linux)
|
||||
run: make cli
|
||||
|
||||
|
||||
Cleanup-Cache:
|
||||
name: "Cleanup snapshot cache"
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
actions: write
|
||||
needs:
|
||||
- Acceptance-Linux
|
||||
- Acceptance-Mac
|
||||
- Cli-Linux
|
||||
steps:
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 #v4.2.1
|
||||
|
||||
- name: Delete snapshot cache
|
||||
run: gh cache delete "snapshot-build-${{ github.run_id }}"
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
||||
+13
-2
@@ -12,10 +12,10 @@ linters:
|
||||
enable:
|
||||
- asciicheck
|
||||
- bodyclose
|
||||
- copyloopvar
|
||||
- dogsled
|
||||
- dupl
|
||||
- errcheck
|
||||
- exportloopref
|
||||
- funlen
|
||||
- gocognit
|
||||
- goconst
|
||||
@@ -30,6 +30,7 @@ linters:
|
||||
- ineffassign
|
||||
- misspell
|
||||
- nakedret
|
||||
- nolintlint
|
||||
- revive
|
||||
- staticcheck
|
||||
- stylecheck
|
||||
@@ -49,10 +50,21 @@ linters-settings:
|
||||
# If lower than 0, disable the check.
|
||||
# Default: 40
|
||||
statements: 50
|
||||
gocritic:
|
||||
enabled-checks:
|
||||
- deferInLoop
|
||||
- ruleguard
|
||||
settings:
|
||||
ruleguard:
|
||||
rules: "test/rules/rules.go"
|
||||
gosec:
|
||||
excludes:
|
||||
- G115
|
||||
output:
|
||||
uniq-by-line: false
|
||||
run:
|
||||
timeout: 10m
|
||||
tests: false
|
||||
|
||||
# do not enable...
|
||||
# - deadcode # The owner seems to have abandoned the linter. Replaced by "unused".
|
||||
@@ -72,7 +84,6 @@ run:
|
||||
# - lll # without a way to specify per-line exception cases, this is not usable
|
||||
# - maligned # this is an excellent linter, but tricky to optimize and we are not sensitive to memory layout optimizations
|
||||
# - nestif
|
||||
# - nolintlint # as of go1.19 this conflicts with the behavior of gofmt, which is a deal-breaker (lint-fix will still fail when running lint)
|
||||
# - prealloc # following this rule isn't consistently a good idea, as it sometimes forces unnecessary allocations that result in less idiomatic code
|
||||
# - rowserrcheck # not in a repo with sql, so this is not useful
|
||||
# - scopelint # deprecated
|
||||
|
||||
+3
-1
@@ -1,3 +1,5 @@
|
||||
version: 2
|
||||
|
||||
release:
|
||||
prerelease: auto
|
||||
draft: false
|
||||
@@ -80,7 +82,7 @@ nfpms:
|
||||
- deb
|
||||
|
||||
brews:
|
||||
- tap:
|
||||
- repository:
|
||||
owner: anchore
|
||||
name: homebrew-syft
|
||||
token: "{{.Env.GITHUB_BREW_TOKEN}}"
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
[opensource@anchore.com](mailto:opensource@anchore.com).
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
+2
-2
@@ -83,7 +83,7 @@ Syft's core library is implemented in the `syft` package and subpackages, where
|
||||
- the `syft` package contains a single function that can take a `source.Source` object and catalog it, producing an `sbom.SBOM` object
|
||||
- the `syft/format` package contains the ability to encode and decode SBOMs to and from different SBOM formats (such as SPDX and CycloneDX)
|
||||
|
||||
The `cmd` pacakge at the highest level execution flow wires up [`spf13/cobra`](https://github.com/spf13/cobra) commands for execution in the main application:
|
||||
The `cmd` package at the highest level execution flow wires up [`spf13/cobra`](https://github.com/spf13/cobra) commands for execution in the main application:
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant main as cmd/syft/main
|
||||
@@ -212,7 +212,7 @@ Finally, here is an example of where the package construction is done within the
|
||||
- [The APK package constructor itself](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/apkdb/package.go#L12-L27)
|
||||
|
||||
Interested in building a new cataloger? Checkout the [list of issues with the `new-cataloger` label](https://github.com/anchore/syft/issues?q=is%3Aopen+is%3Aissue+label%3Anew-cataloger+no%3Aassignee)!
|
||||
If you have questions about implementing a cataloger feel free to file an issue or reach out to us [on slack](https://anchore.com/slack)!
|
||||
If you have questions about implementing a cataloger feel free to file an issue or reach out to us [on discourse](https://anchore.com/discourse)!
|
||||
|
||||
|
||||
#### Searching for files
|
||||
|
||||
@@ -25,8 +25,8 @@ ci-bootstrap-go:
|
||||
|
||||
# this is a bootstrapping catch-all, where if the target doesn't exist, we'll ensure the tools are installed and then try again
|
||||
%:
|
||||
make $(TASK)
|
||||
$(TASK) $@
|
||||
@make --silent $(TASK)
|
||||
@$(TASK) $@
|
||||
|
||||
## Shim targets #################################
|
||||
|
||||
|
||||
@@ -2,25 +2,28 @@
|
||||
<img src="https://user-images.githubusercontent.com/5199289/136844524-1527b09f-c5cb-4aa9-be54-5aa92a6086c1.png" width="271" alt="Cute pink owl syft logo">
|
||||
</p>
|
||||
|
||||
[](https://github.com/anchore/syft/actions/workflows/validations.yaml)
|
||||
[](https://goreportcard.com/report/github.com/anchore/syft)
|
||||
[](https://github.com/anchore/syft/releases/latest)
|
||||
[](https://github.com/anchore/syft)
|
||||
[](https://github.com/anchore/syft/blob/main/LICENSE)
|
||||
[](https://anchore.com/slack)
|
||||
# Syft
|
||||
|
||||
A CLI tool and Go library for generating a Software Bill of Materials (SBOM) from container images and filesystems. Exceptional for vulnerability detection when used with a scanner like [Grype](https://github.com/anchore/grype).
|
||||
**A CLI tool and Go library for generating a Software Bill of Materials (SBOM) from container images and filesystems. Exceptional for vulnerability detection when used with a scanner like [Grype](https://github.com/anchore/grype).**
|
||||
|
||||
### Join our community meetings!
|
||||
|
||||
- Calendar: https://calendar.google.com/calendar/u/0/r?cid=Y182OTM4dGt0MjRtajI0NnNzOThiaGtnM29qNEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t
|
||||
- Agenda: https://docs.google.com/document/d/1ZtSAa6fj2a6KRWviTn3WoJm09edvrNUp4Iz_dOjjyY8/edit?usp=sharing (join [this group](https://groups.google.com/g/anchore-oss-community) for write access)
|
||||
- All are welcome!
|
||||
|
||||
For commercial support options with Syft or Grype, please [contact Anchore](https://get.anchore.com/contact/)
|
||||
<p align="center">
|
||||
<a href="https://github.com/anchore/syft/actions/workflows/validations.yaml" target="_blank"><img alt="Validations" src="https://github.com/anchore/syft/actions/workflows/validations.yaml/badge.svg"></a>
|
||||
<a href="https://goreportcard.com/report/github.com/anchore/syft" target="_blank"><img alt="Go Report Card" src="https://goreportcard.com/badge/github.com/anchore/syft"></a>
|
||||
<a href="https://github.com/anchore/syft/releases/latest" target="_blank"><img alt="GitHub release" src="https://img.shields.io/github/release/anchore/syft.svg"></a>
|
||||
<a href="https://github.com/anchore/syft" target="_blank"><img alt="GitHub go.mod Go version" src="https://img.shields.io/github/go-mod/go-version/anchore/syft.svg"></a>
|
||||
<a href="" target="_blank"><img alt="License: Apache-2.0" src="https://img.shields.io/badge/License-Apache%202.0-blue.svg"></a>
|
||||
<a href="https://anchore.com/discourse" target="_blank"><img alt="Join our Discourse" src="https://img.shields.io/badge/Discourse-Join-blue?logo=discourse"/></a>
|
||||
<a rel="me" href="https://fosstodon.org/@syft"><img alt="Follow on Mastodon" src="https://img.shields.io/badge/Mastodon-Follow-blue?logoColor=white&logo=mastodon"/></a>
|
||||
</p>
|
||||
|
||||

|
||||
|
||||
## Introduction
|
||||
|
||||
Syft is a powerful and easy-to-use open-source tool for generating Software Bill of Materials (SBOMs) for container images and filesystems. It provides detailed visibility into the packages and dependencies in your software, helping you manage vulnerabilities, license compliance, and software supply chain security.
|
||||
|
||||
Syft development is sponsored by [Anchore](https://anchore.com/), and is released under the [Apache-2.0 License](https://github.com/anchore/syft?tab=Apache-2.0-1-ov-file). For commercial support options with Syft or Grype, please [contact Anchore](https://get.anchore.com/contact/).
|
||||
|
||||
## Features
|
||||
- Generates SBOMs for container images, filesystems, archives, and more to discover packages and libraries
|
||||
- Supports OCI, Docker and [Singularity](https://github.com/sylabs/singularity) image formats
|
||||
@@ -29,6 +32,94 @@ For commercial support options with Syft or Grype, please [contact Anchore](http
|
||||
- Able to create signed SBOM attestations using the [in-toto specification](https://github.com/in-toto/attestation/blob/main/spec/README.md)
|
||||
- Convert between SBOM formats, such as CycloneDX, SPDX, and Syft's own format.
|
||||
|
||||
## Installation
|
||||
|
||||
Syft binaries are provided for Linux, macOS and Windows.
|
||||
|
||||
### Recommended
|
||||
> ```bash
|
||||
> curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
|
||||
> ```
|
||||
|
||||
Install script options:
|
||||
- `-b`: Specify a custom installation directory (defaults to `./bin`)
|
||||
- `-d`: More verbose logging levels (`-d` for debug, `-dd` for trace)
|
||||
- `-v`: Verify the signature of the downloaded artifact before installation (requires [`cosign`](https://github.com/sigstore/cosign) to be installed)
|
||||
|
||||
### Homebrew
|
||||
```bash
|
||||
brew install syft
|
||||
```
|
||||
|
||||
### Scoop
|
||||
|
||||
```powershell
|
||||
scoop install syft
|
||||
```
|
||||
|
||||
### Chocolatey
|
||||
|
||||
The chocolatey distribution of Syft is community-maintained and not distributed by the Anchore team
|
||||
|
||||
```powershell
|
||||
choco install syft -y
|
||||
```
|
||||
|
||||
### Nix
|
||||
|
||||
**Note**: Nix packaging of Syft is [community maintained](https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/admin/syft/default.nix). Syft is available in the [stable channel](https://wiki.nixos.org/wiki/Nix_channels#The_official_channels) since NixOS `22.05`.
|
||||
|
||||
```bash
|
||||
nix-env -i syft
|
||||
```
|
||||
|
||||
... or, just try it out in an ephemeral nix shell:
|
||||
|
||||
```bash
|
||||
nix-shell -p syft
|
||||
```
|
||||
|
||||
## Getting started
|
||||
|
||||
### SBOM
|
||||
|
||||
To generate an SBOM for a container image:
|
||||
|
||||
```bash
|
||||
syft <image>
|
||||
```
|
||||
|
||||
The above output includes only software that is visible in the container (i.e., the squashed representation of the image). To include software from all image layers in the SBOM, regardless of its presence in the final image, provide `--scope all-layers`:
|
||||
|
||||
```bash
|
||||
syft <image> --scope all-layers
|
||||
```
|
||||
|
||||
### Output formats
|
||||
|
||||
The output format for Syft is configurable as well using the `-o` (or `--output`) option:
|
||||
|
||||
```
|
||||
syft <image> -o <format>
|
||||
```
|
||||
|
||||
Where the `formats` available are:
|
||||
- `syft-json`: Use this to get as much information out of Syft as possible!
|
||||
- `syft-text`: A row-oriented, human-and-machine-friendly output.
|
||||
- `cyclonedx-xml`: A XML report conforming to the [CycloneDX 1.6 specification](https://cyclonedx.org/specification/overview/).
|
||||
- `cyclonedx-xml@1.5`: A XML report conforming to the [CycloneDX 1.5 specification](https://cyclonedx.org/specification/overview/).
|
||||
- `cyclonedx-json`: A JSON report conforming to the [CycloneDX 1.6 specification](https://cyclonedx.org/specification/overview/).
|
||||
- `cyclonedx-json@1.5`: A JSON report conforming to the [CycloneDX 1.5 specification](https://cyclonedx.org/specification/overview/).
|
||||
- `spdx-tag-value`: A tag-value formatted report conforming to the [SPDX 2.3 specification](https://spdx.github.io/spdx-spec/v2.3/).
|
||||
- `spdx-tag-value@2.2`: A tag-value formatted report conforming to the [SPDX 2.2 specification](https://spdx.github.io/spdx-spec/v2.2.2/).
|
||||
- `spdx-json`: A JSON report conforming to the [SPDX 2.3 JSON Schema](https://github.com/spdx/spdx-spec/blob/v2.3/schemas/spdx-schema.json).
|
||||
- `spdx-json@2.2`: A JSON report conforming to the [SPDX 2.2 JSON Schema](https://github.com/spdx/spdx-spec/blob/v2.2/schemas/spdx-schema.json).
|
||||
- `github-json`: A JSON report conforming to GitHub's dependency snapshot format.
|
||||
- `syft-table`: A columnar summary (default).
|
||||
- `template`: Lets the user specify the output format. See ["Using templates"](#using-templates) below.
|
||||
|
||||
Note that flags using the @<version> can be used for earlier versions of each specification as well.
|
||||
|
||||
### Supported Ecosystems
|
||||
|
||||
- Alpine (apk)
|
||||
@@ -56,816 +147,35 @@ For commercial support options with Syft or Grype, please [contact Anchore](http
|
||||
- Swift (cocoapods, swift-package-manager)
|
||||
- Wordpress plugins
|
||||
|
||||
## Installation
|
||||
|
||||
**Note**: Currently, Syft is built only for Linux, macOS and Windows.
|
||||
|
||||
### Recommended
|
||||
```bash
|
||||
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
|
||||
```
|
||||
|
||||
... or, you can specify a release version and destination directory for the installation:
|
||||
|
||||
```
|
||||
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b <DESTINATION_DIR> <RELEASE_VERSION>
|
||||
```
|
||||
|
||||
### Chocolatey
|
||||
|
||||
The chocolatey distribution of syft is community maintained and not distributed by the anchore team
|
||||
|
||||
```powershell
|
||||
choco install syft -y
|
||||
```
|
||||
|
||||
### Scoop
|
||||
|
||||
```powershell
|
||||
scoop install syft
|
||||
```
|
||||
|
||||
### Homebrew
|
||||
```bash
|
||||
brew install syft
|
||||
```
|
||||
|
||||
### Nix
|
||||
|
||||
**Note**: Nix packaging of Syft is [community maintained](https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/admin/syft/default.nix). Syft is available in the [stable channel](https://nixos.wiki/wiki/Nix_channels#The_official_channels) since NixOS `22.05`.
|
||||
|
||||
```bash
|
||||
nix-env -i syft
|
||||
```
|
||||
|
||||
... or, just try it out in an ephemeral nix shell:
|
||||
|
||||
```bash
|
||||
nix-shell -p syft
|
||||
```
|
||||
|
||||
## Getting started
|
||||
|
||||
### SBOM
|
||||
|
||||
To generate an SBOM for a container image:
|
||||
|
||||
```bash
|
||||
syft <image>
|
||||
```
|
||||
|
||||
The above output includes only software that is visible in the container (i.e., the squashed representation of the image). To include software from all image layers in the SBOM, regardless of its presence in the final image, provide `--scope all-layers`:
|
||||
|
||||
```bash
|
||||
syft <image> --scope all-layers
|
||||
```
|
||||
|
||||
### Supported sources
|
||||
|
||||
Syft can generate an SBOM from a variety of sources including images, files, directories, and archives. Syft will attempt to
|
||||
determine the type of source based on provided input, for example:
|
||||
|
||||
```bash
|
||||
# catalog a container image archive (from the result of `docker image save ...`, `podman save ...`, or `skopeo copy` commands)
|
||||
syft path/to/image.tar
|
||||
|
||||
# catalog a Singularity Image Format (SIF) container
|
||||
syft path/to/image.sif
|
||||
|
||||
# catalog a directory
|
||||
syft path/to/dir
|
||||
```
|
||||
|
||||
To explicitly specify the source behavior, use the `--from` flag. Allowable options are:
|
||||
|
||||
```
|
||||
docker use images from the Docker daemon
|
||||
podman use images from the Podman daemon
|
||||
containerd use images from the Containerd daemon
|
||||
docker-archive use a tarball from disk for archives created from "docker save"
|
||||
oci-archive use a tarball from disk for OCI archives (from Skopeo or otherwise)
|
||||
oci-dir read directly from a path on disk for OCI layout directories (from Skopeo or otherwise)
|
||||
singularity read directly from a Singularity Image Format (SIF) container on disk
|
||||
dir read directly from a path on disk (any directory)
|
||||
file read directly from a path on disk (any single file)
|
||||
registry pull image directly from a registry (no container runtime required)
|
||||
```
|
||||
If a source is not provided and Syft identifies the input as a potential image reference, Syft will attempt to resolve it using:
|
||||
the Docker, Podman, and Containerd daemons followed by direct registry access, in that order.
|
||||
|
||||
This default behavior can be overridden with the `default-image-pull-source` configuration option (See [Configuration](#configuration) for more details).
|
||||
|
||||
|
||||
### File selection
|
||||
|
||||
By default, Syft will catalog file details and digests for files that are owned by discovered packages. You can change this behavior by using the `SYFT_FILE_METADATA_SELECTION` environment variable or the `file.metadata.selection` configuration option. The options are:
|
||||
|
||||
- `all`: capture all files from the search space
|
||||
- `owned-by-package`: capture only files owned by packages (default)
|
||||
- `none`: disable capturing any file information
|
||||
|
||||
|
||||
### Package cataloger selection
|
||||
|
||||
#### Concepts
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Syft uses a different set of catalogers by default when scanning files directly than it does when scanning images
|
||||
|
||||
The catalogers for an image scan assumes that package installation steps have already been completed. For example, Syft will identify Python packages that have egg or wheel metadata files under a `site-packages` directory, since this is how the canonical tooling `pip` installs python packages.
|
||||
|
||||
The catalogers for a directory scan will look for installed software as well as declared dependencies that are not necessarily installed. For example, dependencies listed in a Python `requirements.txt`.
|
||||
|
||||
This default set of catalogers being dynamic is critical as this allows Syft to be used in a variety of contexts while still generating accurate SBOMs.
|
||||
Overriding the set of default catalogers is not recommended for most purposes, however, is possible if needed.
|
||||
|
||||
Catalogers can be referenced in two different ways:
|
||||
- *by name*: the exact cataloger name (e.g. `java-pom-cataloger` or `java-archive-cataloger`)
|
||||
- *by tag*: a tag that is associated with a cataloger (e.g. `java`)
|
||||
|
||||
Syft can take lists of references on the CLI or in the application configuration to define which catalogers to use.
|
||||
|
||||
You can **set** the list of catalogers explicitly to use with the `--override-default-catalogers` CLI flag, accepting a comma-separated list of cataloger names or tags.
|
||||
|
||||
You can also **add** to, **remove** from, or **sub-select** catalogers to use within the default set of catalogers by using the `--select-catalogers` CLI flag.
|
||||
- To **sub-select** catalogers simply provide a tag (e.g. `--select-catalogers TAG`). Catalogers will always be selected from the default set of catalogers (e.g. `--select-catalogers java,go` will select all the `java` catalogers in the default set and all the `go` catalogers in the default set).
|
||||
- To **add** a cataloger prefix the cataloger name with `+` (e.g. `--select-catalogers +NAME`). Added catalogers will _always be added_ regardless of removals, filtering, or other defaults.
|
||||
- To **remove** a cataloger prefix the cataloger name or tag with `-` (e.g. `--select-catalogers -NAME_OR_TAG`). Catalogers are removed from the set of default catalogers after processing any sub-selections.
|
||||
|
||||
These rules and the dynamic default cataloger sets approximates to the following logic:
|
||||
|
||||
```
|
||||
image_catalogers = all_catalogers AND catalogers_tagged("image")
|
||||
|
||||
directory_catalogers = all_catalogers AND catalogers_tagged("directory")
|
||||
|
||||
default_catalogers = image_catalogers OR directory_catalogers
|
||||
|
||||
sub_selected_catalogers = default_catalogers INTERSECT catalogers_tagged(TAG) [ UNION sub_selected_catalogers ... ]
|
||||
|
||||
base_catalogers = default_catalogers OR sub_selected_catalogers
|
||||
|
||||
final_set = (base_catalogers SUBTRACT removed_catalogers) UNION added_catalogers
|
||||
```
|
||||
|
||||
|
||||
#### Examples
|
||||
|
||||
Only scan for python related packages with catalogers appropriate for the source type (image or directory):
|
||||
```bash
|
||||
syft <some container image> --select-catalogers "python"
|
||||
# results in the following catalogers being used:
|
||||
# - python-installed-package-cataloger
|
||||
```
|
||||
|
||||
Same command, but the set of catalogers changes based on what is being analyzed (in this case a directory):
|
||||
```bash
|
||||
syft <a directory> --select-catalogers "python"
|
||||
# results in the following catalogers being used:
|
||||
# - python-installed-package-cataloger
|
||||
# - python-package-cataloger
|
||||
```
|
||||
|
||||
Use the default set of catalogers and add a cataloger to the set:
|
||||
```bash
|
||||
syft ... --select-catalogers "+sbom-cataloger"
|
||||
```
|
||||
|
||||
Use the default set of catalogers but remove any catalogers that deal with RPMs:
|
||||
```bash
|
||||
syft ... --select-catalogers "-rpm"
|
||||
```
|
||||
|
||||
Only scan with catalogers that:
|
||||
- are tagged with "go"
|
||||
- always use the sbom-cataloger
|
||||
- are appropriate for the source type (image or directory)
|
||||
|
||||
```bash
|
||||
syft <some container image> --select-catalogers "go,+sbom-cataloger"
|
||||
# results in the following catalogers being used:
|
||||
# - go-module-binary-cataloger
|
||||
# - sbom-cataloger
|
||||
```
|
||||
|
||||
Scan with all catalogers that deal with binary analysis, regardless of the source type:
|
||||
```bash
|
||||
syft ... --override-default-catalogers "binary"
|
||||
# results in the following catalogers being used:
|
||||
# - binary-cataloger
|
||||
# - cargo-auditable-binary-cataloger
|
||||
# - dotnet-portable-executable-cataloger
|
||||
# - go-module-binary-cataloger
|
||||
```
|
||||
|
||||
Only scan with the specific `go-module-binary-cataloger` and `go-module-file-cataloger` catalogers:
|
||||
```bash
|
||||
syft ... --override-default-catalogers "go-module-binary-cataloger,go-module-file-cataloger"
|
||||
```
|
||||
|
||||
|
||||
### Excluding file paths
|
||||
|
||||
Syft can exclude files and paths from being scanned within a source by using glob expressions
|
||||
with one or more `--exclude` parameters:
|
||||
```
|
||||
syft <source> --exclude './out/**/*.json' --exclude /etc
|
||||
```
|
||||
**Note:** in the case of _image scanning_, since the entire filesystem is scanned it is
|
||||
possible to use absolute paths like `/etc` or `/usr/**/*.txt` whereas _directory scans_
|
||||
exclude files _relative to the specified directory_. For example: scanning `/usr/foo` with
|
||||
`--exclude ./package.json` would exclude `/usr/foo/package.json` and `--exclude '**/package.json'`
|
||||
would exclude all `package.json` files under `/usr/foo`. For _directory scans_,
|
||||
it is required to begin path expressions with `./`, `*/`, or `**/`, all of which
|
||||
will be resolved _relative to the specified scan directory_. Keep in mind, your shell
|
||||
may attempt to expand wildcards, so put those parameters in single quotes, like:
|
||||
`'**/*.json'`.
|
||||
|
||||
### Output formats
|
||||
|
||||
The output format for Syft is configurable as well using the
|
||||
`-o` (or `--output`) option:
|
||||
|
||||
```
|
||||
syft <image> -o <format>
|
||||
```
|
||||
|
||||
Where the `formats` available are:
|
||||
- `syft-json`: Use this to get as much information out of Syft as possible!
|
||||
- `syft-text`: A row-oriented, human-and-machine-friendly output.
|
||||
- `cyclonedx-xml`: A XML report conforming to the [CycloneDX 1.4 specification](https://cyclonedx.org/specification/overview/).
|
||||
- `cyclonedx-json`: A JSON report conforming to the [CycloneDX 1.4 specification](https://cyclonedx.org/specification/overview/).
|
||||
- `spdx-tag-value`: A tag-value formatted report conforming to the [SPDX 2.3 specification](https://spdx.github.io/spdx-spec/v2.3/).
|
||||
- `spdx-tag-value@2.2`: A tag-value formatted report conforming to the [SPDX 2.2 specification](https://spdx.github.io/spdx-spec/v2.2.2/).
|
||||
- `spdx-json`: A JSON report conforming to the [SPDX 2.3 JSON Schema](https://github.com/spdx/spdx-spec/blob/v2.3/schemas/spdx-schema.json).
|
||||
- `spdx-json@2.2`: A JSON report conforming to the [SPDX 2.2 JSON Schema](https://github.com/spdx/spdx-spec/blob/v2.2/schemas/spdx-schema.json).
|
||||
- `github-json`: A JSON report conforming to GitHub's dependency snapshot format.
|
||||
- `syft-table`: A columnar summary (default).
|
||||
- `template`: Lets the user specify the output format. See ["Using templates"](#using-templates) below.
|
||||
|
||||
## Using templates
|
||||
|
||||
Syft lets you define custom output formats, using [Go templates](https://pkg.go.dev/text/template) relative to the Syft JSON output. Here's how it works:
|
||||
|
||||
- Define your format as a Go template, and save this template as a file.
|
||||
|
||||
- Set the output format to "template" (`-o template`).
|
||||
|
||||
- Specify the path to the template file (`-t ./path/to/custom.template`).
|
||||
|
||||
- Syft's template processing uses the same data models as the `syft-json` output format — so if you're wondering what data is available as you author a template, you can use the output from `syft <image> -o syft-json` as a reference.
|
||||
|
||||
**Example:** You could make Syft output data in CSV format by writing a Go template that renders CSV data and then running `syft <image> -o template -t ~/path/to/csv.tmpl`.
|
||||
|
||||
Here's what the `csv.tmpl` file might look like:
|
||||
```gotemplate
|
||||
"Package","Version Installed", "Found by"
|
||||
{{- range .artifacts}}
|
||||
"{{.name}}","{{.version}}","{{.foundBy}}"
|
||||
{{- end}}
|
||||
```
|
||||
|
||||
Which would produce output like:
|
||||
```text
|
||||
"Package","Version Installed","Found by"
|
||||
"alpine-baselayout","3.2.0-r20","apkdb-cataloger"
|
||||
"alpine-baselayout-data","3.2.0-r20","apkdb-cataloger"
|
||||
"alpine-keys","2.4-r1","apkdb-cataloger"
|
||||
...
|
||||
```
|
||||
|
||||
Syft also includes a vast array of utility templating functions from [sprig](http://masterminds.github.io/sprig/) apart from the default Golang [text/template](https://pkg.go.dev/text/template#hdr-Functions) to allow users to customize the output format.
|
||||
|
||||
Lastly, Syft has custom templating functions defined in `./syft/format/template/encoder.go` to help parse the passed-in JSON structs.
|
||||
|
||||
> [!NOTE]
|
||||
> If you have templates being used before Syft v0.102.0 that are no longer working. This is because templating keys were relative to the internal go structs before this version whereas now the keys are relative to the Syft JSON output. To get the legacy behavior back you can set the `format.template.legacy` option to `true` in your configuration.
|
||||
|
||||
## Multiple outputs
|
||||
|
||||
Syft can also output _multiple_ files in differing formats by appending
|
||||
`=<file>` to the option, for example to output Syft JSON and SPDX JSON:
|
||||
|
||||
```shell
|
||||
syft <image> -o syft-json=sbom.syft.json -o spdx-json=sbom.spdx.json
|
||||
```
|
||||
|
||||
## Private Registry Authentication
|
||||
|
||||
### Local Docker Credentials
|
||||
When a container runtime is not present, Syft can still utilize credentials configured in common credential sources (such as `~/.docker/config.json`). It will pull images from private registries using these credentials. The config file is where your credentials are stored when authenticating with private registries via some command like `docker login`. For more information see the `go-containerregistry` [documentation](https://github.com/google/go-containerregistry/tree/main/pkg/authn).
|
||||
|
||||
An example `config.json` looks something like this:
|
||||
```json
|
||||
{
|
||||
"auths": {
|
||||
"registry.example.com": {
|
||||
"username": "AzureDiamond",
|
||||
"password": "hunter2"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can run the following command as an example. It details the mount/environment configuration a container needs to access a private registry:
|
||||
|
||||
```
|
||||
docker run -v ./config.json:/config/config.json -e "DOCKER_CONFIG=/config" anchore/syft:latest <private_image>
|
||||
```
|
||||
|
||||
### Docker Credentials in Kubernetes
|
||||
|
||||
Here's a simple workflow to mount this config file as a secret into a container on Kubernetes.
|
||||
|
||||
1. Create a secret. The value of `config.json` is important. It refers to the specification detailed [here](https://github.com/google/go-containerregistry/tree/main/pkg/authn#the-config-file). Below this section is the `secret.yaml` file that the pod configuration will consume as a volume. The key `config.json` is important. It will end up being the name of the file when mounted into the pod.
|
||||
|
||||
```yaml
|
||||
# secret.yaml
|
||||
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: registry-config
|
||||
namespace: syft
|
||||
data:
|
||||
config.json: <base64 encoded config.json>
|
||||
```
|
||||
|
||||
`kubectl apply -f secret.yaml`
|
||||
|
||||
|
||||
2. Create your pod running syft. The env `DOCKER_CONFIG` is important because it advertises where to look for the credential file. In the below example, setting `DOCKER_CONFIG=/config` informs syft that credentials can be found at `/config/config.json`. This is why we used `config.json` as the key for our secret. When mounted into containers the secrets' key is used as the filename. The `volumeMounts` section mounts our secret to `/config`. The `volumes` section names our volume and leverages the secret we created in step one.
|
||||
|
||||
```yaml
|
||||
# pod.yaml
|
||||
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: syft-k8s-usage
|
||||
spec:
|
||||
containers:
|
||||
- image: anchore/syft:latest
|
||||
name: syft-private-registry-demo
|
||||
env:
|
||||
- name: DOCKER_CONFIG
|
||||
value: /config
|
||||
volumeMounts:
|
||||
- mountPath: /config
|
||||
name: registry-config
|
||||
readOnly: true
|
||||
args:
|
||||
- <private_image>
|
||||
volumes:
|
||||
- name: registry-config
|
||||
secret:
|
||||
secretName: registry-config
|
||||
```
|
||||
|
||||
`kubectl apply -f pod.yaml`
|
||||
|
||||
|
||||
3. The user can now run `kubectl logs syft-private-registry-demo`. The logs should show the Syft analysis for the `<private_image>` provided in the pod configuration.
|
||||
|
||||
Using the above information, users should be able to configure private registry access without having to do so in the `grype` or `syft` configuration files. They will also not be dependent on a Docker daemon, (or some other runtime software) for registry configuration and access.
|
||||
|
||||
## Format conversion (experimental)
|
||||
|
||||
The ability to convert existing SBOMs means you can create SBOMs in different formats quickly, without the need to regenerate the SBOM from scratch, which may take significantly more time.
|
||||
|
||||
```
|
||||
syft convert <ORIGINAL-SBOM-FILE> -o <NEW-SBOM-FORMAT>[=<NEW-SBOM-FILE>]
|
||||
```
|
||||
|
||||
This feature is experimental and data might be lost when converting formats. Packages are the main SBOM component easily transferable across formats, whereas files and relationships, as well as other information Syft doesn't support, are more likely to be lost.
|
||||
|
||||
We support formats with wide community usage AND good encode/decode support by Syft. The supported formats are:
|
||||
- Syft JSON (```-o syft-json```)
|
||||
- SPDX 2.2 JSON (```-o spdx-json```)
|
||||
- SPDX 2.2 tag-value (```-o spdx-tag-value```)
|
||||
- CycloneDX 1.4 JSON (```-o cyclonedx-json```)
|
||||
- CycloneDX 1.4 XML (```-o cyclonedx-xml```)
|
||||
|
||||
Conversion example:
|
||||
```sh
|
||||
syft alpine:latest -o syft-json=sbom.syft.json # generate a syft SBOM
|
||||
syft convert sbom.syft.json -o cyclonedx-json=sbom.cdx.json # convert it to CycloneDX
|
||||
```
|
||||
|
||||
## Attestation (experimental)
|
||||
### Keyless support
|
||||
Syft supports generating attestations using cosign's [keyless](https://github.com/sigstore/cosign/blob/main/KEYLESS.md) signatures.
|
||||
|
||||
Note: users need to have >= v1.12.0 of cosign installed for this command to function
|
||||
|
||||
To use this feature with a format like CycloneDX json simply run:
|
||||
```
|
||||
syft attest --output cyclonedx-json <IMAGE WITH OCI WRITE ACCESS>
|
||||
```
|
||||
This command will open a web browser and allow the user to authenticate their OIDC identity as the root of trust for the attestation (Github, Google, Microsoft).
|
||||
|
||||
After authenticating, Syft will upload the attestation to the OCI registry specified by the image that the user has write access to.
|
||||
|
||||
You will need to make sure your credentials are configured for the OCI registry you are uploading to so that the attestation can write successfully.
|
||||
|
||||
Users can then verify the attestation(or any image with attestations) by running:
|
||||
```
|
||||
COSIGN_EXPERIMENTAL=1 cosign verify-attestation <IMAGE_WITH_ATTESTATIONS>
|
||||
```
|
||||
|
||||
Users should see that the uploaded attestation claims are validated, the claims exist within the transparency log, and certificates on the attestations were verified against [fulcio](https://github.com/SigStore/fulcio).
|
||||
There will also be a printout of the certificates subject `<user identity>` and the certificate issuer URL: `<provider of user identity (Github, Google, Microsoft)>`:
|
||||
```
|
||||
Certificate subject: test.email@testdomain.com
|
||||
Certificate issuer URL: https://accounts.google.com
|
||||
```
|
||||
|
||||
### Local private key support
|
||||
|
||||
To generate an SBOM attestation for a container image using a local private key:
|
||||
```
|
||||
syft attest --output [FORMAT] --key [KEY] [SOURCE] [flags]
|
||||
```
|
||||
|
||||
The above output is in the form of the [DSSE envelope](https://github.com/secure-systems-lab/dsse/blob/master/envelope.md#dsse-envelope).
|
||||
The payload is a base64 encoded `in-toto` statement with the generated SBOM as the predicate. For details on workflows using this command see [here](#adding-an-sbom-to-an-image-as-an-attestation-using-syft).
|
||||
|
||||
|
||||
|
||||
## Configuration
|
||||
|
||||
Configuration search paths:
|
||||
|
||||
- `.syft.yaml`
|
||||
- `.syft/config.yaml`
|
||||
- `~/.syft.yaml`
|
||||
- `<XDG_CONFIG_HOME>/syft/config.yaml`
|
||||
|
||||
Configuration options (example values are the default):
|
||||
|
||||
```yaml
|
||||
# the output format(s) of the SBOM report (options: syft-table, syft-text, syft-json, spdx-json, ...)
|
||||
# to specify multiple output files in differing formats, use a list:
|
||||
# output:
|
||||
# - "syft-json=<syft-json-output-file>"
|
||||
# - "spdx-json=<spdx-json-output-file>"
|
||||
# SYFT_OUTPUT env var / -o, --output flags
|
||||
output:
|
||||
- "syft-table"
|
||||
|
||||
# suppress all output (except for the SBOM report)
|
||||
# SYFT_QUIET env var / -q flag
|
||||
quiet: false
|
||||
|
||||
# enable/disable checking for application updates on startup
|
||||
# SYFT_CHECK_FOR_APP_UPDATE env var
|
||||
check-for-app-update: true
|
||||
|
||||
# maximum number of workers used to process the list of package catalogers in parallel
|
||||
parallelism: 1
|
||||
|
||||
# a list of globs to exclude from scanning, for example:
|
||||
# exclude:
|
||||
# - "/etc/**"
|
||||
# - "./out/**/*.json"
|
||||
# SYFT_EXCLUDE env var / --exclude flag
|
||||
exclude: []
|
||||
|
||||
# os and/or architecture to use when referencing container images (e.g. "windows/armv6" or "arm64")
|
||||
# SYFT_PLATFORM env var / --platform flag
|
||||
platform: ""
|
||||
|
||||
# the search space to look for file and package data (options: all-layers, squashed)
|
||||
# SYFT_SCOPE env var
|
||||
scope: "squashed"
|
||||
|
||||
# set the list of package catalogers to use when generating the SBOM
|
||||
# default = empty (cataloger set determined automatically by the source type [image or file/directory])
|
||||
# Use `syft cataloger list` for a list of catalogers you can specify
|
||||
# DEPRECATED: please use default-catalogers and select-catalogers configuration options instead
|
||||
# SYFT_CATALOGERS env var / --catalogers flag
|
||||
catalogers:
|
||||
|
||||
# set the base set of catalogers to use (defaults to 'image' or 'directory' depending on the scan source)
|
||||
# SYFT_DEFAULT_CATALOGERS env var / --override-default-catalogers flag
|
||||
default-catalogers: []
|
||||
|
||||
# add, remove, and filter the catalogers to be used
|
||||
# SYFT_SELECT_CATALOGERS env var / --select-catalogers flag;
|
||||
select-catalogers: []
|
||||
|
||||
# all format configuration
|
||||
format:
|
||||
|
||||
# default value for all formats that support the "pretty" option (default is unset)
|
||||
# SYFT_FORMAT_PRETTY env var
|
||||
pretty:
|
||||
|
||||
# all syft-json format options
|
||||
json:
|
||||
|
||||
# include space indention and newlines (inherits default value from 'format.pretty' or 'false' if parent is unset)
|
||||
# note: inherits default value from 'format.pretty' or 'false' if parent is unset
|
||||
# SYFT_FORMAT_JSON_PRETTY env var
|
||||
pretty: false
|
||||
|
||||
# transform any syft-json output to conform to an approximation of the v11.0.1 schema. This includes:
|
||||
# - using the package metadata type names from before v12 of the JSON schema (changed in https://github.com/anchore/syft/pull/1983)
|
||||
#
|
||||
# Note: this will still include package types and fields that were added at or after json schema v12. This means
|
||||
# that output might not strictly be json schema v11 compliant, however, for consumers that require time to port
|
||||
# over to the final syft 1.0 json output this option can be used to ease the transition.
|
||||
#
|
||||
# Note: long term support for this option is not guaranteed (it may change or break at any time).
|
||||
# SYFT_FORMAT_JSON_LEGACY env var
|
||||
legacy: false
|
||||
|
||||
# all template format options
|
||||
template:
|
||||
# path to the template file to use when rendering the output with the `template` output format.
|
||||
# Note that all template paths are based on the current syft-json schema.
|
||||
# SYFT_FORMAT_TEMPLATE_PATH env var / -t flag
|
||||
path: ""
|
||||
|
||||
# if true, uses the go structs for the syft-json format for templating.
|
||||
# if false, uses the syft-json output for templating (which follows the syft JSON schema exactly).
|
||||
#
|
||||
# Note: long term support for this option is not guaranteed (it may change or break at any time).
|
||||
# SYFT_FORMAT_TEMPLATE_LEGACY env var
|
||||
legacy: false
|
||||
|
||||
# all spdx-json format options
|
||||
spdx-json:
|
||||
|
||||
# include space indention and newlines
|
||||
# note: inherits default value from 'format.pretty' or 'false' if parent is unset
|
||||
# SYFT_FORMAT_SPDX_JSON_PRETTY env var
|
||||
pretty: false
|
||||
|
||||
# all cyclonedx-json format options
|
||||
cyclonedx-json:
|
||||
|
||||
# include space indention and newlines
|
||||
# note: inherits default value from 'format.pretty' or 'false' if parent is unset
|
||||
# SYFT_FORMAT_CYCLONEDX_JSON_PRETTY env var
|
||||
pretty: false
|
||||
|
||||
# all cyclonedx-xml format options
|
||||
cyclonedx-xml:
|
||||
|
||||
# include space indention
|
||||
# note: inherits default value from 'format.pretty' or 'false' if parent is unset
|
||||
# SYFT_FORMAT_CYCLONEDX_XML_PRETTY env var
|
||||
pretty: false
|
||||
|
||||
|
||||
file:
|
||||
|
||||
metadata:
|
||||
# select which files should be captured by the file-metadata cataloger and included in the SBOM.
|
||||
# Options include:
|
||||
# - "all": capture all files from the search space
|
||||
# - "owned-by-package": capture only files owned by packages
|
||||
# - "none", "": do not capture any files
|
||||
# SYFT_FILE_METADATA_SELECTION env var
|
||||
selection: "owned-by-package"
|
||||
|
||||
# the file digest algorithms to use when cataloging files (options: "md5", "sha1", "sha224", "sha256", "sha384", "sha512")
|
||||
# SYFT_FILE_METADATA_DIGESTS env var
|
||||
digests:
|
||||
- "sha256"
|
||||
- "sha1"
|
||||
|
||||
# capture the contents of select files in the SBOM
|
||||
content:
|
||||
# skip searching a file entirely if it is above the given size (default = 1MB; unit = bytes)
|
||||
# SYFT_FILE_CONTENT_SKIP_FILES_ABOVE_SIZE env var
|
||||
skip-files-above-size: 1048576
|
||||
|
||||
# file globs for the cataloger to match on
|
||||
# SYFT_FILE_CONTENT_GLOBS env var
|
||||
globs: []
|
||||
|
||||
|
||||
# cataloging packages is exposed through the packages and power-user subcommands
|
||||
package:
|
||||
|
||||
# search within archives that do contain a file index to search against (zip)
|
||||
# note: for now this only applies to the java package cataloger
|
||||
# SYFT_PACKAGE_SEARCH_INDEXED_ARCHIVES env var
|
||||
search-indexed-archives: true
|
||||
|
||||
# search within archives that do not contain a file index to search against (tar, tar.gz, tar.bz2, etc)
|
||||
# note: enabling this may result in a performance impact since all discovered compressed tars will be decompressed
|
||||
# note: for now this only applies to the java package cataloger
|
||||
# SYFT_PACKAGE_SEARCH_UNINDEXED_ARCHIVES env var
|
||||
search-unindexed-archives: false
|
||||
|
||||
# allows users to exclude synthetic binary packages from the sbom
|
||||
# these packages are removed if an overlap with a non-synthetic package is found
|
||||
# SYFT_PACKAGE_EXCLUDE_BINARY_OVERLAP_BY_OWNERSHIP env var
|
||||
exclude-binary-overlap-by-ownership: true
|
||||
|
||||
|
||||
golang:
|
||||
# search for go package licences in the GOPATH of the system running Syft, note that this is outside the
|
||||
# container filesystem and potentially outside the root of a local directory scan
|
||||
# SYFT_GOLANG_SEARCH_LOCAL_MOD_CACHE_LICENSES env var
|
||||
search-local-mod-cache-licenses: false
|
||||
|
||||
# specify an explicit go mod cache directory, if unset this defaults to $GOPATH/pkg/mod or $HOME/go/pkg/mod
|
||||
# SYFT_GOLANG_LOCAL_MOD_CACHE_DIR env var
|
||||
local-mod-cache-dir: ""
|
||||
|
||||
# search for go package licences by retrieving the package from a network proxy
|
||||
# SYFT_GOLANG_SEARCH_REMOTE_LICENSES env var
|
||||
search-remote-licenses: false
|
||||
|
||||
# remote proxy to use when retrieving go packages from the network,
|
||||
# if unset this defaults to $GOPROXY followed by https://proxy.golang.org
|
||||
# SYFT_GOLANG_PROXY env var
|
||||
proxy: ""
|
||||
|
||||
# specifies packages which should not be fetched by proxy
|
||||
# if unset this defaults to $GONOPROXY
|
||||
# SYFT_GOLANG_NOPROXY env var
|
||||
no-proxy: ""
|
||||
|
||||
# the go main module version discovered from binaries built with the go compiler will
|
||||
# always show (devel) as the version. Use these options to control heuristics to guess
|
||||
# a more accurate version from the binary.
|
||||
main-module-version:
|
||||
|
||||
# look for LD flags that appear to be setting a version (e.g. -X main.version=1.0.0)
|
||||
# SYFT_GOLANG_MAIN_MODULE_VERSION_FROM_LD_FLAGS env var
|
||||
from-ld-flags: true
|
||||
|
||||
# use the build settings (e.g. vcs.version & vcs.time) to craft a v0 pseudo version
|
||||
# (e.g. v0.0.0-20220308212642-53e6d0aaf6fb) when a more accurate version cannot be found otherwise.
|
||||
# SYFT_GOLANG_MAIN_MODULE_VERSION_FROM_BUILD_SETTINGS env var
|
||||
from-build-settings: true
|
||||
|
||||
# search for semver-like strings in the binary contents.
|
||||
# SYFT_GOLANG_MAIN_MODULE_VERSION_FROM_CONTENTS env var
|
||||
from-contents: true
|
||||
|
||||
java:
|
||||
maven-url: "https://repo1.maven.org/maven2"
|
||||
max-parent-recursive-depth: 5
|
||||
# enables Syft to use the network to fill in more detailed information about artifacts
|
||||
# currently this enables searching maven-url for license data
|
||||
# when running across pom.xml files that could have more information, syft will
|
||||
# explicitly search maven for license information by querying the online pom when this is true
|
||||
# this option is helpful for when the parent pom has more data,
|
||||
# that is not accessible from within the final built artifact
|
||||
use-network: false
|
||||
|
||||
linux-kernel:
|
||||
# whether to catalog linux kernel modules found within lib/modules/** directories
|
||||
# SYFT_LINUX_KERNEL_CATALOG_MODULES env var
|
||||
catalog-modules: true
|
||||
|
||||
python:
|
||||
# when running across entries in requirements.txt that do not specify a specific version
|
||||
# (e.g. "sqlalchemy >= 1.0.0, <= 2.0.0, != 3.0.0, <= 3.0.0"), attempt to guess what the version could
|
||||
# be based on the version requirements specified (e.g. "1.0.0"). When enabled the lowest expressible version
|
||||
# when given an arbitrary constraint will be used (even if that version may not be available/published).
|
||||
guess-unpinned-requirements: false
|
||||
|
||||
javascript:
|
||||
search-remote-licenses: false
|
||||
npm-base-url: "https://registry.npmjs.org"
|
||||
|
||||
|
||||
# configuration for the source that the SBOM is generated from (e.g. a file, directory, or container image)
|
||||
source:
|
||||
# alias name for the source
|
||||
# SYFT_SOURCE_NAME env var / --source-name flag
|
||||
name: ""
|
||||
|
||||
# alias version for the source
|
||||
# SYFT_SOURCE_VERSION env var / --source-version flag
|
||||
version: ""
|
||||
|
||||
# base directory for scanning, no links will be followed above this directory, and all paths will be
|
||||
# reported relative to this directory
|
||||
# SYFT_SOURCE_BASE_PATH env var
|
||||
base-path: ''
|
||||
|
||||
# options affecting the file source type
|
||||
file:
|
||||
# the file digest algorithms to use on the scanned file (options: "md5", "sha1", "sha224", "sha256", "sha384", "sha512")
|
||||
digests:
|
||||
- "sha256"
|
||||
|
||||
image:
|
||||
|
||||
# allows users to specify which image source should be used to generate the sbom
|
||||
# valid values are: registry, docker, podman
|
||||
# SYFT_SOURCE_IMAGE_DEFAULT_PULL_SOURCE env var
|
||||
default-pull-source: ""
|
||||
|
||||
|
||||
# options when pulling directly from a registry via the "registry:" or "containerd:" scheme
|
||||
registry:
|
||||
# skip TLS verification when communicating with the registry
|
||||
# SYFT_REGISTRY_INSECURE_SKIP_TLS_VERIFY env var
|
||||
insecure-skip-tls-verify: false
|
||||
|
||||
# use http instead of https when connecting to the registry
|
||||
# SYFT_REGISTRY_INSECURE_USE_HTTP env var
|
||||
insecure-use-http: false
|
||||
|
||||
# filepath to a CA certificate (or directory containing *.crt, *.cert, *.pem) used to generate the client certificate
|
||||
# SYFT_REGISTRY_CA_CERT env var
|
||||
ca-cert: ""
|
||||
|
||||
# credentials for specific registries
|
||||
auth:
|
||||
# the URL to the registry (e.g. "docker.io", "localhost:5000", etc.)
|
||||
# SYFT_REGISTRY_AUTH_AUTHORITY env var
|
||||
- authority: ""
|
||||
|
||||
# SYFT_REGISTRY_AUTH_USERNAME env var
|
||||
username: ""
|
||||
|
||||
# SYFT_REGISTRY_AUTH_PASSWORD env var
|
||||
password: ""
|
||||
|
||||
# note: token and username/password are mutually exclusive
|
||||
# SYFT_REGISTRY_AUTH_TOKEN env var
|
||||
token: ""
|
||||
|
||||
# filepath to the client certificate used for TLS authentication to the registry
|
||||
# SYFT_REGISTRY_AUTH_TLS_CERT env var
|
||||
tls-cert: ""
|
||||
|
||||
# filepath to the client key used for TLS authentication to the registry
|
||||
# SYFT_REGISTRY_AUTH_TLS_KEY env var
|
||||
tls-key: ""
|
||||
|
||||
# - ... # note, more credentials can be provided via config file only (not env vars)
|
||||
|
||||
# generate an attested SBOM
|
||||
attest:
|
||||
# path to the private key file to use for attestation
|
||||
# SYFT_ATTEST_KEY env var
|
||||
key: "cosign.key"
|
||||
|
||||
# password to decrypt to given private key
|
||||
# SYFT_ATTEST_PASSWORD env var, additionally responds to COSIGN_PASSWORD
|
||||
password: ""
|
||||
|
||||
log:
|
||||
# use structured logging
|
||||
# SYFT_LOG_STRUCTURED env var
|
||||
structured: false
|
||||
|
||||
# the log level; note: detailed logging suppress the ETUI
|
||||
# SYFT_LOG_LEVEL env var
|
||||
level: "error"
|
||||
|
||||
# location to write the log file (default is not to have a log file)
|
||||
# SYFT_LOG_FILE env var
|
||||
file: ""
|
||||
```
|
||||
|
||||
### Adding an SBOM to an image as an attestation using Syft
|
||||
|
||||
`syft attest --output [FORMAT] --key [KEY] [SOURCE] [flags]`
|
||||
|
||||
SBOMs themselves can serve as input to different analysis tools. [Grype](https://github.com/anchore/grype), a vulnerability scanner CLI tool from Anchore, is one such tool. Publishers of container images can use attestations to enable their consumers to trust Syft-generated SBOM descriptions of those container images. To create and provide these attestations, image publishers can run `syft attest` in conjunction with the [cosign](https://github.com/sigstore/cosign) tool to attach SBOM attestations to their images.
|
||||
|
||||
#### Example attestation
|
||||
Note for the following example replace `docker.io/image:latest` with an image you own. You should also have push access to
|
||||
its remote reference. Replace `$MY_PRIVATE_KEY` with a private key you own or have generated with cosign.
|
||||
|
||||
```bash
|
||||
syft attest --key $MY_PRIVATE_KEY -o spdx-json docker.io/image:latest > image_latest_sbom_attestation.json
|
||||
cosign attach attestation --attestation image_latest_sbom_attestation.json docker.io/image:latest
|
||||
```
|
||||
|
||||
Verify the new attestation exists on your image.
|
||||
|
||||
```bash
|
||||
cosign verify-attestation --key $MY_PUBLIC_KEY --type spdxjson docker.io/image:latest | jq '.payload | @base64d | .payload | fromjson | .predicate'
|
||||
```
|
||||
|
||||
You should see this output along with the attached SBOM:
|
||||
|
||||
```
|
||||
Verification for docker.io/image:latest --
|
||||
The following checks were performed on each of these signatures:
|
||||
- The cosign claims were validated
|
||||
- The signatures were verified against the specified public key
|
||||
- Any certificates were verified against the Fulcio roots.
|
||||
```
|
||||
|
||||
Consumers of your image can now trust that the SBOM associated with your image is correct and from a trusted source.
|
||||
|
||||
The SBOM can be piped to Grype:
|
||||
|
||||
|
||||
```bash
|
||||
cosign verify-attestation --key $MY_PUBLIC_KEY --type spdxjson docker.io/image:latest | jq '.payload | @base64d | .payload | fromjson | .predicate' | grype
|
||||
```
|
||||
## Documentation
|
||||
|
||||
Our [wiki](https://github.com/anchore/syft/wiki) contains further details on the following topics:
|
||||
|
||||
* [Supported Sources](https://github.com/anchore/syft/wiki/supported-sources)
|
||||
* [File Selection](https://github.com/anchore/syft/wiki/file-selection)
|
||||
* [Excluding file paths](https://github.com/anchore/syft/wiki/excluding-file-paths)
|
||||
* [Output formats](https://github.com/anchore/syft/wiki/output-formats)
|
||||
* [Package Cataloger Selection](https://github.com/anchore/syft/wiki/package-cataloger-selection)
|
||||
* [Concepts](https://github.com/anchore/syft/wiki/package-cataloger-selection#concepts)
|
||||
* [Examples](https://github.com/anchore/syft/wiki/package-cataloger-selection#examples)
|
||||
* [Using templates](https://github.com/anchore/syft/wiki/using-templates)
|
||||
* [Multiple outputs](https://github.com/anchore/syft/wiki/multiple-outputs)
|
||||
* [Private Registry Authentication](https://github.com/anchore/syft/wiki/private-registry-authentication)
|
||||
* [Local Docker Credentials](https://github.com/anchore/syft/wiki/private-registry-authentication#local-docker)
|
||||
* [Docker Credentials in Kubernetes](https://github.com/anchore/syft/wiki/private-registry-authentication#docker-credentials-in-kubernetes)
|
||||
* [Attestation (experimental)](https://github.com/anchore/syft/wiki/attestation)
|
||||
* [Keyless Support](https://github.com/anchore/syft/wiki/attestation#keyless-support)
|
||||
* [Local private key support](https://github.com/anchore/syft/wiki/attestation#local-private-key-support)
|
||||
* [Adding an SBOM to an image as an attestation using Syft](https://github.com/anchore/syft/wiki/attestation#adding-an-sbom-to-an-image-as-an-attestation-using-syft)
|
||||
* [Configuration](https://github.com/anchore/syft/wiki/configuration)
|
||||
|
||||
## Contributing
|
||||
|
||||
Check out our [contributing](/CONTRIBUTING.md) guide and [developer](/DEVELOPING.md) docs.
|
||||
|
||||
## Syft Team Meetings
|
||||
|
||||
The Syft Team hold regular community meetings online. All are welcome to join to bring topics for discussion.
|
||||
- Check the [calendar](https://calendar.google.com/calendar/u/0/r?cid=Y182OTM4dGt0MjRtajI0NnNzOThiaGtnM29qNEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t) for the next meeting date.
|
||||
- Add items to the [agenda](https://docs.google.com/document/d/1ZtSAa6fj2a6KRWviTn3WoJm09edvrNUp4Iz_dOjjyY8/edit?usp=sharing) (join [this group](https://groups.google.com/g/anchore-oss-community) for write access to the [agenda](https://docs.google.com/document/d/1ZtSAa6fj2a6KRWviTn3WoJm09edvrNUp4Iz_dOjjyY8/edit?usp=sharing))
|
||||
- See you there!
|
||||
|
||||
+13
-86
@@ -1,5 +1,16 @@
|
||||
# Release
|
||||
|
||||
A release of syft comprises:
|
||||
- a new semver git tag from the current tip of the main branch
|
||||
- a new [github release](https://github.com/anchore/syft/releases) with a changelog and archived binary assets
|
||||
- docker images published to `ghcr.io` and `dockerhub`, including multi architecture images + manifest
|
||||
- [`anchore/homebrew-syft`](https://github.com/anchore/homebrew-syft) tap updated to point to assets in the latest github release
|
||||
|
||||
Ideally releasing should be done often with small increments when possible. Unless a
|
||||
breaking change is blocking the release, or no fixes/features have been merged, a good
|
||||
target release cadence is between every 1 or 2 weeks.
|
||||
|
||||
|
||||
## Creating a release
|
||||
|
||||
This release process itself should be as automated as possible, and has only a few steps:
|
||||
@@ -9,16 +20,10 @@ This release process itself should be as automated as possible, and has only a f
|
||||
you can abort and adjust the labels on the PRs and issues to be included in the release and
|
||||
re-run the release trigger command.
|
||||
|
||||
1. A release admin must approve the release on the GitHub Actions release pipeline run page.
|
||||
1. A release admin must approve the release on the GitHub Actions [release pipeline](https://github.com/anchore/syft/actions/workflows/release.yaml) run page.
|
||||
Once approved, the release pipeline will generate all assets and publish a GitHub Release.
|
||||
|
||||
1. If there is a release Milestone, close it.
|
||||
|
||||
Ideally releasing should be done often with small increments when possible. Unless a
|
||||
breaking change is blocking the release, or no fixes/features have been merged, a good
|
||||
target release cadence is between every 1 or 2 weeks.
|
||||
|
||||
|
||||
|
||||
## Retracting a release
|
||||
|
||||
If a release is found to be problematic, it can be retracted with the following steps:
|
||||
@@ -32,81 +37,3 @@ If a release is found to be problematic, it can be retracted with the following
|
||||
in the go proxy, which will cause confusion when trying to reuse the tag later (the H1 hash will not match and there
|
||||
will be a warning when users try to pull the new release).
|
||||
|
||||
|
||||
## Background
|
||||
|
||||
A good release process has the following qualities:
|
||||
|
||||
1. There is a way to plan what should be in a release
|
||||
1. There is a way to see what is actually in a release
|
||||
1. Allow for different kinds of releases (major breaking vs backwards compatible enhancements vs patch updates)
|
||||
1. Specify a repeatable way to build and publish software artifacts
|
||||
|
||||
|
||||
### Planning a release
|
||||
|
||||
To indicate a set of features to be released together add each issue to an in-repository
|
||||
Milestone named with major-minor version to be released (e.g. `v0.1`). It is OK for other
|
||||
features to be in the release that were not originally planned, and these issues and PRs
|
||||
do not need to be added to the Milestone in question. Only the set of features that, when
|
||||
completed, would allow the release to be considered complete. A Milestone is only used to:
|
||||
|
||||
- Plan what is desired to be in a release
|
||||
- Track progress to indicate when we may be ready to cut a new release
|
||||
|
||||
Not all releases need to be planned. For instance, patch releases for fixes should be
|
||||
released when they are ready and when releasing would not interfere with another current
|
||||
release (where some partial or breaking features have already been merged).
|
||||
|
||||
Unless necessary, feature releases should be small and frequent, which may obviate the
|
||||
need for regular release planning under a Milestone.
|
||||
|
||||
|
||||
### What is in a release
|
||||
|
||||
Milestones are specifically for planning a release, not necessarily tracking all changes
|
||||
that a release may bring (and more importantly, not all releases are necessarily planned
|
||||
either).
|
||||
|
||||
This is one of the (many) reasons for a Changelog. A good Changelog lists changes grouped
|
||||
by the type of change (new, enhancement, deprecation, breaking, bug fix, security fix), in
|
||||
chronological order (within groups), linking the PR where the change was made in the
|
||||
Changelog line. Furthermore, there should be a place to see all released versions, the
|
||||
release date for each release, the semantic version of the release, and the set of changes
|
||||
for each release.
|
||||
|
||||
**This project auto-generates the Changelog contents for each current release and posts the
|
||||
generated contents to the GitHub Release page**. Leveraging the GitHub Releases feature
|
||||
allows GitHub to manage the Changelog on each release outside of the git source tree while
|
||||
still being hosted with the released assets.
|
||||
|
||||
The Changelog is generated from the metadata from in-repository issues and PRs, using
|
||||
labels to guide what kind of change each item is (e.g. breaking, new feature, bug fix,
|
||||
etx). Only issues/PRs with select labels are included in the Changelog, and only if the
|
||||
issue/PR was created after the last release. Additional labels are used to exclude items
|
||||
from the Changelog.
|
||||
|
||||
The above suggestions imply that we should:
|
||||
|
||||
- Ensure there is a sufficient title for each PR and issue title to be included in the
|
||||
Changelog
|
||||
- The appropriate label is applied to PRs and/or issues to drive specific change type
|
||||
sections (deprecated, breaking, security, bug, etc)
|
||||
|
||||
**With this approach as we cultivate good organization of PRs and issues we automatically
|
||||
get an equally good Changelog.**
|
||||
|
||||
|
||||
### Major, minor, and patch releases
|
||||
|
||||
The latest version of the tool is the only supported version, which implies that multiple
|
||||
parallel release branches will not be a regular process (if ever). Multiple releases can
|
||||
be planned in parallel, however, only one can be actively developed at a time. That is, if
|
||||
PRs attached to a release Milestone have been merged into the main branch, that release is
|
||||
now the "next" release. **This implies that the source of truth for release lies with the
|
||||
git log and Changelog, not with the release Milestones** (which are purely for planning and
|
||||
tracking).
|
||||
|
||||
Semantic versioning should be used to indicate breaking changes, new features, and fixes.
|
||||
The exception to this is `< 1.0`, where the major version is not bumped for breaking changes,
|
||||
instead the minor version indicates both new features and breaking changes.
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
<!-- Use this section to tell people about which versions of your project are
|
||||
currently being supported with security updates.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 5.1.x | :white_check_mark: |
|
||||
| 5.0.x | :x: |
|
||||
| 4.0.x | :white_check_mark: |
|
||||
| < 4.0 | :x: |
|
||||
|
||||
-->
|
||||
|
||||
Security updates are applied only to the most recent release, try to always be up to date.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
<!-- Use this section to tell people how to report a vulnerability.
|
||||
|
||||
Tell them where to go, how often they can expect to get an update on a
|
||||
reported vulnerability, what to expect if the vulnerability is accepted or
|
||||
declined, etc. -->
|
||||
|
||||
To report a security issue, please email
|
||||
[security@anchore.com](mailto:security@anchore.com)
|
||||
with a description of the issue, the steps you took to create the issue,
|
||||
affected versions, and, if known, mitigations for the issue.
|
||||
|
||||
All support will be made on the best effort base, so please indicate the "urgency level" of the vulnerability as Critical, High, Medium or Low.
|
||||
+223
-54
@@ -4,9 +4,19 @@ vars:
|
||||
OWNER: anchore
|
||||
PROJECT: syft
|
||||
|
||||
CACHE_IMAGE: ghcr.io/{{ .OWNER }}/{{ .PROJECT }}/test-fixture-cache:latest
|
||||
|
||||
# static file dirs
|
||||
TOOL_DIR: .tool
|
||||
TMP_DIR: .tmp
|
||||
ORAS_CACHE: "{{ .TMP_DIR }}/oras-cache"
|
||||
CACHE_PATHS_FILE: "{{ .TMP_DIR }}/cache_paths.json"
|
||||
LAST_CACHE_PULL_FILE: "{{ .TMP_DIR }}/last_cache_paths.json"
|
||||
|
||||
# TOOLS
|
||||
ORAS: "{{ .TOOL_DIR }}/oras"
|
||||
YQ: "{{ .TOOL_DIR }}/yq"
|
||||
TASK: "{{ .TOOL_DIR }}/task"
|
||||
|
||||
# used for changelog generation
|
||||
CHANGELOG: CHANGELOG.md
|
||||
@@ -33,6 +43,9 @@ vars:
|
||||
COMPARE_DIR: ./test/compare
|
||||
COMPARE_TEST_IMAGE: centos:8.2.2004
|
||||
|
||||
env:
|
||||
GNUMAKEFLAGS: '--no-print-directory'
|
||||
|
||||
tasks:
|
||||
|
||||
## High-level tasks #################################
|
||||
@@ -65,6 +78,7 @@ tasks:
|
||||
- task: benchmark
|
||||
- task: test-utils
|
||||
- task: cli
|
||||
- task: check-docker-cache
|
||||
|
||||
## Bootstrap tasks #################################
|
||||
|
||||
@@ -212,10 +226,6 @@ tasks:
|
||||
# that the cache being restored with the correct binary will be rebuilt since the timestamps
|
||||
# and local checksums will not line up.
|
||||
deps: [tools, snapshot]
|
||||
sources:
|
||||
- "{{ .SNAPSHOT_BIN }}"
|
||||
- ./test/cli/**
|
||||
- ./**/*.go
|
||||
cmds:
|
||||
- cmd: "echo 'testing binary: {{ .SNAPSHOT_BIN }}'"
|
||||
silent: true
|
||||
@@ -229,18 +239,14 @@ tasks:
|
||||
|
||||
test-utils:
|
||||
desc: Run tests for pipeline utils
|
||||
sources:
|
||||
- .github/scripts/labeler*.py
|
||||
cmds:
|
||||
- cmd: python .github/scripts/labeler_test.py
|
||||
- cmd: .github/scripts/labeler_test.py
|
||||
|
||||
|
||||
## Benchmark test targets #################################
|
||||
|
||||
benchmark:
|
||||
deps: [tmpdir]
|
||||
sources:
|
||||
- ./**/*.go
|
||||
generates:
|
||||
- "{{ .TMP_DIR }}/benchmark-main.txt"
|
||||
cmds:
|
||||
@@ -253,8 +259,6 @@ tasks:
|
||||
|
||||
show-benchstat:
|
||||
deps: [benchmark, tmpdir]
|
||||
sources:
|
||||
- "{{ .TMP_DIR }}/benchstat.txt"
|
||||
cmds:
|
||||
- cmd: "cat {{ .TMP_DIR }}/benchstat.txt"
|
||||
silent: true
|
||||
@@ -263,56 +267,188 @@ tasks:
|
||||
## Test-fixture-related targets #################################
|
||||
|
||||
fingerprints:
|
||||
desc: Generate test fixture fingerprints
|
||||
desc: Generate fingerprints for all non-docker test fixture
|
||||
silent: true
|
||||
# this will look for `test-fixtures/Makefile` and invoke the `fingerprint` target to calculate all cache input fingerprint files
|
||||
generates:
|
||||
- cmd/syft/internal/test/integration/test-fixtures/cache.fingerprint
|
||||
- syft/file/cataloger/executable/test-fixtures/elf/cache.fingerprint
|
||||
- syft/file/cataloger/executable/test-fixtures/shared-info/cache.fingerprint
|
||||
- syft/pkg/cataloger/binary/test-fixtures/cache.fingerprint
|
||||
- syft/pkg/cataloger/java/test-fixtures/java-builds/cache.fingerprint
|
||||
- syft/pkg/cataloger/golang/test-fixtures/archs/binaries.fingerprint
|
||||
- syft/pkg/cataloger/redhat/test-fixtures/rpms.fingerprint
|
||||
- syft/pkg/cataloger/kernel/test-fixtures/cache.fingerprint
|
||||
- '**/test-fixtures/**/*.fingerprint'
|
||||
- test/install/cache.fingerprint
|
||||
- test/cli/test-fixtures/cache.fingerprint
|
||||
cmds:
|
||||
# for EXECUTABLE unit test fixtures
|
||||
- "cd syft/file/cataloger/executable/test-fixtures/elf && make cache.fingerprint"
|
||||
- "cd syft/file/cataloger/executable/test-fixtures/shared-info && make cache.fingerprint"
|
||||
# for IMAGE integration test fixtures
|
||||
- "cd cmd/syft/internal/test/integration/test-fixtures && make cache.fingerprint"
|
||||
# for BINARY unit test fixtures
|
||||
- "cd syft/pkg/cataloger/binary/test-fixtures && make cache.fingerprint"
|
||||
# for JAVA BUILD unit test fixtures
|
||||
- "cd syft/pkg/cataloger/java/test-fixtures/java-builds && make cache.fingerprint"
|
||||
# for GO BINARY unit test fixtures
|
||||
- "cd syft/pkg/cataloger/golang/test-fixtures/archs && make binaries.fingerprint"
|
||||
# for RPM unit test fixtures
|
||||
- "cd syft/pkg/cataloger/redhat/test-fixtures && make rpms.fingerprint"
|
||||
# for Kernel unit test fixtures
|
||||
- "cd syft/pkg/cataloger/kernel/test-fixtures && make cache.fingerprint"
|
||||
# for INSTALL test fixtures
|
||||
- "cd test/install && make cache.fingerprint"
|
||||
# for CLI test fixtures
|
||||
- "cd test/cli/test-fixtures && make cache.fingerprint"
|
||||
- |
|
||||
BOLD='\033[1m'
|
||||
YELLOW='\033[0;33m'
|
||||
RESET='\033[0m'
|
||||
|
||||
fixtures:
|
||||
desc: Generate test fixtures
|
||||
echo -e "${YELLOW}creating fingerprint files for non-docker fixtures...${RESET}"
|
||||
for dir in $(find . -type d -name 'test-fixtures'); do
|
||||
if [ -f "$dir/Makefile" ]; then
|
||||
# for debugging...
|
||||
#echo -e "${YELLOW}• calculating fingerprints in $dir... ${RESET}"
|
||||
|
||||
(make -C "$dir" fingerprint)
|
||||
fi
|
||||
done
|
||||
|
||||
# for debugging...
|
||||
# echo -e "generated all fixture fingerprints"
|
||||
|
||||
- .github/scripts/fingerprint_docker_fixtures.py
|
||||
- |
|
||||
# if DOWNLOAD_TEST_FIXTURE_CACHE is set to 'false', then we don't need to calculate the fingerprint for the cache
|
||||
if [ "$DOWNLOAD_TEST_FIXTURE_CACHE" = "false" ]; then
|
||||
exit 0
|
||||
fi
|
||||
.github/scripts/find_cache_paths.py {{ .CACHE_PATHS_FILE }} > /dev/null
|
||||
|
||||
|
||||
refresh-fixtures:
|
||||
desc: Clear and fetch all test fixture cache
|
||||
aliases:
|
||||
- fixtures
|
||||
silent: true
|
||||
deps:
|
||||
- tools
|
||||
cmds:
|
||||
- "cd syft/file/cataloger/executable/test-fixtures/elf && make"
|
||||
- "cd syft/file/cataloger/executable/test-fixtures/shared-info && make"
|
||||
- "cd syft/pkg/cataloger/java/test-fixtures/java-builds && make"
|
||||
- "cd syft/pkg/cataloger/redhat/test-fixtures && make"
|
||||
- "cd syft/pkg/cataloger/binary/test-fixtures && make"
|
||||
- |
|
||||
BOLD='\033[1m'
|
||||
PURPLE='\033[0;35m'
|
||||
RESET='\033[0m'
|
||||
|
||||
# if DOWNLOAD_TEST_FIXTURE_CACHE is set to 'false', then skip the cache download and always build
|
||||
if [ "$DOWNLOAD_TEST_FIXTURE_CACHE" = "false" ]; then
|
||||
echo -e "${BOLD}${PURPLE}skipping cache download, rebuilding cache...${RESET}"
|
||||
{{ .TASK }} build-fixtures
|
||||
exit 0
|
||||
fi
|
||||
|
||||
LATEST_FINGERPRINT=$(docker manifest inspect {{ .CACHE_IMAGE }} | {{ .YQ }} -r '.annotations.fingerprint')
|
||||
|
||||
echo "latest cache: $LATEST_FINGERPRINT"
|
||||
|
||||
if [ -f {{ .LAST_CACHE_PULL_FILE }} ]; then
|
||||
LAST_PULL_FINGERPRINT=$(cat {{ .LAST_CACHE_PULL_FILE }} | {{ .YQ }} -r '.digest')
|
||||
else
|
||||
echo -e "${BOLD}${PURPLE}empty cache, downloading cache...${RESET}"
|
||||
{{ .TASK }} download-test-fixture-cache
|
||||
exit 0
|
||||
fi
|
||||
|
||||
{{ .TASK }} fingerprints
|
||||
|
||||
WANT_FINGERPRINT=$(cat {{ .CACHE_PATHS_FILE }} | {{ .YQ }} -r '.digest')
|
||||
|
||||
echo "desired cache: $WANT_FINGERPRINT"
|
||||
echo "last pulled cache: $LAST_PULL_FINGERPRINT"
|
||||
|
||||
# if we already have the latest cache, skip the refresh
|
||||
if [ "$LAST_PULL_FINGERPRINT" = "$WANT_FINGERPRINT" ]; then
|
||||
echo -e "${BOLD}${PURPLE}already have the latest cache (skipping cache download)${RESET}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# at this point we only refresh the cache if we want the same cache that is currently available.
|
||||
# we don't by default refresh the cache if the cache if it is simply different from what we have,
|
||||
# because we may be working on a code change that doesn't require a cache refresh (but could trigger one,
|
||||
# which would be annoying to deal with in a development workflow).
|
||||
|
||||
if [ "$LATEST_FINGERPRINT" = "$WANT_FINGERPRINT" ]; then
|
||||
echo -e "${BOLD}${PURPLE}found newer cache! downloading cache...${RESET}"
|
||||
{{ .TASK }} download-test-fixture-cache
|
||||
else
|
||||
echo -e "${BOLD}${PURPLE}found different cache, but isn't clear if it's newer (skipping cache download and manually building)${RESET}"
|
||||
|
||||
{{ .YQ }} eval '.paths[] | "\(.digest) \(.path)"' {{ .LAST_CACHE_PULL_FILE }} > .tmp/last_cache_lines
|
||||
{{ .YQ }} eval '.paths[] | "\(.digest) \(.path)"' {{ .CACHE_PATHS_FILE }} > .tmp/cache_lines
|
||||
diff .tmp/last_cache_lines .tmp/cache_lines || true
|
||||
|
||||
echo -e "${BOLD}${PURPLE}diff with more context...${RESET}"
|
||||
|
||||
diff -U10000 {{ .LAST_CACHE_PULL_FILE }} {{ .CACHE_PATHS_FILE }} || true
|
||||
|
||||
echo -e "${BOLD}${PURPLE}detected changes to input material, manually building fixtures...${RESET}"
|
||||
|
||||
{{ .TASK }} build-fixtures
|
||||
fi
|
||||
|
||||
build-fixtures:
|
||||
desc: Generate all non-docker test fixtures
|
||||
silent: true
|
||||
# this will look for `test-fixtures/Makefile` and invoke the `fixtures` target to generate any and all test fixtures
|
||||
cmds:
|
||||
- |
|
||||
BOLD='\033[1m'
|
||||
YELLOW='\033[0;33m'
|
||||
RESET='\033[0m'
|
||||
|
||||
# Use a for loop with command substitution to avoid subshell issues
|
||||
for dir in $(find . -type d -name 'test-fixtures'); do
|
||||
if [ -f "$dir/Makefile" ]; then
|
||||
echo -e "${YELLOW}${BOLD}generating fixtures in $dir${RESET}"
|
||||
(make -C "$dir" fixtures)
|
||||
fi
|
||||
done
|
||||
echo -e "${BOLD}generated all fixtures${RESET}"
|
||||
|
||||
download-test-fixture-cache:
|
||||
desc: Download test fixture cache from ghcr.io
|
||||
deps: [tools, clean-cache]
|
||||
vars:
|
||||
CACHE_DIGEST:
|
||||
sh: docker manifest inspect {{ .CACHE_IMAGE }} | {{ .YQ }} -r '.annotations.fingerprint'
|
||||
cmds:
|
||||
- silent: true
|
||||
cmd: |
|
||||
# if oras cache is > 4 GB, delete it
|
||||
if [ -d {{ .ORAS_CACHE }} ]; then
|
||||
total_size=$(du -c {{ .ORAS_CACHE }} | grep total | awk '{print $1}')
|
||||
if [ "$total_size" -gt 4194304 ]; then
|
||||
echo 'deleting oras cache'
|
||||
rm -rf {{ .ORAS_CACHE }}
|
||||
fi
|
||||
fi
|
||||
- "ORAS_CACHE={{ .ORAS_CACHE }} {{ .ORAS }} pull {{ .CACHE_IMAGE }}"
|
||||
- "cp {{ .CACHE_PATHS_FILE }} {{ .LAST_CACHE_PULL_FILE }}"
|
||||
|
||||
upload-test-fixture-cache:
|
||||
desc: Upload the test fixture cache to ghcr.io
|
||||
deps: [tools, fingerprints]
|
||||
silent: true
|
||||
cmd: |
|
||||
set -eu
|
||||
oras_command="{{ .ORAS }} push {{ .CACHE_IMAGE }}"
|
||||
|
||||
paths=$(cat {{ .CACHE_PATHS_FILE }} | {{ .YQ }} -r '.paths[].path')
|
||||
for path in $paths; do
|
||||
oras_command+=" $path"
|
||||
done
|
||||
oras_command+=" {{ .CACHE_PATHS_FILE }}"
|
||||
|
||||
oras_command+=" --annotation org.opencontainers.image.source=https://github.com/{{ .OWNER }}/{{ .PROJECT }}"
|
||||
oras_command+=" --annotation fingerprint=$(cat {{ .CACHE_PATHS_FILE }} | {{ .YQ }} -r '.digest')"
|
||||
|
||||
echo "Executing: $oras_command"
|
||||
eval $oras_command
|
||||
|
||||
show-test-image-cache:
|
||||
silent: true
|
||||
cmds:
|
||||
- "echo '\nDocker daemon cache:'"
|
||||
- "echo 'Docker daemon cache:'"
|
||||
- "docker images --format '{{`{{.ID}}`}} {{`{{.Repository}}`}}:{{`{{.Tag}}`}}' | grep stereoscope-fixture- | sort"
|
||||
- "echo '\nTar cache:'"
|
||||
- 'find . -type f -wholename "**/test-fixtures/snapshot/*" | sort'
|
||||
- 'find . -type f -wholename "**/test-fixtures/cache/stereoscope-fixture-*.tar" | sort'
|
||||
|
||||
check-docker-cache:
|
||||
desc: Ensure docker caches aren't using too much disk space
|
||||
silent: true
|
||||
cmd: |
|
||||
total_size=$(find . | grep cache | grep tar | xargs du -c | grep total | awk '{print $1}')
|
||||
find . | grep cache | grep tar | xargs du
|
||||
echo "total $total_size KB"
|
||||
|
||||
if [ "$total_size" -gt 1048576 ]; then
|
||||
echo 'docker cache is larger than 1GB'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
## install.sh testing targets #################################
|
||||
|
||||
@@ -390,7 +526,7 @@ tasks:
|
||||
|
||||
generate-cpe-dictionary-index:
|
||||
desc: Generate the CPE index based off of the latest available CPE dictionary
|
||||
dir: "syft/pkg/cataloger/common/cpe/dictionary"
|
||||
dir: "syft/pkg/cataloger/internal/cpegenerate/dictionary"
|
||||
cmds:
|
||||
- "go generate"
|
||||
|
||||
@@ -470,6 +606,16 @@ tasks:
|
||||
silent: true
|
||||
- "{{ .RELEASE_CMD }}"
|
||||
|
||||
ci-release-version-file:
|
||||
# desc: "[CI only] Update the version file"
|
||||
deps: [tools]
|
||||
cmds:
|
||||
- task: ci-check
|
||||
- ".github/scripts/update-version-file.sh {{ .RELEASE_VERSION }}"
|
||||
requires:
|
||||
vars:
|
||||
- RELEASE_VERSION
|
||||
|
||||
|
||||
## Cleanup targets #################################
|
||||
|
||||
@@ -479,8 +625,31 @@ tasks:
|
||||
- "rm -rf {{ .SNAPSHOT_DIR }}"
|
||||
- "rm -rf {{ .TMP_DIR }}/goreleaser.yaml"
|
||||
|
||||
clean-cache:
|
||||
desc: Remove all docker cache and local image tar cache
|
||||
clean-docker-cache:
|
||||
desc: Remove all docker cache tars and images from the daemon
|
||||
cmds:
|
||||
- 'find . -type f -wholename "**/test-fixtures/cache/stereoscope-fixture-*.tar" -delete'
|
||||
- "docker images --format '{{`{{.ID}}`}} {{`{{.Repository}}`}}' | grep stereoscope-fixture- | awk '{print $$1}' | uniq | xargs -r docker rmi --force"
|
||||
- find . -type d -wholename "**/test-fixtures/cache" | xargs rm -rf
|
||||
- docker images --format '{{`{{.ID}}`}} {{`{{.Repository}}`}}' | grep stereoscope-fixture- | awk '{print $1}' | uniq | xargs -r docker rmi --force
|
||||
|
||||
clean-oras-cache:
|
||||
desc: Remove all cache for oras commands
|
||||
cmd: rm -rf {{ .ORAS_CACHE }}
|
||||
|
||||
clean-cache:
|
||||
desc: Remove all image docker tar cache, images from the docker daemon, and ephemeral test fixtures
|
||||
cmds:
|
||||
- task: clean-docker-cache
|
||||
- |
|
||||
BOLD='\033[1m'
|
||||
YELLOW='\033[0;33m'
|
||||
RESET='\033[0m'
|
||||
|
||||
# Use a for loop with command substitution to avoid subshell issues
|
||||
for dir in $(find . -type d -name 'test-fixtures'); do
|
||||
if [ -f "$dir/Makefile" ]; then
|
||||
echo -e "${YELLOW}${BOLD}deleting ephemeral test fixtures in $dir${RESET}"
|
||||
(make -C "$dir" clean)
|
||||
fi
|
||||
done
|
||||
echo -e "${BOLD}Deleted all ephemeral test fixtures${RESET}"
|
||||
- rm -f {{ .LAST_CACHE_PULL_FILE }} {{ .CACHE_PATHS_FILE }}
|
||||
|
||||
@@ -48,6 +48,7 @@ func create(id clio.Identification, out io.Writer) (clio.Application, *cobra.Com
|
||||
commands.Attest(app),
|
||||
commands.Convert(app),
|
||||
clio.VersionCommand(id),
|
||||
clio.ConfigCommand(app, nil),
|
||||
cranecmd.NewCmdAuthLogin(id.Name), // syft login uses the same command as crane
|
||||
)
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ type attestOptions struct {
|
||||
options.UpdateCheck `yaml:",inline" mapstructure:",squash"`
|
||||
options.Catalog `yaml:",inline" mapstructure:",squash"`
|
||||
Attest options.Attest `yaml:"attest" mapstructure:"attest"`
|
||||
Cache options.Cache `json:"-" yaml:"cache" mapstructure:"cache"`
|
||||
}
|
||||
|
||||
func Attest(app clio.Application) *cobra.Command {
|
||||
@@ -77,6 +78,7 @@ func defaultAttestOptions() attestOptions {
|
||||
Output: defaultAttestOutputOptions(),
|
||||
UpdateCheck: options.DefaultUpdateCheck(),
|
||||
Catalog: options.DefaultCatalog(),
|
||||
Cache: options.DefaultCache(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,14 +93,13 @@ func defaultAttestOutputOptions() options.Output {
|
||||
string(spdxtagvalue.ID),
|
||||
},
|
||||
Outputs: []string{syftjson.ID.String()},
|
||||
OutputFile: options.OutputFile{ // nolint:staticcheck
|
||||
OutputFile: options.OutputFile{ //nolint:staticcheck
|
||||
Enabled: false, // explicitly not allowed
|
||||
},
|
||||
Format: options.DefaultFormat(),
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:funlen
|
||||
func runAttest(ctx context.Context, id clio.Identification, opts *attestOptions, userInput string) error {
|
||||
// TODO: what other validation here besides binary name?
|
||||
if !commandExists(cosignBinName) {
|
||||
|
||||
@@ -28,7 +28,6 @@ type ConvertOptions struct {
|
||||
options.UpdateCheck `yaml:",inline" mapstructure:",squash"`
|
||||
}
|
||||
|
||||
//nolint:dupl
|
||||
func Convert(app clio.Application) *cobra.Command {
|
||||
id := app.ID()
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ type scanOptions struct {
|
||||
options.Output `yaml:",inline" mapstructure:",squash"`
|
||||
options.UpdateCheck `yaml:",inline" mapstructure:",squash"`
|
||||
options.Catalog `yaml:",inline" mapstructure:",squash"`
|
||||
Cache options.Cache `json:"-" yaml:"cache" mapstructure:"cache"`
|
||||
}
|
||||
|
||||
func defaultScanOptions() *scanOptions {
|
||||
@@ -75,10 +76,10 @@ func defaultScanOptions() *scanOptions {
|
||||
Output: options.DefaultOutput(),
|
||||
UpdateCheck: options.DefaultUpdateCheck(),
|
||||
Catalog: options.DefaultCatalog(),
|
||||
Cache: options.DefaultCache(),
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:dupl
|
||||
func Scan(app clio.Application) *cobra.Command {
|
||||
id := app.ID()
|
||||
|
||||
@@ -159,7 +160,7 @@ func validateArgs(cmd *cobra.Command, args []string, error string) error {
|
||||
if err := cmd.Help(); err != nil {
|
||||
return fmt.Errorf("unable to display help: %w", err)
|
||||
}
|
||||
return fmt.Errorf(error)
|
||||
return fmt.Errorf("%v", error)
|
||||
}
|
||||
|
||||
return cobra.MaximumNArgs(1)(cmd, args)
|
||||
@@ -394,13 +395,13 @@ func getExplanation(expErr task.ErrInvalidExpression) string {
|
||||
|
||||
if errors.Is(err, task.ErrNamesNotAllowed) {
|
||||
if expErr.Operation == task.SubSelectOperation {
|
||||
return "However, " + err.Error() + ".\nIt seems like you are intending to add a cataloger in addition to the default set." // nolint:goconst
|
||||
return "However, " + err.Error() + ".\nIt seems like you are intending to add a cataloger in addition to the default set."
|
||||
}
|
||||
return "However, " + err.Error() + "." // nolint:goconst
|
||||
return "However, " + err.Error() + "."
|
||||
}
|
||||
|
||||
if errors.Is(err, task.ErrTagsNotAllowed) {
|
||||
return "However, " + err.Error() + ".\nAdding groups of catalogers may result in surprising behavior (create inaccurate SBOMs)." // nolint:goconst
|
||||
return "However, " + err.Error() + ".\nAdding groups of catalogers may result in surprising behavior (create inaccurate SBOMs)."
|
||||
}
|
||||
|
||||
if errors.Is(err, task.ErrAllNotAllowed) {
|
||||
|
||||
@@ -12,8 +12,16 @@ type Attest struct {
|
||||
Password secret `yaml:"password" json:"password" mapstructure:"password"`
|
||||
}
|
||||
|
||||
var _ clio.FlagAdder = (*Attest)(nil)
|
||||
var _ interface {
|
||||
clio.FlagAdder
|
||||
clio.FieldDescriber
|
||||
} = (*Attest)(nil)
|
||||
|
||||
func (o *Attest) AddFlags(flags clio.FlagSet) {
|
||||
flags.StringVarP((*string)(&o.Key), "key", "k", "the key to use for the attestation")
|
||||
}
|
||||
|
||||
func (o *Attest) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.Password, `password to decrypt to given private key
|
||||
additionally responds to COSIGN_PASSWORD env var`)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/adrg/xdg"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/internal/cache"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
)
|
||||
|
||||
// Cache provides configuration for the Syft caching behavior
|
||||
type Cache struct {
|
||||
Dir string `yaml:"dir" mapstructure:"dir"`
|
||||
TTL string `yaml:"ttl" mapstructure:"ttl"`
|
||||
}
|
||||
|
||||
func (c *Cache) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&c.Dir, "root directory to cache any downloaded content; empty string will use an in-memory cache")
|
||||
descriptions.Add(&c.TTL, "time to live for cached data; setting this to 0 will disable caching entirely")
|
||||
}
|
||||
|
||||
func (c *Cache) PostLoad() error {
|
||||
ttl, err := parseDuration(c.TTL)
|
||||
if err != nil {
|
||||
log.Warnf("unable to parse duration '%v', using default (%s) due to: %v", c.TTL, durationToString(defaultTTL()), err)
|
||||
ttl = defaultTTL()
|
||||
}
|
||||
// if TTL is <= 0, disable caching entirely
|
||||
if ttl <= 0 {
|
||||
cache.SetManager(nil)
|
||||
return nil
|
||||
}
|
||||
// if dir == "" but we have a TTL, use an in-memory cache
|
||||
if c.Dir == "" {
|
||||
cache.SetManager(cache.NewInMemory(ttl))
|
||||
return nil
|
||||
}
|
||||
dir, err := homedir.Expand(c.Dir)
|
||||
if err != nil {
|
||||
log.Warnf("unable to expand cache directory %s: %v", c.Dir, err)
|
||||
cache.SetManager(cache.NewInMemory(ttl))
|
||||
} else {
|
||||
m, err := cache.NewFromDir(dir, ttl)
|
||||
if err != nil {
|
||||
log.Warnf("unable to get filesystem cache at %s: %v", c.Dir, err)
|
||||
cache.SetManager(cache.NewInMemory(ttl))
|
||||
} else {
|
||||
cache.SetManager(m)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.PostLoader
|
||||
clio.FieldDescriber
|
||||
} = (*Cache)(nil)
|
||||
|
||||
func DefaultCache() Cache {
|
||||
return Cache{
|
||||
Dir: defaultDir(),
|
||||
TTL: durationToString(defaultTTL()),
|
||||
}
|
||||
}
|
||||
|
||||
func defaultTTL() time.Duration {
|
||||
return 7 * 24 * time.Hour
|
||||
}
|
||||
|
||||
func defaultDir() string {
|
||||
var err error
|
||||
cacheRoot := xdg.CacheHome
|
||||
if cacheRoot == "" {
|
||||
cacheRoot, err = homedir.Dir()
|
||||
if err != nil {
|
||||
cacheRoot = os.TempDir()
|
||||
log.Debugf("unable to get stable cache directory due to: %v, defaulting cache to temp dir: %s", err, cacheRoot)
|
||||
} else {
|
||||
cacheRoot = filepath.Join(cacheRoot, ".cache")
|
||||
}
|
||||
}
|
||||
|
||||
return filepath.Join(cacheRoot, "syft")
|
||||
}
|
||||
|
||||
func durationToString(duration time.Duration) string {
|
||||
days := int64(duration / (24 * time.Hour))
|
||||
remain := duration % (24 * time.Hour)
|
||||
out := ""
|
||||
if days > 0 {
|
||||
out = fmt.Sprintf("%vd", days)
|
||||
}
|
||||
if remain != 0 {
|
||||
out += remain.String()
|
||||
}
|
||||
if out == "" {
|
||||
return "0"
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func parseDuration(duration string) (time.Duration, error) {
|
||||
whitespace := regexp.MustCompile(`\s+`)
|
||||
duration = strings.ToLower(whitespace.ReplaceAllString(duration, ""))
|
||||
parts := strings.SplitN(duration, "d", 2)
|
||||
var days time.Duration
|
||||
var remain time.Duration
|
||||
var err error
|
||||
if len(parts) > 1 {
|
||||
numDays, daysErr := strconv.Atoi(parts[0])
|
||||
if daysErr != nil {
|
||||
return 0, daysErr
|
||||
}
|
||||
days = time.Duration(numDays) * 24 * time.Hour
|
||||
if len(parts[1]) > 0 {
|
||||
remain, err = time.ParseDuration(parts[1])
|
||||
}
|
||||
} else {
|
||||
remain, err = time.ParseDuration(duration)
|
||||
}
|
||||
return days + remain, err
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/adrg/xdg"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/internal/cache"
|
||||
)
|
||||
|
||||
func Test_defaultDir(t *testing.T) {
|
||||
tmpDir := filepath.Join(t.TempDir(), "cache-temp")
|
||||
xdgCacheDir := filepath.Join(tmpDir, "fake-xdg-cache")
|
||||
homeDir := filepath.Join(tmpDir, "fake-home")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
env map[string]string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "no-xdg",
|
||||
env: map[string]string{
|
||||
"HOME": homeDir,
|
||||
},
|
||||
expected: homeDir,
|
||||
},
|
||||
{
|
||||
name: "xdg-cache",
|
||||
env: map[string]string{
|
||||
"XDG_CACHE_HOME": xdgCacheDir,
|
||||
},
|
||||
expected: xdgCacheDir,
|
||||
},
|
||||
}
|
||||
|
||||
// capture all the initial environment variables to reset them before we reset library caches
|
||||
env := map[string]string{
|
||||
"HOME": "",
|
||||
"XDG_DATA_HOME": "",
|
||||
"XDG_DATA_DIRS": "",
|
||||
"XDG_CONFIG_HOME": "",
|
||||
"XDG_CONFIG_DIRS": "",
|
||||
"XDG_STATE_HOME": "",
|
||||
"XDG_CACHE_HOME": "",
|
||||
"XDG_RUNTIME_DIR": "",
|
||||
}
|
||||
for k := range env {
|
||||
env[k] = os.Getenv(k)
|
||||
}
|
||||
|
||||
unsetEnv := func(t *testing.T) {
|
||||
for k := range env {
|
||||
t.Setenv(k, "")
|
||||
}
|
||||
}
|
||||
|
||||
resetEnv := func() {
|
||||
for k, v := range env {
|
||||
if v == "" {
|
||||
_ = os.Unsetenv(k)
|
||||
} else {
|
||||
_ = os.Setenv(k, v)
|
||||
}
|
||||
}
|
||||
homedir.Reset()
|
||||
xdg.Reload()
|
||||
}
|
||||
|
||||
t.Cleanup(resetEnv)
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
defer resetEnv()
|
||||
|
||||
unsetEnv(t)
|
||||
for k, v := range test.env {
|
||||
t.Setenv(k, v)
|
||||
}
|
||||
homedir.Reset()
|
||||
xdg.Reload()
|
||||
|
||||
got := defaultDir()
|
||||
|
||||
require.True(t, strings.HasPrefix(got, test.expected))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_cacheOptions(t *testing.T) {
|
||||
tmp := t.TempDir()
|
||||
tests := []struct {
|
||||
name string
|
||||
opts Cache
|
||||
test func(t *testing.T)
|
||||
}{
|
||||
{
|
||||
name: "disable-1",
|
||||
opts: Cache{
|
||||
Dir: "some-dir",
|
||||
TTL: "0",
|
||||
},
|
||||
test: func(t *testing.T) {
|
||||
c := cache.GetManager().GetCache("test-disable-1", "v-disable-1")
|
||||
err := c.Write("key-disable-1", strings.NewReader("some-value-disable-1"))
|
||||
require.NoError(t, err)
|
||||
rdr, err := c.Read("key-disable-1")
|
||||
require.Nil(t, rdr)
|
||||
require.Error(t, err)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "disable-2",
|
||||
opts: Cache{
|
||||
Dir: "some-dir",
|
||||
TTL: "0s",
|
||||
},
|
||||
test: func(t *testing.T) {
|
||||
c := cache.GetManager().GetCache("test-disable-2", "v-disable-2")
|
||||
err := c.Write("key-disable-2", strings.NewReader("some-value-disable-2"))
|
||||
require.NoError(t, err)
|
||||
rdr, err := c.Read("key-disable-2")
|
||||
require.Nil(t, rdr)
|
||||
require.Error(t, err)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "disable-3",
|
||||
opts: Cache{
|
||||
Dir: "some-dir",
|
||||
TTL: "0d",
|
||||
},
|
||||
test: func(t *testing.T) {
|
||||
c := cache.GetManager().GetCache("test-disable-3", "v-disable-3")
|
||||
err := c.Write("key-disable-3", strings.NewReader("some-value-disable-3"))
|
||||
require.NoError(t, err)
|
||||
rdr, err := c.Read("key-disable-3")
|
||||
require.Nil(t, rdr)
|
||||
require.Error(t, err)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "in-memory",
|
||||
opts: Cache{
|
||||
Dir: "",
|
||||
TTL: "10m",
|
||||
},
|
||||
test: func(t *testing.T) {
|
||||
c := cache.GetManager().GetCache("test-mem", "v-mem")
|
||||
err := c.Write("key-mem", strings.NewReader("some-value-mem"))
|
||||
require.NoError(t, err)
|
||||
rdr, err := c.Read("key-mem")
|
||||
require.NotNil(t, rdr)
|
||||
defer internal.CloseAndLogError(rdr, "")
|
||||
require.NoError(t, err)
|
||||
data, err := io.ReadAll(rdr)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "some-value-mem", string(data))
|
||||
require.NoDirExists(t, filepath.Join("test-mem", "v-mem"))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "on disk",
|
||||
opts: Cache{
|
||||
Dir: tmp,
|
||||
TTL: "10m",
|
||||
},
|
||||
test: func(t *testing.T) {
|
||||
c := cache.GetManager().GetCache("test-disk", "v-disk")
|
||||
err := c.Write("key-disk", strings.NewReader("some-value-disk"))
|
||||
require.NoError(t, err)
|
||||
rdr, err := c.Read("key-disk")
|
||||
require.NotNil(t, rdr)
|
||||
defer internal.CloseAndLogError(rdr, "")
|
||||
require.NoError(t, err)
|
||||
data, err := io.ReadAll(rdr)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "some-value-disk", string(data))
|
||||
require.DirExists(t, filepath.Join(tmp, "test-disk", "v-disk"))
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
original := cache.GetManager()
|
||||
defer cache.SetManager(original)
|
||||
|
||||
err := test.opts.PostLoad()
|
||||
require.NoError(t, err)
|
||||
|
||||
test.test(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_parseDuration(t *testing.T) {
|
||||
tests := []struct {
|
||||
duration string
|
||||
expect time.Duration
|
||||
err require.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
duration: "0d",
|
||||
expect: 0,
|
||||
},
|
||||
{
|
||||
duration: "0m",
|
||||
expect: 0,
|
||||
},
|
||||
{
|
||||
duration: "0s",
|
||||
expect: 0,
|
||||
},
|
||||
{
|
||||
duration: "0",
|
||||
expect: 0,
|
||||
},
|
||||
{
|
||||
duration: "1d",
|
||||
expect: 24 * time.Hour,
|
||||
},
|
||||
{
|
||||
duration: "7d",
|
||||
expect: 7 * 24 * time.Hour,
|
||||
},
|
||||
{
|
||||
duration: "365D",
|
||||
expect: 365 * 24 * time.Hour,
|
||||
},
|
||||
{
|
||||
duration: "7d1h1m1s",
|
||||
expect: 7*24*time.Hour + time.Hour + time.Minute + time.Second,
|
||||
},
|
||||
{
|
||||
duration: "7d 1h 1m 1s",
|
||||
expect: 7*24*time.Hour + time.Hour + time.Minute + time.Second,
|
||||
},
|
||||
{
|
||||
duration: "2h",
|
||||
expect: 2 * time.Hour,
|
||||
},
|
||||
{
|
||||
duration: "2h5m",
|
||||
expect: 2*time.Hour + 5*time.Minute,
|
||||
},
|
||||
{
|
||||
duration: "2h 5m",
|
||||
expect: 2*time.Hour + 5*time.Minute,
|
||||
},
|
||||
{
|
||||
duration: "d24h",
|
||||
err: require.Error,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.duration, func(t *testing.T) {
|
||||
got, err := parseDuration(test.duration)
|
||||
if test.err != nil {
|
||||
test.err(t, err)
|
||||
return
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
require.Equal(t, test.expect, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_durationToString(t *testing.T) {
|
||||
tests := []struct {
|
||||
duration time.Duration
|
||||
expect string
|
||||
err require.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
expect: "1d",
|
||||
duration: 24 * time.Hour,
|
||||
},
|
||||
{
|
||||
expect: "7d",
|
||||
duration: 7 * 24 * time.Hour,
|
||||
},
|
||||
{
|
||||
expect: "7d1h1m1s",
|
||||
duration: 7*24*time.Hour + time.Hour + time.Minute + time.Second,
|
||||
},
|
||||
{
|
||||
expect: "2h0m0s",
|
||||
duration: 2 * time.Hour,
|
||||
},
|
||||
{
|
||||
expect: "2h5m0s",
|
||||
duration: 2*time.Hour + 5*time.Minute,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.expect, func(t *testing.T) {
|
||||
got := durationToString(test.duration)
|
||||
require.Equal(t, test.expect, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/anchore/fangs"
|
||||
intFile "github.com/anchore/syft/internal/file"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/internal/task"
|
||||
"github.com/anchore/syft/syft"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
"github.com/anchore/syft/syft/cataloging/filecataloging"
|
||||
@@ -36,6 +37,8 @@ type Catalog struct {
|
||||
Scope string `yaml:"scope" json:"scope" mapstructure:"scope"`
|
||||
Parallelism int `yaml:"parallelism" json:"parallelism" mapstructure:"parallelism"` // the number of catalog workers to run in parallel
|
||||
Relationships relationshipsConfig `yaml:"relationships" json:"relationships" mapstructure:"relationships"`
|
||||
Compliance complianceConfig `yaml:"compliance" json:"compliance" mapstructure:"compliance"`
|
||||
Enrich []string `yaml:"enrich" json:"enrich" mapstructure:"enrich"`
|
||||
|
||||
// ecosystem-specific cataloger configuration
|
||||
Golang golangConfig `yaml:"golang" json:"golang" mapstructure:"golang"`
|
||||
@@ -50,22 +53,28 @@ type Catalog struct {
|
||||
Platform string `yaml:"platform" json:"platform" mapstructure:"platform"`
|
||||
Source sourceConfig `yaml:"source" json:"source" mapstructure:"source"`
|
||||
Exclusions []string `yaml:"exclude" json:"exclude" mapstructure:"exclude"`
|
||||
|
||||
// configuration for inclusion of unknown information within elements
|
||||
Unknowns unknownsConfig `yaml:"unknowns" mapstructure:"unknowns"`
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.FlagAdder
|
||||
clio.PostLoader
|
||||
fangs.FieldDescriber
|
||||
clio.FieldDescriber
|
||||
} = (*Catalog)(nil)
|
||||
|
||||
func DefaultCatalog() Catalog {
|
||||
return Catalog{
|
||||
Compliance: defaultComplianceConfig(),
|
||||
Scope: source.SquashedScope.String(),
|
||||
Package: defaultPackageConfig(),
|
||||
LinuxKernel: defaultLinuxKernelConfig(),
|
||||
Golang: defaultGolangConfig(),
|
||||
Java: defaultJavaConfig(),
|
||||
File: defaultFileConfig(),
|
||||
Relationships: defaultRelationshipsConfig(),
|
||||
Unknowns: defaultUnknowns(),
|
||||
Source: defaultSourceConfig(),
|
||||
Parallelism: 1,
|
||||
}
|
||||
@@ -76,6 +85,8 @@ func (cfg Catalog) ToSBOMConfig(id clio.Identification) *syft.CreateSBOMConfig {
|
||||
WithTool(id.Name, id.Version).
|
||||
WithParallelism(cfg.Parallelism).
|
||||
WithRelationshipsConfig(cfg.ToRelationshipsConfig()).
|
||||
WithComplianceConfig(cfg.ToComplianceConfig()).
|
||||
WithUnknownsConfig(cfg.ToUnknownsConfig()).
|
||||
WithSearchConfig(cfg.ToSearchConfig()).
|
||||
WithPackagesConfig(cfg.ToPackagesConfig()).
|
||||
WithFilesConfig(cfg.ToFilesConfig()).
|
||||
@@ -101,6 +112,20 @@ func (cfg Catalog) ToRelationshipsConfig() cataloging.RelationshipsConfig {
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg Catalog) ToComplianceConfig() cataloging.ComplianceConfig {
|
||||
return cataloging.ComplianceConfig{
|
||||
MissingName: cfg.Compliance.MissingName,
|
||||
MissingVersion: cfg.Compliance.MissingVersion,
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg Catalog) ToUnknownsConfig() cataloging.UnknownsConfig {
|
||||
return cataloging.UnknownsConfig{
|
||||
IncludeExecutablesWithoutPackages: cfg.Unknowns.ExecutablesWithoutPackages,
|
||||
IncludeUnexpandedArchives: cfg.Unknowns.UnexpandedArchives,
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg Catalog) ToFilesConfig() filecataloging.Config {
|
||||
hashers, err := intFile.Hashers(cfg.File.Metadata.Digests...)
|
||||
if err != nil {
|
||||
@@ -129,9 +154,9 @@ func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config {
|
||||
return pkgcataloging.Config{
|
||||
Binary: binary.DefaultClassifierCatalogerConfig(),
|
||||
Golang: golang.DefaultCatalogerConfig().
|
||||
WithSearchLocalModCacheLicenses(cfg.Golang.SearchLocalModCacheLicenses).
|
||||
WithSearchLocalModCacheLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Go, task.Golang), cfg.Golang.SearchLocalModCacheLicenses)).
|
||||
WithLocalModCacheDir(cfg.Golang.LocalModCacheDir).
|
||||
WithSearchRemoteLicenses(cfg.Golang.SearchRemoteLicenses).
|
||||
WithSearchRemoteLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Go, task.Golang), cfg.Golang.SearchRemoteLicenses)).
|
||||
WithProxy(cfg.Golang.Proxy).
|
||||
WithNoProxy(cfg.Golang.NoProxy).
|
||||
WithMainModuleVersion(
|
||||
@@ -141,7 +166,7 @@ func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config {
|
||||
WithFromLDFlags(cfg.Golang.MainModuleVersion.FromLDFlags),
|
||||
),
|
||||
JavaScript: javascript.DefaultCatalogerConfig().
|
||||
WithSearchRemoteLicenses(cfg.JavaScript.SearchRemoteLicenses).
|
||||
WithSearchRemoteLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.JavaScript, task.Node, task.NPM), cfg.JavaScript.SearchRemoteLicenses)).
|
||||
WithNpmBaseURL(cfg.JavaScript.NpmBaseURL),
|
||||
LinuxKernel: kernel.LinuxKernelCatalogerConfig{
|
||||
CatalogModules: cfg.LinuxKernel.CatalogModules,
|
||||
@@ -150,7 +175,9 @@ func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config {
|
||||
GuessUnpinnedRequirements: cfg.Python.GuessUnpinnedRequirements,
|
||||
},
|
||||
JavaArchive: java.DefaultArchiveCatalogerConfig().
|
||||
WithUseNetwork(cfg.Java.UseNetwork).
|
||||
WithUseMavenLocalRepository(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Java, task.Maven), cfg.Java.UseMavenLocalRepository)).
|
||||
WithMavenLocalRepositoryDir(cfg.Java.MavenLocalRepositoryDir).
|
||||
WithUseNetwork(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Java, task.Maven), cfg.Java.UseNetwork)).
|
||||
WithMavenBaseURL(cfg.Java.MavenURL).
|
||||
WithArchiveTraversal(archiveSearch, cfg.Java.MaxParentRecursiveDepth),
|
||||
}
|
||||
@@ -190,6 +217,9 @@ func (cfg *Catalog) AddFlags(flags clio.FlagSet) {
|
||||
flags.StringArrayVarP(&cfg.SelectCatalogers, "select-catalogers", "",
|
||||
"add, remove, and filter the catalogers to be used")
|
||||
|
||||
flags.StringArrayVarP(&cfg.Enrich, "enrich", "",
|
||||
fmt.Sprintf("enable package data enrichment from local and online sources (options: %s)", strings.Join(publicisedEnrichmentOptions, ", ")))
|
||||
|
||||
flags.StringVarP(&cfg.Source.Name, "source-name", "",
|
||||
"set the name of the target being analyzed")
|
||||
|
||||
@@ -202,6 +232,10 @@ func (cfg *Catalog) AddFlags(flags clio.FlagSet) {
|
||||
|
||||
func (cfg *Catalog) DescribeFields(descriptions fangs.FieldDescriptionSet) {
|
||||
descriptions.Add(&cfg.Parallelism, "number of cataloger workers to run in parallel")
|
||||
|
||||
descriptions.Add(&cfg.Enrich, fmt.Sprintf(`Enable data enrichment operations, which can utilize services such as Maven Central and NPM.
|
||||
By default all enrichment is disabled, use: all to enable everything.
|
||||
Available options are: %s`, strings.Join(publicisedEnrichmentOptions, ", ")))
|
||||
}
|
||||
|
||||
func (cfg *Catalog) PostLoad() error {
|
||||
@@ -212,23 +246,12 @@ func (cfg *Catalog) PostLoad() error {
|
||||
return fmt.Errorf("cannot use both 'catalogers' and 'select-catalogers'/'default-catalogers' flags")
|
||||
}
|
||||
|
||||
flatten := func(l []string) []string {
|
||||
var out []string
|
||||
for _, v := range l {
|
||||
for _, s := range strings.Split(v, ",") {
|
||||
out = append(out, strings.TrimSpace(s))
|
||||
}
|
||||
}
|
||||
sort.Strings(out)
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
cfg.From = flatten(cfg.From)
|
||||
|
||||
cfg.Catalogers = flatten(cfg.Catalogers)
|
||||
cfg.DefaultCatalogers = flatten(cfg.DefaultCatalogers)
|
||||
cfg.SelectCatalogers = flatten(cfg.SelectCatalogers)
|
||||
cfg.Enrich = flatten(cfg.Enrich)
|
||||
|
||||
// for backwards compatibility
|
||||
cfg.DefaultCatalogers = append(cfg.DefaultCatalogers, cfg.Catalogers...)
|
||||
@@ -238,5 +261,75 @@ func (cfg *Catalog) PostLoad() error {
|
||||
return fmt.Errorf("bad scope value %q", cfg.Scope)
|
||||
}
|
||||
|
||||
// the binary package exclusion code depends on the file overlap relationships being created upstream in processing
|
||||
if !cfg.Relationships.PackageFileOwnershipOverlap && cfg.Package.ExcludeBinaryOverlapByOwnership {
|
||||
return fmt.Errorf("cannot enable exclude-binary-overlap-by-ownership without enabling package-file-ownership-overlap")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func flatten(commaSeparatedEntries []string) []string {
|
||||
var out []string
|
||||
for _, v := range commaSeparatedEntries {
|
||||
for _, s := range strings.Split(v, ",") {
|
||||
out = append(out, strings.TrimSpace(s))
|
||||
}
|
||||
}
|
||||
sort.Strings(out)
|
||||
return out
|
||||
}
|
||||
|
||||
var publicisedEnrichmentOptions = []string{
|
||||
"all",
|
||||
task.Golang,
|
||||
task.Java,
|
||||
task.JavaScript,
|
||||
}
|
||||
|
||||
func enrichmentEnabled(enrichDirectives []string, features ...string) *bool {
|
||||
if len(enrichDirectives) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
enabled := func(features ...string) *bool {
|
||||
for _, directive := range enrichDirectives {
|
||||
enable := true
|
||||
directive = strings.TrimPrefix(directive, "+") // +java and java are equivalent
|
||||
if strings.HasPrefix(directive, "-") {
|
||||
directive = directive[1:]
|
||||
enable = false
|
||||
}
|
||||
for _, feature := range features {
|
||||
if directive == feature {
|
||||
return &enable
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
enableAll := enabled("all")
|
||||
disableAll := enabled("none")
|
||||
|
||||
if disableAll != nil && *disableAll {
|
||||
if enableAll != nil {
|
||||
log.Warn("you have specified to both enable and disable all enrichment functionality, defaulting to disabled")
|
||||
}
|
||||
enableAll = ptr(false)
|
||||
}
|
||||
|
||||
// check for explicit enable/disable of feature names
|
||||
for _, feat := range features {
|
||||
enableFeature := enabled(feat)
|
||||
if enableFeature != nil {
|
||||
return enableFeature
|
||||
}
|
||||
}
|
||||
|
||||
return enableAll
|
||||
}
|
||||
|
||||
func ptr[T any](val T) *T {
|
||||
return &val
|
||||
}
|
||||
|
||||
@@ -57,6 +57,14 @@ func TestCatalog_PostLoad(t *testing.T) {
|
||||
assert.Empty(t, options.Catalogers)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "must have package overlap flag when pruning binaries by overlap",
|
||||
options: Catalog{
|
||||
Package: packageConfig{ExcludeBinaryOverlapByOwnership: true},
|
||||
Relationships: relationshipsConfig{PackageFileOwnershipOverlap: false},
|
||||
},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -70,3 +78,69 @@ func TestCatalog_PostLoad(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_enrichmentEnabled(t *testing.T) {
|
||||
tests := []struct {
|
||||
directives string
|
||||
test string
|
||||
expected *bool
|
||||
}{
|
||||
{
|
||||
directives: "",
|
||||
test: "java",
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
directives: "none",
|
||||
test: "java",
|
||||
expected: ptr(false),
|
||||
},
|
||||
{
|
||||
directives: "none,+java",
|
||||
test: "java",
|
||||
expected: ptr(true),
|
||||
},
|
||||
{
|
||||
directives: "all,none",
|
||||
test: "java",
|
||||
expected: ptr(false),
|
||||
},
|
||||
{
|
||||
directives: "all",
|
||||
test: "java",
|
||||
expected: ptr(true),
|
||||
},
|
||||
{
|
||||
directives: "golang,js",
|
||||
test: "java",
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
directives: "golang,-js,java",
|
||||
test: "java",
|
||||
expected: ptr(true),
|
||||
},
|
||||
{
|
||||
directives: "golang,js,-java",
|
||||
test: "java",
|
||||
expected: ptr(false),
|
||||
},
|
||||
{
|
||||
directives: "all",
|
||||
test: "java",
|
||||
expected: ptr(true),
|
||||
},
|
||||
{
|
||||
directives: "all,-java",
|
||||
test: "java",
|
||||
expected: ptr(false),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.directives, func(t *testing.T) {
|
||||
got := enrichmentEnabled(flatten([]string{test.directives}), test.test)
|
||||
assert.Equal(t, test.expected, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/anchore/fangs"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
)
|
||||
|
||||
var (
|
||||
_ fangs.FieldDescriber = (*complianceConfig)(nil)
|
||||
_ fangs.PostLoader = (*complianceConfig)(nil)
|
||||
)
|
||||
|
||||
type complianceConfig struct {
|
||||
MissingName cataloging.ComplianceAction `mapstructure:"missing-name" json:"missing-name" yaml:"missing-name"`
|
||||
MissingVersion cataloging.ComplianceAction `mapstructure:"missing-version" json:"missing-version" yaml:"missing-version"`
|
||||
}
|
||||
|
||||
func defaultComplianceConfig() complianceConfig {
|
||||
def := cataloging.DefaultComplianceConfig()
|
||||
return complianceConfig{
|
||||
MissingName: def.MissingName,
|
||||
MissingVersion: def.MissingVersion,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *complianceConfig) DescribeFields(descriptions fangs.FieldDescriptionSet) {
|
||||
descriptions.Add(&r.MissingName, "action to take when a package is missing a name")
|
||||
descriptions.Add(&r.MissingVersion, "action to take when a package is missing a version")
|
||||
}
|
||||
|
||||
func (r *complianceConfig) PostLoad() error {
|
||||
r.MissingName = r.MissingName.Parse()
|
||||
r.MissingVersion = r.MissingVersion.Parse()
|
||||
return nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/scylladb/go-set/strset"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
intFile "github.com/anchore/syft/internal/file"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
)
|
||||
@@ -45,6 +46,11 @@ func defaultFileConfig() fileConfig {
|
||||
}
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.PostLoader
|
||||
clio.FieldDescriber
|
||||
} = (*fileConfig)(nil)
|
||||
|
||||
func (c *fileConfig) PostLoad() error {
|
||||
digests := strset.New(c.Metadata.Digests...).List()
|
||||
sort.Strings(digests)
|
||||
@@ -56,3 +62,17 @@ func (c *fileConfig) PostLoad() error {
|
||||
}
|
||||
return fmt.Errorf("invalid file metadata selection: %q", c.Metadata.Selection)
|
||||
}
|
||||
|
||||
func (c *fileConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&c.Metadata.Selection, `select which files should be captured by the file-metadata cataloger and included in the SBOM.
|
||||
Options include:
|
||||
- "all": capture all files from the search space
|
||||
- "owned-by-package": capture only files owned by packages
|
||||
- "none", "": do not capture any files`)
|
||||
descriptions.Add(&c.Metadata.Digests, `the file digest algorithms to use when cataloging files (options: "md5", "sha1", "sha224", "sha256", "sha384", "sha512")`)
|
||||
|
||||
descriptions.Add(&c.Content.SkipFilesAboveSize, `skip searching a file entirely if it is above the given size (default = 1MB; unit = bytes)`)
|
||||
descriptions.Add(&c.Content.Globs, `file globs for the cataloger to match on`)
|
||||
|
||||
descriptions.Add(&c.Executable.Globs, `file globs for the cataloger to match on`)
|
||||
}
|
||||
|
||||
@@ -7,16 +7,19 @@ import (
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
var _ clio.PostLoader = (*Format)(nil)
|
||||
var _ interface {
|
||||
clio.PostLoader
|
||||
clio.FieldDescriber
|
||||
} = (*Format)(nil)
|
||||
|
||||
// Format contains all user configuration for output formatting.
|
||||
type Format struct {
|
||||
Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"`
|
||||
Template FormatTemplate `yaml:"template" json:"template" mapstructure:"template"`
|
||||
SyftJSON FormatSyftJSON `yaml:"json" json:"json" mapstructure:"json"`
|
||||
SPDXJSON FormatSPDXJSON `yaml:"spdx-json" json:"spdx-json" mapstructure:"spdx-json"`
|
||||
CyclonedxJSON FormatCyclonedxJSON `yaml:"cyclonedx-json" json:"cyclonedx-json" mapstructure:"cyclonedx-json"`
|
||||
CyclonedxXML FormatCyclonedxXML `yaml:"cyclonedx-xml" json:"cyclonedx-xml" mapstructure:"cyclonedx-xml"`
|
||||
Template FormatTemplate `yaml:"template" json:"template" mapstructure:"template" description:"all template format options"`
|
||||
SyftJSON FormatSyftJSON `yaml:"json" json:"json" mapstructure:"json" description:"all syft-json format options"`
|
||||
SPDXJSON FormatSPDXJSON `yaml:"spdx-json" json:"spdx-json" mapstructure:"spdx-json" description:"all spdx-json format options"`
|
||||
CyclonedxJSON FormatCyclonedxJSON `yaml:"cyclonedx-json" json:"cyclonedx-json" mapstructure:"cyclonedx-json" description:"all cyclonedx-json format options"`
|
||||
CyclonedxXML FormatCyclonedxXML `yaml:"cyclonedx-xml" json:"cyclonedx-xml" mapstructure:"cyclonedx-xml" description:"all cyclonedx-xml format options"`
|
||||
}
|
||||
|
||||
func (o *Format) PostLoad() error {
|
||||
@@ -28,6 +31,33 @@ func (o *Format) PostLoad() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Format) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.Pretty, `default value for all formats that support the "pretty" option (default is unset)`)
|
||||
descriptions.Add(&o.SyftJSON, `all syft-json format options`)
|
||||
descriptions.Add(&o.SyftJSON.Legacy, `transform any syft-json output to conform to an approximation of the v11.0.1 schema. This includes:
|
||||
- using the package metadata type names from before v12 of the JSON schema (changed in https://github.com/anchore/syft/pull/1983)
|
||||
|
||||
Note: this will still include package types and fields that were added at or after json schema v12. This means
|
||||
that output might not strictly be json schema v11 compliant, however, for consumers that require time to port
|
||||
over to the final syft 1.0 json output this option can be used to ease the transition.
|
||||
|
||||
Note: long term support for this option is not guaranteed (it may change or break at any time)`)
|
||||
|
||||
descriptions.Add(&o.Template.Path, `path to the template file to use when rendering the output with the template output format.
|
||||
Note that all template paths are based on the current syft-json schema`)
|
||||
descriptions.Add(&o.Template.Legacy, `if true, uses the go structs for the syft-json format for templating.
|
||||
if false, uses the syft-json output for templating (which follows the syft JSON schema exactly).
|
||||
|
||||
Note: long term support for this option is not guaranteed (it may change or break at any time)`)
|
||||
|
||||
prettyDescription := `include space indentation and newlines
|
||||
note: inherits default value from 'format.pretty' or 'false' if parent is unset`
|
||||
descriptions.Add(&o.SyftJSON.Pretty, prettyDescription)
|
||||
descriptions.Add(&o.SPDXJSON.Pretty, prettyDescription)
|
||||
descriptions.Add(&o.CyclonedxJSON.Pretty, prettyDescription)
|
||||
descriptions.Add(&o.CyclonedxXML.Pretty, prettyDescription)
|
||||
}
|
||||
|
||||
func DefaultFormat() Format {
|
||||
return Format{
|
||||
Template: DefaultFormatTemplate(),
|
||||
|
||||
@@ -3,18 +3,41 @@ package options
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/golang"
|
||||
)
|
||||
|
||||
type golangConfig struct {
|
||||
SearchLocalModCacheLicenses bool `json:"search-local-mod-cache-licenses" yaml:"search-local-mod-cache-licenses" mapstructure:"search-local-mod-cache-licenses"`
|
||||
SearchLocalModCacheLicenses *bool `json:"search-local-mod-cache-licenses" yaml:"search-local-mod-cache-licenses" mapstructure:"search-local-mod-cache-licenses"`
|
||||
LocalModCacheDir string `json:"local-mod-cache-dir" yaml:"local-mod-cache-dir" mapstructure:"local-mod-cache-dir"`
|
||||
SearchRemoteLicenses bool `json:"search-remote-licenses" yaml:"search-remote-licenses" mapstructure:"search-remote-licenses"`
|
||||
SearchRemoteLicenses *bool `json:"search-remote-licenses" yaml:"search-remote-licenses" mapstructure:"search-remote-licenses"`
|
||||
Proxy string `json:"proxy" yaml:"proxy" mapstructure:"proxy"`
|
||||
NoProxy string `json:"no-proxy" yaml:"no-proxy" mapstructure:"no-proxy"`
|
||||
MainModuleVersion golangMainModuleVersionConfig `json:"main-module-version" yaml:"main-module-version" mapstructure:"main-module-version"`
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.FieldDescriber
|
||||
} = (*golangConfig)(nil)
|
||||
|
||||
func (o *golangConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.SearchLocalModCacheLicenses, `search for go package licences in the GOPATH of the system running Syft, note that this is outside the
|
||||
container filesystem and potentially outside the root of a local directory scan`)
|
||||
descriptions.Add(&o.LocalModCacheDir, `specify an explicit go mod cache directory, if unset this defaults to $GOPATH/pkg/mod or $HOME/go/pkg/mod`)
|
||||
descriptions.Add(&o.SearchRemoteLicenses, `search for go package licences by retrieving the package from a network proxy`)
|
||||
descriptions.Add(&o.Proxy, `remote proxy to use when retrieving go packages from the network,
|
||||
if unset this defaults to $GOPROXY followed by https://proxy.golang.org`)
|
||||
descriptions.Add(&o.NoProxy, `specifies packages which should not be fetched by proxy
|
||||
if unset this defaults to $GONOPROXY`)
|
||||
descriptions.Add(&o.MainModuleVersion, `the go main module version discovered from binaries built with the go compiler will
|
||||
always show (devel) as the version. Use these options to control heuristics to guess
|
||||
a more accurate version from the binary.`)
|
||||
descriptions.Add(&o.MainModuleVersion.FromLDFlags, `look for LD flags that appear to be setting a version (e.g. -X main.version=1.0.0)`)
|
||||
descriptions.Add(&o.MainModuleVersion.FromBuildSettings, `use the build settings (e.g. vcs.version & vcs.time) to craft a v0 pseudo version
|
||||
(e.g. v0.0.0-20220308212642-53e6d0aaf6fb) when a more accurate version cannot be found otherwise`)
|
||||
descriptions.Add(&o.MainModuleVersion.FromContents, `search for semver-like strings in the binary contents`)
|
||||
}
|
||||
|
||||
type golangMainModuleVersionConfig struct {
|
||||
FromLDFlags bool `json:"from-ld-flags" yaml:"from-ld-flags" mapstructure:"from-ld-flags"`
|
||||
FromContents bool `json:"from-contents" yaml:"from-contents" mapstructure:"from-contents"`
|
||||
@@ -24,9 +47,9 @@ type golangMainModuleVersionConfig struct {
|
||||
func defaultGolangConfig() golangConfig {
|
||||
def := golang.DefaultCatalogerConfig()
|
||||
return golangConfig{
|
||||
SearchLocalModCacheLicenses: def.SearchLocalModCacheLicenses,
|
||||
SearchLocalModCacheLicenses: nil, // this defaults to false, which is the API default
|
||||
LocalModCacheDir: def.LocalModCacheDir,
|
||||
SearchRemoteLicenses: def.SearchRemoteLicenses,
|
||||
SearchRemoteLicenses: nil, // this defaults to false, which is the API default
|
||||
Proxy: strings.Join(def.Proxies, ","),
|
||||
NoProxy: strings.Join(def.NoProxy, ","),
|
||||
MainModuleVersion: golangMainModuleVersionConfig{
|
||||
|
||||
@@ -1,7 +1,46 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/java"
|
||||
)
|
||||
|
||||
type javaConfig struct {
|
||||
UseNetwork bool `yaml:"use-network" json:"use-network" mapstructure:"use-network"`
|
||||
UseNetwork *bool `yaml:"use-network" json:"use-network" mapstructure:"use-network"`
|
||||
UseMavenLocalRepository *bool `yaml:"use-maven-local-repository" json:"use-maven-local-repository" mapstructure:"use-maven-local-repository"`
|
||||
MavenLocalRepositoryDir string `yaml:"maven-local-repository-dir" json:"maven-local-repository-dir" mapstructure:"maven-local-repository-dir"`
|
||||
MavenURL string `yaml:"maven-url" json:"maven-url" mapstructure:"maven-url"`
|
||||
MaxParentRecursiveDepth int `yaml:"max-parent-recursive-depth" json:"max-parent-recursive-depth" mapstructure:"max-parent-recursive-depth"`
|
||||
}
|
||||
|
||||
func defaultJavaConfig() javaConfig {
|
||||
def := java.DefaultArchiveCatalogerConfig()
|
||||
|
||||
return javaConfig{
|
||||
UseNetwork: nil, // this defaults to false, which is the API default
|
||||
MaxParentRecursiveDepth: def.MaxParentRecursiveDepth,
|
||||
UseMavenLocalRepository: nil, // this defaults to false, which is the API default
|
||||
MavenLocalRepositoryDir: def.MavenLocalRepositoryDir,
|
||||
MavenURL: def.MavenBaseURL,
|
||||
}
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.FieldDescriber
|
||||
} = (*javaConfig)(nil)
|
||||
|
||||
func (o *javaConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.UseNetwork, `enables Syft to use the network to fetch version and license information for packages when
|
||||
a parent or imported pom file is not found in the local maven repository.
|
||||
the pom files are downloaded from the remote Maven repository at 'maven-url'`)
|
||||
descriptions.Add(&o.MavenURL, `maven repository to use, defaults to Maven central`)
|
||||
descriptions.Add(&o.MaxParentRecursiveDepth, `depth to recursively resolve parent POMs, no limit if <= 0`)
|
||||
descriptions.Add(&o.UseMavenLocalRepository, `use the local Maven repository to retrieve pom files. When Maven is installed and was previously used
|
||||
for building the software that is being scanned, then most pom files will be available in this
|
||||
repository on the local file system. this greatly speeds up scans. when all pom files are available
|
||||
in the local repository, then 'use-network' is not needed.
|
||||
TIP: If you want to download all required pom files to the local repository without running a full
|
||||
build, run 'mvn help:effective-pom' before performing the scan with syft.`)
|
||||
descriptions.Add(&o.MavenLocalRepositoryDir, `override the default location of the local Maven repository.
|
||||
the default is the subdirectory '.m2/repository' in your home directory`)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
package options
|
||||
|
||||
import "github.com/anchore/clio"
|
||||
|
||||
type javaScriptConfig struct {
|
||||
SearchRemoteLicenses bool `json:"search-remote-licenses" yaml:"search-remote-licenses" mapstructure:"search-remote-licenses"`
|
||||
SearchRemoteLicenses *bool `json:"search-remote-licenses" yaml:"search-remote-licenses" mapstructure:"search-remote-licenses"`
|
||||
NpmBaseURL string `json:"npm-base-url" yaml:"npm-base-url" mapstructure:"npm-base-url"`
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.FieldDescriber
|
||||
} = (*javaScriptConfig)(nil)
|
||||
|
||||
func (o *javaScriptConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.SearchRemoteLicenses, `enables Syft to use the network to fill in more detailed license information`)
|
||||
descriptions.Add(&o.NpmBaseURL, `base NPM url to use`)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package options
|
||||
|
||||
import "github.com/anchore/clio"
|
||||
|
||||
type linuxKernelConfig struct {
|
||||
CatalogModules bool `json:"catalog-modules" yaml:"catalog-modules" mapstructure:"catalog-modules"`
|
||||
}
|
||||
@@ -9,3 +11,11 @@ func defaultLinuxKernelConfig() linuxKernelConfig {
|
||||
CatalogModules: true,
|
||||
}
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.FieldDescriber
|
||||
} = (*linuxKernelConfig)(nil)
|
||||
|
||||
func (o *linuxKernelConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.CatalogModules, `whether to catalog linux kernel modules found within lib/modules/** directories`)
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
var _ interface {
|
||||
clio.FlagAdder
|
||||
clio.PostLoader
|
||||
clio.FieldDescriber
|
||||
} = (*Output)(nil)
|
||||
|
||||
// Output has the standard output options syft accepts: multiple -o, --file, --template
|
||||
@@ -70,6 +71,15 @@ func (o *Output) AddFlags(flags clio.FlagSet) {
|
||||
fmt.Sprintf("report output format (<format>=<file> to output to a file), formats=%v", names))
|
||||
}
|
||||
|
||||
func (o *Output) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.Outputs, `the output format(s) of the SBOM report (options: syft-table, syft-text, syft-json, spdx-json, ...)
|
||||
to specify multiple output files in differing formats, use a list:
|
||||
output:
|
||||
- "syft-json=<syft-json-output-file>"
|
||||
- "spdx-json=<spdx-json-output-file>"
|
||||
`)
|
||||
}
|
||||
|
||||
func (o Output) SBOMWriter() (sbom.Writer, error) {
|
||||
names := o.OutputNameSet()
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ func (o *OutputFile) AddFlags(flags clio.FlagSet) {
|
||||
|
||||
if pfp, ok := flags.(fangs.PFlagSetProvider); ok {
|
||||
flagSet := pfp.PFlagSet()
|
||||
flagSet.Lookup("file").Deprecated = "use: output"
|
||||
flagSet.Lookup("file").Deprecated = "use: --output FORMAT=PATH"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package options
|
||||
|
||||
import "github.com/anchore/syft/syft/cataloging"
|
||||
import (
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
)
|
||||
|
||||
type packageConfig struct {
|
||||
SearchUnindexedArchives bool `yaml:"search-unindexed-archives" json:"search-unindexed-archives" mapstructure:"search-unindexed-archives"`
|
||||
@@ -8,6 +11,20 @@ type packageConfig struct {
|
||||
ExcludeBinaryOverlapByOwnership bool `yaml:"exclude-binary-overlap-by-ownership" json:"exclude-binary-overlap-by-ownership" mapstructure:"exclude-binary-overlap-by-ownership"` // exclude synthetic binary packages owned by os package files
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.FieldDescriber
|
||||
} = (*packageConfig)(nil)
|
||||
|
||||
func (o *packageConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.SearchUnindexedArchives, `search within archives that do contain a file index to search against (zip)
|
||||
note: for now this only applies to the java package cataloger`)
|
||||
descriptions.Add(&o.SearchIndexedArchives, `search within archives that do not contain a file index to search against (tar, tar.gz, tar.bz2, etc)
|
||||
note: enabling this may result in a performance impact since all discovered compressed tars will be decompressed
|
||||
note: for now this only applies to the java package cataloger`)
|
||||
descriptions.Add(&o.ExcludeBinaryOverlapByOwnership, `allows users to exclude synthetic binary packages from the sbom
|
||||
these packages are removed if an overlap with a non-synthetic package is found`)
|
||||
}
|
||||
|
||||
func defaultPackageConfig() packageConfig {
|
||||
c := cataloging.DefaultArchiveSearchConfig()
|
||||
return packageConfig{
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
package options
|
||||
|
||||
import "github.com/anchore/clio"
|
||||
|
||||
type pythonConfig struct {
|
||||
GuessUnpinnedRequirements bool `json:"guess-unpinned-requirements" yaml:"guess-unpinned-requirements" mapstructure:"guess-unpinned-requirements"`
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.FieldDescriber
|
||||
} = (*pythonConfig)(nil)
|
||||
|
||||
func (o *pythonConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.GuessUnpinnedRequirements, `when running across entries in requirements.txt that do not specify a specific version
|
||||
(e.g. "sqlalchemy >= 1.0.0, <= 2.0.0, != 3.0.0, <= 3.0.0"), attempt to guess what the version could
|
||||
be based on the version requirements specified (e.g. "1.0.0"). When enabled the lowest expressible version
|
||||
when given an arbitrary constraint will be used (even if that version may not be available/published).`)
|
||||
}
|
||||
|
||||
@@ -25,7 +25,10 @@ type registryConfig struct {
|
||||
CACert string `yaml:"ca-cert" json:"ca-cert" mapstructure:"ca-cert"`
|
||||
}
|
||||
|
||||
var _ clio.PostLoader = (*registryConfig)(nil)
|
||||
var _ interface {
|
||||
clio.PostLoader
|
||||
clio.FieldDescriber
|
||||
} = (*registryConfig)(nil)
|
||||
|
||||
func (cfg *registryConfig) PostLoad() error {
|
||||
// there may be additional credentials provided by env var that should be appended to the set of credentials
|
||||
@@ -55,6 +58,20 @@ func (cfg *registryConfig) PostLoad() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfg *registryConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&cfg.InsecureSkipTLSVerify, "skip TLS verification when communicating with the registry")
|
||||
descriptions.Add(&cfg.InsecureUseHTTP, "use http instead of https when connecting to the registry")
|
||||
descriptions.Add(&cfg.CACert, "filepath to a CA certificate (or directory containing *.crt, *.cert, *.pem) used to generate the client certificate")
|
||||
descriptions.Add(&cfg.Auth, `Authentication credentials for specific registries. Each entry describes authentication for a specific authority:
|
||||
- authority: the registry authority URL the URL to the registry (e.g. "docker.io", "localhost:5000", etc.) (env: SYFT_REGISTRY_AUTH_AUTHORITY)
|
||||
username: a username if using basic credentials (env: SYFT_REGISTRY_AUTH_USERNAME)
|
||||
password: a corresponding password (env: SYFT_REGISTRY_AUTH_PASSWORD)
|
||||
token: a token if using token-based authentication, mutually exclusive with username/password (env: SYFT_REGISTRY_AUTH_TOKEN)
|
||||
tls-cert: filepath to the client certificate used for TLS authentication to the registry (env: SYFT_REGISTRY_AUTH_TLS_CERT)
|
||||
tls-key: filepath to the client key used for TLS authentication to the registry (env: SYFT_REGISTRY_AUTH_TLS_KEY)
|
||||
`)
|
||||
}
|
||||
|
||||
func hasNonEmptyCredentials(username, password, token, tlsCert, tlsKey string) bool {
|
||||
hasUserPass := username != "" && password != ""
|
||||
hasToken := token != ""
|
||||
|
||||
@@ -17,6 +17,6 @@ func defaultRelationshipsConfig() relationshipsConfig {
|
||||
}
|
||||
|
||||
func (r *relationshipsConfig) DescribeFields(descriptions fangs.FieldDescriptionSet) {
|
||||
descriptions.Add(&r.PackageFileOwnership, "include package-to-file relationships that indicate which files are owned by which packages.")
|
||||
descriptions.Add(&r.PackageFileOwnershipOverlap, "include package-to-package relationships that indicate one package is owned by another due to files claimed to be owned by one package are also evidence of another package's existence.")
|
||||
descriptions.Add(&r.PackageFileOwnership, "include package-to-file relationships that indicate which files are owned by which packages")
|
||||
descriptions.Add(&r.PackageFileOwnershipOverlap, "include package-to-package relationships that indicate one package is owned by another due to files claimed to be owned by one package are also evidence of another package's existence")
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/scylladb/go-set/strset"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/syft/source/sourceproviders"
|
||||
)
|
||||
|
||||
@@ -22,6 +23,16 @@ type fileSource struct {
|
||||
Digests []string `json:"digests" yaml:"digests" mapstructure:"digests"`
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.FieldDescriber
|
||||
} = (*sourceConfig)(nil)
|
||||
|
||||
func (o *sourceConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.File.Digests, `the file digest algorithms to use on the scanned file (options: "md5", "sha1", "sha224", "sha256", "sha384", "sha512")`)
|
||||
descriptions.Add(&o.Image.DefaultPullSource, `allows users to specify which image source should be used to generate the sbom
|
||||
valid values are: registry, docker, podman`)
|
||||
}
|
||||
|
||||
type imageSource struct {
|
||||
DefaultPullSource string `json:"default-pull-source" yaml:"default-pull-source" mapstructure:"default-pull-source"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
)
|
||||
|
||||
type unknownsConfig struct {
|
||||
RemoveWhenPackagesDefined bool `json:"remove-when-packages-defined" yaml:"remove-when-packages-defined" mapstructure:"remove-when-packages-defined"`
|
||||
ExecutablesWithoutPackages bool `json:"executables-without-packages" yaml:"executables-without-packages" mapstructure:"executables-without-packages"`
|
||||
UnexpandedArchives bool `json:"unexpanded-archives" yaml:"unexpanded-archives" mapstructure:"unexpanded-archives"`
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.FieldDescriber
|
||||
} = (*unknownsConfig)(nil)
|
||||
|
||||
func (o *unknownsConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.RemoveWhenPackagesDefined, `remove unknown errors on files with discovered packages`)
|
||||
descriptions.Add(&o.ExecutablesWithoutPackages, `include executables without any identified packages`)
|
||||
descriptions.Add(&o.UnexpandedArchives, `include archives which were not expanded and searched`)
|
||||
}
|
||||
|
||||
func defaultUnknowns() unknownsConfig {
|
||||
def := cataloging.DefaultUnknownsConfig()
|
||||
return unknownsConfig{
|
||||
RemoveWhenPackagesDefined: def.RemoveWhenPackagesDefined,
|
||||
ExecutablesWithoutPackages: def.IncludeExecutablesWithoutPackages,
|
||||
UnexpandedArchives: def.IncludeUnexpandedArchives,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
results
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
func Test_AllLayersIncludesSquashed(t *testing.T) {
|
||||
// This is a verification test for issue #894 (https://github.com/anchore/syft/issues/894)
|
||||
// This is a verification test for issue grype/#894 (https://github.com/anchore/grype/issues/894)
|
||||
allLayers, _ := catalogFixtureImage(t, "image-suse-all-layers", source.AllLayersScope)
|
||||
squashed, _ := catalogFixtureImage(t, "image-suse-all-layers", source.SquashedScope)
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ var imageOnlyTestCases = []testCase{
|
||||
pkgType: pkg.PythonPkg,
|
||||
pkgLanguage: pkg.Python,
|
||||
pkgInfo: map[string]string{
|
||||
"Pygments": "2.6.1",
|
||||
"pygments": "2.6.1",
|
||||
"requests": "2.22.0",
|
||||
"somerequests": "3.22.0",
|
||||
"someotherpkg": "3.19.0",
|
||||
@@ -172,7 +172,7 @@ var dirOnlyTestCases = []testCase{
|
||||
"passlib": "1.7.2",
|
||||
"mypy": "v0.770",
|
||||
// common to image and directory
|
||||
"Pygments": "2.6.1",
|
||||
"pygments": "2.6.1",
|
||||
"requests": "2.22.0",
|
||||
"somerequests": "3.22.0",
|
||||
"someotherpkg": "3.19.0",
|
||||
@@ -388,6 +388,14 @@ var dirOnlyTestCases = []testCase{
|
||||
"swift-numerics": "1.0.2",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find swipl pack package manager packages",
|
||||
pkgType: pkg.SwiplPackPkg,
|
||||
pkgLanguage: pkg.Swipl,
|
||||
pkgInfo: map[string]string{
|
||||
"hdt": "0.5.2",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find github action packages (from usage in workflow files and composite actions)",
|
||||
pkgType: pkg.GithubActionPkg,
|
||||
@@ -402,6 +410,14 @@ var dirOnlyTestCases = []testCase{
|
||||
"octo-org/this-repo/.github/workflows/workflow-1.yml": "172239021f7ba04fe7327647b213799853a9eb89",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find opam package",
|
||||
pkgType: pkg.OpamPkg,
|
||||
pkgLanguage: pkg.OCaml,
|
||||
pkgInfo: map[string]string{
|
||||
"ocaml-base-compiler": "4.14.0",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var commonTestCases = []testCase{
|
||||
@@ -468,4 +484,12 @@ var commonTestCases = []testCase{
|
||||
"memcached": "3.2.0",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find lua rock package",
|
||||
pkgType: pkg.LuaRocksPkg,
|
||||
pkgLanguage: pkg.Lua,
|
||||
pkgInfo: map[string]string{
|
||||
"kong": "3.7.0-0",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -51,6 +51,8 @@ func TestPkgCoverageImage(t *testing.T) {
|
||||
definedLanguages.Remove(pkg.Rust.String())
|
||||
definedLanguages.Remove(pkg.Dart.String())
|
||||
definedLanguages.Remove(pkg.Swift.String())
|
||||
definedLanguages.Remove(pkg.Swipl.String())
|
||||
definedLanguages.Remove(pkg.OCaml.String())
|
||||
definedLanguages.Remove(pkg.CPP.String())
|
||||
definedLanguages.Remove(pkg.Haskell.String())
|
||||
definedLanguages.Remove(pkg.Elixir.String())
|
||||
@@ -76,6 +78,8 @@ func TestPkgCoverageImage(t *testing.T) {
|
||||
definedPkgs.Remove(string(pkg.LinuxKernelPkg))
|
||||
definedPkgs.Remove(string(pkg.LinuxKernelModulePkg))
|
||||
definedPkgs.Remove(string(pkg.SwiftPkg))
|
||||
definedPkgs.Remove(string(pkg.SwiplPackPkg))
|
||||
definedPkgs.Remove(string(pkg.OpamPkg))
|
||||
definedPkgs.Remove(string(pkg.GithubActionPkg))
|
||||
definedPkgs.Remove(string(pkg.GithubActionWorkflowPkg))
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@ package integration
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"regexp"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
@@ -12,8 +14,6 @@ import (
|
||||
|
||||
"github.com/anchore/syft/cmd/syft/internal/options"
|
||||
"github.com/anchore/syft/syft/format"
|
||||
"github.com/anchore/syft/syft/format/cyclonedxjson"
|
||||
"github.com/anchore/syft/syft/format/cyclonedxxml"
|
||||
"github.com/anchore/syft/syft/format/syftjson"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
@@ -43,26 +43,27 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) {
|
||||
},
|
||||
json: true,
|
||||
},
|
||||
{
|
||||
name: cyclonedxjson.ID.String(),
|
||||
redactor: func(in []byte) []byte {
|
||||
// unstable values
|
||||
in = regexp.MustCompile(`"(timestamp|serialNumber|bom-ref|ref)":\s*"(\n|[^"])+"`).ReplaceAll(in, []byte(`"$1": "redacted"`))
|
||||
in = regexp.MustCompile(`"(dependsOn)":\s*\[(?:\s|[^]])+]`).ReplaceAll(in, []byte(`"$1": []`))
|
||||
return in
|
||||
},
|
||||
json: true,
|
||||
},
|
||||
{
|
||||
name: cyclonedxxml.ID.String(),
|
||||
redactor: func(in []byte) []byte {
|
||||
// unstable values
|
||||
in = regexp.MustCompile(`(serialNumber|bom-ref|ref)="[^"]+"`).ReplaceAll(in, []byte{})
|
||||
in = regexp.MustCompile(`<timestamp>[^<]+</timestamp>`).ReplaceAll(in, []byte{})
|
||||
|
||||
return in
|
||||
},
|
||||
},
|
||||
// TODO: ignoring the `ref` field though does create stable results to compare, but the SBOM is fundamentally gutted and not worth comparing (find a better redaction or compare method)
|
||||
//{
|
||||
// name: cyclonedxjson.ID.String(),
|
||||
// redactor: func(in []byte) []byte {
|
||||
// // unstable values
|
||||
// in = regexp.MustCompile(`"(timestamp|serialNumber|bom-ref|ref)":\s*"(\n|[^"])+"`).ReplaceAll(in, []byte(`"$1": "redacted"`))
|
||||
// in = regexp.MustCompile(`"(dependsOn)":\s*\[(?:\s|[^]])+]`).ReplaceAll(in, []byte(`"$1": []`))
|
||||
// return in
|
||||
// },
|
||||
// json: true,
|
||||
//},
|
||||
//{
|
||||
// name: cyclonedxxml.ID.String(),
|
||||
// redactor: func(in []byte) []byte {
|
||||
// // unstable values
|
||||
// in = regexp.MustCompile(`(serialNumber|bom-ref|ref)="[^"]+"`).ReplaceAll(in, []byte{})
|
||||
// in = regexp.MustCompile(`<timestamp>[^<]+</timestamp>`).ReplaceAll(in, []byte{})
|
||||
//
|
||||
// return in
|
||||
// },
|
||||
//},
|
||||
}
|
||||
|
||||
opts := options.DefaultOutput()
|
||||
@@ -112,6 +113,21 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) {
|
||||
diffs := dmp.DiffMain(string(by1), string(by2), true)
|
||||
t.Errorf("diff: %s", dmp.DiffPrettyText(diffs))
|
||||
}
|
||||
|
||||
// write raw IMAGE@NAME-start and IMAGE@NAME-finish to files within the results dir
|
||||
// ... this is helpful for debugging
|
||||
require.NoError(t, os.MkdirAll("results", 0700))
|
||||
|
||||
suffix := "sbom"
|
||||
switch {
|
||||
case strings.Contains(test.name, "json"):
|
||||
suffix = "json"
|
||||
case strings.Contains(test.name, "xml"):
|
||||
suffix = "xml"
|
||||
}
|
||||
|
||||
require.NoError(t, os.WriteFile(filepath.Join("results", image+"@"+test.name+"-start."+suffix), by1, 0600))
|
||||
require.NoError(t, os.WriteFile(filepath.Join("results", image+"@"+test.name+"-finish."+suffix), by2, 0600))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@ func TestGolangCompilerDetection(t *testing.T) {
|
||||
for _, pkg := range packages {
|
||||
foundCompilerVersions[pkg.Version] = struct{}{}
|
||||
foundPURL[pkg.PURL] = struct{}{}
|
||||
for _, cpe := range pkg.CPEs {
|
||||
foundCPE[cpe] = struct{}{}
|
||||
for _, c := range pkg.CPEs {
|
||||
foundCPE[c] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,8 @@ import (
|
||||
func TestMarinerDistroless(t *testing.T) {
|
||||
sbom, _ := catalogFixtureImage(t, "image-mariner-distroless", source.SquashedScope)
|
||||
|
||||
expectedPkgs := 12
|
||||
// 12 RPMs + 2 binaries with ELF package notes claiming to be RPMs
|
||||
expectedPkgs := 14
|
||||
actualPkgs := 0
|
||||
for range sbom.Artifacts.Packages.Enumerate(pkg.RpmPkg) {
|
||||
actualPkgs += 1
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/syft/internal/relationship"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
func TestBinaryElfRelationships(t *testing.T) {
|
||||
// node --> ["dependency of" nodes]
|
||||
expectedGraph := map[string][]string{
|
||||
"glibc": {
|
||||
"libhello_world.so",
|
||||
"syfttestfixture",
|
||||
},
|
||||
"libstdc++": {
|
||||
"syfttestfixture",
|
||||
},
|
||||
"libhello_world.so": {
|
||||
"syfttestfixture",
|
||||
},
|
||||
}
|
||||
|
||||
// run the test...
|
||||
sbom, _ := catalogFixtureImage(t, "elf-test-fixtures", source.SquashedScope)
|
||||
|
||||
// get a mapping of package names to their IDs
|
||||
nameToId := map[string]artifact.ID{}
|
||||
|
||||
recordPkgId := func(name string) {
|
||||
pkgs := sbom.Artifacts.Packages.PackagesByName(name)
|
||||
require.NotEmpty(t, pkgs, "expected package %q to be present in the SBOM", name)
|
||||
for _, p := range pkgs {
|
||||
nameToId[p.Name] = p.ID()
|
||||
}
|
||||
}
|
||||
for name, depNames := range expectedGraph {
|
||||
recordPkgId(name)
|
||||
for _, depName := range depNames {
|
||||
recordPkgId(depName)
|
||||
}
|
||||
}
|
||||
|
||||
relationshipIndex := relationship.NewIndex(sbom.Relationships...)
|
||||
for name, expectedDepNames := range expectedGraph {
|
||||
pkgId := nameToId[name]
|
||||
p := sbom.Artifacts.Packages.Package(pkgId)
|
||||
require.NotNil(t, p, "expected package %q to be present in the SBOM", name)
|
||||
|
||||
rels := relationshipIndex.References(*p, artifact.DependencyOfRelationship)
|
||||
require.NotEmpty(t, rels, "expected package %q to have relationships", name)
|
||||
|
||||
toIds := map[artifact.ID]struct{}{}
|
||||
for _, rel := range rels {
|
||||
toIds[rel.To.ID()] = struct{}{}
|
||||
}
|
||||
|
||||
for _, depName := range expectedDepNames {
|
||||
depId := nameToId[depName]
|
||||
_, exists := toIds[depId]
|
||||
require.True(t, exists, "expected package %q to have a relationship to %q", name, depName)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
//go:build !arm64
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
@@ -7,7 +5,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
@@ -22,41 +19,39 @@ func TestPackageDeduplication(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
scope: source.AllLayersScope,
|
||||
packageCount: 172, // without deduplication this would be 618
|
||||
packageCount: 178, // without deduplication this would be ~600
|
||||
instanceCount: map[string]int{
|
||||
"basesystem": 1,
|
||||
"wget": 1,
|
||||
"curl": 2, // upgraded in the image
|
||||
"vsftpd": 1,
|
||||
"httpd": 1, // rpm, - we exclude binary
|
||||
"basesystem": 1,
|
||||
"wget": 1,
|
||||
"curl-minimal": 2, // upgraded in the image
|
||||
"vsftpd": 1,
|
||||
"httpd": 1, // rpm, - we exclude binary
|
||||
},
|
||||
locationCount: map[string]int{
|
||||
"basesystem-10.0-7.el7.centos": 4,
|
||||
"curl-7.29.0-59.el7": 1, // from base image
|
||||
"curl-7.29.0-59.el7_9.1": 3, // upgrade
|
||||
"wget-1.14-18.el7_6.1": 3,
|
||||
"vsftpd-3.0.2-29.el7_9": 2,
|
||||
"httpd-2.4.6-97.el7.centos.5": 1,
|
||||
// "httpd-2.4.6": 1, // binary
|
||||
"basesystem-11-13.el9": 5, // in all layers
|
||||
"curl-minimal-7.76.1-26.el9_3.2.0.1": 2, // base + wget layer
|
||||
"curl-minimal-7.76.1-29.el9_4.1": 3, // curl upgrade layer + all above layers
|
||||
"wget-1.21.1-8.el9_4": 4, // wget + all above layers
|
||||
"vsftpd-3.0.5-5.el9": 2, // vsftpd + all above layers
|
||||
"httpd-2.4.57-11.el9_4.1": 1, // last layer
|
||||
},
|
||||
},
|
||||
{
|
||||
scope: source.SquashedScope,
|
||||
packageCount: 170,
|
||||
packageCount: 172,
|
||||
instanceCount: map[string]int{
|
||||
"basesystem": 1,
|
||||
"wget": 1,
|
||||
"curl": 1, // upgraded, but the most recent
|
||||
"vsftpd": 1,
|
||||
"httpd": 1, // rpm, binary is now excluded by overlap
|
||||
"basesystem": 1,
|
||||
"wget": 1,
|
||||
"curl-minimal": 1, // upgraded, but the most recent
|
||||
"vsftpd": 1,
|
||||
"httpd": 1, // rpm, binary is now excluded by overlap
|
||||
},
|
||||
locationCount: map[string]int{
|
||||
"basesystem-10.0-7.el7.centos": 1,
|
||||
"curl-7.29.0-59.el7_9.1": 1, // upgrade
|
||||
"wget-1.14-18.el7_6.1": 1,
|
||||
"vsftpd-3.0.2-29.el7_9": 1,
|
||||
"httpd-2.4.6-97.el7.centos.5": 1,
|
||||
// "httpd-2.4.6": 1, // binary (excluded)
|
||||
"basesystem-11-13.el9": 1,
|
||||
"curl-minimal-7.76.1-29.el9_4.1": 1, // upgrade
|
||||
"wget-1.21.1-8.el9_4": 1,
|
||||
"vsftpd-3.0.5-5.el9": 1,
|
||||
"httpd-2.4.57-11.el9_4.1": 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -75,20 +70,21 @@ func TestPackageDeduplication(t *testing.T) {
|
||||
pkgs := sbom.Artifacts.Packages.PackagesByName(name)
|
||||
|
||||
// with multiple packages with the same name, something is wrong (or this is the wrong fixture)
|
||||
require.Len(t, pkgs, expectedInstanceCount)
|
||||
if assert.Len(t, pkgs, expectedInstanceCount, "unexpected package count for %s", name) {
|
||||
for _, p := range pkgs {
|
||||
nameVersion := fmt.Sprintf("%s-%s", name, p.Version)
|
||||
expectedLocationCount, ok := tt.locationCount[nameVersion]
|
||||
if !ok {
|
||||
t.Errorf("missing name-version: %s", nameVersion)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, p := range pkgs {
|
||||
nameVersion := fmt.Sprintf("%s-%s", name, p.Version)
|
||||
expectedLocationCount, ok := tt.locationCount[nameVersion]
|
||||
if !ok {
|
||||
t.Fatalf("missing name-version: %s", nameVersion)
|
||||
// we should see merged locations (assumption, there was 1 location for each package)
|
||||
assert.Len(t, p.Locations.ToSlice(), expectedLocationCount, "unexpected location count for %s", nameVersion)
|
||||
|
||||
// all paths should match
|
||||
assert.Len(t, p.Locations.CoordinateSet().Paths(), 1, "unexpected location count for %s", nameVersion)
|
||||
}
|
||||
|
||||
// we should see merged locations (assumption, there was 1 location for each package)
|
||||
assert.Len(t, p.Locations.ToSlice(), expectedLocationCount)
|
||||
|
||||
// all paths should match
|
||||
assert.Len(t, p.Locations.CoordinateSet().Paths(), 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
func TestSbomMetadataComponent(t *testing.T) {
|
||||
sbom, _ := catalogFixtureImage(t, "image-sbom-metadata-component", source.SquashedScope, "+sbom-cataloger")
|
||||
|
||||
expectedPkgs := []string{"first-subcomponent", "main-component"}
|
||||
foundPkgs := []string{}
|
||||
|
||||
for sbomPkg := range sbom.Artifacts.Packages.Enumerate(pkg.JavaPkg) {
|
||||
foundPkgs = append(foundPkgs, sbomPkg.Name)
|
||||
}
|
||||
|
||||
// check if both the package in `.metadata.component` and the one in `.components` were found
|
||||
if !reflect.DeepEqual(expectedPkgs, foundPkgs) {
|
||||
t.Errorf("expected packages %v, got %v", expectedPkgs, foundPkgs)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,21 @@
|
||||
# change these if you want CI to not use previous stored cache
|
||||
INTEGRATION_CACHE_BUSTER := "894d8ca"
|
||||
FINGERPRINT_FILE := cache.fingerprint
|
||||
|
||||
.PHONY: cache.fingerprint
|
||||
cache.fingerprint:
|
||||
find image-* -type f -exec md5sum {} + | awk '{print $1}' | sort | tee /dev/stderr | md5sum | tee cache.fingerprint && echo "$(INTEGRATION_CACHE_BUSTER)" >> cache.fingerprint
|
||||
.DEFAULT_GOAL := fixtures
|
||||
|
||||
# requirement 1: 'fixtures' goal to generate any and all test fixtures
|
||||
fixtures:
|
||||
@echo "nothing to do"
|
||||
|
||||
# requirement 2: 'fingerprint' goal to determine if the fixture input that indicates any existing cache should be busted
|
||||
fingerprint: $(FINGERPRINT_FILE)
|
||||
|
||||
# requirement 3: we always need to recalculate the fingerprint based on source regardless of any existing fingerprint
|
||||
.PHONY: $(FINGERPRINT_FILE)
|
||||
$(FINGERPRINT_FILE):
|
||||
@find image-* -type f -exec sha256sum {} \; | sort -k2 > $(FINGERPRINT_FILE)
|
||||
@#cat $(FINGERPRINT_FILE) | sha256sum | awk '{print $$1}'
|
||||
|
||||
# requirement 4: 'clean' goal to remove all generated test fixtures
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f $(FINGERPRINT_FILE)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../../syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures
|
||||
@@ -1 +1,6 @@
|
||||
FROM golang:1.18.10-alpine
|
||||
FROM --platform=linux/amd64 golang:1.18.10-alpine
|
||||
|
||||
FROM scratch
|
||||
|
||||
# we don't need the entire golang toolchain, just a single binary with the stdlib baked in
|
||||
COPY --from=0 /usr/local/go/bin/gofmt bin/gofmt
|
||||
|
||||
+6
-2
@@ -1,4 +1,4 @@
|
||||
FROM jenkins/jenkins:2.346.3-slim-jdk17@sha256:028fbbd9112c60ed086f5197fcba71992317864d27644e5949cf9c52ff4b65f0
|
||||
FROM jenkins/jenkins:2.346.3-slim-jdk17@sha256:028fbbd9112c60ed086f5197fcba71992317864d27644e5949cf9c52ff4b65f0 AS base
|
||||
|
||||
USER root
|
||||
|
||||
@@ -12,7 +12,7 @@ RUN apt-get update 2>&1 > /dev/null && apt-get install -y less zip 2>&1 > /dev/n
|
||||
|
||||
RUN unzip ../jenkins.war 2>&1 > /dev/null
|
||||
|
||||
RUN rm -f ./META-INF/MANIFEST.MF
|
||||
RUN rm -rf ./META-INF/MANIFEST.MF ./WEB-INF ./jsbundles ./scripts ./css
|
||||
|
||||
WORKDIR /usr/share/jenkins
|
||||
|
||||
@@ -21,3 +21,7 @@ RUN rm -rf jenkins.war
|
||||
RUN cd ./tmp && zip -r ../jenkins.war . && cd ..
|
||||
|
||||
RUN rm -rf ./tmp
|
||||
|
||||
FROM scratch
|
||||
|
||||
COPY --from=base /usr/share/jenkins/jenkins.war /jenkins.war
|
||||
|
||||
+9
-1
@@ -1,7 +1,15 @@
|
||||
FROM alpine:3.18.3@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a
|
||||
FROM alpine:3.18.3@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a AS base
|
||||
|
||||
RUN wget https://repo1.maven.org/maven2/org/jvnet/hudson/main/hudson-war/2.2.1/hudson-war-2.2.1.war
|
||||
|
||||
RUN mv hudson-war-2.2.1.war hudson.war
|
||||
|
||||
# let's make this image a little smaller as to not take up so much disk space
|
||||
# we'll only keep the jar metadata files (pom data + manifest) and throw away the rest
|
||||
RUN apk add --no-cache python3 py3-pip
|
||||
COPY extract.py /extract.py
|
||||
RUN python extract.py
|
||||
|
||||
FROM scratch
|
||||
|
||||
COPY --from=base /slim /
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
import os
|
||||
import zipfile
|
||||
import io
|
||||
|
||||
ARCHIVE_EXTENSIONS = ('.jar', '.war', '.ear', '.hpi', '.war', '.sar', '.nar', '.par')
|
||||
METADATA_FILES = ('pom.xml', 'pom.properties', 'MANIFEST.MF')
|
||||
|
||||
|
||||
def slim_archive(archive, output_dir, base_path="", archive_name=""):
|
||||
"""
|
||||
extracts metadata files from the archive and creates a slim JAR file
|
||||
containing only these files. handles nested JARs by preserving them.
|
||||
"""
|
||||
slim_buffer = io.BytesIO()
|
||||
with zipfile.ZipFile(archive, 'r') as zip_file:
|
||||
with zipfile.ZipFile(slim_buffer, 'w', zipfile.ZIP_DEFLATED) as slim_zip:
|
||||
for file_name in zip_file.namelist():
|
||||
# check for metadata files or nested JARs
|
||||
if file_name.endswith(METADATA_FILES):
|
||||
# add metadata files directly to the slimmed archive
|
||||
file_data = zip_file.read(file_name)
|
||||
slim_zip.writestr(file_name, file_data)
|
||||
elif file_name.endswith(ARCHIVE_EXTENSIONS):
|
||||
# if it's a nested archive, recursively slim it
|
||||
nested_archive = io.BytesIO(zip_file.read(file_name))
|
||||
nested_slim_buffer = io.BytesIO()
|
||||
slim_archive(
|
||||
nested_archive,
|
||||
nested_slim_buffer,
|
||||
base_path=os.path.join(base_path, os.path.dirname(file_name)),
|
||||
archive_name=os.path.basename(file_name)
|
||||
)
|
||||
# add the slimmed nested archive back to the parent archive
|
||||
nested_slim_buffer.seek(0)
|
||||
slim_zip.writestr(file_name, nested_slim_buffer.read())
|
||||
|
||||
# write out the slimmed JAR to the output directory if output_dir is a directory
|
||||
if isinstance(output_dir, str):
|
||||
output_path = os.path.join(output_dir, base_path, archive_name)
|
||||
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
||||
with open(output_path, 'wb') as f:
|
||||
slim_buffer.seek(0)
|
||||
f.write(slim_buffer.read())
|
||||
else:
|
||||
# if output_dir is a BytesIO buffer (for nested archives), just write to it
|
||||
output_dir.seek(0)
|
||||
output_dir.write(slim_buffer.getvalue())
|
||||
|
||||
|
||||
def walk_directory_and_slim_jars(base_dir, output_dir):
|
||||
"""
|
||||
recursively walks through a directory tree looking for .jar, .war, .ear,
|
||||
.hpi files and slims them down by keeping only metadata files.
|
||||
"""
|
||||
for dirpath, _, filenames in os.walk(base_dir):
|
||||
for filename in filenames:
|
||||
if filename.endswith(ARCHIVE_EXTENSIONS):
|
||||
archive_path = os.path.join(dirpath, filename)
|
||||
print(f"Processing {archive_path}")
|
||||
slim_archive(archive_path, output_dir, os.path.relpath(dirpath, base_dir), filename)
|
||||
|
||||
|
||||
# a helper script for slimming down JAR files by keeping only metadata files but still keeping the jar packaging,
|
||||
# including nested JARs! Useful for testing purposes.
|
||||
if __name__ == "__main__":
|
||||
BASE_DIR = "."
|
||||
OUTPUT_DIR = "./slim"
|
||||
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
||||
walk_directory_and_slim_jars(BASE_DIR, OUTPUT_DIR)
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM alpine@sha256:d9a7354e3845ea8466bb00b22224d9116b183e594527fb5b6c3d30bc01a20378
|
||||
FROM alpine@sha256:d9a7354e3845ea8466bb00b22224d9116b183e594527fb5b6c3d30bc01a20378 AS base
|
||||
|
||||
# we keep these unpinned so that if alpine
|
||||
# changes our integration tests can adapt
|
||||
@@ -6,3 +6,8 @@ RUN apk add --no-cache \
|
||||
tzdata \
|
||||
vim \
|
||||
alpine-sdk
|
||||
|
||||
# we don't need the installed bins for this test, only the APK installed metadata
|
||||
FROM scratch
|
||||
|
||||
COPY --from=base /lib/apk/db/installed /lib/apk/db/installed
|
||||
|
||||
+8
-1
@@ -1 +1,8 @@
|
||||
FROM mcr.microsoft.com/cbl-mariner/distroless/base:2.0.202205275@sha256:f550c5428df17b145851ad75983aca6d613ad4b51ca7983b2a83e67d0ac91a5d
|
||||
FROM mcr.microsoft.com/cbl-mariner/distroless/base:2.0.202205275@sha256:f550c5428df17b145851ad75983aca6d613ad4b51ca7983b2a83e67d0ac91a5d AS base
|
||||
|
||||
# let's shoot for smaller test fixtures
|
||||
FROM scratch
|
||||
|
||||
COPY --from=base /var/lib/rpmmanifest/container-manifest-2 /var/lib/rpmmanifest/container-manifest-2
|
||||
COPY --from=base /usr/bin/gencat /usr/bin/gencat
|
||||
COPY --from=base /usr/bin/openssl /usr/bin/openssl
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
FROM ubuntu:20.04@sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba
|
||||
FROM ubuntu:20.04@sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba AS base
|
||||
# this covers rpm-python
|
||||
RUN apt-get update && apt-get install -y python-pil=6.2.1-3
|
||||
|
||||
# let's save some space...
|
||||
FROM scratch
|
||||
|
||||
COPY --from=base /var/lib/dpkg/status /var/lib/dpkg/status
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
FROM photon:5.0-20230729@sha256:4cf2a1ce0a3f4625f13a0becb6b9bccfdb014c565be6e9a2ec4c4aad1ff8a5d9
|
||||
FROM photon:5.0-20230729@sha256:4cf2a1ce0a3f4625f13a0becb6b9bccfdb014c565be6e9a2ec4c4aad1ff8a5d9 AS base
|
||||
|
||||
FROM scratch
|
||||
|
||||
COPY --from=base /usr/lib/sysimage/rpm /usr/lib/sysimage/rpm
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
opam-version: "2.0"
|
||||
synopsis: "Official release 4.14.0"
|
||||
maintainer: [
|
||||
"David Allsopp <david@tarides.com>"
|
||||
"Florian Angeletti <florian.angeletti@inria.fr>"
|
||||
]
|
||||
authors: "Xavier Leroy and many contributors"
|
||||
license: "LGPL-2.1-or-later WITH OCaml-LGPL-linking-exception"
|
||||
homepage: "https://ocaml.org"
|
||||
bug-reports: "https://github.com/ocaml/opam-repository/issues"
|
||||
depends: [
|
||||
"ocaml" {= "4.14.0" & post}
|
||||
"base-unix" {post}
|
||||
"base-bigarray" {post}
|
||||
"base-threads" {post}
|
||||
"host-arch-arm32" {arch = "arm32" & post}
|
||||
"host-arch-arm64" {arch = "arm64" & post}
|
||||
"host-arch-ppc64" {arch = "ppc64" & post}
|
||||
"host-arch-riscv64" {arch = "riscv64" & post}
|
||||
"host-arch-s390x" {arch = "s390x" & post}
|
||||
"host-arch-x86_32" {os != "win32" & arch = "x86_32" & post}
|
||||
"host-arch-x86_64" {os != "win32" & arch = "x86_64" & post}
|
||||
"host-arch-unknown"
|
||||
{os != "win32" & arch != "arm32" & arch != "arm64" & arch != "ppc64" &
|
||||
arch != "riscv64" &
|
||||
arch != "s390x" &
|
||||
arch != "x86_32" &
|
||||
arch != "x86_64" &
|
||||
post}
|
||||
(("arch-x86_64" {os = "win32" & arch = "x86_64"} &
|
||||
(("system-mingw" & "mingw-w64-shims" {os-distribution = "cygwin" & post}) |
|
||||
"system-msvc")) |
|
||||
("arch-x86_32" {os = "win32"} &
|
||||
(("system-mingw" & "mingw-w64-shims" {os-distribution = "cygwin" & post}) |
|
||||
"system-msvc")) |
|
||||
"host-system-other" {os != "win32" & post})
|
||||
"ocaml-options-vanilla" {post}
|
||||
"flexdll" {>= "0.36" & os = "win32"}
|
||||
]
|
||||
conflict-class: "ocaml-core-compiler"
|
||||
flags: compiler
|
||||
setenv: CAML_LD_LIBRARY_PATH = "%{lib}%/stublibs"
|
||||
build: [
|
||||
[
|
||||
"./configure"
|
||||
"--host=x86_64-pc-windows"
|
||||
{system-msvc:installed & arch-x86_64:installed}
|
||||
"--host=x86_64-w64-mingw32"
|
||||
{os-distribution = "cygwin" & system-mingw:installed &
|
||||
arch-x86_64:installed}
|
||||
"--host=i686-pc-windows" {system-msvc:installed & arch-x86_32:installed}
|
||||
"--host=i686-w64-mingw32"
|
||||
{os-distribution = "cygwin" & system-mingw:installed &
|
||||
arch-x86_32:installed}
|
||||
"--prefix=%{prefix}%"
|
||||
"--docdir=%{doc}%/ocaml"
|
||||
"--with-flexdll=%{flexdll:share}%" {os = "win32" & flexdll:installed}
|
||||
"-C"
|
||||
"CC=cc" {os = "openbsd" | os = "macos"}
|
||||
"ASPP=cc -c" {os = "openbsd" | os = "macos"}
|
||||
]
|
||||
[make "-j%{jobs}%"]
|
||||
]
|
||||
install: [make "install"]
|
||||
build-env: MSYS2_ARG_CONV_EXCL = "*"
|
||||
post-messages: [
|
||||
"""\
|
||||
A failure in the middle of the build may be caused by build parallelism
|
||||
(enabled by default).
|
||||
Please file a bug report at https://github.com/ocaml/opam-repository/issues"""
|
||||
{failure & jobs > "1"}
|
||||
"""\
|
||||
You can try installing again including --jobs=1
|
||||
to force a sequential build instead."""
|
||||
{failure & jobs > "1" & opam-version >= "2.0.5"}
|
||||
]
|
||||
dev-repo: "git+https://github.com/ocaml/ocaml#4.14"
|
||||
url {
|
||||
src: "https://github.com/ocaml/ocaml/archive/4.14.0.tar.gz"
|
||||
checksum:
|
||||
"sha256=39f44260382f28d1054c5f9d8bf4753cb7ad64027da792f7938344544da155e8"
|
||||
}
|
||||
extra-source "ocaml-base-compiler.install" {
|
||||
src:
|
||||
"https://raw.githubusercontent.com/ocaml/opam-source-archives/main/patches/ocaml-base-compiler/ocaml-base-compiler.install"
|
||||
checksum: [
|
||||
"sha256=79f2a1a5044a91350a0eb6ce12e261a72a2855c094c425cddf3860e58c486678"
|
||||
"md5=3e969b841df1f51ca448e6e6295cb451"
|
||||
]
|
||||
}
|
||||
x-env-path-rewrite: [
|
||||
[CAML_LD_LIBRARY_PATH (";" {os = "win32"} ":" {os != "win32"}) "target"]
|
||||
]
|
||||
+612
@@ -0,0 +1,612 @@
|
||||
package = "kong"
|
||||
version = "3.7.0-0"
|
||||
rockspec_format = "3.0"
|
||||
supported_platforms = {"linux", "macosx"}
|
||||
source = {
|
||||
url = "git+https://github.com/Kong/kong.git",
|
||||
tag = "3.7.0"
|
||||
}
|
||||
description = {
|
||||
summary = "Kong is a scalable and customizable API Management Layer built on top of Nginx.",
|
||||
homepage = "https://konghq.com",
|
||||
license = "Apache 2.0"
|
||||
}
|
||||
dependencies = {
|
||||
"inspect == 3.1.3",
|
||||
"luasec == 1.3.2",
|
||||
"luasocket == 3.0-rc1",
|
||||
"penlight == 1.13.1",
|
||||
"lua-resty-http == 0.17.1",
|
||||
"lua-resty-jit-uuid == 0.0.7",
|
||||
"lua-ffi-zlib == 0.6",
|
||||
"multipart == 0.5.9",
|
||||
"version == 1.0.1",
|
||||
"kong-lapis == 1.16.0.1",
|
||||
"kong-pgmoon == 1.16.2",
|
||||
"luatz == 0.4",
|
||||
"lua_system_constants == 0.1.4",
|
||||
"lyaml == 6.2.8",
|
||||
"luasyslog == 2.0.1",
|
||||
"lua_pack == 2.0.0",
|
||||
"binaryheap >= 0.4",
|
||||
"luaxxhash >= 1.0",
|
||||
"lua-protobuf == 0.5.0",
|
||||
"lua-resty-healthcheck == 3.0.1",
|
||||
"lua-messagepack == 0.5.4",
|
||||
"lua-resty-aws == 1.3.6",
|
||||
"lua-resty-openssl == 1.2.0",
|
||||
"lua-resty-counter == 0.2.1",
|
||||
"lua-resty-ipmatcher == 0.6.1",
|
||||
"lua-resty-acme == 0.12.0",
|
||||
"lua-resty-session == 4.0.5",
|
||||
"lua-resty-timer-ng == 0.2.6",
|
||||
"lpeg == 1.1.0",
|
||||
"lua-resty-ljsonschema == 1.1.6-2",
|
||||
}
|
||||
build = {
|
||||
type = "builtin",
|
||||
modules = {
|
||||
["kong"] = "kong/init.lua",
|
||||
["kong.meta"] = "kong/meta.lua",
|
||||
["kong.cache"] = "kong/cache/init.lua",
|
||||
["kong.cache.warmup"] = "kong/cache/warmup.lua",
|
||||
["kong.global"] = "kong/global.lua",
|
||||
["kong.reports"] = "kong/reports.lua",
|
||||
["kong.constants"] = "kong/constants.lua",
|
||||
["kong.concurrency"] = "kong/concurrency.lua",
|
||||
["kong.deprecation"] = "kong/deprecation.lua",
|
||||
["kong.globalpatches"] = "kong/globalpatches.lua",
|
||||
["kong.error_handlers"] = "kong/error_handlers.lua",
|
||||
["kong.hooks"] = "kong/hooks.lua",
|
||||
|
||||
["kong.router"] = "kong/router/init.lua",
|
||||
["kong.router.traditional"] = "kong/router/traditional.lua",
|
||||
["kong.router.compat"] = "kong/router/compat.lua",
|
||||
["kong.router.expressions"] = "kong/router/expressions.lua",
|
||||
["kong.router.atc"] = "kong/router/atc.lua",
|
||||
["kong.router.fields"] = "kong/router/fields.lua",
|
||||
["kong.router.utils"] = "kong/router/utils.lua",
|
||||
|
||||
["kong.conf_loader"] = "kong/conf_loader/init.lua",
|
||||
["kong.conf_loader.constants"] = "kong/conf_loader/constants.lua",
|
||||
["kong.conf_loader.parse"] = "kong/conf_loader/parse.lua",
|
||||
["kong.conf_loader.listeners"] = "kong/conf_loader/listeners.lua",
|
||||
|
||||
["kong.clustering"] = "kong/clustering/init.lua",
|
||||
["kong.clustering.data_plane"] = "kong/clustering/data_plane.lua",
|
||||
["kong.clustering.control_plane"] = "kong/clustering/control_plane.lua",
|
||||
["kong.clustering.utils"] = "kong/clustering/utils.lua",
|
||||
["kong.clustering.events"] = "kong/clustering/events.lua",
|
||||
["kong.clustering.compat"] = "kong/clustering/compat/init.lua",
|
||||
["kong.clustering.compat.version"] = "kong/clustering/compat/version.lua",
|
||||
["kong.clustering.compat.removed_fields"] = "kong/clustering/compat/removed_fields.lua",
|
||||
["kong.clustering.compat.checkers"] = "kong/clustering/compat/checkers.lua",
|
||||
["kong.clustering.config_helper"] = "kong/clustering/config_helper.lua",
|
||||
["kong.clustering.tls"] = "kong/clustering/tls.lua",
|
||||
|
||||
["kong.cluster_events"] = "kong/cluster_events/init.lua",
|
||||
["kong.cluster_events.strategies.postgres"] = "kong/cluster_events/strategies/postgres.lua",
|
||||
["kong.cluster_events.strategies.off"] = "kong/cluster_events/strategies/off.lua",
|
||||
|
||||
["kong.templates.nginx"] = "kong/templates/nginx.lua",
|
||||
["kong.templates.nginx_kong"] = "kong/templates/nginx_kong.lua",
|
||||
["kong.templates.nginx_kong_gui_include"] = "kong/templates/nginx_kong_gui_include.lua",
|
||||
["kong.templates.nginx_kong_stream"] = "kong/templates/nginx_kong_stream.lua",
|
||||
["kong.templates.kong_defaults"] = "kong/templates/kong_defaults.lua",
|
||||
["kong.templates.nginx_inject"] = "kong/templates/nginx_inject.lua",
|
||||
["kong.templates.nginx_kong_inject"] = "kong/templates/nginx_kong_inject.lua",
|
||||
["kong.templates.nginx_kong_stream_inject"] = "kong/templates/nginx_kong_stream_inject.lua",
|
||||
["kong.templates.kong_yml"] = "kong/templates/kong_yml.lua",
|
||||
|
||||
["kong.resty.dns.client"] = "kong/resty/dns/client.lua",
|
||||
["kong.resty.dns.utils"] = "kong/resty/dns/utils.lua",
|
||||
["kong.resty.ctx"] = "kong/resty/ctx.lua",
|
||||
|
||||
["kong.resty.mlcache"] = "kong/resty/mlcache/init.lua",
|
||||
["kong.resty.mlcache.ipc"] = "kong/resty/mlcache/ipc.lua",
|
||||
|
||||
["kong.cmd"] = "kong/cmd/init.lua",
|
||||
["kong.cmd.roar"] = "kong/cmd/roar.lua",
|
||||
["kong.cmd.stop"] = "kong/cmd/stop.lua",
|
||||
["kong.cmd.quit"] = "kong/cmd/quit.lua",
|
||||
["kong.cmd.start"] = "kong/cmd/start.lua",
|
||||
["kong.cmd.check"] = "kong/cmd/check.lua",
|
||||
["kong.cmd.config"] = "kong/cmd/config.lua",
|
||||
["kong.cmd.reload"] = "kong/cmd/reload.lua",
|
||||
["kong.cmd.restart"] = "kong/cmd/restart.lua",
|
||||
["kong.cmd.prepare"] = "kong/cmd/prepare.lua",
|
||||
["kong.cmd.migrations"] = "kong/cmd/migrations.lua",
|
||||
["kong.cmd.health"] = "kong/cmd/health.lua",
|
||||
["kong.cmd.vault"] = "kong/cmd/vault.lua",
|
||||
["kong.cmd.version"] = "kong/cmd/version.lua",
|
||||
["kong.cmd.hybrid"] = "kong/cmd/hybrid.lua",
|
||||
["kong.cmd.utils.log"] = "kong/cmd/utils/log.lua",
|
||||
["kong.cmd.utils.kill"] = "kong/cmd/utils/kill.lua",
|
||||
["kong.cmd.utils.env"] = "kong/cmd/utils/env.lua",
|
||||
["kong.cmd.utils.migrations"] = "kong/cmd/utils/migrations.lua",
|
||||
["kong.cmd.utils.tty"] = "kong/cmd/utils/tty.lua",
|
||||
["kong.cmd.utils.nginx_signals"] = "kong/cmd/utils/nginx_signals.lua",
|
||||
["kong.cmd.utils.prefix_handler"] = "kong/cmd/utils/prefix_handler.lua",
|
||||
["kong.cmd.utils.process_secrets"] = "kong/cmd/utils/process_secrets.lua",
|
||||
["kong.cmd.utils.inject_confs"] = "kong/cmd/utils/inject_confs.lua",
|
||||
|
||||
["kong.api"] = "kong/api/init.lua",
|
||||
["kong.api.api_helpers"] = "kong/api/api_helpers.lua",
|
||||
["kong.api.arguments"] = "kong/api/arguments.lua",
|
||||
["kong.api.endpoints"] = "kong/api/endpoints.lua",
|
||||
["kong.api.routes.cache"] = "kong/api/routes/cache.lua",
|
||||
["kong.api.routes.certificates"] = "kong/api/routes/certificates.lua",
|
||||
["kong.api.routes.clustering"] = "kong/api/routes/clustering.lua",
|
||||
["kong.api.routes.config"] = "kong/api/routes/config.lua",
|
||||
["kong.api.routes.consumers"] = "kong/api/routes/consumers.lua",
|
||||
["kong.api.routes.debug"] = "kong/api/routes/debug.lua",
|
||||
["kong.api.routes.filter_chains"] = "kong/api/routes/filter_chains.lua",
|
||||
["kong.api.routes.health"] = "kong/api/routes/health.lua",
|
||||
["kong.api.routes.kong"] = "kong/api/routes/kong.lua",
|
||||
["kong.api.routes.plugins"] = "kong/api/routes/plugins.lua",
|
||||
["kong.api.routes.snis"] = "kong/api/routes/snis.lua",
|
||||
["kong.api.routes.tags"] = "kong/api/routes/tags.lua",
|
||||
["kong.api.routes.targets"] = "kong/api/routes/targets.lua",
|
||||
["kong.api.routes.upstreams"] = "kong/api/routes/upstreams.lua",
|
||||
|
||||
["kong.admin_gui"] = "kong/admin_gui/init.lua",
|
||||
["kong.admin_gui.utils"] = "kong/admin_gui/utils.lua",
|
||||
|
||||
["kong.status"] = "kong/status/init.lua",
|
||||
["kong.status.ready"] = "kong/status/ready.lua",
|
||||
|
||||
["kong.tools.dns"] = "kong/tools/dns.lua",
|
||||
["kong.tools.grpc"] = "kong/tools/grpc.lua",
|
||||
["kong.tools.utils"] = "kong/tools/utils.lua",
|
||||
["kong.tools.timestamp"] = "kong/tools/timestamp.lua",
|
||||
["kong.tools.stream_api"] = "kong/tools/stream_api.lua",
|
||||
["kong.tools.queue"] = "kong/tools/queue.lua",
|
||||
["kong.tools.queue_schema"] = "kong/tools/queue_schema.lua",
|
||||
["kong.tools.sandbox"] = "kong/tools/sandbox.lua",
|
||||
["kong.tools.uri"] = "kong/tools/uri.lua",
|
||||
["kong.tools.kong-lua-sandbox"] = "kong/tools/kong-lua-sandbox.lua",
|
||||
["kong.tools.protobuf"] = "kong/tools/protobuf.lua",
|
||||
["kong.tools.mime_type"] = "kong/tools/mime_type.lua",
|
||||
["kong.tools.request_aware_table"] = "kong/tools/request_aware_table.lua",
|
||||
["kong.tools.gzip"] = "kong/tools/gzip.lua",
|
||||
["kong.tools.string"] = "kong/tools/string.lua",
|
||||
["kong.tools.table"] = "kong/tools/table.lua",
|
||||
["kong.tools.sha256"] = "kong/tools/sha256.lua",
|
||||
["kong.tools.yield"] = "kong/tools/yield.lua",
|
||||
["kong.tools.uuid"] = "kong/tools/uuid.lua",
|
||||
["kong.tools.rand"] = "kong/tools/rand.lua",
|
||||
["kong.tools.system"] = "kong/tools/system.lua",
|
||||
["kong.tools.time"] = "kong/tools/time.lua",
|
||||
["kong.tools.module"] = "kong/tools/module.lua",
|
||||
["kong.tools.ip"] = "kong/tools/ip.lua",
|
||||
["kong.tools.http"] = "kong/tools/http.lua",
|
||||
["kong.tools.cjson"] = "kong/tools/cjson.lua",
|
||||
["kong.tools.redis.schema"] = "kong/tools/redis/schema.lua",
|
||||
|
||||
["kong.runloop.handler"] = "kong/runloop/handler.lua",
|
||||
["kong.runloop.events"] = "kong/runloop/events.lua",
|
||||
["kong.runloop.log_level"] = "kong/runloop/log_level.lua",
|
||||
["kong.runloop.certificate"] = "kong/runloop/certificate.lua",
|
||||
["kong.runloop.plugins_iterator"] = "kong/runloop/plugins_iterator.lua",
|
||||
["kong.runloop.upstream_ssl"] = "kong/runloop/upstream_ssl.lua",
|
||||
["kong.runloop.balancer"] = "kong/runloop/balancer/init.lua",
|
||||
["kong.runloop.balancer.balancers"] = "kong/runloop/balancer/balancers.lua",
|
||||
["kong.runloop.balancer.consistent_hashing"] = "kong/runloop/balancer/consistent_hashing.lua",
|
||||
["kong.runloop.balancer.healthcheckers"] = "kong/runloop/balancer/healthcheckers.lua",
|
||||
["kong.runloop.balancer.least_connections"] = "kong/runloop/balancer/least_connections.lua",
|
||||
["kong.runloop.balancer.latency"] = "kong/runloop/balancer/latency.lua",
|
||||
["kong.runloop.balancer.round_robin"] = "kong/runloop/balancer/round_robin.lua",
|
||||
["kong.runloop.balancer.targets"] = "kong/runloop/balancer/targets.lua",
|
||||
["kong.runloop.balancer.upstreams"] = "kong/runloop/balancer/upstreams.lua",
|
||||
["kong.runloop.plugin_servers"] = "kong/runloop/plugin_servers/init.lua",
|
||||
["kong.runloop.plugin_servers.process"] = "kong/runloop/plugin_servers/process.lua",
|
||||
["kong.runloop.plugin_servers.mp_rpc"] = "kong/runloop/plugin_servers/mp_rpc.lua",
|
||||
["kong.runloop.plugin_servers.pb_rpc"] = "kong/runloop/plugin_servers/pb_rpc.lua",
|
||||
["kong.runloop.wasm"] = "kong/runloop/wasm.lua",
|
||||
["kong.runloop.wasm.properties"] = "kong/runloop/wasm/properties.lua",
|
||||
|
||||
["kong.workspaces"] = "kong/workspaces/init.lua",
|
||||
|
||||
["kong.db"] = "kong/db/init.lua",
|
||||
["kong.db.utils"] = "kong/db/utils.lua",
|
||||
["kong.db.errors"] = "kong/db/errors.lua",
|
||||
["kong.db.iteration"] = "kong/db/iteration.lua",
|
||||
["kong.db.dao"] = "kong/db/dao/init.lua",
|
||||
["kong.db.dao.certificates"] = "kong/db/dao/certificates.lua",
|
||||
["kong.db.dao.snis"] = "kong/db/dao/snis.lua",
|
||||
["kong.db.dao.targets"] = "kong/db/dao/targets.lua",
|
||||
["kong.db.dao.plugins"] = "kong/db/dao/plugins.lua",
|
||||
["kong.db.dao.tags"] = "kong/db/dao/tags.lua",
|
||||
["kong.db.dao.vaults"] = "kong/db/dao/vaults.lua",
|
||||
["kong.db.dao.workspaces"] = "kong/db/dao/workspaces.lua",
|
||||
["kong.db.dao.services"] = "kong/db/dao/services.lua",
|
||||
["kong.db.dao.ca_certificates"] = "kong/db/dao/ca_certificates.lua",
|
||||
["kong.db.declarative"] = "kong/db/declarative/init.lua",
|
||||
["kong.db.declarative.marshaller"] = "kong/db/declarative/marshaller.lua",
|
||||
["kong.db.declarative.export"] = "kong/db/declarative/export.lua",
|
||||
["kong.db.declarative.import"] = "kong/db/declarative/import.lua",
|
||||
["kong.db.schema"] = "kong/db/schema/init.lua",
|
||||
["kong.db.dao.keys"] = "kong/db/dao/keys.lua",
|
||||
["kong.db.dao.key_sets"] = "kong/db/dao/key_sets.lua",
|
||||
["kong.db.schema.entities.keys"] = "kong/db/schema/entities/keys.lua",
|
||||
["kong.db.schema.entities.key_sets"] = "kong/db/schema/entities/key_sets.lua",
|
||||
["kong.db.schema.entities.consumers"] = "kong/db/schema/entities/consumers.lua",
|
||||
["kong.db.schema.entities.routes"] = "kong/db/schema/entities/routes.lua",
|
||||
["kong.db.schema.entities.routes_subschemas"] = "kong/db/schema/entities/routes_subschemas.lua",
|
||||
["kong.db.schema.entities.services"] = "kong/db/schema/entities/services.lua",
|
||||
["kong.db.schema.entities.certificates"] = "kong/db/schema/entities/certificates.lua",
|
||||
["kong.db.schema.entities.snis"] = "kong/db/schema/entities/snis.lua",
|
||||
["kong.db.schema.entities.upstreams"] = "kong/db/schema/entities/upstreams.lua",
|
||||
["kong.db.schema.entities.targets"] = "kong/db/schema/entities/targets.lua",
|
||||
["kong.db.schema.entities.plugins"] = "kong/db/schema/entities/plugins.lua",
|
||||
["kong.db.schema.entities.tags"] = "kong/db/schema/entities/tags.lua",
|
||||
["kong.db.schema.entities.ca_certificates"] = "kong/db/schema/entities/ca_certificates.lua",
|
||||
["kong.db.schema.entities.vaults"] = "kong/db/schema/entities/vaults.lua",
|
||||
["kong.db.schema.entities.workspaces"] = "kong/db/schema/entities/workspaces.lua",
|
||||
["kong.db.schema.entities.clustering_data_planes"] = "kong/db/schema/entities/clustering_data_planes.lua",
|
||||
["kong.db.schema.entities.parameters"] = "kong/db/schema/entities/parameters.lua",
|
||||
["kong.db.schema.entities.filter_chains"] = "kong/db/schema/entities/filter_chains.lua",
|
||||
["kong.db.schema.json"] = "kong/db/schema/json.lua",
|
||||
["kong.db.schema.others.migrations"] = "kong/db/schema/others/migrations.lua",
|
||||
["kong.db.schema.others.declarative_config"] = "kong/db/schema/others/declarative_config.lua",
|
||||
["kong.db.schema.entity"] = "kong/db/schema/entity.lua",
|
||||
["kong.db.schema.metaschema"] = "kong/db/schema/metaschema.lua",
|
||||
["kong.db.schema.typedefs"] = "kong/db/schema/typedefs.lua",
|
||||
["kong.db.schema.plugin_loader"] = "kong/db/schema/plugin_loader.lua",
|
||||
["kong.db.schema.vault_loader"] = "kong/db/schema/vault_loader.lua",
|
||||
["kong.db.schema.topological_sort"] = "kong/db/schema/topological_sort.lua",
|
||||
["kong.db.strategies"] = "kong/db/strategies/init.lua",
|
||||
["kong.db.strategies.connector"] = "kong/db/strategies/connector.lua",
|
||||
["kong.db.strategies.postgres"] = "kong/db/strategies/postgres/init.lua",
|
||||
["kong.db.strategies.postgres.connector"] = "kong/db/strategies/postgres/connector.lua",
|
||||
["kong.db.strategies.postgres.tags"] = "kong/db/strategies/postgres/tags.lua",
|
||||
["kong.db.strategies.postgres.services"] = "kong/db/strategies/postgres/services.lua",
|
||||
["kong.db.strategies.postgres.plugins"] = "kong/db/strategies/postgres/plugins.lua",
|
||||
["kong.db.strategies.off"] = "kong/db/strategies/off/init.lua",
|
||||
["kong.db.strategies.off.connector"] = "kong/db/strategies/off/connector.lua",
|
||||
["kong.db.strategies.off.tags"] = "kong/db/strategies/off/tags.lua",
|
||||
|
||||
["kong.db.migrations.state"] = "kong/db/migrations/state.lua",
|
||||
["kong.db.migrations.subsystems"] = "kong/db/migrations/subsystems.lua",
|
||||
["kong.db.migrations.core"] = "kong/db/migrations/core/init.lua",
|
||||
["kong.db.migrations.core.000_base"] = "kong/db/migrations/core/000_base.lua",
|
||||
["kong.db.migrations.core.003_100_to_110"] = "kong/db/migrations/core/003_100_to_110.lua",
|
||||
["kong.db.migrations.core.004_110_to_120"] = "kong/db/migrations/core/004_110_to_120.lua",
|
||||
["kong.db.migrations.core.005_120_to_130"] = "kong/db/migrations/core/005_120_to_130.lua",
|
||||
["kong.db.migrations.core.006_130_to_140"] = "kong/db/migrations/core/006_130_to_140.lua",
|
||||
["kong.db.migrations.core.007_140_to_150"] = "kong/db/migrations/core/007_140_to_150.lua",
|
||||
["kong.db.migrations.core.008_150_to_200"] = "kong/db/migrations/core/008_150_to_200.lua",
|
||||
["kong.db.migrations.core.009_200_to_210"] = "kong/db/migrations/core/009_200_to_210.lua",
|
||||
["kong.db.migrations.core.010_210_to_211"] = "kong/db/migrations/core/010_210_to_211.lua",
|
||||
["kong.db.migrations.core.011_212_to_213"] = "kong/db/migrations/core/011_212_to_213.lua",
|
||||
["kong.db.migrations.core.012_213_to_220"] = "kong/db/migrations/core/012_213_to_220.lua",
|
||||
["kong.db.migrations.core.013_220_to_230"] = "kong/db/migrations/core/013_220_to_230.lua",
|
||||
["kong.db.migrations.core.014_230_to_270"] = "kong/db/migrations/core/014_230_to_270.lua",
|
||||
["kong.db.migrations.core.015_270_to_280"] = "kong/db/migrations/core/015_270_to_280.lua",
|
||||
["kong.db.migrations.core.016_280_to_300"] = "kong/db/migrations/core/016_280_to_300.lua",
|
||||
["kong.db.migrations.core.017_300_to_310"] = "kong/db/migrations/core/017_300_to_310.lua",
|
||||
["kong.db.migrations.core.018_310_to_320"] = "kong/db/migrations/core/018_310_to_320.lua",
|
||||
["kong.db.migrations.core.019_320_to_330"] = "kong/db/migrations/core/019_320_to_330.lua",
|
||||
["kong.db.migrations.core.020_330_to_340"] = "kong/db/migrations/core/020_330_to_340.lua",
|
||||
["kong.db.migrations.core.021_340_to_350"] = "kong/db/migrations/core/021_340_to_350.lua",
|
||||
["kong.db.migrations.core.022_350_to_360"] = "kong/db/migrations/core/022_350_to_360.lua",
|
||||
["kong.db.migrations.operations.200_to_210"] = "kong/db/migrations/operations/200_to_210.lua",
|
||||
["kong.db.migrations.operations.212_to_213"] = "kong/db/migrations/operations/212_to_213.lua",
|
||||
["kong.db.migrations.operations.280_to_300"] = "kong/db/migrations/operations/280_to_300.lua",
|
||||
["kong.db.migrations.migrate_path_280_300"] = "kong/db/migrations/migrate_path_280_300.lua",
|
||||
["kong.db.declarative.migrations"] = "kong/db/declarative/migrations/init.lua",
|
||||
["kong.db.declarative.migrations.route_path"] = "kong/db/declarative/migrations/route_path.lua",
|
||||
|
||||
["kong.pdk"] = "kong/pdk/init.lua",
|
||||
["kong.pdk.private.checks"] = "kong/pdk/private/checks.lua",
|
||||
["kong.pdk.private.phases"] = "kong/pdk/private/phases.lua",
|
||||
["kong.pdk.private.node"] = "kong/pdk/private/node.lua",
|
||||
["kong.pdk.client"] = "kong/pdk/client.lua",
|
||||
["kong.pdk.client.tls"] = "kong/pdk/client/tls.lua",
|
||||
["kong.pdk.ctx"] = "kong/pdk/ctx.lua",
|
||||
["kong.pdk.ip"] = "kong/pdk/ip.lua",
|
||||
["kong.pdk.log"] = "kong/pdk/log.lua",
|
||||
["kong.pdk.service"] = "kong/pdk/service.lua",
|
||||
["kong.pdk.service.request"] = "kong/pdk/service/request.lua",
|
||||
["kong.pdk.service.response"] = "kong/pdk/service/response.lua",
|
||||
["kong.pdk.router"] = "kong/pdk/router.lua",
|
||||
["kong.pdk.request"] = "kong/pdk/request.lua",
|
||||
["kong.pdk.response"] = "kong/pdk/response.lua",
|
||||
["kong.pdk.table"] = "kong/pdk/table.lua",
|
||||
["kong.pdk.node"] = "kong/pdk/node.lua",
|
||||
["kong.pdk.nginx"] = "kong/pdk/nginx.lua",
|
||||
["kong.pdk.cluster"] = "kong/pdk/cluster.lua",
|
||||
["kong.pdk.vault"] = "kong/pdk/vault.lua",
|
||||
["kong.pdk.tracing"] = "kong/pdk/tracing.lua",
|
||||
["kong.pdk.plugin"] = "kong/pdk/plugin.lua",
|
||||
|
||||
["kong.plugins.basic-auth.migrations"] = "kong/plugins/basic-auth/migrations/init.lua",
|
||||
["kong.plugins.basic-auth.migrations.000_base_basic_auth"] = "kong/plugins/basic-auth/migrations/000_base_basic_auth.lua",
|
||||
["kong.plugins.basic-auth.migrations.002_130_to_140"] = "kong/plugins/basic-auth/migrations/002_130_to_140.lua",
|
||||
["kong.plugins.basic-auth.migrations.003_200_to_210"] = "kong/plugins/basic-auth/migrations/003_200_to_210.lua",
|
||||
["kong.plugins.basic-auth.crypto"] = "kong/plugins/basic-auth/crypto.lua",
|
||||
["kong.plugins.basic-auth.handler"] = "kong/plugins/basic-auth/handler.lua",
|
||||
["kong.plugins.basic-auth.access"] = "kong/plugins/basic-auth/access.lua",
|
||||
["kong.plugins.basic-auth.schema"] = "kong/plugins/basic-auth/schema.lua",
|
||||
["kong.plugins.basic-auth.daos"] = "kong/plugins/basic-auth/daos.lua",
|
||||
|
||||
["kong.plugins.key-auth.migrations"] = "kong/plugins/key-auth/migrations/init.lua",
|
||||
["kong.plugins.key-auth.migrations.000_base_key_auth"] = "kong/plugins/key-auth/migrations/000_base_key_auth.lua",
|
||||
["kong.plugins.key-auth.migrations.002_130_to_140"] = "kong/plugins/key-auth/migrations/002_130_to_140.lua",
|
||||
["kong.plugins.key-auth.migrations.003_200_to_210"] = "kong/plugins/key-auth/migrations/003_200_to_210.lua",
|
||||
["kong.plugins.key-auth.migrations.004_320_to_330"] = "kong/plugins/key-auth/migrations/004_320_to_330.lua",
|
||||
["kong.plugins.key-auth.handler"] = "kong/plugins/key-auth/handler.lua",
|
||||
["kong.plugins.key-auth.schema"] = "kong/plugins/key-auth/schema.lua",
|
||||
["kong.plugins.key-auth.daos"] = "kong/plugins/key-auth/daos.lua",
|
||||
|
||||
["kong.plugins.oauth2.migrations"] = "kong/plugins/oauth2/migrations/init.lua",
|
||||
["kong.plugins.oauth2.migrations.000_base_oauth2"] = "kong/plugins/oauth2/migrations/000_base_oauth2.lua",
|
||||
["kong.plugins.oauth2.migrations.003_130_to_140"] = "kong/plugins/oauth2/migrations/003_130_to_140.lua",
|
||||
["kong.plugins.oauth2.migrations.004_200_to_210"] = "kong/plugins/oauth2/migrations/004_200_to_210.lua",
|
||||
["kong.plugins.oauth2.migrations.005_210_to_211"] = "kong/plugins/oauth2/migrations/005_210_to_211.lua",
|
||||
["kong.plugins.oauth2.migrations.006_320_to_330"] = "kong/plugins/oauth2/migrations/006_320_to_330.lua",
|
||||
["kong.plugins.oauth2.migrations.007_320_to_330"] = "kong/plugins/oauth2/migrations/007_320_to_330.lua",
|
||||
["kong.plugins.oauth2.handler"] = "kong/plugins/oauth2/handler.lua",
|
||||
["kong.plugins.oauth2.secret"] = "kong/plugins/oauth2/secret.lua",
|
||||
["kong.plugins.oauth2.access"] = "kong/plugins/oauth2/access.lua",
|
||||
["kong.plugins.oauth2.schema"] = "kong/plugins/oauth2/schema.lua",
|
||||
["kong.plugins.oauth2.daos"] = "kong/plugins/oauth2/daos.lua",
|
||||
["kong.plugins.oauth2.daos.oauth2_tokens"] = "kong/plugins/oauth2/daos/oauth2_tokens.lua",
|
||||
|
||||
["kong.plugins.tcp-log.handler"] = "kong/plugins/tcp-log/handler.lua",
|
||||
["kong.plugins.tcp-log.schema"] = "kong/plugins/tcp-log/schema.lua",
|
||||
|
||||
["kong.plugins.udp-log.handler"] = "kong/plugins/udp-log/handler.lua",
|
||||
["kong.plugins.udp-log.schema"] = "kong/plugins/udp-log/schema.lua",
|
||||
|
||||
["kong.plugins.http-log.handler"] = "kong/plugins/http-log/handler.lua",
|
||||
["kong.plugins.http-log.schema"] = "kong/plugins/http-log/schema.lua",
|
||||
["kong.plugins.http-log.migrations"] = "kong/plugins/http-log/migrations/init.lua",
|
||||
["kong.plugins.http-log.migrations.001_280_to_300"] = "kong/plugins/http-log/migrations/001_280_to_300.lua",
|
||||
|
||||
["kong.plugins.file-log.handler"] = "kong/plugins/file-log/handler.lua",
|
||||
["kong.plugins.file-log.schema"] = "kong/plugins/file-log/schema.lua",
|
||||
|
||||
["kong.plugins.rate-limiting.migrations"] = "kong/plugins/rate-limiting/migrations/init.lua",
|
||||
["kong.plugins.rate-limiting.migrations.000_base_rate_limiting"] = "kong/plugins/rate-limiting/migrations/000_base_rate_limiting.lua",
|
||||
["kong.plugins.rate-limiting.migrations.003_10_to_112"] = "kong/plugins/rate-limiting/migrations/003_10_to_112.lua",
|
||||
["kong.plugins.rate-limiting.migrations.004_200_to_210"] = "kong/plugins/rate-limiting/migrations/004_200_to_210.lua",
|
||||
["kong.plugins.rate-limiting.migrations.005_320_to_330"] = "kong/plugins/rate-limiting/migrations/005_320_to_330.lua",
|
||||
["kong.plugins.rate-limiting.migrations.006_350_to_360"] = "kong/plugins/rate-limiting/migrations/006_350_to_360.lua",
|
||||
["kong.plugins.rate-limiting.expiration"] = "kong/plugins/rate-limiting/expiration.lua",
|
||||
["kong.plugins.rate-limiting.handler"] = "kong/plugins/rate-limiting/handler.lua",
|
||||
["kong.plugins.rate-limiting.schema"] = "kong/plugins/rate-limiting/schema.lua",
|
||||
["kong.plugins.rate-limiting.daos"] = "kong/plugins/rate-limiting/daos.lua",
|
||||
["kong.plugins.rate-limiting.policies"] = "kong/plugins/rate-limiting/policies/init.lua",
|
||||
["kong.plugins.rate-limiting.policies.cluster"] = "kong/plugins/rate-limiting/policies/cluster.lua",
|
||||
["kong.plugins.rate-limiting.clustering.compat.redis_translation"] = "kong/plugins/rate-limiting/clustering/compat/redis_translation.lua",
|
||||
|
||||
["kong.plugins.response-ratelimiting.migrations"] = "kong/plugins/response-ratelimiting/migrations/init.lua",
|
||||
["kong.plugins.response-ratelimiting.migrations.000_base_response_rate_limiting"] = "kong/plugins/response-ratelimiting/migrations/000_base_response_rate_limiting.lua",
|
||||
["kong.plugins.response-ratelimiting.migrations.001_350_to_360"] = "kong/plugins/response-ratelimiting/migrations/001_350_to_360.lua",
|
||||
["kong.plugins.response-ratelimiting.handler"] = "kong/plugins/response-ratelimiting/handler.lua",
|
||||
["kong.plugins.response-ratelimiting.access"] = "kong/plugins/response-ratelimiting/access.lua",
|
||||
["kong.plugins.response-ratelimiting.header_filter"] = "kong/plugins/response-ratelimiting/header_filter.lua",
|
||||
["kong.plugins.response-ratelimiting.log"] = "kong/plugins/response-ratelimiting/log.lua",
|
||||
["kong.plugins.response-ratelimiting.schema"] = "kong/plugins/response-ratelimiting/schema.lua",
|
||||
["kong.plugins.response-ratelimiting.policies"] = "kong/plugins/response-ratelimiting/policies/init.lua",
|
||||
["kong.plugins.response-ratelimiting.policies.cluster"] = "kong/plugins/response-ratelimiting/policies/cluster.lua",
|
||||
["kong.plugins.response-ratelimiting.clustering.compat.redis_translation"] = "kong/plugins/response-ratelimiting/clustering/compat/redis_translation.lua",
|
||||
|
||||
["kong.plugins.request-size-limiting.handler"] = "kong/plugins/request-size-limiting/handler.lua",
|
||||
["kong.plugins.request-size-limiting.schema"] = "kong/plugins/request-size-limiting/schema.lua",
|
||||
|
||||
["kong.plugins.response-transformer.handler"] = "kong/plugins/response-transformer/handler.lua",
|
||||
["kong.plugins.response-transformer.body_transformer"] = "kong/plugins/response-transformer/body_transformer.lua",
|
||||
["kong.plugins.response-transformer.header_transformer"] = "kong/plugins/response-transformer/header_transformer.lua",
|
||||
["kong.plugins.response-transformer.schema"] = "kong/plugins/response-transformer/schema.lua",
|
||||
|
||||
["kong.plugins.cors.handler"] = "kong/plugins/cors/handler.lua",
|
||||
["kong.plugins.cors.schema"] = "kong/plugins/cors/schema.lua",
|
||||
|
||||
["kong.plugins.ip-restriction.handler"] = "kong/plugins/ip-restriction/handler.lua",
|
||||
["kong.plugins.ip-restriction.schema"] = "kong/plugins/ip-restriction/schema.lua",
|
||||
["kong.plugins.ip-restriction.migrations"] = "kong/plugins/ip-restriction/migrations/init.lua",
|
||||
["kong.plugins.ip-restriction.migrations.001_200_to_210"] = "kong/plugins/ip-restriction/migrations/001_200_to_210.lua",
|
||||
|
||||
["kong.plugins.acl.migrations"] = "kong/plugins/acl/migrations/init.lua",
|
||||
["kong.plugins.acl.migrations.000_base_acl"] = "kong/plugins/acl/migrations/000_base_acl.lua",
|
||||
["kong.plugins.acl.migrations.002_130_to_140"] = "kong/plugins/acl/migrations/002_130_to_140.lua",
|
||||
["kong.plugins.acl.migrations.003_200_to_210"] = "kong/plugins/acl/migrations/003_200_to_210.lua",
|
||||
["kong.plugins.acl.migrations.004_212_to_213"] = "kong/plugins/acl/migrations/004_212_to_213.lua",
|
||||
["kong.plugins.acl.handler"] = "kong/plugins/acl/handler.lua",
|
||||
["kong.plugins.acl.schema"] = "kong/plugins/acl/schema.lua",
|
||||
["kong.plugins.acl.daos"] = "kong/plugins/acl/daos.lua",
|
||||
["kong.plugins.acl.groups"] = "kong/plugins/acl/groups.lua",
|
||||
["kong.plugins.acl.acls"] = "kong/plugins/acl/acls.lua",
|
||||
["kong.plugins.acl.api"] = "kong/plugins/acl/api.lua",
|
||||
|
||||
["kong.plugins.correlation-id.handler"] = "kong/plugins/correlation-id/handler.lua",
|
||||
["kong.plugins.correlation-id.schema"] = "kong/plugins/correlation-id/schema.lua",
|
||||
|
||||
["kong.plugins.jwt.migrations"] = "kong/plugins/jwt/migrations/init.lua",
|
||||
["kong.plugins.jwt.migrations.000_base_jwt"] = "kong/plugins/jwt/migrations/000_base_jwt.lua",
|
||||
["kong.plugins.jwt.migrations.002_130_to_140"] = "kong/plugins/jwt/migrations/002_130_to_140.lua",
|
||||
["kong.plugins.jwt.migrations.003_200_to_210"] = "kong/plugins/jwt/migrations/003_200_to_210.lua",
|
||||
["kong.plugins.jwt.handler"] = "kong/plugins/jwt/handler.lua",
|
||||
["kong.plugins.jwt.schema"] = "kong/plugins/jwt/schema.lua",
|
||||
["kong.plugins.jwt.daos"] = "kong/plugins/jwt/daos.lua",
|
||||
["kong.plugins.jwt.jwt_parser"] = "kong/plugins/jwt/jwt_parser.lua",
|
||||
|
||||
["kong.plugins.hmac-auth.migrations"] = "kong/plugins/hmac-auth/migrations/init.lua",
|
||||
["kong.plugins.hmac-auth.migrations.000_base_hmac_auth"] = "kong/plugins/hmac-auth/migrations/000_base_hmac_auth.lua",
|
||||
["kong.plugins.hmac-auth.migrations.002_130_to_140"] = "kong/plugins/hmac-auth/migrations/002_130_to_140.lua",
|
||||
["kong.plugins.hmac-auth.migrations.003_200_to_210"] = "kong/plugins/hmac-auth/migrations/003_200_to_210.lua",
|
||||
["kong.plugins.hmac-auth.handler"] = "kong/plugins/hmac-auth/handler.lua",
|
||||
["kong.plugins.hmac-auth.access"] = "kong/plugins/hmac-auth/access.lua",
|
||||
["kong.plugins.hmac-auth.schema"] = "kong/plugins/hmac-auth/schema.lua",
|
||||
["kong.plugins.hmac-auth.daos"] = "kong/plugins/hmac-auth/daos.lua",
|
||||
|
||||
["kong.plugins.ldap-auth.handler"] = "kong/plugins/ldap-auth/handler.lua",
|
||||
["kong.plugins.ldap-auth.access"] = "kong/plugins/ldap-auth/access.lua",
|
||||
["kong.plugins.ldap-auth.schema"] = "kong/plugins/ldap-auth/schema.lua",
|
||||
["kong.plugins.ldap-auth.ldap"] = "kong/plugins/ldap-auth/ldap.lua",
|
||||
["kong.plugins.ldap-auth.asn1"] = "kong/plugins/ldap-auth/asn1.lua",
|
||||
|
||||
["kong.plugins.syslog.handler"] = "kong/plugins/syslog/handler.lua",
|
||||
["kong.plugins.syslog.schema"] = "kong/plugins/syslog/schema.lua",
|
||||
|
||||
["kong.plugins.loggly.handler"] = "kong/plugins/loggly/handler.lua",
|
||||
["kong.plugins.loggly.schema"] = "kong/plugins/loggly/schema.lua",
|
||||
|
||||
["kong.plugins.datadog.handler"] = "kong/plugins/datadog/handler.lua",
|
||||
["kong.plugins.datadog.schema"] = "kong/plugins/datadog/schema.lua",
|
||||
["kong.plugins.datadog.statsd_logger"] = "kong/plugins/datadog/statsd_logger.lua",
|
||||
|
||||
["kong.plugins.statsd.constants"] = "kong/plugins/statsd/constants.lua",
|
||||
["kong.plugins.statsd.handler"] = "kong/plugins/statsd/handler.lua",
|
||||
["kong.plugins.statsd.log"] = "kong/plugins/statsd/log.lua",
|
||||
["kong.plugins.statsd.schema"] = "kong/plugins/statsd/schema.lua",
|
||||
["kong.plugins.statsd.statsd_logger"] = "kong/plugins/statsd/statsd_logger.lua",
|
||||
|
||||
["kong.plugins.bot-detection.handler"] = "kong/plugins/bot-detection/handler.lua",
|
||||
["kong.plugins.bot-detection.schema"] = "kong/plugins/bot-detection/schema.lua",
|
||||
["kong.plugins.bot-detection.rules"] = "kong/plugins/bot-detection/rules.lua",
|
||||
["kong.plugins.bot-detection.migrations"] = "kong/plugins/bot-detection/migrations/init.lua",
|
||||
["kong.plugins.bot-detection.migrations.001_200_to_210"] = "kong/plugins/bot-detection/migrations/001_200_to_210.lua",
|
||||
|
||||
["kong.plugins.request-termination.handler"] = "kong/plugins/request-termination/handler.lua",
|
||||
["kong.plugins.request-termination.schema"] = "kong/plugins/request-termination/schema.lua",
|
||||
|
||||
["kong.plugins.aws-lambda.handler"] = "kong/plugins/aws-lambda/handler.lua",
|
||||
["kong.plugins.aws-lambda.schema"] = "kong/plugins/aws-lambda/schema.lua",
|
||||
["kong.plugins.aws-lambda.request-util"] = "kong/plugins/aws-lambda/request-util.lua",
|
||||
|
||||
["kong.plugins.grpc-gateway.deco"] = "kong/plugins/grpc-gateway/deco.lua",
|
||||
["kong.plugins.grpc-gateway.handler"] = "kong/plugins/grpc-gateway/handler.lua",
|
||||
["kong.plugins.grpc-gateway.schema"] = "kong/plugins/grpc-gateway/schema.lua",
|
||||
|
||||
["kong.plugins.acme.api"] = "kong/plugins/acme/api.lua",
|
||||
["kong.plugins.acme.client"] = "kong/plugins/acme/client.lua",
|
||||
["kong.plugins.acme.clustering.compat.redis_translation"] = "kong/plugins/acme/clustering/compat/redis_translation.lua",
|
||||
["kong.plugins.acme.daos"] = "kong/plugins/acme/daos.lua",
|
||||
["kong.plugins.acme.handler"] = "kong/plugins/acme/handler.lua",
|
||||
["kong.plugins.acme.migrations.000_base_acme"] = "kong/plugins/acme/migrations/000_base_acme.lua",
|
||||
["kong.plugins.acme.migrations.001_280_to_300"] = "kong/plugins/acme/migrations/001_280_to_300.lua",
|
||||
["kong.plugins.acme.migrations.002_320_to_330"] = "kong/plugins/acme/migrations/002_320_to_330.lua",
|
||||
["kong.plugins.acme.migrations.003_350_to_360"] = "kong/plugins/acme/migrations/003_350_to_360.lua",
|
||||
["kong.plugins.acme.migrations"] = "kong/plugins/acme/migrations/init.lua",
|
||||
["kong.plugins.acme.schema"] = "kong/plugins/acme/schema.lua",
|
||||
["kong.plugins.acme.storage.kong"] = "kong/plugins/acme/storage/kong.lua",
|
||||
["kong.plugins.acme.storage.config_adapters"] = "kong/plugins/acme/storage/config_adapters/init.lua",
|
||||
["kong.plugins.acme.storage.config_adapters.redis"] = "kong/plugins/acme/storage/config_adapters/redis.lua",
|
||||
["kong.plugins.acme.reserved_words"] = "kong/plugins/acme/reserved_words.lua",
|
||||
|
||||
["kong.plugins.prometheus.api"] = "kong/plugins/prometheus/api.lua",
|
||||
["kong.plugins.prometheus.status_api"] = "kong/plugins/prometheus/status_api.lua",
|
||||
["kong.plugins.prometheus.exporter"] = "kong/plugins/prometheus/exporter.lua",
|
||||
["kong.plugins.prometheus.handler"] = "kong/plugins/prometheus/handler.lua",
|
||||
["kong.plugins.prometheus.prometheus"] = "kong/plugins/prometheus/prometheus.lua",
|
||||
["kong.plugins.prometheus.serve"] = "kong/plugins/prometheus/serve.lua",
|
||||
["kong.plugins.prometheus.schema"] = "kong/plugins/prometheus/schema.lua",
|
||||
|
||||
["kong.plugins.session.handler"] = "kong/plugins/session/handler.lua",
|
||||
["kong.plugins.session.schema"] = "kong/plugins/session/schema.lua",
|
||||
["kong.plugins.session.access"] = "kong/plugins/session/access.lua",
|
||||
["kong.plugins.session.header_filter"] = "kong/plugins/session/header_filter.lua",
|
||||
["kong.plugins.session.session"] = "kong/plugins/session/session.lua",
|
||||
["kong.plugins.session.daos"] = "kong/plugins/session/daos.lua",
|
||||
["kong.plugins.session.storage.kong"] = "kong/plugins/session/storage/kong.lua",
|
||||
["kong.plugins.session.migrations.000_base_session"] = "kong/plugins/session/migrations/000_base_session.lua",
|
||||
["kong.plugins.session.migrations.001_add_ttl_index"] = "kong/plugins/session/migrations/001_add_ttl_index.lua",
|
||||
["kong.plugins.session.migrations.002_320_to_330"] = "kong/plugins/session/migrations/002_320_to_330.lua",
|
||||
["kong.plugins.session.migrations"] = "kong/plugins/session/migrations/init.lua",
|
||||
|
||||
["kong.plugins.proxy-cache.handler"] = "kong/plugins/proxy-cache/handler.lua",
|
||||
["kong.plugins.proxy-cache.cache_key"] = "kong/plugins/proxy-cache/cache_key.lua",
|
||||
["kong.plugins.proxy-cache.schema"] = "kong/plugins/proxy-cache/schema.lua",
|
||||
["kong.plugins.proxy-cache.api"] = "kong/plugins/proxy-cache/api.lua",
|
||||
["kong.plugins.proxy-cache.strategies"] = "kong/plugins/proxy-cache/strategies/init.lua",
|
||||
["kong.plugins.proxy-cache.strategies.memory"] = "kong/plugins/proxy-cache/strategies/memory.lua",
|
||||
|
||||
["kong.plugins.grpc-web.deco"] = "kong/plugins/grpc-web/deco.lua",
|
||||
["kong.plugins.grpc-web.handler"] = "kong/plugins/grpc-web/handler.lua",
|
||||
["kong.plugins.grpc-web.schema"] = "kong/plugins/grpc-web/schema.lua",
|
||||
|
||||
["kong.plugins.pre-function._handler"] = "kong/plugins/pre-function/_handler.lua",
|
||||
["kong.plugins.pre-function._schema"] = "kong/plugins/pre-function/_schema.lua",
|
||||
["kong.plugins.pre-function.migrations._001_280_to_300"] = "kong/plugins/pre-function/migrations/_001_280_to_300.lua",
|
||||
|
||||
["kong.plugins.pre-function.handler"] = "kong/plugins/pre-function/handler.lua",
|
||||
["kong.plugins.pre-function.schema"] = "kong/plugins/pre-function/schema.lua",
|
||||
["kong.plugins.pre-function.migrations"] = "kong/plugins/pre-function/migrations/init.lua",
|
||||
["kong.plugins.pre-function.migrations.001_280_to_300"] = "kong/plugins/pre-function/migrations/001_280_to_300.lua",
|
||||
|
||||
["kong.plugins.post-function.handler"] = "kong/plugins/post-function/handler.lua",
|
||||
["kong.plugins.post-function.schema"] = "kong/plugins/post-function/schema.lua",
|
||||
["kong.plugins.post-function.migrations"] = "kong/plugins/post-function/migrations/init.lua",
|
||||
["kong.plugins.post-function.migrations.001_280_to_300"] = "kong/plugins/post-function/migrations/001_280_to_300.lua",
|
||||
|
||||
["kong.plugins.zipkin.handler"] = "kong/plugins/zipkin/handler.lua",
|
||||
["kong.plugins.zipkin.reporter"] = "kong/plugins/zipkin/reporter.lua",
|
||||
["kong.plugins.zipkin.span"] = "kong/plugins/zipkin/span.lua",
|
||||
["kong.plugins.zipkin.schema"] = "kong/plugins/zipkin/schema.lua",
|
||||
["kong.plugins.zipkin.request_tags"] = "kong/plugins/zipkin/request_tags.lua",
|
||||
|
||||
["kong.plugins.request-transformer.migrations.postgres"] = "kong/plugins/request-transformer/migrations/postgres.lua",
|
||||
["kong.plugins.request-transformer.migrations.common"] = "kong/plugins/request-transformer/migrations/common.lua",
|
||||
["kong.plugins.request-transformer.handler"] = "kong/plugins/request-transformer/handler.lua",
|
||||
["kong.plugins.request-transformer.access"] = "kong/plugins/request-transformer/access.lua",
|
||||
["kong.plugins.request-transformer.schema"] = "kong/plugins/request-transformer/schema.lua",
|
||||
|
||||
["kong.plugins.azure-functions.handler"] = "kong/plugins/azure-functions/handler.lua",
|
||||
["kong.plugins.azure-functions.schema"] = "kong/plugins/azure-functions/schema.lua",
|
||||
|
||||
["kong.plugins.opentelemetry.handler"] = "kong/plugins/opentelemetry/handler.lua",
|
||||
["kong.plugins.opentelemetry.schema"] = "kong/plugins/opentelemetry/schema.lua",
|
||||
["kong.plugins.opentelemetry.proto"] = "kong/plugins/opentelemetry/proto.lua",
|
||||
["kong.plugins.opentelemetry.otlp"] = "kong/plugins/opentelemetry/otlp.lua",
|
||||
|
||||
["kong.plugins.ai-proxy.handler"] = "kong/plugins/ai-proxy/handler.lua",
|
||||
["kong.plugins.ai-proxy.schema"] = "kong/plugins/ai-proxy/schema.lua",
|
||||
|
||||
["kong.plugins.ai-request-transformer.handler"] = "kong/plugins/ai-request-transformer/handler.lua",
|
||||
["kong.plugins.ai-request-transformer.schema"] = "kong/plugins/ai-request-transformer/schema.lua",
|
||||
|
||||
["kong.plugins.ai-response-transformer.handler"] = "kong/plugins/ai-response-transformer/handler.lua",
|
||||
["kong.plugins.ai-response-transformer.schema"] = "kong/plugins/ai-response-transformer/schema.lua",
|
||||
|
||||
["kong.llm"] = "kong/llm/init.lua",
|
||||
["kong.llm.drivers.shared"] = "kong/llm/drivers/shared.lua",
|
||||
["kong.llm.drivers.openai"] = "kong/llm/drivers/openai.lua",
|
||||
["kong.llm.drivers.azure"] = "kong/llm/drivers/azure.lua",
|
||||
["kong.llm.drivers.cohere"] = "kong/llm/drivers/cohere.lua",
|
||||
["kong.llm.drivers.anthropic"] = "kong/llm/drivers/anthropic.lua",
|
||||
["kong.llm.drivers.mistral"] = "kong/llm/drivers/mistral.lua",
|
||||
["kong.llm.drivers.llama2"] = "kong/llm/drivers/llama2.lua",
|
||||
|
||||
["kong.plugins.ai-prompt-decorator.handler"] = "kong/plugins/ai-prompt-decorator/handler.lua",
|
||||
["kong.plugins.ai-prompt-decorator.schema"] = "kong/plugins/ai-prompt-decorator/schema.lua",
|
||||
|
||||
["kong.plugins.ai-prompt-template.handler"] = "kong/plugins/ai-prompt-template/handler.lua",
|
||||
["kong.plugins.ai-prompt-template.schema"] = "kong/plugins/ai-prompt-template/schema.lua",
|
||||
["kong.plugins.ai-prompt-template.templater"] = "kong/plugins/ai-prompt-template/templater.lua",
|
||||
|
||||
["kong.plugins.ai-prompt-guard.handler"] = "kong/plugins/ai-prompt-guard/handler.lua",
|
||||
["kong.plugins.ai-prompt-guard.schema"] = "kong/plugins/ai-prompt-guard/schema.lua",
|
||||
|
||||
["kong.vaults.env"] = "kong/vaults/env/init.lua",
|
||||
["kong.vaults.env.schema"] = "kong/vaults/env/schema.lua",
|
||||
|
||||
["kong.tracing.instrumentation"] = "kong/tracing/instrumentation.lua",
|
||||
["kong.tracing.propagation"] = "kong/tracing/propagation.lua",
|
||||
["kong.tracing.request_id"] = "kong/tracing/request_id.lua",
|
||||
["kong.tracing.tracing_context"] = "kong/tracing/tracing_context.lua",
|
||||
|
||||
["kong.timing"] = "kong/timing/init.lua",
|
||||
["kong.timing.context"] = "kong/timing/context.lua",
|
||||
["kong.timing.hooks"] = "kong/timing/hooks/init.lua",
|
||||
["kong.timing.hooks.dns"] = "kong/timing/hooks/dns.lua",
|
||||
["kong.timing.hooks.http"] = "kong/timing/hooks/http.lua",
|
||||
["kong.timing.hooks.redis"] = "kong/timing/hooks/redis.lua",
|
||||
["kong.timing.hooks.socket"] = "kong/timing/hooks/socket.lua",
|
||||
|
||||
["kong.dynamic_hook"] = "kong/dynamic_hook/init.lua",
|
||||
["kong.dynamic_hook.wrap_function_gen"] = "kong/dynamic_hook/wrap_function_gen.lua",
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
name(hdt).
|
||||
version('0.5.2').
|
||||
% TODO: swipl_version([90121]).
|
||||
title('Access RDF HDT files').
|
||||
keywords(['RDF']).
|
||||
author( 'Jan Wielemaker', 'J.Wielemaker@vu.nl' ).
|
||||
packager( 'Jan Wielemaker', 'J.Wielemaker@vu.nl' ).
|
||||
maintainer( 'Jan Wielemaker', 'J.Wielemaker@vu.nl' ).
|
||||
home( 'https://github.com/JanWielemaker/hdt' ).
|
||||
download( 'https://github.com/JanWielemaker/hdt/archive/V*.zip' ).
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
FROM scratch
|
||||
COPY test.cdx.json /
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"bomFormat" : "CycloneDX",
|
||||
"specVersion" : "1.5",
|
||||
"serialNumber" : "urn:uuid:dc807d4b-0415-35ab-ba61-49b5d39bc2d9",
|
||||
"version" : 1,
|
||||
"metadata" : {
|
||||
"component" : {
|
||||
"name" : "main-component",
|
||||
"version" : "1.2.3",
|
||||
"purl" : "pkg:maven/org.example/main-component@1.2.3",
|
||||
"type" : "library",
|
||||
"bom-ref" : "pkg:maven/org.example/main-component@1.2.3"
|
||||
}
|
||||
},
|
||||
"components" : [
|
||||
{
|
||||
"name" : "first-subcomponent",
|
||||
"version" : "2.3.4",
|
||||
"purl" : "pkg:maven/org.example/first-subcomponent@2.3.4",
|
||||
"type" : "library",
|
||||
"bom-ref" : "pkg:maven/org.example/first-subcomponent@2.3.4"
|
||||
}
|
||||
],
|
||||
"dependencies" : [
|
||||
{
|
||||
"ref" : "pkg:maven/org.example/main-component-assembly@1.2.3",
|
||||
"dependsOn" : [
|
||||
"pkg:maven/org.example/first-subcomponent@2.3.4"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1 +1,6 @@
|
||||
FROM fedora:35@sha256:36af84ba69e21c9ef86a0424a090674c433b2b80c2462e57503886f1d823abe8
|
||||
FROM fedora:35@sha256:36af84ba69e21c9ef86a0424a090674c433b2b80c2462e57503886f1d823abe8 AS base
|
||||
|
||||
# lets save some space
|
||||
FROM scratch
|
||||
|
||||
COPY --from=base /var/lib/rpm /var/lib/rpm
|
||||
|
||||
@@ -1,2 +1,11 @@
|
||||
FROM registry.suse.com/suse/sle15:15.3.17.20.20@sha256:fd657ecbab5ca564d6933e887f6ae8542a9398e6a4b399f352ce10c3a24afc64
|
||||
FROM registry.suse.com/suse/sle15:15.3.17.20.20@sha256:fd657ecbab5ca564d6933e887f6ae8542a9398e6a4b399f352ce10c3a24afc64 AS base
|
||||
RUN zypper in -y wget
|
||||
|
||||
# let's save some space... we really just need an image that has an RPM DB that is linked across layers
|
||||
FROM --platform=linux/amd64 busybox:1.36.1
|
||||
|
||||
# setup a link /var/lib/rpm -> ../../usr/lib/sysimage/rpm
|
||||
RUN mkdir -p /var/lib && ln -s ../../usr/lib/sysimage/rpm /var/lib/rpm
|
||||
|
||||
# copy the RPM DB from the SUSE image
|
||||
COPY --from=base /usr/lib/sysimage/rpm/Packages.db /usr/lib/sysimage/rpm/Packages.db
|
||||
|
||||
@@ -1 +1,18 @@
|
||||
FROM anchore/test_images:java-1abc58f@sha256:3add9f90e9ed35739cc99b7830767e09eec921052e2412adf4491648c741f066
|
||||
FROM docker.io/anchore/test_images:java-88948cc@sha256:dea0e6c24636937f53bdc997d9960c2a18966d1e38bcd8ebd0c395d4e169b806 AS base
|
||||
|
||||
# not covered in testing...
|
||||
RUN rm /packages/gradle-7.1.1-bin.zip
|
||||
|
||||
RUN apk add --no-cache python3 py3-pip
|
||||
|
||||
COPY extract.py /extract.py
|
||||
|
||||
WORKDIR /
|
||||
|
||||
# let's make this image a little smaller as to not take up so much disk space
|
||||
# we'll only keep the jar metadata files (pom data + manifest) and throw away the rest
|
||||
RUN python extract.py
|
||||
|
||||
FROM scratch
|
||||
|
||||
COPY --from=base /slim/packages /packages
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import os
|
||||
import zipfile
|
||||
import io
|
||||
|
||||
ARCHIVE_EXTENSIONS = ('.jar', '.war', '.ear', '.hpi', '.war', '.sar', '.nar', '.par')
|
||||
METADATA_FILES = ('pom.xml', 'pom.properties', 'MANIFEST.MF')
|
||||
|
||||
|
||||
def slim_archive(archive, output_dir, base_path="", archive_name=""):
|
||||
"""
|
||||
extracts metadata files from the archive and creates a slim JAR file
|
||||
containing only these files. handles nested JARs by preserving them.
|
||||
"""
|
||||
slim_buffer = io.BytesIO()
|
||||
with zipfile.ZipFile(archive, 'r') as zip_file:
|
||||
with zipfile.ZipFile(slim_buffer, 'w', zipfile.ZIP_DEFLATED) as slim_zip:
|
||||
for file_name in zip_file.namelist():
|
||||
# check for metadata files or nested JARs
|
||||
if file_name.endswith(METADATA_FILES):
|
||||
# add metadata files directly to the slimmed archive
|
||||
file_data = zip_file.read(file_name)
|
||||
slim_zip.writestr(file_name, file_data)
|
||||
elif file_name.endswith(ARCHIVE_EXTENSIONS):
|
||||
# if it's a nested archive, recursively slim it
|
||||
nested_archive = io.BytesIO(zip_file.read(file_name))
|
||||
nested_slim_buffer = io.BytesIO()
|
||||
slim_archive(
|
||||
nested_archive,
|
||||
nested_slim_buffer,
|
||||
base_path=os.path.join(base_path, os.path.dirname(file_name)),
|
||||
archive_name=os.path.basename(file_name)
|
||||
)
|
||||
# add the slimmed nested archive back to the parent archive
|
||||
nested_slim_buffer.seek(0)
|
||||
slim_zip.writestr(file_name, nested_slim_buffer.read())
|
||||
|
||||
# write out the slimmed JAR to the output directory if output_dir is a directory
|
||||
if isinstance(output_dir, str):
|
||||
output_path = os.path.join(output_dir, base_path, archive_name)
|
||||
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
||||
with open(output_path, 'wb') as f:
|
||||
slim_buffer.seek(0)
|
||||
f.write(slim_buffer.read())
|
||||
else:
|
||||
# if output_dir is a BytesIO buffer (for nested archives), just write to it
|
||||
output_dir.seek(0)
|
||||
output_dir.write(slim_buffer.getvalue())
|
||||
|
||||
|
||||
def walk_directory_and_slim_jars(base_dir, output_dir):
|
||||
"""
|
||||
recursively walks through a directory tree looking for .jar, .war, .ear,
|
||||
.hpi files and slims them down by keeping only metadata files.
|
||||
"""
|
||||
for dirpath, _, filenames in os.walk(base_dir):
|
||||
for filename in filenames:
|
||||
if filename.endswith(ARCHIVE_EXTENSIONS):
|
||||
archive_path = os.path.join(dirpath, filename)
|
||||
print(f"Processing {archive_path}")
|
||||
slim_archive(archive_path, output_dir, os.path.relpath(dirpath, base_dir), filename)
|
||||
|
||||
|
||||
# a helper script for slimming down JAR files by keeping only metadata files but still keeping the jar packaging,
|
||||
# including nested JARs! Useful for testing purposes.
|
||||
if __name__ == "__main__":
|
||||
BASE_DIR = "."
|
||||
OUTPUT_DIR = "./slim"
|
||||
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
||||
walk_directory_and_slim_jars(BASE_DIR, OUTPUT_DIR)
|
||||
+25
-4
@@ -1,6 +1,27 @@
|
||||
FROM centos:7.9.2009@sha256:be65f488b7764ad3638f236b7b515b3678369a5124c47b8d32916d6487418ea4
|
||||
FROM --platform=linux/amd64 rockylinux:9.3.20231119@sha256:d644d203142cd5b54ad2a83a203e1dee68af2229f8fe32f52a30c6e1d3c3a9e0 AS base
|
||||
|
||||
# modifying the RPM DB multiple times will result in duplicate packages when using all-layers (if there was no de-dup logic)
|
||||
# curl is tricky, it already exists in the image and is being upgraded
|
||||
RUN yum install -y wget-1.14-18.el7_6.1 curl-7.29.0-59.el7_9.1
|
||||
RUN yum install -y vsftpd-3.0.2-29.el7_9
|
||||
RUN yum install -y httpd-2.4.6-97.el7.centos.5
|
||||
|
||||
# but... we want to make the test image as small as possible, so we are making the changes in stages and then
|
||||
# copying the RPM DB from each stage to a final stage in separate layers. This will result in a much smaller image.
|
||||
|
||||
FROM base AS stage1
|
||||
RUN dnf install -y wget
|
||||
|
||||
FROM stage1 AS stage2
|
||||
RUN dnf update -y curl-minimal
|
||||
|
||||
FROM stage2 AS stage3
|
||||
RUN dnf install -y vsftpd
|
||||
|
||||
FROM stage3 AS stage4
|
||||
RUN dnf install -y httpd
|
||||
|
||||
FROM scratch
|
||||
|
||||
COPY --from=base /var/lib/rpm /var/lib/rpm
|
||||
COPY --from=stage1 /var/lib/rpm /var/lib/rpm
|
||||
COPY --from=stage2 /var/lib/rpm /var/lib/rpm
|
||||
COPY --from=stage3 /var/lib/rpm /var/lib/rpm
|
||||
COPY --from=stage4 /var/lib/rpm /var/lib/rpm
|
||||
|
||||
@@ -32,7 +32,6 @@ func catalogFixtureImageWithConfig(t *testing.T, fixtureImageName string, cfg *s
|
||||
cfg.CatalogerSelection = cfg.CatalogerSelection.WithDefaults(pkgcataloging.ImageTag)
|
||||
|
||||
// get the fixture image tar file
|
||||
imagetest.GetFixtureImage(t, "docker-archive", fixtureImageName)
|
||||
tarPath := imagetest.GetFixtureImageTarPath(t, fixtureImageName)
|
||||
|
||||
// get the source to build an SBOM against
|
||||
|
||||
@@ -1,99 +1,111 @@
|
||||
module github.com/anchore/syft
|
||||
|
||||
go 1.21.0
|
||||
go 1.22.5
|
||||
|
||||
toolchain go1.22.8
|
||||
|
||||
require (
|
||||
github.com/CycloneDX/cyclonedx-go v0.8.0
|
||||
github.com/CycloneDX/cyclonedx-go v0.9.1
|
||||
github.com/Masterminds/semver v1.5.0
|
||||
github.com/Masterminds/sprig/v3 v3.2.3
|
||||
github.com/Masterminds/sprig/v3 v3.3.0
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
|
||||
github.com/acobaugh/osrelease v0.1.0
|
||||
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9
|
||||
github.com/anchore/clio v0.0.0-20240209204744-cb94e40a4f65
|
||||
github.com/anchore/fangs v0.0.0-20231201140849-5075d28d6d8b
|
||||
github.com/anchore/clio v0.0.0-20240522144804-d81e109008aa
|
||||
github.com/anchore/fangs v0.0.0-20240903175602-e716ef12c23d
|
||||
github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537
|
||||
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a
|
||||
github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb
|
||||
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04
|
||||
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20240312213626-055233e539b4
|
||||
github.com/anchore/stereoscope v0.0.2-0.20240229175558-fe426d1b1c84
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20241018175412-5c22e6360c4f
|
||||
github.com/anchore/stereoscope v0.0.5-0.20241018131503-a38c93517fc7
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
|
||||
// we are hinting brotli to latest due to warning when installing archiver v3:
|
||||
// go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption
|
||||
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46
|
||||
github.com/bmatcuk/doublestar/v4 v4.6.1
|
||||
github.com/charmbracelet/bubbles v0.18.0
|
||||
github.com/charmbracelet/bubbletea v0.25.0
|
||||
github.com/charmbracelet/lipgloss v0.10.0
|
||||
github.com/dave/jennifer v1.7.0
|
||||
github.com/bmatcuk/doublestar/v4 v4.7.1
|
||||
github.com/charmbracelet/bubbles v0.20.0
|
||||
github.com/charmbracelet/bubbletea v1.1.1
|
||||
github.com/charmbracelet/lipgloss v0.13.0
|
||||
github.com/dave/jennifer v1.7.1
|
||||
github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da
|
||||
github.com/distribution/reference v0.6.0
|
||||
github.com/docker/docker v26.0.0+incompatible
|
||||
github.com/docker/docker v27.3.1+incompatible
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/elliotchance/phpserialize v1.4.0
|
||||
github.com/facebookincubator/nvdtools v0.1.5
|
||||
github.com/github/go-spdx/v2 v2.2.0
|
||||
github.com/gkampitakis/go-snaps v0.5.3
|
||||
github.com/github/go-spdx/v2 v2.3.2
|
||||
github.com/gkampitakis/go-snaps v0.5.7
|
||||
github.com/go-git/go-billy/v5 v5.5.0
|
||||
github.com/go-git/go-git/v5 v5.12.0
|
||||
github.com/go-test/deep v1.1.0
|
||||
github.com/go-test/deep v1.1.1
|
||||
github.com/google/go-cmp v0.6.0
|
||||
github.com/google/go-containerregistry v0.19.1
|
||||
github.com/google/go-containerregistry v0.20.2
|
||||
github.com/google/licensecheck v0.3.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gookit/color v1.5.4
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/iancoleman/strcase v0.3.0
|
||||
github.com/invopop/jsonschema v0.7.0
|
||||
github.com/jedib0t/go-pretty/v6 v6.5.8
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.1
|
||||
github.com/jinzhu/copier v0.4.0
|
||||
github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953
|
||||
github.com/knqyf263/go-rpmdb v0.1.0
|
||||
github.com/knqyf263/go-rpmdb v0.1.1
|
||||
github.com/mholt/archiver/v3 v3.5.1
|
||||
github.com/microsoft/go-rustaudit v0.0.0-20220730194248-4b17361d90a5
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/moby/sys/mountinfo v0.7.1
|
||||
github.com/moby/sys/mountinfo v0.7.2
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
github.com/saferwall/pe v1.5.2
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.22
|
||||
github.com/saferwall/pe v1.5.4
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d
|
||||
github.com/sanity-io/litter v1.5.5
|
||||
github.com/sassoftware/go-rpmutils v0.3.0
|
||||
github.com/sassoftware/go-rpmutils v0.4.0
|
||||
// pinned to pull in 386 arch fix: https://github.com/scylladb/go-set/commit/cc7b2070d91ebf40d233207b633e28f5bd8f03a5
|
||||
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
|
||||
github.com/spdx/tools-golang v0.5.3
|
||||
github.com/spdx/tools-golang v0.5.5
|
||||
github.com/spf13/afero v1.11.0
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/vbatts/go-mtree v0.5.3
|
||||
github.com/vbatts/go-mtree v0.5.4
|
||||
github.com/vifraa/gopom v1.0.0
|
||||
github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651
|
||||
github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1
|
||||
go.uber.org/goleak v1.3.0
|
||||
golang.org/x/mod v0.17.0
|
||||
golang.org/x/net v0.24.0
|
||||
golang.org/x/mod v0.21.0
|
||||
golang.org/x/net v0.30.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
modernc.org/sqlite v1.29.6
|
||||
modernc.org/sqlite v1.33.1
|
||||
)
|
||||
|
||||
require google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.4.0
|
||||
github.com/OneOfOne/xxhash v1.2.8
|
||||
github.com/adrg/xdg v0.5.1
|
||||
github.com/magiconair/properties v1.8.7
|
||||
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678
|
||||
)
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
|
||||
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect
|
||||
github.com/DataDog/zstd v1.5.5 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/Microsoft/hcsshim v0.11.4 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.3.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/Microsoft/hcsshim v0.11.7 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.0.0 // indirect
|
||||
github.com/adrg/xdg v0.4.0 // indirect
|
||||
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492 // indirect
|
||||
@@ -101,19 +113,23 @@ require (
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/becheran/wildmatch-go v1.0.0 // indirect
|
||||
github.com/charmbracelet/harmonica v0.2.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.2.3 // indirect
|
||||
github.com/charmbracelet/x/term v0.2.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.8 // indirect
|
||||
github.com/containerd/cgroups v1.1.0 // indirect
|
||||
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
|
||||
github.com/containerd/containerd v1.7.11 // indirect
|
||||
github.com/containerd/containerd v1.7.23 // indirect
|
||||
github.com/containerd/containerd/api v1.7.19 // indirect
|
||||
github.com/containerd/continuity v0.4.2 // indirect
|
||||
github.com/containerd/errdefs v0.3.0 // indirect
|
||||
github.com/containerd/fifo v1.1.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/platforms v0.2.1 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
|
||||
github.com/containerd/ttrpc v1.2.2 // indirect
|
||||
github.com/containerd/ttrpc v1.2.5 // indirect
|
||||
github.com/containerd/typeurl/v2 v2.1.1 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/docker/cli v24.0.0+incompatible // indirect
|
||||
github.com/docker/cli v27.3.1+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
@@ -122,42 +138,41 @@ require (
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
|
||||
github.com/edsrzf/mmap-go v1.1.0 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
github.com/felixge/fgprof v0.9.3 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.6 // indirect
|
||||
github.com/gkampitakis/ciinfo v0.3.0 // indirect
|
||||
github.com/gkampitakis/go-diff v1.3.2 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-logr/logr v1.2.4 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-restruct/restruct v1.2.0-alpha // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 // indirect
|
||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/huandu/xstrings v1.3.3 // indirect
|
||||
github.com/huandu/xstrings v1.5.0 // indirect
|
||||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
|
||||
github.com/imdario/mergo v0.3.15 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/klauspost/compress v1.17.8 // indirect
|
||||
github.com/klauspost/pgzip v1.2.5 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 // indirect
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/maruel/natural v1.1.1 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.18 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
@@ -165,19 +180,19 @@ require (
|
||||
github.com/moby/locker v1.0.1 // indirect
|
||||
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||
github.com/moby/sys/signal v0.7.0 // indirect
|
||||
github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 // indirect
|
||||
github.com/moby/sys/user v0.3.0 // indirect
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/reflow v0.3.0 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/nwaples/rardecode v1.1.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc3 // indirect
|
||||
github.com/opencontainers/runc v1.1.12 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.1.0 // indirect
|
||||
github.com/opencontainers/selinux v1.11.0 // indirect
|
||||
github.com/pborman/indent v1.2.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.15 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.19 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/profile v1.7.0 // indirect
|
||||
@@ -185,57 +200,54 @@ require (
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/sahilm/fuzzy v0.1.1 // indirect
|
||||
github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d // indirect
|
||||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/skeema/knownhosts v1.2.2 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/cast v1.5.1 // indirect
|
||||
github.com/spf13/cast v1.7.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.17.0 // indirect
|
||||
github.com/spf13/viper v1.19.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/sylabs/sif/v2 v2.11.5 // indirect
|
||||
github.com/sylabs/squashfs v0.6.1 // indirect
|
||||
github.com/sylabs/sif/v2 v2.19.1 // indirect
|
||||
github.com/sylabs/squashfs v1.0.0 // indirect
|
||||
github.com/therootcompany/xz v1.0.1 // indirect
|
||||
github.com/tidwall/gjson v1.17.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tidwall/sjson v1.2.5 // indirect
|
||||
github.com/ulikunitz/xz v0.5.11 // indirect
|
||||
github.com/ulikunitz/xz v0.5.12 // indirect
|
||||
github.com/vbatts/tar-split v0.11.3 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect
|
||||
go.opentelemetry.io/otel v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.19.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
|
||||
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
golang.org/x/term v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.17.0 // indirect
|
||||
golang.org/x/crypto v0.28.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.26.0 // indirect
|
||||
golang.org/x/term v0.25.0 // indirect
|
||||
golang.org/x/text v0.19.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect
|
||||
google.golang.org/grpc v1.59.0 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect
|
||||
google.golang.org/grpc v1.62.1 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
|
||||
modernc.org/libc v1.41.0 // indirect
|
||||
modernc.org/libc v1.55.3 // indirect
|
||||
modernc.org/mathutil v1.6.0 // indirect
|
||||
modernc.org/memory v1.7.2 // indirect
|
||||
modernc.org/memory v1.8.0 // indirect
|
||||
modernc.org/strutil v1.2.0 // indirect
|
||||
modernc.org/token v1.1.0 // indirect
|
||||
)
|
||||
|
||||
@@ -45,8 +45,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
||||
@@ -57,9 +57,11 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg6
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/CycloneDX/cyclonedx-go v0.8.0 h1:FyWVj6x6hoJrui5uRQdYZcSievw3Z32Z88uYzG/0D6M=
|
||||
github.com/CycloneDX/cyclonedx-go v0.8.0/go.mod h1:K2bA+324+Og0X84fA8HhN2X066K7Bxz4rpMQ4ZhjtSk=
|
||||
github.com/CycloneDX/cyclonedx-go v0.9.1 h1:yffaWOZsv77oTJa/SdVZYdgAgFioCeycBUKkqS2qzQM=
|
||||
github.com/CycloneDX/cyclonedx-go v0.9.1/go.mod h1:NE/EWvzELOFlG6+ljX/QeMlVt9VKcTwu8u0ccsACEsw=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ=
|
||||
github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
||||
@@ -67,24 +69,26 @@ github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJ
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
|
||||
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
|
||||
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
|
||||
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
|
||||
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=
|
||||
github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/Microsoft/hcsshim v0.11.7 h1:vl/nj3Bar/CvJSYo7gIQPyRWc9f3c6IeSNavBTSZNZQ=
|
||||
github.com/Microsoft/hcsshim v0.11.7/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
|
||||
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
|
||||
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
||||
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
|
||||
github.com/acobaugh/osrelease v0.1.0 h1:Yb59HQDGGNhCj4suHaFQQfBps5wyoKLSSX/J/+UifRE=
|
||||
github.com/acobaugh/osrelease v0.1.0/go.mod h1:4bFEs0MtgHNHBrmHCt67gNisnabCRAlzdVasCEGHTWY=
|
||||
github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls=
|
||||
github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E=
|
||||
github.com/adrg/xdg v0.5.1 h1:Im8iDbEFARltY09yOJlSGu4Asjk2vF85+3Dyru8uJ0U=
|
||||
github.com/adrg/xdg v0.5.1/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
@@ -93,10 +97,10 @@ github.com/anchore/archiver/v3 v3.5.2 h1:Bjemm2NzuRhmHy3m0lRe5tNoClB9A4zYyDV58Pa
|
||||
github.com/anchore/archiver/v3 v3.5.2/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
||||
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9 h1:p0ZIe0htYOX284Y4axJaGBvXHU0VCCzLN5Wf5XbKStU=
|
||||
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9/go.mod h1:3ZsFB9tzW3vl4gEiUeuSOMDnwroWxIxJelOOHUp8dSw=
|
||||
github.com/anchore/clio v0.0.0-20240209204744-cb94e40a4f65 h1:u9XrEabKlGPsrmRvAER+kUKkwXiJfLyqGhmOTFsXjX4=
|
||||
github.com/anchore/clio v0.0.0-20240209204744-cb94e40a4f65/go.mod h1:8Jr7CjmwFVcBPtkJdTpaAGHimoGJGfbExypjzOu87Og=
|
||||
github.com/anchore/fangs v0.0.0-20231201140849-5075d28d6d8b h1:L/djgY7ZbZ/38+wUtdkk398W3PIBJLkt1N8nU/7e47A=
|
||||
github.com/anchore/fangs v0.0.0-20231201140849-5075d28d6d8b/go.mod h1:TLcE0RE5+8oIx2/NPWem/dq1DeaMoC+fPEH7hoSzPLo=
|
||||
github.com/anchore/clio v0.0.0-20240522144804-d81e109008aa h1:pwlAn4O9SBUnlgfa69YcqIynbUyobLVFYu8HxSoCffA=
|
||||
github.com/anchore/clio v0.0.0-20240522144804-d81e109008aa/go.mod h1:nD3H5uIvjxlfmakOBgtyFQbk5Zjp3l538kxfpHPslzI=
|
||||
github.com/anchore/fangs v0.0.0-20240903175602-e716ef12c23d h1:ZD4wdCBgJJzJybjTUIEiiupLF7B9H3WLuBTjspBO2Mc=
|
||||
github.com/anchore/fangs v0.0.0-20240903175602-e716ef12c23d/go.mod h1:Xh4ObY3fmoMzOEVXwDtS1uK44JC7+nRD0n29/1KYFYg=
|
||||
github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537 h1:GjNGuwK5jWjJMyVppBjYS54eOiiSNv4Ba869k4wh72Q=
|
||||
github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537/go.mod h1:1aiktV46ATCkuVg0O573ZrH56BUawTECPETbZyBcqT8=
|
||||
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a h1:nJ2G8zWKASyVClGVgG7sfM5mwoZlZ2zYpIzN2OhjWkw=
|
||||
@@ -109,10 +113,10 @@ github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 h1:VzprUTpc0v
|
||||
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04/go.mod h1:6dK64g27Qi1qGQZ67gFmBFvEHScy0/C8qhQhNe5B5pQ=
|
||||
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZVsCYMrIZBpFxwV26CbsuoEh5muXD5I1Ods=
|
||||
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E=
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20240312213626-055233e539b4 h1:SjemQ90fgflz39HG+VMkNfrpUVJpcFW6ZFA3TDXqzBM=
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20240312213626-055233e539b4/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4=
|
||||
github.com/anchore/stereoscope v0.0.2-0.20240229175558-fe426d1b1c84 h1:/E74wU51M87fX5UWHubLZiENXbuAci+xtbSb+JFsIYg=
|
||||
github.com/anchore/stereoscope v0.0.2-0.20240229175558-fe426d1b1c84/go.mod h1:evQiJMQG56Z7/L5uhA8kfhhjF6ESJUZzUH9ms6bQ2Co=
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20241018175412-5c22e6360c4f h1:dAQPIrQ3a5PBqZeZ+B9NGZsGmodk4NO9OjDIsQmQyQM=
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20241018175412-5c22e6360c4f/go.mod h1:KoYIv7tdP5+CC9VGkeZV4/vGCKsY55VvoG+5dadg4YI=
|
||||
github.com/anchore/stereoscope v0.0.5-0.20241018131503-a38c93517fc7 h1:CBKDfuMWKRt12EnKtgT/an9FQSQI83mOU1KT57z81IU=
|
||||
github.com/anchore/stereoscope v0.0.5-0.20241018131503-a38c93517fc7/go.mod h1:wH79ZauZcd3erKPocg9+qhDC6Q/z125sD+Isi4d61a4=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
@@ -141,8 +145,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I=
|
||||
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||
github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q=
|
||||
github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||
github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M=
|
||||
github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
|
||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
@@ -153,14 +157,18 @@ github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0=
|
||||
github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw=
|
||||
github.com/charmbracelet/bubbletea v0.25.0 h1:bAfwk7jRz7FKFl9RzlIULPkStffg5k6pNt5dywy4TcM=
|
||||
github.com/charmbracelet/bubbletea v0.25.0/go.mod h1:EN3QDR1T5ZdWmdfDzYcqOCAps45+QIJbLOBxmVNWNNg=
|
||||
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
|
||||
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
|
||||
github.com/charmbracelet/bubbletea v1.1.1 h1:KJ2/DnmpfqFtDNVTvYZ6zpPFL9iRCRr0qqKOCvppbPY=
|
||||
github.com/charmbracelet/bubbletea v1.1.1/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4=
|
||||
github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ=
|
||||
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
|
||||
github.com/charmbracelet/lipgloss v0.10.0 h1:KWeXFSexGcfahHX+54URiZGkBFazf70JNMtwg/AFW3s=
|
||||
github.com/charmbracelet/lipgloss v0.10.0/go.mod h1:Wig9DSfvANsxqkRsqj6x87irdy123SR4dOXlKa91ciE=
|
||||
github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw=
|
||||
github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY=
|
||||
github.com/charmbracelet/x/ansi v0.2.3 h1:VfFN0NUpcjBRd4DnKfRaIRo53KRgey/nhOoEqosGDEY=
|
||||
github.com/charmbracelet/x/ansi v0.2.3/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
|
||||
github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0=
|
||||
github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
@@ -168,8 +176,8 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
||||
github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqwI=
|
||||
github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
@@ -182,20 +190,24 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
|
||||
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
|
||||
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
|
||||
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY=
|
||||
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
||||
github.com/containerd/containerd v1.7.11 h1:lfGKw3eU35sjV0aG2eYZTiwFEY1pCzxdzicHP3SZILw=
|
||||
github.com/containerd/containerd v1.7.11/go.mod h1:5UluHxHTX2rdvYuZ5OJTC5m/KJNs0Zs9wVoJm9zf5ZE=
|
||||
github.com/containerd/containerd v1.7.23 h1:H2CClyUkmpKAGlhQp95g2WXHfLYc7whAuvZGBNYOOwQ=
|
||||
github.com/containerd/containerd v1.7.23/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw=
|
||||
github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA=
|
||||
github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig=
|
||||
github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM=
|
||||
github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
|
||||
github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4=
|
||||
github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
|
||||
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
|
||||
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
|
||||
github.com/containerd/ttrpc v1.2.2 h1:9vqZr0pxwOF5koz6N0N3kJ0zDHokrcPxIR/ZR2YFtOs=
|
||||
github.com/containerd/ttrpc v1.2.2/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak=
|
||||
github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU=
|
||||
github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
|
||||
github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4=
|
||||
github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
@@ -203,12 +215,12 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/dave/jennifer v1.7.0 h1:uRbSBH9UTS64yXbh4FrMHfgfY762RD+C7bUPKODpSJE=
|
||||
github.com/dave/jennifer v1.7.0/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc=
|
||||
github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo=
|
||||
github.com/dave/jennifer v1.7.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc=
|
||||
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -219,12 +231,12 @@ github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da/go.mod h1:B3tI9iGHi4i
|
||||
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/cli v24.0.0+incompatible h1:0+1VshNwBQzQAx9lOl+OYCTCEAD8fKs/qeXMx3O0wqM=
|
||||
github.com/docker/cli v24.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ=
|
||||
github.com/docker/cli v27.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v26.0.0+incompatible h1:Ng2qi+gdKADUa/VM+6b6YaY2nlZhk/lVJiKR/2bMudU=
|
||||
github.com/docker/docker v26.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI=
|
||||
github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
|
||||
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
@@ -257,6 +269,8 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.
|
||||
github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||
github.com/facebookincubator/flog v0.0.0-20190930132826-d2511d0ce33c/go.mod h1:QGzNH9ujQ2ZUr/CjDGZGWeDAVStrWNjHeEcjJL96Nuk=
|
||||
github.com/facebookincubator/nvdtools v0.1.5 h1:jbmDT1nd6+k+rlvKhnkgMokrCAzHoASWE5LtHbX2qFQ=
|
||||
github.com/facebookincubator/nvdtools v0.1.5/go.mod h1:Kh55SAWnjckS96TBSrXI99KrEKH4iB0OJby3N8GRJO4=
|
||||
@@ -267,24 +281,24 @@ github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA=
|
||||
github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI=
|
||||
github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
|
||||
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
|
||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
|
||||
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.0 h1:Cn9dkdYsMIu56tGho+fqzh7XmvY2YyGU0FnbhiOsEro=
|
||||
github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc=
|
||||
github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/github/go-spdx/v2 v2.2.0 h1:yBBLMasHA70Ujd35OpL/OjJOWWVNXcJGbars0GinGRI=
|
||||
github.com/github/go-spdx/v2 v2.2.0/go.mod h1:hMCrsFgT0QnCwn7G8gxy/MxMpy67WgZrwFeISTn0o6w=
|
||||
github.com/github/go-spdx/v2 v2.3.2 h1:IfdyNHTqzs4zAJjXdVQfRnxt1XMfycXoHBE2Vsm1bjs=
|
||||
github.com/github/go-spdx/v2 v2.3.2/go.mod h1:2ZxKsOhvBp+OYBDlsGnUMcchLeo2mrpEBn2L1C+U3IQ=
|
||||
github.com/gkampitakis/ciinfo v0.3.0 h1:gWZlOC2+RYYttL0hBqcoQhM7h1qNkVqvRCV1fOvpAv8=
|
||||
github.com/gkampitakis/ciinfo v0.3.0/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo=
|
||||
github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M=
|
||||
github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk=
|
||||
github.com/gkampitakis/go-snaps v0.5.3 h1:2cJnBgHzJhh0Jk5XBIyDYDe1Ylfncoa9r9bVJ5qvOAE=
|
||||
github.com/gkampitakis/go-snaps v0.5.3/go.mod h1:ZABkO14uCuVxBHAXAfKG+bqNz+aa1bGPAg8jkI0Nk8Y=
|
||||
github.com/gkampitakis/go-snaps v0.5.7 h1:uVGjHR4t4pPHU944udMx7VKHpwepZXmvDMF+yDmI0rg=
|
||||
github.com/gkampitakis/go-snaps v0.5.7/go.mod h1:ZABkO14uCuVxBHAXAfKG+bqNz+aa1bGPAg8jkI0Nk8Y=
|
||||
github.com/glebarez/go-sqlite v1.20.3 h1:89BkqGOXR9oRmG58ZrzgoY/Fhy5x0M+/WV48U5zVrZ4=
|
||||
github.com/glebarez/go-sqlite v1.20.3/go.mod h1:u3N6D/wftiAzIOJtZl6BmedqxmmkDfH3q+ihjqxC9u0=
|
||||
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
||||
@@ -305,16 +319,16 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-restruct/restruct v1.2.0-alpha h1:2Lp474S/9660+SJjpVxoKuWX09JsXHSrdV7Nv3/gkvc=
|
||||
github.com/go-restruct/restruct v1.2.0-alpha/go.mod h1:KqrpKpn4M8OLznErihXTGLlsXFGeLxHUrLRRI/1YjGk=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
|
||||
github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
|
||||
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
@@ -351,8 +365,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
@@ -374,8 +388,8 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-containerregistry v0.19.1 h1:yMQ62Al6/V0Z7CqIrrS1iYoA5/oQCm88DeNujc7C1KY=
|
||||
github.com/google/go-containerregistry v0.19.1/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI=
|
||||
github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo=
|
||||
github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/licensecheck v0.3.1 h1:QoxgoDkaeC4nFrtGN1jV7IPmDCHFNIVh54e5hSt6sPs=
|
||||
github.com/google/licensecheck v0.3.1/go.mod h1:ORkR35t/JjW+emNKtfJDII0zlciG9JgbT7SmsohlHmY=
|
||||
@@ -398,10 +412,9 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
|
||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@@ -453,8 +466,8 @@ github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOn
|
||||
github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
|
||||
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
|
||||
github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
|
||||
github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
|
||||
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
|
||||
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk=
|
||||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
|
||||
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||
@@ -463,9 +476,6 @@ github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
|
||||
github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
@@ -473,8 +483,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/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/jedib0t/go-pretty/v6 v6.5.8 h1:8BCzJdSvUbaDuRba4YVh+SKMGcAAKdkcF3SVFbrHAtQ=
|
||||
github.com/jedib0t/go-pretty/v6 v6.5.8/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E=
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.1 h1:iJ65Xjb680rHcikRj6DSIbzCex2huitmc7bDtxYVWyc=
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.1/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E=
|
||||
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
|
||||
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
@@ -492,13 +502,13 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
|
||||
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
|
||||
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
|
||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/knqyf263/go-rpmdb v0.1.0 h1:pOgjtOGtW0B+ibY905hP3ETrYFmLZsHiReKsplcs+to=
|
||||
github.com/knqyf263/go-rpmdb v0.1.0/go.mod h1:9LQcoMCMQ9vrF7HcDtXfvqGO4+ddxFQ8+YF/0CVGDww=
|
||||
github.com/knqyf263/go-rpmdb v0.1.1 h1:oh68mTCvp1XzxdU7EfafcWzzfstUZAEa3MW0IJye584=
|
||||
github.com/knqyf263/go-rpmdb v0.1.1/go.mod h1:9LQcoMCMQ9vrF7HcDtXfvqGO4+ddxFQ8+YF/0CVGDww=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
@@ -512,8 +522,9 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
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/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible/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/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
|
||||
@@ -536,16 +547,13 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
|
||||
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 h1:P8UmIzZMYDR+NGImiFvErt6VWfIRPuGM+vyjiEdkmIw=
|
||||
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.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
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-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
@@ -555,7 +563,6 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N
|
||||
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
||||
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
|
||||
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
@@ -568,19 +575,22 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
|
||||
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||
github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g=
|
||||
github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
||||
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
|
||||
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
|
||||
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
||||
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
|
||||
github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
|
||||
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
|
||||
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
||||
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
||||
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
|
||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@@ -590,12 +600,10 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 h1:kMlmsLSbjkikxQJ1IPwaM+7LJ9ltFu/fi8CRzvSnQmA=
|
||||
github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
|
||||
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
|
||||
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
||||
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
@@ -609,12 +617,10 @@ github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
|
||||
github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss=
|
||||
github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8=
|
||||
github.com/opencontainers/runtime-spec v1.1.0-rc.1 h1:wHa9jroFfKGQqFHj0I1fMRKLl0pfj+ynAqBxo3v6u9w=
|
||||
github.com/opencontainers/runtime-spec v1.1.0-rc.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
||||
github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
|
||||
github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
|
||||
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
@@ -624,11 +630,11 @@ github.com/pborman/indent v1.2.1/go.mod h1:FitS+t35kIYtB5xWTZAPhnmrxcciEEOdbyrrp
|
||||
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0=
|
||||
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pierrec/lz4/v4 v4.1.19 h1:tYLzDnjDXh9qIxSTKHwXwOYmm9d887Y7Y1ZkyXYHAN4=
|
||||
github.com/pierrec/lz4/v4 v4.1.19/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
@@ -657,12 +663,12 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
|
||||
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE=
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
@@ -674,37 +680,38 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/saferwall/pe v1.5.2 h1:h5lLtLsyxGHQ9dN6cd8EfeLEBEo5gdqJpkuw4o4vTMY=
|
||||
github.com/saferwall/pe v1.5.2/go.mod h1:SNzv3cdgk8SBI0UwHfyTcdjawfdnN+nbydnEL7GZ25s=
|
||||
github.com/saferwall/pe v1.5.4 h1:tLmMggEMUfeqrpJ25zS/okUQmyFdD5xWKL2+z9njCqg=
|
||||
github.com/saferwall/pe v1.5.4/go.mod h1:mJx+PuptmNpoPFBNhWs/uDMFL/kTHVZIkg0d4OUJFbQ=
|
||||
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
|
||||
github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
|
||||
github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
|
||||
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
||||
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/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f h1:MvTmaQdww/z0Q4wrYjDSCcZ78NoftLQyHBSLW/Cx79Y=
|
||||
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
|
||||
github.com/sahilm/fuzzy v0.1.1/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/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/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
|
||||
github.com/sassoftware/go-rpmutils v0.3.0 h1:tE4TZ8KcOXay5iIP64P291s6Qxd9MQCYhI7DU+f3gFA=
|
||||
github.com/sassoftware/go-rpmutils v0.3.0/go.mod h1:hM9wdxFsjUFR/tJ6SMsLrJuChcucCa0DsCzE9RMfwMo=
|
||||
github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtCdFLPWhpg=
|
||||
github.com/sassoftware/go-rpmutils v0.4.0/go.mod h1:3goNWi7PGAT3/dlql2lv3+MSN5jNYPjT5mVcQcIsYzI=
|
||||
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e h1:7q6NSFZDeGfvvtIRwBrU/aegEYJYmvev0cHAwo17zZQ=
|
||||
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd78rljTxKAnTDPFqXSGxvETQnJyuSOQwsHycqfs=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y=
|
||||
github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
|
||||
github.com/sebdah/goldie/v2 v2.5.5 h1:rx1mwF95RxZ3/83sdS4Yp7t2C5TCokvWP4TBRbAyEWY=
|
||||
github.com/sebdah/goldie/v2 v2.5.5/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
|
||||
github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d h1:RQqyEogx5J6wPdoxqL132b100j8KjcVHO1c0KLRoIhc=
|
||||
github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d/go.mod h1:PegD7EVqlN88z7TpCqH92hHP+GBpfomGCCnw1PFtNOA=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
|
||||
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
@@ -714,25 +721,24 @@ github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9yS
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM=
|
||||
github.com/spdx/tools-golang v0.5.3 h1:ialnHeEYUC4+hkm5vJm4qz2x+oEJbS0mAMFrNXdQraY=
|
||||
github.com/spdx/tools-golang v0.5.3/go.mod h1:/ETOahiAo96Ob0/RAIBmFZw6XN0yTnyr/uFZm2NTMhI=
|
||||
github.com/spdx/tools-golang v0.5.5 h1:61c0KLfAcNqAjlg6UNMdkwpMernhw3zVRwDZ2x9XOmk=
|
||||
github.com/spdx/tools-golang v0.5.5/go.mod h1:MVIsXx8ZZzaRWNQpUDhC4Dud34edUYJYecciXgrw5vE=
|
||||
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
|
||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
|
||||
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
|
||||
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
|
||||
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4=
|
||||
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
||||
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM=
|
||||
github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI=
|
||||
github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI=
|
||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
||||
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
@@ -756,10 +762,10 @@ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/sylabs/sif/v2 v2.11.5 h1:7ssPH3epSonsTrzbS1YxeJ9KuqAN7ISlSM61a7j/mQM=
|
||||
github.com/sylabs/sif/v2 v2.11.5/go.mod h1:GBoZs9LU3e4yJH1dcZ3Akf/jsqYgy5SeguJQC+zd75Y=
|
||||
github.com/sylabs/squashfs v0.6.1 h1:4hgvHnD9JGlYWwT0bPYNt9zaz23mAV3Js+VEgQoRGYQ=
|
||||
github.com/sylabs/squashfs v0.6.1/go.mod h1:ZwpbPCj0ocIvMy2br6KZmix6Gzh6fsGQcCnydMF+Kx8=
|
||||
github.com/sylabs/sif/v2 v2.19.1 h1:1eeMmFc8elqJe60ZiWwXgL3gMheb0IP4GmNZ4q0IEA0=
|
||||
github.com/sylabs/sif/v2 v2.19.1/go.mod h1:U1SUhvl8X1JIxAylC0DYz1fa/Xba6EMZD1dGPGBH83E=
|
||||
github.com/sylabs/squashfs v1.0.0 h1:xAyMS21ogglkuR5HaY55PCfqY3H32ma9GkasTYo28Zg=
|
||||
github.com/sylabs/squashfs v1.0.0/go.mod h1:rhWzvgefq1X+R+LZdts10hfMsTg3g74OfGunW8tvg/4=
|
||||
github.com/terminalstatic/go-xsd-validate v0.1.5 h1:RqpJnf6HGE2CB/lZB1A8BYguk8uRtcvYAPLCF15qguo=
|
||||
github.com/terminalstatic/go-xsd-validate v0.1.5/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw=
|
||||
github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw=
|
||||
@@ -777,12 +783,12 @@ github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
|
||||
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
|
||||
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/vbatts/go-mtree v0.5.3 h1:S/jYlfG8rZ+a0bhZd+RANXejy7M4Js8fq9U+XoWTd5w=
|
||||
github.com/vbatts/go-mtree v0.5.3/go.mod h1:eXsdoPMdL2jcJx6HweWi9lYQxBsTp4lNhqqAjgkZUg8=
|
||||
github.com/vbatts/go-mtree v0.5.4 h1:OMAb8jaCyiFA7zXj0Zc/oARcxBDBoeu2LizjB8BVJl0=
|
||||
github.com/vbatts/go-mtree v0.5.4/go.mod h1:5GqJbVhm9BBiCc4K5uc/c42FPgXulHaQs4sFUEfIWMo=
|
||||
github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck=
|
||||
github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY=
|
||||
github.com/vifraa/gopom v1.0.0 h1:L9XlKbyvid8PAIK8nr0lihMApJQg/12OBvMA28BcWh0=
|
||||
@@ -802,8 +808,8 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@@ -815,8 +821,6 @@ github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1/go.mod h1:ly2RB
|
||||
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
||||
go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs=
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak=
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
@@ -826,20 +830,20 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q=
|
||||
go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
|
||||
go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
|
||||
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
|
||||
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
|
||||
go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE=
|
||||
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
|
||||
go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
|
||||
go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
|
||||
go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
|
||||
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
|
||||
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
|
||||
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
|
||||
go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8=
|
||||
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
|
||||
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
|
||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
||||
@@ -864,11 +868,10 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -909,8 +912,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -951,15 +954,14 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
|
||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -990,8 +992,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1051,6 +1053,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -1065,21 +1068,19 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
|
||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
|
||||
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -1092,8 +1093,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -1155,8 +1156,8 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -1265,12 +1266,12 @@ google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ6
|
||||
google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ=
|
||||
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc=
|
||||
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y=
|
||||
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 h1:rIo7ocm2roD9DcFIX67Ym8icoGCKSARAiPljFhh5suQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c h1:lfpJ/2rWPa/kJgxyyXM8PrNnfCzcmxJ265mADgwmvLI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@@ -1298,8 +1299,8 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
|
||||
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
|
||||
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
|
||||
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
@@ -1314,8 +1315,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@@ -1334,7 +1335,6 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
@@ -1349,18 +1349,28 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ=
|
||||
modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
|
||||
modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y=
|
||||
modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s=
|
||||
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
||||
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
||||
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
|
||||
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
|
||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI=
|
||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
|
||||
modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk=
|
||||
modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY=
|
||||
modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U=
|
||||
modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w=
|
||||
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||
modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
|
||||
modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
|
||||
modernc.org/sqlite v1.29.6 h1:0lOXGrycJPptfHDuohfYgNqoe4hu+gYuN/pKgY5XjS4=
|
||||
modernc.org/sqlite v1.29.6/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U=
|
||||
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
|
||||
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
|
||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
|
||||
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
|
||||
modernc.org/sqlite v1.33.1 h1:trb6Z3YYoeM9eDL1O8do81kP+0ejv+YzgyFo+Gwy0nM=
|
||||
modernc.org/sqlite v1.33.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k=
|
||||
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
|
||||
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
@@ -1368,4 +1378,4 @@ modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
|
||||
+220
-53
@@ -2,34 +2,26 @@
|
||||
# note: we require errors to propagate (don't set -e)
|
||||
set -u
|
||||
|
||||
PROJECT_NAME="syft"
|
||||
PROJECT_NAME=syft
|
||||
OWNER=anchore
|
||||
REPO="${PROJECT_NAME}"
|
||||
GITHUB_DOWNLOAD_PREFIX=https://github.com/${OWNER}/${REPO}/releases/download
|
||||
INSTALL_SH_BASE_URL=https://raw.githubusercontent.com/${OWNER}/${PROJECT_NAME}
|
||||
PROGRAM_ARGS=$@
|
||||
|
||||
# signature verification options
|
||||
|
||||
# the location to the cosign binary (allowed to be overridden by the user)
|
||||
COSIGN_BINARY=${COSIGN_BINARY:-cosign}
|
||||
VERIFY_SIGN=false
|
||||
# this is the earliest tag in the repo where cosign sign-blob was introduced in the release process (see the goreleaser config)
|
||||
VERIFY_SIGN_SUPPORTED_VERSION=v0.104.0
|
||||
# this is the earliest tag in the repo where the -v flag was introduced to this install.sh script
|
||||
VERIFY_SIGN_FLAG_VERSION=v1.6.0
|
||||
|
||||
# do not change the name of this parameter (this must always be backwards compatible)
|
||||
DOWNLOAD_TAG_INSTALL_SCRIPT=${DOWNLOAD_TAG_INSTALL_SCRIPT:-true}
|
||||
|
||||
#
|
||||
# usage [script-name]
|
||||
#
|
||||
usage() (
|
||||
this=$1
|
||||
cat <<EOF
|
||||
$this: download go binaries for anchore/syft
|
||||
|
||||
Usage: $this [-b] dir [-d] [tag]
|
||||
-b the installation directory (dDefaults to ./bin)
|
||||
-d turns on debug logging
|
||||
-dd turns on trace logging
|
||||
[tag] the specific release to use (if missing, then the latest will be used)
|
||||
EOF
|
||||
exit 2
|
||||
)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
# https://github.com/client9/shlib - portable posix shell functions
|
||||
# Public domain - http://unlicense.org
|
||||
@@ -270,21 +262,21 @@ hash_sha256() (
|
||||
)
|
||||
|
||||
hash_sha256_verify() (
|
||||
TARGET=$1
|
||||
target=$1
|
||||
checksums=$2
|
||||
if [ -z "$checksums" ]; then
|
||||
log_err "hash_sha256_verify checksum file not specified in arg2"
|
||||
log_err "hash_sha256_verify checksum file not specified as argument"
|
||||
return 1
|
||||
fi
|
||||
BASENAME=${TARGET##*/}
|
||||
want=$(grep "${BASENAME}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1)
|
||||
target_basename=${target##*/}
|
||||
want=$(grep "${target_basename}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1)
|
||||
if [ -z "$want" ]; then
|
||||
log_err "hash_sha256_verify unable to find checksum for '${TARGET}' in '${checksums}'"
|
||||
log_err "hash_sha256_verify unable to find checksum for '${target}' in '${checksums}'"
|
||||
return 1
|
||||
fi
|
||||
got=$(hash_sha256 "$TARGET")
|
||||
got=$(hash_sha256 "$target")
|
||||
if [ "$want" != "$got" ]; then
|
||||
log_err "hash_sha256_verify checksum for '$TARGET' did not verify ${want} vs $got"
|
||||
log_err "hash_sha256_verify checksum for '$target' did not verify ${want} vs $got"
|
||||
return 1
|
||||
fi
|
||||
)
|
||||
@@ -358,28 +350,69 @@ github_release_tag() (
|
||||
echo "$tag"
|
||||
)
|
||||
|
||||
# github_release_asset_url [release-url-prefix] [name] [version] [output-dir] [filename]
|
||||
#
|
||||
# outputs the url to the release asset
|
||||
#
|
||||
github_release_asset_url() (
|
||||
download_url="$1"
|
||||
name="$2"
|
||||
version="$3"
|
||||
filename="$4"
|
||||
|
||||
complete_filename="${name}_${version}_${filename}"
|
||||
complete_url="${download_url}/${complete_filename}"
|
||||
|
||||
echo "${complete_url}"
|
||||
)
|
||||
|
||||
# download_github_release_checksums_files [release-url-prefix] [name] [version] [output-dir] [filename]
|
||||
#
|
||||
# outputs path to the downloaded checksums related file
|
||||
#
|
||||
download_github_release_checksums_files() (
|
||||
download_url="$1"
|
||||
name="$2"
|
||||
version="$3"
|
||||
output_dir="$4"
|
||||
filename="$5"
|
||||
|
||||
log_trace "download_github_release_checksums_files(url=${download_url}, name=${name}, version=${version}, output_dir=${output_dir}, filename=${filename})"
|
||||
|
||||
complete_filename="${name}_${version}_${filename}"
|
||||
complete_url=$(github_release_asset_url "${download_url}" "${name}" "${version}" "${filename}")
|
||||
output_path="${output_dir}/${complete_filename}"
|
||||
|
||||
http_download "${output_path}" "${complete_url}" ""
|
||||
asset_file_exists "${output_path}"
|
||||
|
||||
log_trace "download_github_release_checksums_files() returned '${output_path}' for file '${complete_filename}'"
|
||||
|
||||
echo "${output_path}"
|
||||
)
|
||||
|
||||
# download_github_release_checksums [release-url-prefix] [name] [version] [output-dir]
|
||||
#
|
||||
# outputs path to the downloaded checksums file
|
||||
#
|
||||
download_github_release_checksums() (
|
||||
download_url="$1"
|
||||
name="$2"
|
||||
version="$3"
|
||||
output_dir="$4"
|
||||
download_github_release_checksums_files "$@" "checksums.txt"
|
||||
)
|
||||
|
||||
log_trace "download_github_release_checksums(url=${download_url}, name=${name}, version=${version}, output_dir=${output_dir})"
|
||||
# github_release_checksums_sig_url [release-url-prefix] [name] [version]
|
||||
#
|
||||
# outputs the url to the release checksums signature file
|
||||
#
|
||||
github_release_checksums_sig_url() (
|
||||
github_release_asset_url "$@" "checksums.txt.sig"
|
||||
)
|
||||
|
||||
checksum_filename=${name}_${version}_checksums.txt
|
||||
checksum_url=${download_url}/${checksum_filename}
|
||||
output_path="${output_dir}/${checksum_filename}"
|
||||
|
||||
http_download "${output_path}" "${checksum_url}" ""
|
||||
asset_file_exists "${output_path}"
|
||||
|
||||
log_trace "download_github_release_checksums() returned '${output_path}'"
|
||||
|
||||
echo "${output_path}"
|
||||
# github_release_checksums_cert_url [release-url-prefix] [name] [version]
|
||||
#
|
||||
# outputs the url to the release checksums certificate file
|
||||
#
|
||||
github_release_checksums_cert_url() (
|
||||
github_release_asset_url "$@" "checksums.txt.pem"
|
||||
)
|
||||
|
||||
# search_for_asset [checksums-file-path] [name] [os] [arch] [format]
|
||||
@@ -535,7 +568,10 @@ download_and_install_asset() (
|
||||
format="$8"
|
||||
binary="$9"
|
||||
|
||||
asset_filepath=$(download_asset "${download_url}" "${download_path}" "${name}" "${os}" "${arch}" "${version}" "${format}")
|
||||
if ! asset_filepath=$(download_asset "${download_url}" "${download_path}" "${name}" "${os}" "${arch}" "${version}" "${format}"); then
|
||||
log_err "could not download asset for os='${os}' arch='${arch}' format='${format}'"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# don't continue if we couldn't download an asset
|
||||
if [ -z "${asset_filepath}" ]; then
|
||||
@@ -546,6 +582,36 @@ download_and_install_asset() (
|
||||
install_asset "${asset_filepath}" "${install_path}" "${binary}"
|
||||
)
|
||||
|
||||
# verify_sign [checksums-file-path] [certificate-reference] [signature-reference] [version]
|
||||
#
|
||||
# attempts verify the signature of the checksums file from the release workflow in Github Actions run against the main branch.
|
||||
#
|
||||
verify_sign() {
|
||||
checksums_file=$1
|
||||
cert_reference=$2
|
||||
sig_reference=$3
|
||||
|
||||
log_trace "verifying artifact $1"
|
||||
|
||||
log_file=$(mktemp)
|
||||
|
||||
${COSIGN_BINARY} \
|
||||
verify-blob "$checksums_file" \
|
||||
--certificate "$cert_reference" \
|
||||
--signature "$sig_reference" \
|
||||
--certificate-identity "https://github.com/${OWNER}/${REPO}/.github/workflows/release.yaml@refs/heads/main" \
|
||||
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" > "${log_file}" 2>&1
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
log_err "$(cat "${log_file}")"
|
||||
rm -f "${log_file}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
rm -f "${log_file}"
|
||||
}
|
||||
|
||||
|
||||
# download_asset [release-url-prefix] [download-path] [name] [os] [arch] [version] [format] [binary]
|
||||
#
|
||||
# outputs the path to the downloaded asset asset_filepath
|
||||
@@ -572,6 +638,20 @@ download_asset() (
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$VERIFY_SIGN" = true ]; then
|
||||
checksum_sig_file_url=$(github_release_checksums_sig_url "${download_url}" "${name}" "${version}")
|
||||
log_trace "checksums signature url: ${checksum_sig_file_url}"
|
||||
|
||||
checksums_cert_file_url=$(github_release_checksums_cert_url "${download_url}" "${name}" "${version}")
|
||||
log_trace "checksums certificate url: ${checksums_cert_file_url}"
|
||||
|
||||
if ! verify_sign "${checksums_filepath}" "${checksums_cert_file_url}" "${checksum_sig_file_url}"; then
|
||||
log_err "signature verification failed"
|
||||
return 1
|
||||
fi
|
||||
log_info "signature verification succeeded"
|
||||
fi
|
||||
|
||||
asset_url="${download_url}/${asset_filename}"
|
||||
asset_filepath="${destination}/${asset_filename}"
|
||||
http_download "${asset_filepath}" "${asset_url}" ""
|
||||
@@ -609,6 +689,79 @@ install_asset() (
|
||||
install "${archive_dir}/${binary}" "${destination}/"
|
||||
)
|
||||
|
||||
# compare two semver strings. Returns 0 if version1 >= version2, 1 otherwise.
|
||||
# Note: pre-release (-) and metadata (+) are not supported.
|
||||
compare_semver() {
|
||||
# remove leading 'v' if present
|
||||
version1=${1#v}
|
||||
version2=${2#v}
|
||||
|
||||
IFS=. read -r major1 minor1 patch1 <<EOF
|
||||
$version1
|
||||
EOF
|
||||
IFS=. read -r major2 minor2 patch2 <<EOF
|
||||
$version2
|
||||
EOF
|
||||
|
||||
if [ "$major1" -gt "$major2" ]; then
|
||||
return 0
|
||||
elif [ "$major1" -lt "$major2" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$minor1" -gt "$minor2" ]; then
|
||||
return 0
|
||||
elif [ "$minor1" -lt "$minor2" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$patch1" -gt "$patch2" ]; then
|
||||
return 0
|
||||
elif [ "$patch1" -lt "$patch2" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# versions are equal
|
||||
return 0
|
||||
}
|
||||
|
||||
prep_signature_verification() {
|
||||
version="$1"
|
||||
|
||||
if [ "$VERIFY_SIGN" != true ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# is there any cryptographic material produced at release that we can use for signature verification?
|
||||
if ! compare_semver "$version" "$VERIFY_SIGN_SUPPORTED_VERSION"; then
|
||||
log_err "${PROJECT_NAME} release '$version' does not support signature verification"
|
||||
log_err "you can still install ${PROJECT_NAME} by removing the -v flag or using a release that supports signature verification (>= '$VERIFY_SIGN_SUPPORTED_VERSION')"
|
||||
log_err "aborting installation"
|
||||
return 1
|
||||
else
|
||||
log_trace "${PROJECT_NAME} release '$version' supports signature verification (>= '$VERIFY_SIGN_SUPPORTED_VERSION')"
|
||||
fi
|
||||
|
||||
# will invoking an earlier version of this script work (considering the -v flag)?
|
||||
if ! compare_semver "$version" "$VERIFY_SIGN_FLAG_VERSION"; then
|
||||
# the -v argument did not always exist, so we cannot be guaranteed that invoking an earlier version of this script
|
||||
# will work (error with "illegal option -v"). However, the user requested signature verification, so we will
|
||||
# attempt to install the application with this version of the script (keeping signature verification).
|
||||
DOWNLOAD_TAG_INSTALL_SCRIPT=false
|
||||
log_debug "provided version install script does not support -v flag (>= '$VERIFY_SIGN_FLAG_VERSION'), using current script for installation"
|
||||
else
|
||||
log_trace "provided version install script supports -v flag (>= '$VERIFY_SIGN_FLAG_VERSION')"
|
||||
fi
|
||||
|
||||
# check to see if the cosign binary is installed
|
||||
if is_command "${COSIGN_BINARY}"; then
|
||||
log_trace "${COSIGN_BINARY} binary is installed"
|
||||
else
|
||||
log_err "signature verification is requested but ${COSIGN_BINARY} binary is not installed (see https://docs.sigstore.dev/system_config/installation/ to install it)"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
main() (
|
||||
# parse arguments
|
||||
|
||||
@@ -616,7 +769,7 @@ main() (
|
||||
install_dir=${install_dir:-./bin}
|
||||
|
||||
# note: never change the program flags or arguments (this must always be backwards compatible)
|
||||
while getopts "b:dh?x" arg; do
|
||||
while getopts "b:dvh?x" arg; do
|
||||
case "$arg" in
|
||||
b) install_dir="$OPTARG" ;;
|
||||
d)
|
||||
@@ -628,25 +781,37 @@ main() (
|
||||
log_set_priority $log_trace_priority
|
||||
fi
|
||||
;;
|
||||
h | \?) usage "$0" ;;
|
||||
v) VERIFY_SIGN=true;;
|
||||
h | \?)
|
||||
cat <<EOF
|
||||
Download and install a released binary for ${OWNER}/${REPO} from the github releases page
|
||||
|
||||
Usage: $0 [-v] [-b DIR] [-d] [TAG]
|
||||
-b DIR the installation directory (defaults to ./bin)
|
||||
-d turns on debug logging
|
||||
-dd turns on trace logging
|
||||
-v verify checksum signature (requires cosign binary to be installed).
|
||||
TAG the specific release to use (if missing, then the latest will be used)
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
x) set -x ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
set +u
|
||||
tag=$1
|
||||
|
||||
if [ -z "${tag}" ]; then
|
||||
log_debug "checking github for the current release tag"
|
||||
log_info "checking github for the current release tag"
|
||||
tag=""
|
||||
else
|
||||
log_debug "checking github for release tag='${tag}'"
|
||||
log_info "checking github for release tag='${tag}'"
|
||||
fi
|
||||
set -u
|
||||
|
||||
tag=$(get_release_tag "${OWNER}" "${REPO}" "${tag}")
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
if ! tag=$(get_release_tag "${OWNER}" "${REPO}" "${tag}"); then
|
||||
log_err "unable to find tag='${tag}'"
|
||||
log_err "do not specify a version or select a valid version from https://github.com/${OWNER}/${REPO}/releases"
|
||||
return 1
|
||||
@@ -661,6 +826,10 @@ main() (
|
||||
binary=$(get_binary_name "${os}" "${arch}" "${PROJECT_NAME}")
|
||||
download_url="${GITHUB_DOWNLOAD_PREFIX}/${tag}"
|
||||
|
||||
if ! prep_signature_verification "$version"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# we always use the install.sh script that is associated with the tagged release. Why? the latest install.sh is not
|
||||
# guaranteed to be able to install every version of the application. We use the DOWNLOAD_TAG_INSTALL_SCRIPT env var
|
||||
# to indicate if we should continue processing with the existing script or to download the script from the given tag.
|
||||
@@ -678,10 +847,8 @@ main() (
|
||||
|
||||
log_debug "downloading files into ${download_dir}"
|
||||
|
||||
download_and_install_asset "${download_url}" "${download_dir}" "${install_dir}" "${PROJECT_NAME}" "${os}" "${arch}" "${version}" "${format}" "${binary}"
|
||||
|
||||
# don't continue if we couldn't install the asset
|
||||
if [ "$?" != "0" ]; then
|
||||
if ! download_and_install_asset "${download_url}" "${download_dir}" "${install_dir}" "${PROJECT_NAME}" "${os}" "${arch}" "${version}" "${format}" "${binary}"; then
|
||||
log_err "failed to install ${PROJECT_NAME}"
|
||||
return 1
|
||||
fi
|
||||
@@ -697,4 +864,4 @@ if [ -z "${TEST_INSTALL_SH}" ]; then
|
||||
main "$@"
|
||||
exit $?
|
||||
fi
|
||||
set -u
|
||||
set -u
|
||||
|
||||
Vendored
+51
@@ -0,0 +1,51 @@
|
||||
# Caching
|
||||
|
||||
All caches are created from a global `manager`. By default this is a `bypassedCache`, which performs no caching.
|
||||
One benefit of this is that tests don't need to worry about caching causing issues unless they explicitly need
|
||||
to test the cache and can opt-in using the `cache.TestCache(t)` helper.
|
||||
|
||||
Syft sets a `filesystemCache` when the [cache options](../../cmd/syft/internal/options/cache.go) are loaded.
|
||||
|
||||
When using the `filesystemCache` all items are stored on disk under a root directory, generally in the form of:
|
||||
```
|
||||
<rootDir>/<named-cache>/<data-version>/path/to/data
|
||||
```
|
||||
|
||||
# Using the cache
|
||||
|
||||
The easiest and preferred method to use the cache is a `cache.Resolver`, which automatically creates a `<data-version>`
|
||||
based on the _structure_ of the provided type.
|
||||
If the structure changes in any way it will end up with a new version key and all will re populate this new key,
|
||||
ignoring cached values from older, different versions.
|
||||
The resolver will store items using the `json` package to serialize/deserialize values, so to save space
|
||||
it is encouraged to use `omitempty`. For example:
|
||||
|
||||
```go
|
||||
type myCacheItem struct {
|
||||
Name string `json:"name",omitempty`
|
||||
}
|
||||
```
|
||||
|
||||
It is possible to use core types such as `pkg.Package` as long as they support the standard `json` serialization,
|
||||
but this is discouraged in order to decouple changes to them from affecting the information stored in the cache.
|
||||
|
||||
To get a cache for this type:
|
||||
```go
|
||||
resolver := cache.GetResolver[myCacheItem]("myCacheName", "v1")
|
||||
```
|
||||
|
||||
Using the `resolver` is a single call, which manages checking for items in the cache, expiry times,
|
||||
and if not found invoking the callback to populate the cache and return a value:
|
||||
```go
|
||||
data := resolver.Resolve("some/cache/key", func() (myCacheItem, error) {
|
||||
// do things to return a myCacheItem or error
|
||||
})
|
||||
```
|
||||
|
||||
If it is common that checking for an item will result in errors, and you do not want to re-run the resolve function
|
||||
when errors are encountered, instead of using `GetResolver`, you can use `GetResolverCachingErrors`, which is useful
|
||||
for things such as resolving artifacts over a network, where a number of them will not be resolved, and you do not want
|
||||
to continue to have the expense of running the network resolution. This should be used when it is acceptable a network
|
||||
outage and cached errors is an acceptable risk.
|
||||
|
||||
An example can be seen in the [golang cataloger](../../syft/pkg/cataloger/golang/licenses.go) fetching remote licenses.
|
||||
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
package cache
|
||||
|
||||
import "io"
|
||||
|
||||
type bypassedCache struct{}
|
||||
|
||||
func (b *bypassedCache) Read(_ string) (ReaderAtCloser, error) {
|
||||
return nil, errNotFound
|
||||
}
|
||||
|
||||
func (b *bypassedCache) Write(_ string, contents io.Reader) error {
|
||||
if closer, ok := contents.(io.Closer); ok {
|
||||
_ = closer.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *bypassedCache) GetCache(_, _ string) Cache {
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *bypassedCache) RootDirs() []string {
|
||||
return nil
|
||||
}
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_bypassedCache(t *testing.T) {
|
||||
m := bypassedCache{}
|
||||
cache := m.GetCache("name", "version")
|
||||
err := cache.Write("test", strings.NewReader("value"))
|
||||
require.NoError(t, err)
|
||||
rdr, err := cache.Read("test")
|
||||
require.Nil(t, rdr)
|
||||
require.ErrorIs(t, err, errNotFound)
|
||||
}
|
||||
Vendored
+49
@@ -0,0 +1,49 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// Manager is responsible for managing cache data and instantiating all caches
|
||||
type Manager interface {
|
||||
// GetCache returns a cache scoped to the given named, versioned data
|
||||
GetCache(name, version string) Cache
|
||||
|
||||
// RootDirs returns any root directories this cache manager uses
|
||||
RootDirs() []string
|
||||
}
|
||||
|
||||
// ReaderAtCloser is an amalgamation of: io.Reader, io.ReaderAt, and io.Closer
|
||||
type ReaderAtCloser interface {
|
||||
io.Reader
|
||||
io.ReaderAt
|
||||
io.Closer
|
||||
}
|
||||
|
||||
// Cache is what the application interacts with to get and set cached data
|
||||
type Cache interface {
|
||||
// Read returns a reader for the cache value, if found and not expired
|
||||
// or errors when unable to find / expired
|
||||
Read(key string) (ReaderAtCloser, error)
|
||||
|
||||
// Write writes the contents of the reader to the cache
|
||||
// and closes it, if the reader implements io.Closer
|
||||
Write(key string, contents io.Reader) error
|
||||
}
|
||||
|
||||
// GetManager returns the global cache manager, which is used to instantiate all caches
|
||||
func GetManager() Manager {
|
||||
return manager
|
||||
}
|
||||
|
||||
// SetManager sets the global cache manager, which is used to instantiate all caches.
|
||||
// Setting this to nil disables caching.
|
||||
func SetManager(m Manager) {
|
||||
if m == nil {
|
||||
manager = &bypassedCache{}
|
||||
} else {
|
||||
manager = m
|
||||
}
|
||||
}
|
||||
|
||||
var manager Manager = &bypassedCache{}
|
||||
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_SetManager(t *testing.T) {
|
||||
original := GetManager()
|
||||
defer SetManager(original)
|
||||
|
||||
SetManager(nil)
|
||||
|
||||
require.NotNil(t, GetManager())
|
||||
require.IsType(t, &bypassedCache{}, GetManager())
|
||||
|
||||
SetManager(NewInMemory(0))
|
||||
|
||||
require.NotNil(t, GetManager())
|
||||
require.IsType(t, &bypassedCache{}, GetManager())
|
||||
|
||||
SetManager(NewInMemory(1 * time.Hour))
|
||||
|
||||
require.NotNil(t, GetManager())
|
||||
require.IsType(t, &filesystemCache{}, GetManager())
|
||||
|
||||
SetManager(nil)
|
||||
require.NotNil(t, GetManager())
|
||||
require.IsType(t, &bypassedCache{}, GetManager())
|
||||
}
|
||||
Vendored
+40
@@ -0,0 +1,40 @@
|
||||
package cache
|
||||
|
||||
import "fmt"
|
||||
|
||||
// GetResolverCachingErrors returns a Resolver that caches errors and will return them
|
||||
// instead of continuing to call the provided resolve functions
|
||||
func GetResolverCachingErrors[T any](name, version string) Resolver[T] {
|
||||
return &errorResolver[T]{
|
||||
resolver: GetResolver[errResponse[T]](name, version),
|
||||
}
|
||||
}
|
||||
|
||||
type errResponse[T any] struct {
|
||||
Error string `json:"err,omitempty"`
|
||||
Value T `json:"val,omitempty"`
|
||||
}
|
||||
|
||||
type errorResolver[T any] struct {
|
||||
resolver Resolver[errResponse[T]]
|
||||
}
|
||||
|
||||
func (r *errorResolver[T]) Resolve(key string, resolver resolverFunc[T]) (T, error) {
|
||||
v, err := r.resolver.Resolve(key, func() (errResponse[T], error) {
|
||||
v, err := resolver()
|
||||
out := errResponse[T]{
|
||||
Value: v,
|
||||
}
|
||||
if err != nil {
|
||||
out.Error = err.Error()
|
||||
}
|
||||
return out, nil
|
||||
})
|
||||
if err != nil {
|
||||
return v.Value, err
|
||||
}
|
||||
if v.Error != "" {
|
||||
return v.Value, fmt.Errorf("failed to resolve cache: %s", v.Error)
|
||||
}
|
||||
return v.Value, nil
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_errorResolver(t *testing.T) {
|
||||
original := GetManager()
|
||||
defer SetManager(original)
|
||||
SetManager(NewInMemory(time.Hour))
|
||||
|
||||
resolver := GetResolverCachingErrors[string]("theCache", "theVersion")
|
||||
|
||||
resolveCount := 0
|
||||
resolveFunc := func() (string, error) {
|
||||
resolveCount++
|
||||
return "theValue", nil
|
||||
}
|
||||
|
||||
val, err := resolver.Resolve("theKey", resolveFunc)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, resolveCount)
|
||||
require.Equal(t, "theValue", val)
|
||||
|
||||
val, err = resolver.Resolve("theKey", resolveFunc)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, resolveCount)
|
||||
require.Equal(t, "theValue", val)
|
||||
|
||||
errorCount := 0
|
||||
errorFunc := func() (string, error) {
|
||||
errorCount++
|
||||
return "", fmt.Errorf("an error")
|
||||
}
|
||||
|
||||
_, err = resolver.Resolve("errorValue", errorFunc)
|
||||
require.ErrorContains(t, err, "an error")
|
||||
require.Equal(t, 1, errorCount)
|
||||
|
||||
_, err = resolver.Resolve("errorValue", errorFunc)
|
||||
require.ErrorContains(t, err, "an error")
|
||||
require.Equal(t, 1, errorCount)
|
||||
}
|
||||
Vendored
+120
@@ -0,0 +1,120 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/afero"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
)
|
||||
|
||||
// NewFromDir creates a new cache manager which returns caches stored on disk, rooted at the given directory
|
||||
func NewFromDir(dir string, ttl time.Duration) (Manager, error) {
|
||||
dir = filepath.Clean(dir)
|
||||
fsys, err := subFs(afero.NewOsFs(), dir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &filesystemCache{
|
||||
dir: dir,
|
||||
fs: fsys,
|
||||
ttl: ttl,
|
||||
}, nil
|
||||
}
|
||||
|
||||
const filePermissions = 0700
|
||||
const dirPermissions = os.ModeDir | filePermissions
|
||||
|
||||
type filesystemCache struct {
|
||||
dir string
|
||||
fs afero.Fs
|
||||
ttl time.Duration
|
||||
}
|
||||
|
||||
func (d *filesystemCache) GetCache(name, version string) Cache {
|
||||
fsys, err := subFs(d.fs, name, version)
|
||||
if err != nil {
|
||||
log.Warnf("error getting cache for: %s/%s: %v", name, version, err)
|
||||
return &bypassedCache{}
|
||||
}
|
||||
return &filesystemCache{
|
||||
dir: filepath.Join(d.dir, name, version),
|
||||
fs: fsys,
|
||||
ttl: d.ttl,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *filesystemCache) RootDirs() []string {
|
||||
if d.dir == "" {
|
||||
return nil
|
||||
}
|
||||
return []string{d.dir}
|
||||
}
|
||||
|
||||
func (d *filesystemCache) Read(key string) (ReaderAtCloser, error) {
|
||||
path := makeDiskKey(key)
|
||||
f, err := d.fs.Open(path)
|
||||
if err != nil {
|
||||
log.Tracef("no cache entry for %s %s: %v", d.dir, key, err)
|
||||
return nil, errNotFound
|
||||
} else if stat, err := f.Stat(); err != nil || stat == nil || time.Since(stat.ModTime()) > d.ttl {
|
||||
log.Tracef("cache entry is too old for %s %s", d.dir, key)
|
||||
return nil, errExpired
|
||||
}
|
||||
log.Tracef("using cache for %s %s", d.dir, key)
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (d *filesystemCache) Write(key string, contents io.Reader) error {
|
||||
path := makeDiskKey(key)
|
||||
return afero.WriteReader(d.fs, path, contents)
|
||||
}
|
||||
|
||||
// subFs returns a writable directory with the given name under the root cache directory returned from findRoot,
|
||||
// the directory will be created if it does not exist
|
||||
func subFs(fsys afero.Fs, subDirs ...string) (afero.Fs, error) {
|
||||
dir := filepath.Join(subDirs...)
|
||||
dir = filepath.Clean(dir)
|
||||
stat, err := fsys.Stat(dir)
|
||||
if errors.Is(err, afero.ErrFileNotFound) {
|
||||
err = fsys.MkdirAll(dir, dirPermissions)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create directory at '%s': %v", dir, err)
|
||||
}
|
||||
stat, err = fsys.Stat(dir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err != nil || stat == nil || !stat.IsDir() {
|
||||
return nil, fmt.Errorf("unable to verify directory '%s': %v", dir, err)
|
||||
}
|
||||
fsys = afero.NewBasePathFs(fsys, dir)
|
||||
return fsys, err
|
||||
}
|
||||
|
||||
var keyReplacer = regexp.MustCompile("[^-._/a-zA-Z0-9]")
|
||||
|
||||
// makeDiskKey makes a safe sub-path but not escape forward slashes, this allows for logical partitioning on disk
|
||||
func makeDiskKey(key string) string {
|
||||
// encode single dot directory
|
||||
if key == "." {
|
||||
return "%2E"
|
||||
}
|
||||
// replace any disallowed chars with encoded form
|
||||
key = keyReplacer.ReplaceAllStringFunc(key, url.QueryEscape)
|
||||
// allow . in names but not ..
|
||||
key = strings.ReplaceAll(key, "..", "%2E%2E")
|
||||
return key
|
||||
}
|
||||
|
||||
var errNotFound = fmt.Errorf("not found")
|
||||
var errExpired = fmt.Errorf("expired")
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user