mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-12 15:50:15 -08:00
feat: add virtual machine scan command (#2910)
Co-authored-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
7
.github/workflows/semantic-pr.yaml
vendored
7
.github/workflows/semantic-pr.yaml
vendored
@@ -42,6 +42,7 @@ jobs:
|
||||
sbom
|
||||
server
|
||||
k8s
|
||||
vm
|
||||
|
||||
alpine
|
||||
redhat
|
||||
@@ -66,7 +67,7 @@ jobs:
|
||||
go
|
||||
c
|
||||
c++
|
||||
|
||||
|
||||
os
|
||||
lang
|
||||
|
||||
@@ -82,11 +83,11 @@ jobs:
|
||||
|
||||
cli
|
||||
flag
|
||||
|
||||
|
||||
cyclonedx
|
||||
spdx
|
||||
|
||||
helm
|
||||
report
|
||||
db
|
||||
deps
|
||||
deps
|
||||
|
||||
27
.github/workflows/vm-test.yaml
vendored
Normal file
27
.github/workflows/vm-test.yaml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: VM Test
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'pkg/fanal/vm/**'
|
||||
- 'pkg/fanal/walker/vm.go'
|
||||
- 'pkg/fanal/artifact/vm/**'
|
||||
- 'integration/vm_test.go'
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
vm-test:
|
||||
name: VM Integration Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
- name: Run vm integration tests
|
||||
run: |
|
||||
make test-vm-integration
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -25,6 +25,7 @@ thumbs.db
|
||||
# test fixtures
|
||||
coverage.txt
|
||||
integration/testdata/fixtures/images
|
||||
integration/testdata/fixtures/vm-images
|
||||
|
||||
# SBOMs generated during CI
|
||||
/bom.json
|
||||
@@ -33,4 +34,4 @@ integration/testdata/fixtures/images
|
||||
dist
|
||||
|
||||
# WebAssembly
|
||||
*.wasm
|
||||
*.wasm
|
||||
11
Makefile
11
Makefile
@@ -77,6 +77,15 @@ test-integration: integration/testdata/fixtures/images/*.tar.gz
|
||||
test-module-integration: integration/testdata/fixtures/images/*.tar.gz $(EXAMPLE_MODULES)
|
||||
go test -v -tags=module_integration ./integration/...
|
||||
|
||||
# Run VM integration tests
|
||||
.PHONY: test-vm-integration
|
||||
test-vm-integration: integration/testdata/fixtures/vm-images/*.img.gz
|
||||
go test -v -tags=vm_integration ./integration/...
|
||||
|
||||
integration/testdata/fixtures/vm-images/*.img.gz:
|
||||
integration/scripts/download-vm-images.sh
|
||||
|
||||
|
||||
.PHONY: lint
|
||||
lint: $(GOBIN)/golangci-lint
|
||||
$(GOBIN)/golangci-lint run --timeout 5m
|
||||
@@ -121,4 +130,4 @@ mkdocs-serve:
|
||||
# Generate JSON marshaler/unmarshaler for TinyGo/WebAssembly as TinyGo doesn't support encoding/json.
|
||||
.PHONY: easyjson
|
||||
easyjson: $(GOBIN)/easyjson
|
||||
easyjson pkg/module/serialize/types.go
|
||||
easyjson pkg/module/serialize/types.go
|
||||
@@ -11,13 +11,15 @@
|
||||
[📖 Documentation][docs]
|
||||
</div>
|
||||
|
||||
Trivy ([pronunciation][pronunciation]) is a comprehensive and versatile security scanner. Trivy has *scanners* that look for security issues, and *targets* where it can find those issues.
|
||||
Trivy ([pronunciation][pronunciation]) is a comprehensive and versatile security scanner.
|
||||
Trivy has *scanners* that look for security issues, and *targets* where it can find those issues.
|
||||
|
||||
Targets (what Trivy can scan):
|
||||
|
||||
- Container Image
|
||||
- Filesystem
|
||||
- Git repository (remote)
|
||||
- Git Repository (remote)
|
||||
- Virtual Machine Image
|
||||
- Kubernetes
|
||||
- AWS
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ This documentation details how to use Trivy to access the features listed below.
|
||||
|
||||
Please see [LICENSE][license] for Trivy licensing information.
|
||||
|
||||
[installation]: ../index.md
|
||||
[installation]: ../getting-started/installation.md
|
||||
[vuln]: ../docs/vulnerability/scanning/index.md
|
||||
[misconf]: ../docs/misconfiguration/scanning.md
|
||||
[kubernetesoperator]: ../docs/kubernetes/operator/index.md
|
||||
@@ -63,7 +63,7 @@ Please see [LICENSE][license] for Trivy licensing information.
|
||||
[lang]: ../docs/vulnerability/detection/language.md
|
||||
|
||||
[builtin]: ../docs/misconfiguration/policy/builtin.md
|
||||
[quickstart]: ../getting-started/quickstart.md
|
||||
[quickstart]: ../index.md
|
||||
[podman]: ../docs/advanced/container/podman.md
|
||||
|
||||
[sbom]: ../docs/sbom/index.md
|
||||
|
||||
70
docs/docs/vm/aws.md
Normal file
70
docs/docs/vm/aws.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# AWS EC2
|
||||
|
||||
Trivy can scan the following targets in AWS EC2.
|
||||
|
||||
- Amazon Machine Image (AMI)
|
||||
- Elastic Block Store (EBS) Snapshot
|
||||
|
||||
## Amazon Machine Image (AMI)
|
||||
You can specify your AMI ID with the `ami:` prefix.
|
||||
|
||||
```shell
|
||||
$ trivy vm ami:${your_ami_id}
|
||||
```
|
||||
|
||||
!!! note
|
||||
AMIs in the marketplace are not supported because the EBS direct APIs don't support that.
|
||||
See [the AWS documentation][ebsapi-elements] for the detail.
|
||||
|
||||
### Example
|
||||
|
||||
```shell
|
||||
$ trivy vm --security-checks vuln ami:ami-0123456789abcdefg
|
||||
```
|
||||
|
||||
!!! tip
|
||||
The scanning could be faster if you enable only vulnerability scanning (`--security-checks vuln`) because Trivy tries to download only necessary blocks for vulnerability detection.
|
||||
|
||||
|
||||
### Required Actions
|
||||
Some actions on EBS are also necessary since Trivy scans an EBS snapshot tied to the specified AMI under the hood.
|
||||
|
||||
- ec2:DescribeImages
|
||||
- ebs:ListSnapshotBlocks
|
||||
- ebs:GetSnapshotBlock
|
||||
|
||||
## Elastic Block Store (EBS) Snapshot
|
||||
You can specify your EBS snapshot ID with the `ebs:` prefix.
|
||||
|
||||
```shell
|
||||
$ trivy vm ebs:${your_ebs_snapshot_id}
|
||||
```
|
||||
|
||||
!!! note
|
||||
Public snapshots are not supported because the EBS direct APIs don't support that.
|
||||
See [the AWS documentation][ebsapi-elements] for the detail.
|
||||
|
||||
### Example
|
||||
```shell
|
||||
$ trivy vm --security-checks vuln ebs:snap-0123456789abcdefg
|
||||
```
|
||||
|
||||
!!! tip
|
||||
The scanning could be faster if you enable only vulnerability scanning (`--security-checks vuln`) because Trivy tries to download only necessary blocks for vulnerability detection.
|
||||
|
||||
The above command takes a while as it calls EBS API and fetches the EBS blocks.
|
||||
If you want to scan the same snapshot several times, you can download the snapshot locally by using [coldsnap][coldsnap] maintained by AWS.
|
||||
Then, Trivy can scan the local VM image file.
|
||||
|
||||
```shell
|
||||
$ coldsnap download snap-0123456789abcdefg disk.img
|
||||
$ trivy vm ./disk.img
|
||||
```
|
||||
|
||||
### Required Actions
|
||||
|
||||
- ebs:ListSnapshotBlocks
|
||||
- ebs:GetSnapshotBlock
|
||||
|
||||
[ebsapi-elements]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-accessing-snapshot.html#ebsapi-elements
|
||||
[coldsnap]: https://github.com/awslabs/coldsnap
|
||||
121
docs/docs/vm/index.md
Normal file
121
docs/docs/vm/index.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# Virtual Machine Image
|
||||
|
||||
!!! warning "EXPERIMENTAL"
|
||||
This feature might change without preserving backwards compatibility.
|
||||
|
||||
## Scanning
|
||||
Trivy supports VM image scanning for vulnerabilities, secrets, etc.
|
||||
The following targets are currently supported:
|
||||
|
||||
- Local file
|
||||
- [AWS EC2][aws]
|
||||
|
||||
To scan VM images, you can use the `vm` subcommand.
|
||||
|
||||
### Local file
|
||||
Pass the path to your local VM image file.
|
||||
|
||||
```bash
|
||||
$ trivy vm --security-checks vuln disk.vmdk
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Result</summary>
|
||||
|
||||
```
|
||||
disk.vmdk (amazon 2 (Karoo))
|
||||
===========================================================================================
|
||||
Total: 802 (UNKNOWN: 0, LOW: 17, MEDIUM: 554, HIGH: 221, CRITICAL: 10)
|
||||
|
||||
┌────────────────────────────┬────────────────┬──────────┬───────────────────────────────┬───────────────────────────────┬──────────────────────────────────────────────────────────────┐
|
||||
│ Library │ Vulnerability │ Severity │ Installed Version │ Fixed Version │ Title │
|
||||
├────────────────────────────┼────────────────┼──────────┼───────────────────────────────┼───────────────────────────────┼──────────────────────────────────────────────────────────────┤
|
||||
│ amazon-ssm-agent │ CVE-2022-24675 │ HIGH │ 3.0.529.0-1.amzn2 │ 3.1.1575.0-1.amzn2 │ golang: encoding/pem: fix stack overflow in Decode │
|
||||
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2022-24675 │
|
||||
├────────────────────────────┼────────────────┤ ├───────────────────────────────┼───────────────────────────────┼──────────────────────────────────────────────────────────────┤
|
||||
│ bind-export-libs │ CVE-2021-25215 │ │ 32:9.11.4-26.P2.amzn2.4 │ 32:9.11.4-26.P2.amzn2.5 │ bind: An assertion check can fail while answering queries │
|
||||
│ │ │ │ │ │ for DNAME records... │
|
||||
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2021-25215 │
|
||||
│ ├────────────────┼──────────┤ ├───────────────────────────────┼──────────────────────────────────────────────────────────────┤
|
||||
│ │ CVE-2021-25214 │ MEDIUM │ │ 32:9.11.4-26.P2.amzn2.5.2 │ bind: Broken inbound incremental zone update (IXFR) can │
|
||||
│ │ │ │ │ │ cause named to terminate... │
|
||||
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2021-25214 │
|
||||
├────────────────────────────┼────────────────┼──────────┤ ├───────────────────────────────┼──────────────────────────────────────────────────────────────┤
|
||||
│ bind-libs │ CVE-2021-25215 │ HIGH │ │ 32:9.11.4-26.P2.amzn2.5 │ bind: An assertion check can fail while answering queries │
|
||||
│ │ │ │ │ │ for DNAME records... │
|
||||
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2021-25215 │
|
||||
│ ├────────────────┼──────────┤ ├───────────────────────────────┼──────────────────────────────────────────────────────────────┤
|
||||
│ │ CVE-2021-25214 │ MEDIUM │ │ 32:9.11.4-26.P2.amzn2.5.2 │ bind: Broken inbound incremental zone update (IXFR) can │
|
||||
│ │ │ │ │ │ cause named to terminate... │
|
||||
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2021-25214 │
|
||||
├────────────────────────────┼────────────────┼──────────┤ ├───────────────────────────────┼──────────────────────────────────────────────────────────────┤
|
||||
│ bind-libs-lite │ CVE-2021-25215 │ HIGH │ │ 32:9.11.4-26.P2.amzn2.5 │ bind: An assertion check can fail while answering queries │
|
||||
│ │ │ │ │ │ for DNAME records... │
|
||||
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2021-25215 │
|
||||
│ ├────────────────┼──────────┤ ├───────────────────────────────┼──────────────────────────────────────────────────────────────┤
|
||||
│ │ CVE-2021-25214 │ MEDIUM │ │ 32:9.11.4-26.P2.amzn2.5.2 │ bind: Broken inbound incremental zone update (IXFR) can │
|
||||
│ │ │ │ │ │ cause named to terminate... │
|
||||
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2021-25214 │
|
||||
├────────────────────────────┼────────────────┼──────────┤ ├───────────────────────────────┼──────────────────────────────────────────────────────────────┤
|
||||
...
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### AWS EC2
|
||||
|
||||
See [here][aws] for the detail.
|
||||
|
||||
## Supported architectures
|
||||
|
||||
### Virtual machine images
|
||||
|
||||
| Image format | Support |
|
||||
|--------------|:-------:|
|
||||
| VMDK | ✔ |
|
||||
| OVA | |
|
||||
| VHD | |
|
||||
| VHDX | |
|
||||
| QCOW2 | |
|
||||
|
||||
|
||||
#### VMDK disk types
|
||||
|
||||
| VMDK disk type | Support |
|
||||
|-----------------------------|:-------:|
|
||||
| streamOptimized | ✔ |
|
||||
| monolithicSparse | |
|
||||
| vmfs | |
|
||||
| vmfsSparse | |
|
||||
| twoGbMaxExtentSparse | |
|
||||
| monolithicFlat | |
|
||||
| twoGbMaxExtentFlat | |
|
||||
| vmfsRaw | |
|
||||
| fullDevice | |
|
||||
| partitionedDevice | |
|
||||
| vmfsRawDeviceMap | |
|
||||
| vmfsPassthroughRawDeviceMap | |
|
||||
|
||||
Reference: [VMware Virtual Disk Format 1.1.pdf][vmdk]
|
||||
|
||||
|
||||
### Disk partitions
|
||||
|
||||
| Disk format | Support |
|
||||
|------------------------------|:-------:|
|
||||
| Master boot record (MBR) | ✔ |
|
||||
| Extended master boot record | |
|
||||
| GUID partition table (GPT) | ✔ |
|
||||
| Logical volume manager (LVM) | |
|
||||
|
||||
### Filesystems
|
||||
|
||||
| Filesystem format | Support |
|
||||
|-------------------|:-------:|
|
||||
| XFS | ✔ |
|
||||
| EXT4 | ✔ |
|
||||
| EXT2/3 | |
|
||||
| ZFS | |
|
||||
|
||||
[aws]: ./aws.md
|
||||
[vmdk]: https://www.vmware.com/app/vmdk/?src=vmdk
|
||||
@@ -1,11 +1,9 @@
|
||||
# Vulnerability Scanning
|
||||
|
||||
Trivy scans [Container Images][image], [Rootfs][rootfs], [Filesystem][fs], and [Git Repositories][repo] to detect vulnerabilities.
|
||||
|
||||
![vulnerability][vuln]
|
||||
Trivy scans [Container Images][image], [Rootfs][rootfs], [Filesystem][fs], [Virtual Machine Image][vm] and [Git Repositories][repo] to detect vulnerabilities.
|
||||
|
||||
[image]: image.md
|
||||
[rootfs]: rootfs.md
|
||||
[fs]: filesystem.md
|
||||
[repo]: git-repository.md
|
||||
[vuln]: ../../../imgs/vulnerability.png
|
||||
[vm]: ../../vm/index.md
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 846 KiB |
@@ -22,7 +22,8 @@ Targets (what Trivy can scan):
|
||||
|
||||
- Container Image
|
||||
- Filesystem
|
||||
- Git repository (remote)
|
||||
- Git Repository (remote)
|
||||
- Virtual Machine Image
|
||||
- Kubernetes
|
||||
- AWS
|
||||
|
||||
@@ -150,8 +151,8 @@ Trivy is an [Aqua Security][aquasec] open source project.
|
||||
Learn about our open source work and portfolio [here][oss].
|
||||
Contact us about any matter by opening a GitHub Discussion [here][discussions]
|
||||
|
||||
[Ecosystem]: ./ecosystem/overview
|
||||
[Installation]: getting-started/installation/
|
||||
[Ecosystem]: ./ecosystem/index.md
|
||||
[Installation]: getting-started/installation.md
|
||||
[pronunciation]: #how-to-pronounce-the-name-trivy
|
||||
|
||||
[aquasec]: https://aquasec.com
|
||||
@@ -160,4 +161,4 @@ Contact us about any matter by opening a GitHub Discussion [here][discussions]
|
||||
|
||||
[Tutorials]: ./tutorials/overview
|
||||
[CLI]: ./docs
|
||||
[Contributing]: ./contributing/issue
|
||||
[Contributing]: ./community/contribute/issue
|
||||
|
||||
18
go.mod
18
go.mod
@@ -23,8 +23,9 @@ require (
|
||||
github.com/aquasecurity/trivy-kubernetes v0.3.1-0.20221021174315-8d74450b4506
|
||||
github.com/aws/aws-sdk-go v1.44.136
|
||||
github.com/aws/aws-sdk-go-v2 v1.17.1
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.0
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.17.2
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.3
|
||||
github.com/aws/aws-sdk-go-v2/service/ec2 v1.63.1
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.17.5
|
||||
github.com/caarlos0/env/v6 v6.10.1
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible
|
||||
github.com/cheggaaa/pb/v3 v3.1.0
|
||||
@@ -42,13 +43,19 @@ require (
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/google/wire v0.5.0
|
||||
github.com/hashicorp/go-getter v1.6.2
|
||||
github.com/hashicorp/golang-lru v0.5.4
|
||||
github.com/in-toto/in-toto-golang v0.5.0
|
||||
github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f
|
||||
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d
|
||||
github.com/knqyf263/go-rpm-version v0.0.0-20220614171824-631e686d1075
|
||||
github.com/kylelemons/godebug v1.1.0
|
||||
github.com/mailru/easyjson v0.7.7
|
||||
github.com/masahiro331/go-disk v0.0.0-20220919035250-c8da316f91ac
|
||||
github.com/masahiro331/go-ebs-file v0.0.0-20221125181850-09c63351e38c
|
||||
github.com/masahiro331/go-ext4-filesystem v0.0.0-20221016160854-4b40d7ee6193
|
||||
github.com/masahiro331/go-mvn-version v0.0.0-20210429150710-d3157d602a08
|
||||
github.com/masahiro331/go-vmdk-parser v0.0.0-20221124162251-5eeffd974e5a
|
||||
github.com/masahiro331/go-xfs-filesystem v0.0.0-20221123035428-5c173df8b3f6
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2
|
||||
github.com/open-policy-agent/opa v0.44.1-0.20220927105354-00e835a7cc15
|
||||
github.com/owenrumney/go-sarif/v2 v2.1.2
|
||||
@@ -68,7 +75,7 @@ require (
|
||||
go.etcd.io/bbolt v1.3.6
|
||||
go.uber.org/zap v1.23.0
|
||||
golang.org/x/exp v0.0.0-20220823124025-807a23277127
|
||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2
|
||||
google.golang.org/protobuf v1.28.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed
|
||||
@@ -77,7 +84,7 @@ require (
|
||||
require (
|
||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.8 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19 // indirect
|
||||
@@ -94,7 +101,7 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/service/codebuild v1.19.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/docdb v1.19.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.17.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ec2 v1.63.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ebs v1.15.19 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.17.18 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ecs v1.18.23 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/efs v1.17.15 // indirect
|
||||
@@ -138,6 +145,7 @@ require (
|
||||
github.com/liamg/iamgo v0.0.9 // indirect
|
||||
github.com/liamg/jfather v0.0.7 // indirect
|
||||
github.com/liamg/memoryfs v1.4.3 // indirect
|
||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // indirect
|
||||
github.com/microsoft/go-rustaudit v0.0.0-20220808201409-204dfee52032 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
|
||||
31
go.sum
31
go.sum
@@ -239,10 +239,10 @@ github.com/aws/aws-sdk-go-v2 v1.17.1 h1:02c72fDJr87N8RAC2s3Qu0YuvMRZKNZJ9F+lAehC
|
||||
github.com/aws/aws-sdk-go-v2 v1.17.1/go.mod h1:JLnGeGONAyi2lWXI1p0PCIOIy333JMVK1U7Hf0aRFLw=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.8 h1:tcFliCWne+zOuUfKNRn8JdFBuWPDuISDH08wD2ULkhk=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.8/go.mod h1:JTnlBSot91steJeti4ryyu/tLd4Sk84O5W22L7O2EQU=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.0 h1:ULASZmfhKR/QE9UeZ7mzYjUzsnIydy/K1YMT6uH1KC0=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.0/go.mod h1:H13DRX9Nv5tAcQvPABrE3dm5XnLp1RC7fVSM3OWiLvA=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.0 h1:W5f73j1qurASap+jdScUo4aGzSXxaC7wq1i7CiwhvU8=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.0/go.mod h1:prZpUfBu1KZLBLVX482Sq4DpDXGugAre08TPEc21GUg=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.3 h1:3kfBKcX3votFX84dm00U8RGA1sCCh3eRMOGzg5dCWfU=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.3/go.mod h1:BYdrbeCse3ZnOD5+2/VE/nATOK8fEUpBtmPMdKSyhMU=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.3 h1:ur+FHdp4NbVIv/49bUjBW+FE7e57HOo03ELodttmagk=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.3/go.mod h1:/rOMmqYBcFfNbRPU0iN9IgGqD5+V2yp3iWNmIlz0wI4=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19 h1:E3PXZSI3F2bzyj6XxUXdTIfvp425HHhwKsFvmzBwHgs=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19/go.mod h1:VihW95zQpeKQWVPGkwT+2+WJNQV8UXFfMTWdU6VErL8=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23/go.mod h1:2DFxAQ9pfIRy0imBCJv+vZ2X6RKxves6fbnEuSry6b4=
|
||||
@@ -277,6 +277,8 @@ github.com/aws/aws-sdk-go-v2/service/docdb v1.19.11 h1:+jNOF3BdrSwCHWHU+lXYR78DC
|
||||
github.com/aws/aws-sdk-go-v2/service/docdb v1.19.11/go.mod h1:p2/C5LVvGstUjTb0z0qQNDf356iVEDrAMOvFJAkJQbA=
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.17.1 h1:1QpTkQIAaZpR387it1L+erjB5bStGFCJRvmXsodpPEU=
|
||||
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.17.1/go.mod h1:BZhn/C3z13ULTSstVi2Kymc62bgjFh/JwLO9Tm2OFYI=
|
||||
github.com/aws/aws-sdk-go-v2/service/ebs v1.15.19 h1:6S06aB1xyXs3C9RE5RyJROw1v1ByXGHo/cxTZ13VRp0=
|
||||
github.com/aws/aws-sdk-go-v2/service/ebs v1.15.19/go.mod h1:pJhytP5qZaPIqCF2BewXttD4bc29KIPm6LMSIBhMCFI=
|
||||
github.com/aws/aws-sdk-go-v2/service/ec2 v1.63.1 h1:jSS5gynKz4XaGcs6m25idCTN+tvPkRJ2WedSWCcZEjI=
|
||||
github.com/aws/aws-sdk-go-v2/service/ec2 v1.63.1/go.mod h1:0+6fPoY0SglgzQUs2yml7X/fup12cMlVumJufh5npRQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.17.18 h1:uiF/RI+Up8H2xdgT2GWa20YzxiKEalHieqNjm6HC3Xk=
|
||||
@@ -336,8 +338,8 @@ github.com/aws/aws-sdk-go-v2/service/sso v1.11.25 h1:GFZitO48N/7EsFDt8fMa5iYdmWq
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.25/go.mod h1:IARHuzTXmj1C0KS35vboR0FeJ89OkEy1M9mWbK2ifCI=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8 h1:jcw6kKZrtNfBPJkaHrscDOZoe5gvi9wjudnxvozYFJo=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8/go.mod h1:er2JHN+kBY6FcMfcBBKNGCT3CarImmdFzishsqBmSRI=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.17.2 h1:tpwEMRdMf2UsplengAOnmSIRdvAxf75oUFR+blBr92I=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.17.2/go.mod h1:bXcN3koeVYiJcdDU89n3kCYILob7Y34AeLopUbZgLT4=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.17.5 h1:60SJ4lhvn///8ygCzYy2l53bFW/Q15bVfyjyAWo6zuw=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.17.5/go.mod h1:bXcN3koeVYiJcdDU89n3kCYILob7Y34AeLopUbZgLT4=
|
||||
github.com/aws/aws-sdk-go-v2/service/workspaces v1.23.0 h1:lrgZ9pZm9utPOPAXmQhqtf8oWRRksoSFxOE8RoD+pHc=
|
||||
github.com/aws/aws-sdk-go-v2/service/workspaces v1.23.0/go.mod h1:vPam8+zGthTXeaFWgl3Uqbzo/0QEoXF22jpuMZ97hSk=
|
||||
github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
|
||||
@@ -972,6 +974,8 @@ github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/hcl/v2 v2.14.1 h1:x0BpjfZ+CYdbiz+8yZTQ+gdLO7IXvOut7Da+XJayx34=
|
||||
@@ -1094,6 +1098,8 @@ github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
|
||||
github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo=
|
||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc=
|
||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||
@@ -1113,8 +1119,18 @@ github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2
|
||||
github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI=
|
||||
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
|
||||
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
|
||||
github.com/masahiro331/go-disk v0.0.0-20220919035250-c8da316f91ac h1:QyRucnGOLHJag1eB9CtuZwZk+/LpvTSYr5mnFLLFlgA=
|
||||
github.com/masahiro331/go-disk v0.0.0-20220919035250-c8da316f91ac/go.mod h1:J7Vb0sf0JzOhT0uHTeCqO6dqP/ELVcQvQ6yQ/56ZRGw=
|
||||
github.com/masahiro331/go-ebs-file v0.0.0-20221125181850-09c63351e38c h1:sBVxQbdRxqMoczqQYPxUwe3V3msmAUj9KPuPZRpD13k=
|
||||
github.com/masahiro331/go-ebs-file v0.0.0-20221125181850-09c63351e38c/go.mod h1:5NOkqebMwu8UiOTSjwqam1Ykdr7fci52TVE2xDQnIiM=
|
||||
github.com/masahiro331/go-ext4-filesystem v0.0.0-20221016160854-4b40d7ee6193 h1:1005OfmUUdBL4540DpkovaDrV+lkiEda7Nb/t792LEg=
|
||||
github.com/masahiro331/go-ext4-filesystem v0.0.0-20221016160854-4b40d7ee6193/go.mod h1:X08d9nmB+eg7Gj2XWAOkiG8lbMFbgGXPsDKEvkFwyF8=
|
||||
github.com/masahiro331/go-mvn-version v0.0.0-20210429150710-d3157d602a08 h1:AevUBW4cc99rAF8q8vmddIP8qd/0J5s/UyltGbp66dg=
|
||||
github.com/masahiro331/go-mvn-version v0.0.0-20210429150710-d3157d602a08/go.mod h1:JOkBRrE1HvgTyjk6diFtNGgr8XJMtIfiBzkL5krqzVk=
|
||||
github.com/masahiro331/go-vmdk-parser v0.0.0-20221124162251-5eeffd974e5a h1:R2wjAgJt2IwTqKfSDc4mJ0SIz66lIslqmAjW/Dmi5fE=
|
||||
github.com/masahiro331/go-vmdk-parser v0.0.0-20221124162251-5eeffd974e5a/go.mod h1:5f7mCJGW9cJb8SDn3z8qodGxpMCOo8d/2nls/tiwRrw=
|
||||
github.com/masahiro331/go-xfs-filesystem v0.0.0-20221123035428-5c173df8b3f6 h1:UHo9uZWmmUVmYUJqTXPSHNUnPaO6ofKKdTWpEQtpxho=
|
||||
github.com/masahiro331/go-xfs-filesystem v0.0.0-20221123035428-5c173df8b3f6/go.mod h1:QKBZqdn6teT0LK3QhAf3K6xakItd1LonOShOEC44idQ=
|
||||
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
|
||||
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
@@ -2016,8 +2032,9 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0=
|
||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build integration || module_integration
|
||||
//go:build integration || vm_integration || module_integration
|
||||
|
||||
package integration
|
||||
|
||||
|
||||
24
integration/scripts/download-vm-images.sh
Executable file
24
integration/scripts/download-vm-images.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
TEST_VM=ghcr.io/aquasecurity/trivy-test-vm-images
|
||||
|
||||
CRANE_IMG=gcr.io/go-containerregistry/crane:v0.12.1
|
||||
ORAS_IMG=ghcr.io/oras-project/oras:v0.16.0
|
||||
|
||||
CURRENT=$(cd $(dirname $0);pwd)
|
||||
|
||||
mkdir -p ${CURRENT}/../testdata/fixtures/vm-images/
|
||||
|
||||
# List the tags
|
||||
TAGS=$(docker run --rm ${CRANE_IMG} ls ${TEST_VM})
|
||||
|
||||
# Download missing images
|
||||
for tag in $TAGS
|
||||
do
|
||||
dir=${CURRENT}/../testdata/fixtures/vm-images/
|
||||
if [ ! -e "${dir}/${tag}.img.gz" ] || [ ! -e "${dir}/${tag}.vmdk.gz" ]; then
|
||||
echo "Downloading $tag..."
|
||||
echo "oras pull ${TEST_VM}:${tag}"
|
||||
docker run --rm -v ${dir}:/workspace ${ORAS_IMG} pull "${TEST_VM}:${tag}"
|
||||
fi
|
||||
done
|
||||
66
integration/testdata/amazonlinux2-gp2-x86-vm.json.golden
vendored
Normal file
66
integration/testdata/amazonlinux2-gp2-x86-vm.json.golden
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"SchemaVersion": 2,
|
||||
"ArtifactName": "disk.img",
|
||||
"ArtifactType": "vm",
|
||||
"Metadata": {
|
||||
"OS": {
|
||||
"Family": "amazon",
|
||||
"Name": "2 (Karoo)"
|
||||
},
|
||||
"ImageConfig": {
|
||||
"architecture": "",
|
||||
"created": "0001-01-01T00:00:00Z",
|
||||
"os": "",
|
||||
"rootfs": {
|
||||
"type": "",
|
||||
"diff_ids": null
|
||||
},
|
||||
"config": {}
|
||||
}
|
||||
},
|
||||
"Results": [
|
||||
{
|
||||
"Target": "disk.img (amazon 2 (Karoo))",
|
||||
"Class": "os-pkgs",
|
||||
"Type": "amazon",
|
||||
"Vulnerabilities": [
|
||||
{
|
||||
"VulnerabilityID": "CVE-2022-21233",
|
||||
"PkgID": "microcode_ctl@2.1-47.amzn2.0.12.x86_64",
|
||||
"PkgName": "microcode_ctl",
|
||||
"InstalledVersion": "2:2.1-47.amzn2.0.12",
|
||||
"FixedVersion": "2:2.1-47.amzn2.0.13",
|
||||
"Layer": {},
|
||||
"SeveritySource": "nvd",
|
||||
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2022-21233",
|
||||
"DataSource": {
|
||||
"ID": "amazon",
|
||||
"Name": "Amazon Linux Security Center",
|
||||
"URL": "https://alas.aws.amazon.com/"
|
||||
},
|
||||
"Title": "hw: cpu: Intel: Stale Data Read from legacy xAPIC vulnerability",
|
||||
"Description": "Improper isolation of shared resources in some Intel(R) Processors may allow",
|
||||
"Severity": "MEDIUM",
|
||||
"CVSS": {
|
||||
"nvd": {
|
||||
"V3Vector": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
|
||||
"V3Score": 5.5
|
||||
},
|
||||
"redhat": {
|
||||
"V3Vector": "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:H/I:N/A:N",
|
||||
"V3Score": 6
|
||||
}
|
||||
},
|
||||
"References": [
|
||||
"https://access.redhat.com/security/cve/CVE-2022-21233",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-21233",
|
||||
"https://security.netapp.com/advisory/ntap-20220923-0002/",
|
||||
"https://ubuntu.com/security/notices/USN-5612-1"
|
||||
],
|
||||
"PublishedDate": "2022-08-18T20:15:00Z",
|
||||
"LastModifiedDate": "2022-09-23T15:15:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
7
integration/testdata/fixtures/db/amazon.yaml
vendored
7
integration/testdata/fixtures/db/amazon.yaml
vendored
@@ -17,4 +17,9 @@
|
||||
FixedVersion: 7.61.1-11.amzn2.0.2
|
||||
- key: CVE-2019-5481
|
||||
value:
|
||||
FixedVersion: 7.61.1-12.amzn2.0.1
|
||||
FixedVersion: 7.61.1-12.amzn2.0.1
|
||||
- bucket: microcode_ctl
|
||||
pairs:
|
||||
- key: CVE-2022-21233
|
||||
value:
|
||||
FixedVersion: 2:2.1-47.amzn2.0.13
|
||||
|
||||
2
integration/testdata/fixtures/db/redhat.yaml
vendored
2
integration/testdata/fixtures/db/redhat.yaml
vendored
@@ -72,4 +72,4 @@
|
||||
- 857
|
||||
- 858
|
||||
Cves:
|
||||
- Severity: 2.0
|
||||
- Severity: 2.0
|
||||
7
integration/testdata/fixtures/db/ubuntu.yaml
vendored
7
integration/testdata/fixtures/db/ubuntu.yaml
vendored
@@ -12,3 +12,10 @@
|
||||
- key: CVE-2019-5094
|
||||
value:
|
||||
FixedVersion: 1.44.1-1ubuntu1.2
|
||||
- bucket: ubuntu 22.04
|
||||
pairs:
|
||||
- bucket: bind9
|
||||
pairs:
|
||||
- key: CVE-2022-2795
|
||||
value:
|
||||
FixedVersion: 1:9.18.1-1ubuntu1.2
|
||||
@@ -1,5 +1,61 @@
|
||||
- bucket: vulnerability
|
||||
pairs:
|
||||
- key: CVE-2022-21233
|
||||
value:
|
||||
Title: "hw: cpu: Intel: Stale Data Read from legacy xAPIC vulnerability"
|
||||
Description: "Improper isolation of shared resources in some Intel(R) Processors may allow"
|
||||
Severity: MEDIUM
|
||||
CVSS:
|
||||
nvd:
|
||||
V3Score: 5.5
|
||||
V3Vector: "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N"
|
||||
redhat:
|
||||
V3Score: 6.0
|
||||
V3Vector: "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:H/I:N/A:N"
|
||||
LastModifiedDate: "2022-09-23T15:15:00Z"
|
||||
PublishedDate: "2022-08-18T20:15:00Z"
|
||||
References:
|
||||
- "https://access.redhat.com/security/cve/CVE-2022-21233"
|
||||
- "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-21233"
|
||||
- "https://security.netapp.com/advisory/ntap-20220923-0002/"
|
||||
- "https://ubuntu.com/security/notices/USN-5612-1"
|
||||
VendorSeverity:
|
||||
arch-linux: 2
|
||||
nvd: 2
|
||||
redhat: 2
|
||||
ubuntu: 2
|
||||
- key: CVE-2022-2795
|
||||
value:
|
||||
Title: "bind: processing large delegations may severely degrade resolver performance"
|
||||
Severity: HIGH
|
||||
Description: By flooding the target resolver with queries exploiting this flaw an attacker
|
||||
CVSS:
|
||||
nvd:
|
||||
V3Score: 7.5
|
||||
V3Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
|
||||
redhat:
|
||||
V3Score: 5.3
|
||||
V3Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
|
||||
CweIDs:
|
||||
- CWE-400
|
||||
LastModifiedDate: 2022-10-06T20:15:00Z
|
||||
PublishedDate: 2022-09-21T11:15:00Z
|
||||
References:
|
||||
- http://www.openwall.com/lists/oss-security/2022/09/21/3
|
||||
- https://access.redhat.com/security/cve/CVE-2022-2795
|
||||
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-2795
|
||||
- https://kb.isc.org/docs/cve-2022-2795
|
||||
- https://lists.debian.org/debian-lts-announce/2022/10/msg00007.html
|
||||
- https://nvd.nist.gov/vuln/detail/CVE-2022-2795
|
||||
- https://ubuntu.com/security/notices/USN-5626-1
|
||||
- https://ubuntu.com/security/notices/USN-5626-2
|
||||
- https://www.debian.org/security/2022/dsa-5235
|
||||
VendorSeverity:
|
||||
cbl-mariner: 3.0
|
||||
nvd: 3.0
|
||||
photon: 3.0
|
||||
redhat: 1.0
|
||||
ubuntu: 2.0
|
||||
- key: CVE-2016-9401
|
||||
value:
|
||||
CVSS:
|
||||
@@ -1247,4 +1303,4 @@
|
||||
- "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-14155",
|
||||
- "https://nvd.nist.gov/vuln/detail/CVE-2020-14155"
|
||||
PublishedDate: "2020-06-15T17:15:00Z"
|
||||
LastModifiedDate: "2022-04-28T15:06:00Z"
|
||||
LastModifiedDate: "2022-04-28T15:06:00Z"
|
||||
|
||||
147
integration/testdata/ubuntu-gp2-x86-vm.json.golden
vendored
Normal file
147
integration/testdata/ubuntu-gp2-x86-vm.json.golden
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
{
|
||||
"SchemaVersion": 2,
|
||||
"ArtifactName": "disk.img",
|
||||
"ArtifactType": "vm",
|
||||
"Metadata": {
|
||||
"OS": {
|
||||
"Family": "ubuntu",
|
||||
"Name": "22.04"
|
||||
},
|
||||
"ImageConfig": {
|
||||
"architecture": "",
|
||||
"created": "0001-01-01T00:00:00Z",
|
||||
"os": "",
|
||||
"rootfs": {
|
||||
"type": "",
|
||||
"diff_ids": null
|
||||
},
|
||||
"config": {}
|
||||
}
|
||||
},
|
||||
"Results": [
|
||||
{
|
||||
"Target": "disk.img (ubuntu 22.04)",
|
||||
"Class": "os-pkgs",
|
||||
"Type": "ubuntu",
|
||||
"Vulnerabilities": [
|
||||
{
|
||||
"VulnerabilityID": "CVE-2022-2795",
|
||||
"PkgID": "bind9-dnsutils@1:9.18.1-1ubuntu1.1",
|
||||
"PkgName": "bind9-dnsutils",
|
||||
"InstalledVersion": "1:9.18.1-1ubuntu1.1",
|
||||
"FixedVersion": "1:9.18.1-1ubuntu1.2",
|
||||
"Layer": {},
|
||||
"SeveritySource": "nvd",
|
||||
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2022-2795",
|
||||
"Title": "bind: processing large delegations may severely degrade resolver performance",
|
||||
"Description": "By flooding the target resolver with queries exploiting this flaw an attacker",
|
||||
"Severity": "HIGH",
|
||||
"CweIDs": [
|
||||
"CWE-400"
|
||||
],
|
||||
"CVSS": {
|
||||
"nvd": {
|
||||
"V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
|
||||
"V3Score": 7.5
|
||||
},
|
||||
"redhat": {
|
||||
"V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
|
||||
"V3Score": 5.3
|
||||
}
|
||||
},
|
||||
"References": [
|
||||
"http://www.openwall.com/lists/oss-security/2022/09/21/3",
|
||||
"https://access.redhat.com/security/cve/CVE-2022-2795",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-2795",
|
||||
"https://kb.isc.org/docs/cve-2022-2795",
|
||||
"https://lists.debian.org/debian-lts-announce/2022/10/msg00007.html",
|
||||
"https://nvd.nist.gov/vuln/detail/CVE-2022-2795",
|
||||
"https://ubuntu.com/security/notices/USN-5626-1",
|
||||
"https://ubuntu.com/security/notices/USN-5626-2",
|
||||
"https://www.debian.org/security/2022/dsa-5235"
|
||||
],
|
||||
"PublishedDate": "2022-09-21T11:15:00Z",
|
||||
"LastModifiedDate": "2022-10-06T20:15:00Z"
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2022-2795",
|
||||
"PkgID": "bind9-host@1:9.18.1-1ubuntu1.1",
|
||||
"PkgName": "bind9-host",
|
||||
"InstalledVersion": "1:9.18.1-1ubuntu1.1",
|
||||
"FixedVersion": "1:9.18.1-1ubuntu1.2",
|
||||
"Layer": {},
|
||||
"SeveritySource": "nvd",
|
||||
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2022-2795",
|
||||
"Title": "bind: processing large delegations may severely degrade resolver performance",
|
||||
"Description": "By flooding the target resolver with queries exploiting this flaw an attacker",
|
||||
"Severity": "HIGH",
|
||||
"CweIDs": [
|
||||
"CWE-400"
|
||||
],
|
||||
"CVSS": {
|
||||
"nvd": {
|
||||
"V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
|
||||
"V3Score": 7.5
|
||||
},
|
||||
"redhat": {
|
||||
"V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
|
||||
"V3Score": 5.3
|
||||
}
|
||||
},
|
||||
"References": [
|
||||
"http://www.openwall.com/lists/oss-security/2022/09/21/3",
|
||||
"https://access.redhat.com/security/cve/CVE-2022-2795",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-2795",
|
||||
"https://kb.isc.org/docs/cve-2022-2795",
|
||||
"https://lists.debian.org/debian-lts-announce/2022/10/msg00007.html",
|
||||
"https://nvd.nist.gov/vuln/detail/CVE-2022-2795",
|
||||
"https://ubuntu.com/security/notices/USN-5626-1",
|
||||
"https://ubuntu.com/security/notices/USN-5626-2",
|
||||
"https://www.debian.org/security/2022/dsa-5235"
|
||||
],
|
||||
"PublishedDate": "2022-09-21T11:15:00Z",
|
||||
"LastModifiedDate": "2022-10-06T20:15:00Z"
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2022-2795",
|
||||
"PkgID": "bind9-libs@1:9.18.1-1ubuntu1.1",
|
||||
"PkgName": "bind9-libs",
|
||||
"InstalledVersion": "1:9.18.1-1ubuntu1.1",
|
||||
"FixedVersion": "1:9.18.1-1ubuntu1.2",
|
||||
"Layer": {},
|
||||
"SeveritySource": "nvd",
|
||||
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2022-2795",
|
||||
"Title": "bind: processing large delegations may severely degrade resolver performance",
|
||||
"Description": "By flooding the target resolver with queries exploiting this flaw an attacker",
|
||||
"Severity": "HIGH",
|
||||
"CweIDs": [
|
||||
"CWE-400"
|
||||
],
|
||||
"CVSS": {
|
||||
"nvd": {
|
||||
"V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
|
||||
"V3Score": 7.5
|
||||
},
|
||||
"redhat": {
|
||||
"V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
|
||||
"V3Score": 5.3
|
||||
}
|
||||
},
|
||||
"References": [
|
||||
"http://www.openwall.com/lists/oss-security/2022/09/21/3",
|
||||
"https://access.redhat.com/security/cve/CVE-2022-2795",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-2795",
|
||||
"https://kb.isc.org/docs/cve-2022-2795",
|
||||
"https://lists.debian.org/debian-lts-announce/2022/10/msg00007.html",
|
||||
"https://nvd.nist.gov/vuln/detail/CVE-2022-2795",
|
||||
"https://ubuntu.com/security/notices/USN-5626-1",
|
||||
"https://ubuntu.com/security/notices/USN-5626-2",
|
||||
"https://www.debian.org/security/2022/dsa-5235"
|
||||
],
|
||||
"PublishedDate": "2022-09-21T11:15:00Z",
|
||||
"LastModifiedDate": "2022-10-06T20:15:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
112
integration/vm_test.go
Normal file
112
integration/vm_test.go
Normal file
@@ -0,0 +1,112 @@
|
||||
//go:build vm_integration
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/aquasecurity/trivy/internal/testutil"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
func TestVM(t *testing.T) {
|
||||
type args struct {
|
||||
input string
|
||||
format string
|
||||
artifactType string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
golden string
|
||||
override types.Report
|
||||
}{
|
||||
{
|
||||
name: "amazon linux 2 in VMDK, filesystem XFS",
|
||||
args: args{
|
||||
input: "testdata/fixtures/vm-images/amazon-2.vmdk.gz",
|
||||
format: "json",
|
||||
artifactType: "vm",
|
||||
},
|
||||
golden: "testdata/amazonlinux2-gp2-x86-vm.json.golden",
|
||||
},
|
||||
{
|
||||
name: "amazon linux 2 in Snapshot, filesystem XFS",
|
||||
args: args{
|
||||
input: "testdata/fixtures/vm-images/amazon-2.img.gz",
|
||||
format: "json",
|
||||
artifactType: "vm",
|
||||
},
|
||||
golden: "testdata/amazonlinux2-gp2-x86-vm.json.golden",
|
||||
},
|
||||
{
|
||||
name: "Ubuntu in Snapshot, filesystem EXT4",
|
||||
args: args{
|
||||
input: "testdata/fixtures/vm-images/ubuntu-2204.img.gz",
|
||||
format: "json",
|
||||
artifactType: "vm",
|
||||
},
|
||||
golden: "testdata/ubuntu-gp2-x86-vm.json.golden",
|
||||
},
|
||||
{
|
||||
name: "Ubuntu in VMDK, filesystem EXT4",
|
||||
args: args{
|
||||
input: "testdata/fixtures/vm-images/ubuntu-2204.vmdk.gz",
|
||||
format: "json",
|
||||
artifactType: "vm",
|
||||
},
|
||||
golden: "testdata/ubuntu-gp2-x86-vm.json.golden",
|
||||
},
|
||||
}
|
||||
|
||||
// Set up testing DB
|
||||
cacheDir := initDB(t)
|
||||
|
||||
// Keep the current working directory
|
||||
currentDir, err := os.Getwd()
|
||||
require.NoError(t, err)
|
||||
|
||||
const imageFile = "disk.img"
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
osArgs := []string{
|
||||
"--cache-dir", cacheDir, "vm", "--security-checks", "vuln", "-q", "--skip-db-update",
|
||||
"--format", tt.args.format,
|
||||
}
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
// Set up the output file
|
||||
outputFile := filepath.Join(tmpDir, "output.json")
|
||||
if *update {
|
||||
outputFile = tt.golden
|
||||
}
|
||||
|
||||
// Get the absolute path of the golden file
|
||||
goldenFile, err := filepath.Abs(tt.golden)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Decompress the gzipped image file
|
||||
imagePath := filepath.Join(tmpDir, imageFile)
|
||||
testutil.DecompressGzip(t, tt.args.input, imagePath)
|
||||
|
||||
// Change the current working directory so that targets in the result could be the same as golden files.
|
||||
err = os.Chdir(tmpDir)
|
||||
require.NoError(t, err)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
osArgs = append(osArgs, "--output", outputFile)
|
||||
osArgs = append(osArgs, imageFile)
|
||||
|
||||
// Run "trivy vm"
|
||||
err = execute(osArgs)
|
||||
require.NoError(t, err)
|
||||
compareReports(t, goldenFile, outputFile)
|
||||
})
|
||||
}
|
||||
}
|
||||
28
internal/testutil/gzip.go
Normal file
28
internal/testutil/gzip.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package testutil
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const max = int64(10) << 30 // 10GB
|
||||
|
||||
func DecompressGzip(t *testing.T, src, dst string) {
|
||||
w, err := os.Create(dst)
|
||||
require.NoError(t, err)
|
||||
defer w.Close()
|
||||
|
||||
f, err := os.Open(src)
|
||||
require.NoError(t, err)
|
||||
defer f.Close()
|
||||
|
||||
gr, err := gzip.NewReader(f)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = io.CopyN(w, gr, max)
|
||||
require.ErrorIs(t, err, io.EOF)
|
||||
}
|
||||
@@ -89,10 +89,13 @@ nav:
|
||||
- Compliance: docs/kubernetes/cli/compliance.md
|
||||
- Operator:
|
||||
- Overview: docs/kubernetes/operator/index.md
|
||||
- Compliance:
|
||||
- Reports: docs/compliance/compliance.md
|
||||
- Cloud:
|
||||
- AWS: docs/cloud/aws/scanning.md
|
||||
- Virtual Machine Image:
|
||||
- Overview: docs/vm/index.md
|
||||
- AWS EC2: docs/vm/aws.md
|
||||
- Compliance:
|
||||
- Reports: docs/compliance/compliance.md
|
||||
- SBOM:
|
||||
- Overview: docs/sbom/index.md
|
||||
- CycloneDX: docs/sbom/cyclonedx.md
|
||||
|
||||
@@ -87,6 +87,7 @@ func NewApp(version string) *cobra.Command {
|
||||
NewSBOMCommand(globalFlags),
|
||||
NewVersionCommand(globalFlags),
|
||||
NewAWSCommand(globalFlags),
|
||||
NewVMCommand(globalFlags),
|
||||
)
|
||||
rootCmd.AddCommand(loadPluginCommands()...)
|
||||
|
||||
@@ -824,7 +825,7 @@ func NewAWSCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
Use: "aws [flags]",
|
||||
Aliases: []string{},
|
||||
Args: cobra.ExactArgs(0),
|
||||
Short: "scan aws account",
|
||||
Short: "[EXPERIMENTAL] Scan AWS account",
|
||||
Long: fmt.Sprintf(`Scan an AWS account for misconfigurations. Trivy uses the same authentication methods as the AWS CLI. See https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html
|
||||
|
||||
The following services are supported:
|
||||
@@ -869,6 +870,62 @@ The following services are supported:
|
||||
return cmd
|
||||
}
|
||||
|
||||
func NewVMCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
reportFlagGroup := flag.NewReportFlagGroup()
|
||||
reportFlagGroup.ReportFormat = nil // TODO: support --report summary
|
||||
|
||||
vmFlags := &flag.Flags{
|
||||
CacheFlagGroup: flag.NewCacheFlagGroup(),
|
||||
DBFlagGroup: flag.NewDBFlagGroup(),
|
||||
LicenseFlagGroup: flag.NewLicenseFlagGroup(),
|
||||
MisconfFlagGroup: flag.NewMisconfFlagGroup(),
|
||||
RemoteFlagGroup: flag.NewClientFlags(), // for client/server mode
|
||||
ReportFlagGroup: reportFlagGroup,
|
||||
ScanFlagGroup: flag.NewScanFlagGroup(),
|
||||
SecretFlagGroup: flag.NewSecretFlagGroup(),
|
||||
VulnerabilityFlagGroup: flag.NewVulnerabilityFlagGroup(),
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "vm [flags] VM_IMAGE",
|
||||
Aliases: []string{},
|
||||
Short: "[EXPERIMENTAL] Scan a virtual machine image",
|
||||
Example: ` # Scan your AWS AMI
|
||||
$ trivy vm --security-checks vuln ami:${your_ami_id}
|
||||
|
||||
# Scan your AWS EBS snapshot
|
||||
$ trivy vm ebs:${your_ebs_snapshot_id}
|
||||
`,
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := vmFlags.Bind(cmd); err != nil {
|
||||
return xerrors.Errorf("flag bind error: %w", err)
|
||||
}
|
||||
return validateArgs(cmd, args)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := vmFlags.Bind(cmd); err != nil {
|
||||
return xerrors.Errorf("flag bind error: %w", err)
|
||||
}
|
||||
options, err := vmFlags.ToOptions(cmd.Version, args, globalFlags, outputWriter)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("flag error: %w", err)
|
||||
}
|
||||
if options.Timeout < time.Minute*30 {
|
||||
options.Timeout = time.Minute * 30
|
||||
log.Logger.Debug("Timeout is set to less than 30 min - upgrading to 30 min for this command.")
|
||||
}
|
||||
return artifact.Run(cmd.Context(), options, artifact.TargetVM)
|
||||
},
|
||||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
}
|
||||
cmd.SetFlagErrorFunc(flagErrorFunc)
|
||||
vmFlags.AddFlags(cmd)
|
||||
cmd.SetUsageTemplate(fmt.Sprintf(usageTemplate, vmFlags.Usages(cmd)))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func NewSBOMCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
reportFlagGroup := flag.NewReportFlagGroup()
|
||||
reportFlagGroup.DependencyTree = nil // disable '--dependency-tree'
|
||||
|
||||
@@ -57,6 +57,13 @@ func initializeSBOMScanner(ctx context.Context, filePath string, artifactCache c
|
||||
return scanner.Scanner{}, nil, nil
|
||||
}
|
||||
|
||||
func initializeVMScanner(ctx context.Context, filePath string, artifactCache cache.ArtifactCache,
|
||||
localArtifactCache cache.Cache, artifactOption artifact.Option) (
|
||||
scanner.Scanner, func(), error) {
|
||||
wire.Build(scanner.StandaloneVMSet)
|
||||
return scanner.Scanner{}, nil, nil
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Client/Server
|
||||
/////////////////
|
||||
@@ -91,3 +98,10 @@ func initializeRemoteSBOMScanner(ctx context.Context, path string, artifactCache
|
||||
wire.Build(scanner.RemoteSBOMSet)
|
||||
return scanner.Scanner{}, nil, nil
|
||||
}
|
||||
|
||||
// initializeRemoteVMScanner is for vm scanning in client/server mode
|
||||
func initializeRemoteVMScanner(ctx context.Context, path string, artifactCache cache.ArtifactCache,
|
||||
remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
wire.Build(scanner.RemoteVMSet)
|
||||
return scanner.Scanner{}, nil, nil
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ const (
|
||||
TargetRepository TargetKind = "repo"
|
||||
TargetImageArchive TargetKind = "archive"
|
||||
TargetSBOM TargetKind = "sbom"
|
||||
TargetVM TargetKind = "vm"
|
||||
|
||||
devVersion = "dev"
|
||||
)
|
||||
@@ -78,6 +79,8 @@ type Runner interface {
|
||||
ScanRepository(ctx context.Context, opts flag.Options) (types.Report, error)
|
||||
// ScanSBOM scans SBOM
|
||||
ScanSBOM(ctx context.Context, opts flag.Options) (types.Report, error)
|
||||
// ScanVM scans VM
|
||||
ScanVM(ctx context.Context, opts flag.Options) (types.Report, error)
|
||||
// Filter filter a report
|
||||
Filter(ctx context.Context, opts flag.Options, report types.Report) (types.Report, error)
|
||||
// Report a writes a report
|
||||
@@ -224,6 +227,22 @@ func (r *runner) ScanSBOM(ctx context.Context, opts flag.Options) (types.Report,
|
||||
return r.scanArtifact(ctx, opts, s)
|
||||
}
|
||||
|
||||
func (r *runner) ScanVM(ctx context.Context, opts flag.Options) (types.Report, error) {
|
||||
// TODO: Does VM scan disable lock file..?
|
||||
opts.DisabledAnalyzers = analyzer.TypeLockfiles
|
||||
|
||||
var s InitializeScanner
|
||||
if opts.ServerAddr == "" {
|
||||
// Scan virtual machine in standalone mode
|
||||
s = vmStandaloneScanner
|
||||
} else {
|
||||
// Scan virtual machine in client/server mode
|
||||
s = vmRemoteScanner
|
||||
}
|
||||
|
||||
return r.scanArtifact(ctx, opts, s)
|
||||
}
|
||||
|
||||
func (r *runner) scanArtifact(ctx context.Context, opts flag.Options, initializeScanner InitializeScanner) (types.Report, error) {
|
||||
report, err := scan(ctx, opts, initializeScanner, r.cache)
|
||||
if err != nil {
|
||||
@@ -385,6 +404,10 @@ func Run(ctx context.Context, opts flag.Options, targetKind TargetKind) (err err
|
||||
if report, err = r.ScanSBOM(ctx, opts); err != nil {
|
||||
return xerrors.Errorf("sbom scan error: %w", err)
|
||||
}
|
||||
case TargetVM:
|
||||
if report, err = r.ScanVM(ctx, opts); err != nil {
|
||||
return xerrors.Errorf("vm scan error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
report, err = r.Filter(ctx, opts, report)
|
||||
|
||||
@@ -111,3 +111,22 @@ func sbomRemoteScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner
|
||||
}
|
||||
return s, cleanup, nil
|
||||
}
|
||||
|
||||
// vmStandaloneScanner initializes a VM scanner in standalone mode
|
||||
func vmStandaloneScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||
s, cleanup, err := initializeVMScanner(ctx, conf.Target, conf.ArtifactCache, conf.LocalArtifactCache,
|
||||
conf.ArtifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a vm scanner: %w", err)
|
||||
}
|
||||
return s, cleanup, nil
|
||||
}
|
||||
|
||||
// vmRemoteScanner initializes a VM scanner in client/server mode
|
||||
func vmRemoteScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||
s, cleanup, err := initializeRemoteVMScanner(ctx, conf.Target, conf.ArtifactCache, conf.RemoteOption, conf.ArtifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a vm scanner: %w", err)
|
||||
}
|
||||
return s, cleanup, nil
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
local2 "github.com/aquasecurity/trivy/pkg/fanal/artifact/local"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact/remote"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact/sbom"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact/vm"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/image"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
@@ -129,6 +130,22 @@ func initializeSBOMScanner(ctx context.Context, filePath string, artifactCache c
|
||||
}, nil
|
||||
}
|
||||
|
||||
func initializeVMScanner(ctx context.Context, filePath string, artifactCache cache.ArtifactCache, localArtifactCache cache.Cache, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
v := _wireValue
|
||||
applierApplier := applier.NewApplier(localArtifactCache, v...)
|
||||
detector := ospkg.Detector{}
|
||||
config := db.Config{}
|
||||
client := vulnerability.NewClient(config)
|
||||
localScanner := local.NewScanner(applierApplier, detector, client)
|
||||
artifactArtifact, err := vm.NewArtifact(filePath, artifactCache, artifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, err
|
||||
}
|
||||
scannerScanner := scanner.NewScanner(localScanner, artifactArtifact)
|
||||
return scannerScanner, func() {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// initializeRemoteDockerScanner is for container image scanning in client/server mode
|
||||
// e.g. dockerd, container registry, podman, etc.
|
||||
func initializeRemoteDockerScanner(ctx context.Context, imageName string, artifactCache cache.ArtifactCache, remoteScanOptions client.ScannerOption, dockerOpt types.DockerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
@@ -197,3 +214,16 @@ func initializeRemoteSBOMScanner(ctx context.Context, path string, artifactCache
|
||||
return scannerScanner, func() {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// initializeRemoteVMScanner is for vm scanning in client/server mode
|
||||
func initializeRemoteVMScanner(ctx context.Context, path string, artifactCache cache.ArtifactCache, remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
v := _wireValue3
|
||||
clientScanner := client.NewScanner(remoteScanOptions, v...)
|
||||
artifactArtifact, err := vm.NewArtifact(path, artifactCache, artifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, err
|
||||
}
|
||||
scannerScanner := scanner.NewScanner(clientScanner, artifactArtifact)
|
||||
return scannerScanner, func() {
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ func (a gobinaryLibraryAnalyzer) Analyze(_ context.Context, input analyzer.Analy
|
||||
if errors.Is(err, binary.ErrUnrecognizedExe) || errors.Is(err, binary.ErrNonGoBinary) {
|
||||
return nil, nil
|
||||
} else if err != nil {
|
||||
return nil, xerrors.Errorf("go binary parse error: %w", err)
|
||||
return nil, xerrors.Errorf("go binary (filepath: %s) parse error: %w", input.FilePath, err)
|
||||
}
|
||||
|
||||
return language.ToAnalysisResult(types.GoBinary, input.FilePath, "", libs, deps), nil
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"golang.org/x/exp/slices"
|
||||
"golang.org/x/sync/semaphore"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
|
||||
@@ -22,10 +21,7 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/log"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/walker"
|
||||
)
|
||||
|
||||
const (
|
||||
parallel = 5
|
||||
"github.com/aquasecurity/trivy/pkg/semaphore"
|
||||
)
|
||||
|
||||
type Artifact struct {
|
||||
@@ -205,12 +201,7 @@ func (a Artifact) consolidateCreatedBy(diffIDs, layerKeys []string, configFile *
|
||||
func (a Artifact) inspect(ctx context.Context, missingImage string, layerKeys, baseDiffIDs []string, layerKeyMap map[string]LayerInfo) error {
|
||||
done := make(chan struct{})
|
||||
errCh := make(chan error)
|
||||
|
||||
limit := semaphore.NewWeighted(parallel)
|
||||
if a.artifactOption.Slow {
|
||||
// Inspect layers in series
|
||||
limit = semaphore.NewWeighted(1)
|
||||
}
|
||||
limit := semaphore.New(a.artifactOption.Slow)
|
||||
|
||||
var osFound types.OS
|
||||
for _, k := range layerKeys {
|
||||
@@ -279,11 +270,7 @@ func (a Artifact) inspectLayer(ctx context.Context, layerInfo LayerInfo, disable
|
||||
var wg sync.WaitGroup
|
||||
opts := analyzer.AnalysisOptions{Offline: a.artifactOption.Offline}
|
||||
result := analyzer.NewAnalysisResult()
|
||||
limit := semaphore.NewWeighted(parallel)
|
||||
if a.artifactOption.Slow {
|
||||
// Analyze files in series
|
||||
limit = semaphore.NewWeighted(1)
|
||||
}
|
||||
limit := semaphore.New(a.artifactOption.Slow)
|
||||
|
||||
// Walk a tar layer
|
||||
opqDirs, whFiles, err := a.walker.Walk(r, func(filePath string, info os.FileInfo, opener analyzer.Opener) error {
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
"golang.org/x/sync/semaphore"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
|
||||
@@ -19,10 +18,7 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/handler"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/walker"
|
||||
)
|
||||
|
||||
const (
|
||||
parallel = 10
|
||||
"github.com/aquasecurity/trivy/pkg/semaphore"
|
||||
)
|
||||
|
||||
type Artifact struct {
|
||||
@@ -78,11 +74,7 @@ func buildAbsPaths(base string, paths []string) []string {
|
||||
func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error) {
|
||||
var wg sync.WaitGroup
|
||||
result := analyzer.NewAnalysisResult()
|
||||
limit := semaphore.NewWeighted(parallel)
|
||||
if a.artifactOption.Slow {
|
||||
// Analyze files in series
|
||||
limit = semaphore.NewWeighted(1)
|
||||
}
|
||||
limit := semaphore.New(a.artifactOption.Slow)
|
||||
|
||||
err := a.walker.Walk(a.rootPath, func(filePath string, info os.FileInfo, opener analyzer.Opener) error {
|
||||
directory := a.rootPath
|
||||
|
||||
66
pkg/fanal/artifact/vm/ami.go
Normal file
66
pkg/fanal/artifact/vm/ami.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/config"
|
||||
"github.com/aws/aws-sdk-go-v2/service/ec2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
type AMI struct {
|
||||
*EBS
|
||||
|
||||
imageID string
|
||||
}
|
||||
|
||||
func newAMI(imageID string, storage Storage) (*AMI, error) {
|
||||
// TODO: propagate context
|
||||
ctx := context.TODO()
|
||||
cfg, err := config.LoadDefaultConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("aws config load error: %w", err)
|
||||
}
|
||||
client := ec2.NewFromConfig(cfg)
|
||||
output, err := client.DescribeImages(ctx, &ec2.DescribeImagesInput{
|
||||
ImageIds: []string{imageID},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("ec2.DescribeImages: %w", err)
|
||||
} else if len(output.Images) == 0 {
|
||||
return nil, xerrors.Errorf("%s not found", imageID)
|
||||
}
|
||||
|
||||
// Take the first snapshot
|
||||
for _, mapping := range output.Images[0].BlockDeviceMappings {
|
||||
snapshotID := aws.ToString(mapping.Ebs.SnapshotId)
|
||||
if snapshotID == "" {
|
||||
continue
|
||||
}
|
||||
log.Logger.Infof("Snapshot %s found", snapshotID)
|
||||
ebs, err := newEBS(snapshotID, storage)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("new EBS error: %w", err)
|
||||
}
|
||||
return &AMI{
|
||||
EBS: ebs,
|
||||
imageID: imageID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, xerrors.New("no snapshot found")
|
||||
}
|
||||
|
||||
func (a *AMI) Inspect(ctx context.Context) (types.ArtifactReference, error) {
|
||||
ref, err := a.EBS.Inspect(ctx)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, err
|
||||
}
|
||||
ref.Name = a.imageID
|
||||
return ref, nil
|
||||
}
|
||||
120
pkg/fanal/artifact/vm/ebs.go
Normal file
120
pkg/fanal/artifact/vm/ebs.go
Normal file
@@ -0,0 +1,120 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
ebsfile "github.com/masahiro331/go-ebs-file"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
// default block size 512 KB
|
||||
// Max cache memory size 64 MB
|
||||
const storageEBSCacheSize = 128
|
||||
|
||||
// EBS represents an artifact for AWS EBS snapshots
|
||||
type EBS struct {
|
||||
Storage
|
||||
snapshotID string
|
||||
ebs ebsfile.EBSAPI
|
||||
}
|
||||
|
||||
func newEBS(snapshotID string, vm Storage) (*EBS, error) {
|
||||
ebs, err := ebsfile.New(ebsfile.Option{})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("new ebsfile error: %w", err)
|
||||
}
|
||||
|
||||
return &EBS{
|
||||
Storage: vm,
|
||||
snapshotID: snapshotID,
|
||||
ebs: ebs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *EBS) Inspect(ctx context.Context) (types.ArtifactReference, error) {
|
||||
sr, err := a.openEBS(ctx)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("EBS open error: %w", err)
|
||||
}
|
||||
|
||||
cacheKey, err := a.calcCacheKey(a.snapshotID)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("cache key calculation error: %w", err)
|
||||
}
|
||||
|
||||
if a.hasCache(cacheKey) {
|
||||
return types.ArtifactReference{
|
||||
Name: a.snapshotID,
|
||||
Type: types.ArtifactVM,
|
||||
ID: cacheKey, // use a cache key as pseudo artifact ID
|
||||
BlobIDs: []string{cacheKey},
|
||||
}, nil
|
||||
}
|
||||
|
||||
blobInfo, err := a.Analyze(ctx, sr)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("inspection error: %w", err)
|
||||
}
|
||||
|
||||
if err = a.cache.PutBlob(cacheKey, blobInfo); err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("failed to store blob (%s) in cache: %w", cacheKey, err)
|
||||
}
|
||||
|
||||
return types.ArtifactReference{
|
||||
Name: a.snapshotID,
|
||||
Type: types.ArtifactVM,
|
||||
ID: cacheKey, // use a cache key as pseudo artifact ID
|
||||
BlobIDs: []string{cacheKey},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *EBS) openEBS(ctx context.Context) (*io.SectionReader, error) {
|
||||
c, err := lru.New(storageEBSCacheSize)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("lru cache error: %w", err)
|
||||
}
|
||||
|
||||
r, err := ebsfile.Open(a.snapshotID, ctx, c, a.ebs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("EBS error: %w", err)
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (a *EBS) Clean(_ types.ArtifactReference) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *EBS) SetEBS(ebs ebsfile.EBSAPI) {
|
||||
a.ebs = ebs
|
||||
}
|
||||
|
||||
func (a *EBS) calcCacheKey(key string) (string, error) {
|
||||
s, err := cache.CalcKey(key, a.analyzer.AnalyzerVersions(), a.handlerManager.Versions(), a.artifactOption)
|
||||
if err != nil {
|
||||
return "", xerrors.Errorf("failed to calculate cache key: %w", err)
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (a *EBS) hasCache(cacheKey string) bool {
|
||||
_, missingCacheKeys, err := a.cache.MissingBlobs(cacheKey, []string{cacheKey})
|
||||
if err != nil {
|
||||
log.Logger.Debugf("Unable to query missing cache: %s", err)
|
||||
return false
|
||||
}
|
||||
|
||||
// Cache exists
|
||||
if len(missingCacheKeys) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
log.Logger.Debugf("Missing virtual machine cache: %s", cacheKey)
|
||||
return false
|
||||
}
|
||||
112
pkg/fanal/artifact/vm/file.go
Normal file
112
pkg/fanal/artifact/vm/file.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/vm"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/vm/disk"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
// default vmdk block size 64 KB
|
||||
// If vm type vmdk max cache memory size 64 MB
|
||||
const storageFILECacheSize = 1024
|
||||
|
||||
// ImageFile represents an local VM image file
|
||||
type ImageFile struct {
|
||||
Storage
|
||||
|
||||
filePath string
|
||||
file *os.File
|
||||
reader *io.SectionReader
|
||||
}
|
||||
|
||||
func newFile(filePath string, storage Storage) (*ImageFile, error) {
|
||||
f, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("file open error: %w", err)
|
||||
}
|
||||
|
||||
c, err := lru.New(storageFILECacheSize)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to create new lru cache: %w", err)
|
||||
}
|
||||
|
||||
reader, err := disk.New(f, c)
|
||||
if err != nil {
|
||||
if errors.Is(err, vm.ErrUnsupportedType) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Logger.Debugf("VM image not detected: %s", err)
|
||||
log.Logger.Debugf("Assume raw image")
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("file stat error: %w", err)
|
||||
}
|
||||
reader = io.NewSectionReader(f, 0, fi.Size())
|
||||
}
|
||||
|
||||
return &ImageFile{
|
||||
Storage: storage,
|
||||
|
||||
filePath: filePath,
|
||||
file: f,
|
||||
reader: reader,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *ImageFile) Inspect(ctx context.Context) (types.ArtifactReference, error) {
|
||||
blobInfo, err := a.Analyze(ctx, a.reader)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("inspection error: %w", err)
|
||||
}
|
||||
|
||||
cacheKey, err := a.calcCacheKey(blobInfo)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("cache calculation error: %w", err)
|
||||
}
|
||||
|
||||
if err = a.cache.PutBlob(cacheKey, blobInfo); err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("failed to store blob (%s) in cache: %w", cacheKey, err)
|
||||
}
|
||||
|
||||
return types.ArtifactReference{
|
||||
Name: a.filePath,
|
||||
Type: types.ArtifactVM,
|
||||
ID: cacheKey, // use a cache key as pseudo artifact ID
|
||||
BlobIDs: []string{cacheKey},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *ImageFile) calcCacheKey(blobInfo types.BlobInfo) (string, error) {
|
||||
// calculate hash of JSON and use it as pseudo artifactID and blobID
|
||||
h := sha256.New()
|
||||
if err := json.NewEncoder(h).Encode(blobInfo); err != nil {
|
||||
return "", xerrors.Errorf("json error: %w", err)
|
||||
}
|
||||
|
||||
d := digest.NewDigest(digest.SHA256, h)
|
||||
cacheKey, err := cache.CalcKey(d.String(), a.analyzer.AnalyzerVersions(), a.handlerManager.Versions(), a.artifactOption)
|
||||
if err != nil {
|
||||
return "", xerrors.Errorf("cache key: %w", err)
|
||||
}
|
||||
|
||||
return cacheKey, nil
|
||||
}
|
||||
|
||||
func (a *ImageFile) Clean(reference types.ArtifactReference) error {
|
||||
_ = a.file.Close()
|
||||
return a.cache.DeleteBlobs(reference.BlobIDs)
|
||||
}
|
||||
BIN
pkg/fanal/artifact/vm/testdata/AmazonLinux2.img.gz
vendored
Normal file
BIN
pkg/fanal/artifact/vm/testdata/AmazonLinux2.img.gz
vendored
Normal file
Binary file not shown.
BIN
pkg/fanal/artifact/vm/testdata/monolithicSparse.vmdk
vendored
Normal file
BIN
pkg/fanal/artifact/vm/testdata/monolithicSparse.vmdk
vendored
Normal file
Binary file not shown.
1
pkg/fanal/artifact/vm/testdata/rawdata.img
vendored
Normal file
1
pkg/fanal/artifact/vm/testdata/rawdata.img
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package testdata
|
||||
138
pkg/fanal/artifact/vm/vm.go
Normal file
138
pkg/fanal/artifact/vm/vm.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/handler"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/walker"
|
||||
"github.com/aquasecurity/trivy/pkg/semaphore"
|
||||
)
|
||||
|
||||
type Type string
|
||||
|
||||
func (t Type) Prefix() string {
|
||||
return string(t) + ":"
|
||||
}
|
||||
|
||||
const (
|
||||
TypeAMI Type = "ami"
|
||||
TypeEBS Type = "ebs"
|
||||
TypeFile Type = "file"
|
||||
)
|
||||
|
||||
type Storage struct {
|
||||
cache cache.ArtifactCache
|
||||
analyzer analyzer.AnalyzerGroup
|
||||
handlerManager handler.Manager
|
||||
walker walker.VM
|
||||
|
||||
artifactOption artifact.Option
|
||||
}
|
||||
|
||||
func (a *Storage) Analyze(ctx context.Context, r *io.SectionReader) (types.BlobInfo, error) {
|
||||
var wg sync.WaitGroup
|
||||
limit := semaphore.New(a.artifactOption.Slow)
|
||||
result := analyzer.NewAnalysisResult()
|
||||
|
||||
// TODO: Always walk from the root directory. Consider whether there is a need to be able to set optional
|
||||
err := a.walker.Walk(r, "/", func(filePath string, info os.FileInfo, opener analyzer.Opener) error {
|
||||
opts := analyzer.AnalysisOptions{Offline: a.artifactOption.Offline}
|
||||
path := strings.TrimPrefix(filePath, "/")
|
||||
if err := a.analyzer.AnalyzeFile(ctx, &wg, limit, result, "/", path, info, opener, nil, opts); err != nil {
|
||||
return xerrors.Errorf("analyze file (%s): %w", path, err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// Wait for all the goroutine to finish.
|
||||
wg.Wait()
|
||||
|
||||
if err != nil {
|
||||
return types.BlobInfo{}, xerrors.Errorf("walk vm error: %w", err)
|
||||
}
|
||||
|
||||
result.Sort()
|
||||
|
||||
blobInfo := types.BlobInfo{
|
||||
SchemaVersion: types.BlobJSONSchemaVersion,
|
||||
OS: result.OS,
|
||||
Repository: result.Repository,
|
||||
PackageInfos: result.PackageInfos,
|
||||
Applications: result.Applications,
|
||||
Secrets: result.Secrets,
|
||||
Licenses: result.Licenses,
|
||||
CustomResources: result.CustomResources,
|
||||
}
|
||||
|
||||
if err = a.handlerManager.PostHandle(ctx, result, &blobInfo); err != nil {
|
||||
return types.BlobInfo{}, xerrors.Errorf("failed to call hooks: %w", err)
|
||||
}
|
||||
|
||||
return blobInfo, nil
|
||||
}
|
||||
|
||||
func NewArtifact(target string, c cache.ArtifactCache, opt artifact.Option) (artifact.Artifact, error) {
|
||||
handlerManager, err := handler.NewManager(opt)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("handler init error: %w", err)
|
||||
}
|
||||
a, err := analyzer.NewAnalyzerGroup(analyzer.AnalyzerOptions{
|
||||
Group: opt.AnalyzerGroup,
|
||||
FilePatterns: opt.FilePatterns,
|
||||
DisabledAnalyzers: opt.DisabledAnalyzers,
|
||||
SecretScannerOption: opt.SecretScannerOption,
|
||||
LicenseScannerOption: opt.LicenseScannerOption,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("analyzer group error: %w", err)
|
||||
}
|
||||
|
||||
storage := Storage{
|
||||
cache: c,
|
||||
analyzer: a,
|
||||
handlerManager: handlerManager,
|
||||
walker: walker.NewVM(opt.SkipFiles, opt.SkipDirs, opt.Slow),
|
||||
artifactOption: opt,
|
||||
}
|
||||
|
||||
targetType := detectType(target)
|
||||
switch targetType {
|
||||
case TypeAMI:
|
||||
target = strings.TrimPrefix(target, TypeAMI.Prefix())
|
||||
return newAMI(target, storage)
|
||||
case TypeEBS:
|
||||
target = strings.TrimPrefix(target, TypeEBS.Prefix())
|
||||
e, err := newEBS(target, storage)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("new EBS error: %w", err)
|
||||
}
|
||||
return e, nil
|
||||
case TypeFile:
|
||||
target = strings.TrimPrefix(target, TypeFile.Prefix())
|
||||
return newFile(target, storage)
|
||||
}
|
||||
return nil, xerrors.Errorf("unsupported format")
|
||||
}
|
||||
|
||||
func detectType(target string) Type {
|
||||
switch {
|
||||
case strings.HasPrefix(target, TypeAMI.Prefix()):
|
||||
return TypeAMI
|
||||
case strings.HasPrefix(target, TypeEBS.Prefix()):
|
||||
return TypeEBS
|
||||
case strings.HasPrefix(target, TypeFile.Prefix()):
|
||||
return TypeFile
|
||||
default:
|
||||
return TypeFile
|
||||
}
|
||||
}
|
||||
453
pkg/fanal/artifact/vm/vm_test.go
Normal file
453
pkg/fanal/artifact/vm/vm_test.go
Normal file
@@ -0,0 +1,453 @@
|
||||
package vm_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/aquasecurity/trivy/internal/testutil"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/analyzer/config"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact/vm"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
ebsfile "github.com/masahiro331/go-ebs-file"
|
||||
|
||||
_ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/all"
|
||||
)
|
||||
|
||||
const (
|
||||
ebsPrefix = string(vm.TypeEBS) + ":"
|
||||
filePrefix = string(vm.TypeFile) + ":"
|
||||
)
|
||||
|
||||
func TestNewArtifact(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
target string
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "happy path for file",
|
||||
target: "testdata/rawdata.img",
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "happy path for EBS",
|
||||
target: "ebs:ebs-012345",
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "sad path unsupported vm format",
|
||||
target: "testdata/monolithicSparse.vmdk",
|
||||
wantErr: func(t assert.TestingT, err error, args ...interface{}) bool {
|
||||
return assert.ErrorContains(t, err, "unsupported type error")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "sad path file not found",
|
||||
target: "testdata/no-file",
|
||||
wantErr: func(t assert.TestingT, err error, args ...interface{}) bool {
|
||||
return assert.ErrorContains(t, err, "no such file or directory")
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, err := vm.NewArtifact(tt.target, nil, artifact.Option{})
|
||||
tt.wantErr(t, err, fmt.Sprintf("NewArtifact(%v, nil, nil)", tt.target))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestArtifact_Inspect(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
filePath string
|
||||
artifactOpt artifact.Option
|
||||
scannerOpt config.ScannerOption
|
||||
disabledAnalyzers []analyzer.Type
|
||||
disabledHandlers []types.HandlerType
|
||||
missingBlobsExpectation cache.ArtifactCacheMissingBlobsExpectation
|
||||
putBlobExpectation cache.ArtifactCachePutBlobExpectation
|
||||
putArtifactExpectations []cache.ArtifactCachePutArtifactExpectation
|
||||
want types.ArtifactReference
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "happy path for raw image",
|
||||
filePath: "testdata/AmazonLinux2.img.gz",
|
||||
putBlobExpectation: cache.ArtifactCachePutBlobExpectation{
|
||||
Args: cache.ArtifactCachePutBlobArgs{
|
||||
BlobID: "sha256:d59c327eb3a3c71c8728f5e3d597b1c5dbf25adb54d7e9237a0f1c8a495032d6",
|
||||
BlobInfo: types.BlobInfo{
|
||||
SchemaVersion: types.BlobJSONSchemaVersion,
|
||||
OS: &types.OS{
|
||||
Family: "amazon",
|
||||
Name: "2 (Karoo)",
|
||||
},
|
||||
PackageInfos: []types.PackageInfo{
|
||||
{
|
||||
FilePath: "var/lib/rpm/Packages",
|
||||
Packages: expectPackages,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
putArtifactExpectations: []cache.ArtifactCachePutArtifactExpectation{
|
||||
{
|
||||
Args: cache.ArtifactCachePutArtifactArgs{
|
||||
ArtifactID: "sha256:d59c327eb3a3c71c8728f5e3d597b1c5dbf25adb54d7e9237a0f1c8a495032d6",
|
||||
ArtifactInfo: types.ArtifactInfo{
|
||||
SchemaVersion: types.ArtifactJSONSchemaVersion,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
want: types.ArtifactReference{
|
||||
Name: "testdata/AmazonLinux2.img.gz",
|
||||
Type: types.ArtifactVM,
|
||||
ID: "sha256:d59c327eb3a3c71c8728f5e3d597b1c5dbf25adb54d7e9237a0f1c8a495032d6",
|
||||
BlobIDs: []string{
|
||||
"sha256:d59c327eb3a3c71c8728f5e3d597b1c5dbf25adb54d7e9237a0f1c8a495032d6",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "happy path for ebs",
|
||||
filePath: "ebs:ebs-012345",
|
||||
missingBlobsExpectation: cache.ArtifactCacheMissingBlobsExpectation{
|
||||
Args: cache.ArtifactCacheMissingBlobsArgs{
|
||||
ArtifactID: "sha256:a0a5dc5e371203bcfe6e8d9d24c6910b3ca2fd661cb53de62b6371fc177dcb69",
|
||||
BlobIDs: []string{"sha256:a0a5dc5e371203bcfe6e8d9d24c6910b3ca2fd661cb53de62b6371fc177dcb69"},
|
||||
},
|
||||
},
|
||||
putBlobExpectation: cache.ArtifactCachePutBlobExpectation{
|
||||
Args: cache.ArtifactCachePutBlobArgs{
|
||||
BlobID: "sha256:a0a5dc5e371203bcfe6e8d9d24c6910b3ca2fd661cb53de62b6371fc177dcb69",
|
||||
BlobInfo: types.BlobInfo{
|
||||
SchemaVersion: types.BlobJSONSchemaVersion,
|
||||
OS: &types.OS{
|
||||
Family: "amazon",
|
||||
Name: "2 (Karoo)",
|
||||
},
|
||||
PackageInfos: []types.PackageInfo{
|
||||
{
|
||||
FilePath: "var/lib/rpm/Packages",
|
||||
Packages: expectPackages,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Returns: cache.ArtifactCachePutBlobReturns{},
|
||||
},
|
||||
putArtifactExpectations: []cache.ArtifactCachePutArtifactExpectation{
|
||||
{
|
||||
Args: cache.ArtifactCachePutArtifactArgs{
|
||||
ArtifactID: "sha256:a0a5dc5e371203bcfe6e8d9d24c6910b3ca2fd661cb53de62b6371fc177dcb69",
|
||||
ArtifactInfo: types.ArtifactInfo{
|
||||
SchemaVersion: types.ArtifactJSONSchemaVersion,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: types.ArtifactReference{
|
||||
Name: "ebs-012345",
|
||||
Type: types.ArtifactVM,
|
||||
ID: "sha256:a0a5dc5e371203bcfe6e8d9d24c6910b3ca2fd661cb53de62b6371fc177dcb69",
|
||||
BlobIDs: []string{
|
||||
"sha256:a0a5dc5e371203bcfe6e8d9d24c6910b3ca2fd661cb53de62b6371fc177dcb69",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := new(cache.MockArtifactCache)
|
||||
c.ApplyPutBlobExpectation(tt.putBlobExpectation)
|
||||
c.ApplyMissingBlobsExpectation(tt.missingBlobsExpectation)
|
||||
c.ApplyPutArtifactExpectations(tt.putArtifactExpectations)
|
||||
|
||||
filePath := tt.filePath
|
||||
if !strings.HasPrefix(tt.filePath, ebsPrefix) {
|
||||
filePath = filepath.Join(t.TempDir(), "disk.img")
|
||||
testutil.DecompressGzip(t, tt.filePath, filePath)
|
||||
}
|
||||
|
||||
a, err := vm.NewArtifact(filePath, c, tt.artifactOpt)
|
||||
require.NoError(t, err)
|
||||
|
||||
if aa, ok := a.(*vm.EBS); ok {
|
||||
// blockSize: 512 KB, volumeSize: 40MB
|
||||
ebs := ebsfile.NewMockEBS("testdata/AmazonLinux2.img.gz", 512<<10, 40<<20)
|
||||
aa.SetEBS(ebs)
|
||||
}
|
||||
|
||||
got, err := a.Inspect(context.Background())
|
||||
if tt.wantErr != "" {
|
||||
require.Error(t, err)
|
||||
assert.ErrorContains(t, err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
tt.want.Name = trimPrefix(filePath)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func trimPrefix(s string) string {
|
||||
s = strings.TrimPrefix(s, ebsPrefix)
|
||||
s = strings.TrimPrefix(s, filePrefix)
|
||||
return s
|
||||
}
|
||||
|
||||
/*
|
||||
How to create test image with Ubuntu.
|
||||
|
||||
# Create empty image
|
||||
$ dd of=Linux.img count=0 seek=1 bs=41943040
|
||||
|
||||
# Create loop device
|
||||
$ losetup /dev/loop5 Linux.img
|
||||
|
||||
# Create partition
|
||||
$ parted /dev/loop5
|
||||
(parted)$ mklabel gpt
|
||||
(parted)$ mkpart primary 1MiB 2MiB
|
||||
(parted)$ set 1 boot on
|
||||
(parted)$ mkpart primary xfs 2MiB 100%
|
||||
(parted)$ quit
|
||||
|
||||
# Format XFS and mount
|
||||
$ mkfs.xfs /dev/loop5p2
|
||||
$ mount /dev/loop5p2 /mnt/xfs
|
||||
|
||||
# Create some files
|
||||
$ mkdir /mnt/xfs/etc/
|
||||
$ cp system-release /mnt/xfs/etc/system-release
|
||||
|
||||
# Un tup and unmount
|
||||
$ umount /mnt/xfs
|
||||
$ losetup -d /dev/loop5
|
||||
*/
|
||||
|
||||
var expectPackages = []types.Package{
|
||||
{ID: "amazon-linux-extras@1.6.7-1.amzn2.noarch", Name: "amazon-linux-extras", Version: "1.6.7", Release: "1.amzn2", Arch: "noarch", SrcName: "amazon-linux-extras", SrcVersion: "1.6.7",
|
||||
SrcRelease: "1.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv2"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "coreutils@8.22-21.amzn2.x86_64", "python@2.7.14-58.amzn2.0.4.x86_64", "system-release@2-10.amzn2.x86_64"}},
|
||||
{ID: "basesystem@10.0-7.amzn2.0.1.noarch", Name: "basesystem", Version: "10.0", Release: "7.amzn2.0.1", Arch: "noarch", SrcName: "basesystem", SrcVersion: "10.0",
|
||||
SrcRelease: "7.amzn2.0.1", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"Public Domain"}, DependsOn: []string{"filesystem@3.2-25.amzn2.0.4.x86_64", "setup@2.8.71-10.amzn2.noarch"}},
|
||||
{ID: "bash@4.2.46-30.amzn2.x86_64", Name: "bash", Version: "4.2.46", Release: "30.amzn2", Arch: "x86_64", SrcName: "bash", SrcVersion: "4.2.46",
|
||||
SrcRelease: "30.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv3+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "ncurses-libs@6.0-8.20170212.amzn2.1.2.x86_64"}},
|
||||
{ID: "bzip2-libs@1.0.6-13.amzn2.0.2.x86_64", Name: "bzip2-libs", Version: "1.0.6", Release: "13.amzn2.0.2", Arch: "x86_64", SrcName: "bzip2", SrcVersion: "1.0.6",
|
||||
SrcRelease: "13.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"BSD"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "ca-certificates@2018.2.22-70.0.amzn2.noarch", Name: "ca-certificates", Version: "2018.2.22", Release: "70.0.amzn2", Arch: "noarch", SrcName: "ca-certificates", SrcVersion: "2018.2.22",
|
||||
SrcRelease: "70.0.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"Public Domain"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "p11-kit-trust@0.23.5-3.amzn2.0.2.x86_64", "p11-kit@0.23.5-3.amzn2.0.2.x86_64"}},
|
||||
{ID: "chkconfig@1.7.4-1.amzn2.0.2.x86_64", Name: "chkconfig", Version: "1.7.4", Release: "1.amzn2.0.2", Arch: "x86_64", SrcName: "chkconfig", SrcVersion: "1.7.4",
|
||||
SrcRelease: "1.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv2"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "libselinux@2.5-12.amzn2.0.2.x86_64", "libsepol@2.5-8.1.amzn2.0.2.x86_64", "popt@1.13-16.amzn2.0.2.x86_64"}},
|
||||
{ID: "coreutils@8.22-21.amzn2.x86_64", Name: "coreutils", Version: "8.22", Release: "21.amzn2", Arch: "x86_64", SrcName: "coreutils", SrcVersion: "8.22",
|
||||
SrcRelease: "21.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv3+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "gmp@6.0.0-15.amzn2.0.2.x86_64", "grep@2.20-3.amzn2.0.2.x86_64", "libacl@2.2.51-14.amzn2.x86_64", "libattr@2.4.46-12.amzn2.0.2.x86_64", "libcap@2.22-9.amzn2.0.2.x86_64", "libselinux@2.5-12.amzn2.0.2.x86_64", "ncurses@6.0-8.20170212.amzn2.1.2.x86_64", "openssl-libs@1.0.2k-16.amzn2.1.1.x86_64"}},
|
||||
{ID: "cpio@2.11-27.amzn2.x86_64", Name: "cpio", Version: "2.11", Release: "27.amzn2", Arch: "x86_64", SrcName: "cpio", SrcVersion: "2.11",
|
||||
SrcRelease: "27.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv3+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "curl@7.61.1-9.amzn2.0.1.x86_64", Name: "curl", Version: "7.61.1", Release: "9.amzn2.0.1", Arch: "x86_64", SrcName: "curl", SrcVersion: "7.61.1",
|
||||
SrcRelease: "9.amzn2.0.1", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MIT"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "libcurl@7.61.1-9.amzn2.0.1.x86_64", "libmetalink@0.1.2-7.amzn2.0.2.x86_64", "openssl-libs@1.0.2k-16.amzn2.1.1.x86_64", "zlib@1.2.7-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "cyrus-sasl-lib@2.1.26-23.amzn2.x86_64", Name: "cyrus-sasl-lib", Version: "2.1.26", Release: "23.amzn2", Arch: "x86_64", SrcName: "cyrus-sasl", SrcVersion: "2.1.26",
|
||||
SrcRelease: "23.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"BSD with advertising"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "krb5-libs@1.15.1-20.amzn2.0.1.x86_64", "libcom_err@1.42.9-12.amzn2.0.2.x86_64", "libcrypt@2.26-32.amzn2.0.1.x86_64", "libdb@5.3.21-24.amzn2.0.3.x86_64"}},
|
||||
{ID: "diffutils@3.3-4.amzn2.0.2.x86_64", Name: "diffutils", Version: "3.3", Release: "4.amzn2.0.2", Arch: "x86_64", SrcName: "diffutils", SrcVersion: "3.3",
|
||||
SrcRelease: "4.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv3+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "info@5.1-5.amzn2.x86_64"}},
|
||||
{ID: "elfutils-libelf@0.170-4.amzn2.x86_64", Name: "elfutils-libelf", Version: "0.170", Release: "4.amzn2", Arch: "x86_64", SrcName: "elfutils", SrcVersion: "0.170",
|
||||
SrcRelease: "4.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv2+ or LGPLv3+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "zlib@1.2.7-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "expat@2.1.0-10.amzn2.0.2.x86_64", Name: "expat", Version: "2.1.0", Release: "10.amzn2.0.2", Arch: "x86_64", SrcName: "expat", SrcVersion: "2.1.0",
|
||||
SrcRelease: "10.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MIT"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "file-libs@5.11-33.amzn2.0.2.x86_64", Name: "file-libs", Version: "5.11", Release: "33.amzn2.0.2", Arch: "x86_64", SrcName: "file", SrcVersion: "5.11",
|
||||
SrcRelease: "33.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"BSD"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "zlib@1.2.7-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "filesystem@3.2-25.amzn2.0.4.x86_64", Name: "filesystem", Version: "3.2", Release: "25.amzn2.0.4", Arch: "x86_64", SrcName: "filesystem", SrcVersion: "3.2",
|
||||
SrcRelease: "25.amzn2.0.4", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"Public Domain"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "setup@2.8.71-10.amzn2.noarch"}},
|
||||
{ID: "findutils@4.5.11-5.amzn2.0.2.x86_64", Name: "findutils", Version: "4.5.11", Release: "5.amzn2.0.2", Arch: "x86_64", SrcName: "findutils", SrcVersion: "4.5.11",
|
||||
SrcRelease: "5.amzn2.0.2", Epoch: 1, SrcEpoch: 1, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv3+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "libselinux@2.5-12.amzn2.0.2.x86_64"}},
|
||||
{ID: "gawk@4.0.2-4.amzn2.1.2.x86_64", Name: "gawk", Version: "4.0.2", Release: "4.amzn2.1.2", Arch: "x86_64", SrcName: "gawk", SrcVersion: "4.0.2",
|
||||
SrcRelease: "4.amzn2.1.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv3+ and GPL and LGPLv3+ and LGPL and BSD"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "gdbm@1.13-6.amzn2.0.2.x86_64", Name: "gdbm", Version: "1.13", Release: "6.amzn2.0.2", Arch: "x86_64", SrcName: "gdbm", SrcVersion: "1.13",
|
||||
SrcRelease: "6.amzn2.0.2", Epoch: 1, SrcEpoch: 1, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv3+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "ncurses-libs@6.0-8.20170212.amzn2.1.2.x86_64", "readline@6.2-10.amzn2.0.2.x86_64"}},
|
||||
{ID: "glib2@2.54.2-2.amzn2.x86_64", Name: "glib2", Version: "2.54.2", Release: "2.amzn2", Arch: "x86_64", SrcName: "glib2", SrcVersion: "2.54.2",
|
||||
SrcRelease: "2.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "libffi@3.0.13-18.amzn2.0.2.x86_64", "libgcc@7.3.1-5.amzn2.0.2.x86_64", "libmount@2.30.2-2.amzn2.0.4.x86_64", "libselinux@2.5-12.amzn2.0.2.x86_64", "pcre@8.32-17.amzn2.0.2.x86_64", "shared-mime-info@1.8-4.amzn2.x86_64", "zlib@1.2.7-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "glibc@2.26-32.amzn2.0.1.x86_64", Name: "glibc", Version: "2.26", Release: "32.amzn2.0.1", Arch: "x86_64", SrcName: "glibc", SrcVersion: "2.26",
|
||||
SrcRelease: "32.amzn2.0.1", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+ and LGPLv2+ with exceptions and GPLv2+"}, DependsOn: []string{"basesystem@10.0-7.amzn2.0.1.noarch", "glibc-common@2.26-32.amzn2.0.1.x86_64", "glibc-minimal-langpack@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "glibc-common@2.26-32.amzn2.0.1.x86_64", Name: "glibc-common", Version: "2.26", Release: "32.amzn2.0.1", Arch: "x86_64", SrcName: "glibc", SrcVersion: "2.26",
|
||||
SrcRelease: "32.amzn2.0.1", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+ and LGPLv2+ with exceptions and GPLv2+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "libselinux@2.5-12.amzn2.0.2.x86_64", "tzdata@2018i-1.amzn2.noarch"}},
|
||||
{ID: "glibc-langpack-en@2.26-32.amzn2.0.1.x86_64", Name: "glibc-langpack-en", Version: "2.26", Release: "32.amzn2.0.1", Arch: "x86_64", SrcName: "glibc", SrcVersion: "2.26",
|
||||
SrcRelease: "32.amzn2.0.1", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+ and LGPLv2+ with exceptions and GPLv2+"}, DependsOn: []string{"glibc-common@2.26-32.amzn2.0.1.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "glibc-minimal-langpack@2.26-32.amzn2.0.1.x86_64", Name: "glibc-minimal-langpack", Version: "2.26", Release: "32.amzn2.0.1", Arch: "x86_64", SrcName: "glibc", SrcVersion: "2.26",
|
||||
SrcRelease: "32.amzn2.0.1", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+ and LGPLv2+ with exceptions and GPLv2+"}, DependsOn: []string{"glibc-common@2.26-32.amzn2.0.1.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "gmp@6.0.0-15.amzn2.0.2.x86_64", Name: "gmp", Version: "6.0.0", Release: "15.amzn2.0.2", Arch: "x86_64", SrcName: "gmp", SrcVersion: "6.0.0",
|
||||
SrcRelease: "15.amzn2.0.2", Epoch: 1, SrcEpoch: 1, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv3+ or GPLv2+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "libgcc@7.3.1-5.amzn2.0.2.x86_64", "libstdc++@7.3.1-5.amzn2.0.2.x86_64"}},
|
||||
{ID: "gnupg2@2.0.22-5.amzn2.0.3.x86_64", Name: "gnupg2", Version: "2.0.22", Release: "5.amzn2.0.3", Arch: "x86_64", SrcName: "gnupg2", SrcVersion: "2.0.22",
|
||||
SrcRelease: "5.amzn2.0.3", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv3+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "bzip2-libs@1.0.6-13.amzn2.0.2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "libassuan@2.1.0-3.amzn2.0.2.x86_64", "libcurl@7.61.1-9.amzn2.0.1.x86_64", "libgcrypt@1.5.3-14.amzn2.0.2.x86_64", "libgpg-error@1.12-3.amzn2.0.3.x86_64", "openldap@2.4.44-15.amzn2.x86_64", "pinentry@0.8.1-17.amzn2.0.2.x86_64", "pth@2.0.7-23.amzn2.0.2.x86_64", "readline@6.2-10.amzn2.0.2.x86_64", "zlib@1.2.7-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "gpg-pubkey@c87f5b1a-593863f8.", Name: "gpg-pubkey", Version: "c87f5b1a", Release: "593863f8", Arch: "None", SrcName: "", SrcVersion: "",
|
||||
SrcRelease: "", Epoch: 0, SrcEpoch: 0, Maintainer: "", Layer: types.Layer{}, Licenses: []string{"pubkey"}},
|
||||
{ID: "gpgme@1.3.2-5.amzn2.0.2.x86_64", Name: "gpgme", Version: "1.3.2", Release: "5.amzn2.0.2", Arch: "x86_64", SrcName: "gpgme", SrcVersion: "1.3.2",
|
||||
SrcRelease: "5.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "gnupg2@2.0.22-5.amzn2.0.3.x86_64", "libassuan@2.1.0-3.amzn2.0.2.x86_64", "libgpg-error@1.12-3.amzn2.0.3.x86_64"}},
|
||||
{ID: "grep@2.20-3.amzn2.0.2.x86_64", Name: "grep", Version: "2.20", Release: "3.amzn2.0.2", Arch: "x86_64", SrcName: "grep", SrcVersion: "2.20",
|
||||
SrcRelease: "3.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv3+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "pcre@8.32-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "info@5.1-5.amzn2.x86_64", Name: "info", Version: "5.1", Release: "5.amzn2", Arch: "x86_64", SrcName: "texinfo", SrcVersion: "5.1",
|
||||
SrcRelease: "5.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv3+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "ncurses-libs@6.0-8.20170212.amzn2.1.2.x86_64", "zlib@1.2.7-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "keyutils-libs@1.5.8-3.amzn2.0.2.x86_64", Name: "keyutils-libs", Version: "1.5.8", Release: "3.amzn2.0.2", Arch: "x86_64", SrcName: "keyutils", SrcVersion: "1.5.8",
|
||||
SrcRelease: "3.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv2+ and LGPLv2+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "krb5-libs@1.15.1-20.amzn2.0.1.x86_64", Name: "krb5-libs", Version: "1.15.1", Release: "20.amzn2.0.1", Arch: "x86_64", SrcName: "krb5", SrcVersion: "1.15.1",
|
||||
SrcRelease: "20.amzn2.0.1", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MIT"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "coreutils@8.22-21.amzn2.x86_64", "gawk@4.0.2-4.amzn2.1.2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "grep@2.20-3.amzn2.0.2.x86_64", "keyutils-libs@1.5.8-3.amzn2.0.2.x86_64", "libcom_err@1.42.9-12.amzn2.0.2.x86_64", "libselinux@2.5-12.amzn2.0.2.x86_64", "libverto@0.2.5-4.amzn2.0.2.x86_64", "openssl-libs@1.0.2k-16.amzn2.1.1.x86_64", "sed@4.2.2-5.amzn2.0.2.x86_64"}},
|
||||
{ID: "libacl@2.2.51-14.amzn2.x86_64", Name: "libacl", Version: "2.2.51", Release: "14.amzn2", Arch: "x86_64", SrcName: "acl", SrcVersion: "2.2.51",
|
||||
SrcRelease: "14.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "libattr@2.4.46-12.amzn2.0.2.x86_64"}},
|
||||
{ID: "libassuan@2.1.0-3.amzn2.0.2.x86_64", Name: "libassuan", Version: "2.1.0", Release: "3.amzn2.0.2", Arch: "x86_64", SrcName: "libassuan", SrcVersion: "2.1.0",
|
||||
SrcRelease: "3.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+ and GPLv3+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "libgpg-error@1.12-3.amzn2.0.3.x86_64"}},
|
||||
{ID: "libattr@2.4.46-12.amzn2.0.2.x86_64", Name: "libattr", Version: "2.4.46", Release: "12.amzn2.0.2", Arch: "x86_64", SrcName: "attr", SrcVersion: "2.4.46",
|
||||
SrcRelease: "12.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "libblkid@2.30.2-2.amzn2.0.4.x86_64", Name: "libblkid", Version: "2.30.2", Release: "2.amzn2.0.4", Arch: "x86_64", SrcName: "util-linux", SrcVersion: "2.30.2",
|
||||
SrcRelease: "2.amzn2.0.4", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "coreutils@8.22-21.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "libuuid@2.30.2-2.amzn2.0.4.x86_64"}},
|
||||
{ID: "libcap@2.22-9.amzn2.0.2.x86_64", Name: "libcap", Version: "2.22", Release: "9.amzn2.0.2", Arch: "x86_64", SrcName: "libcap", SrcVersion: "2.22",
|
||||
SrcRelease: "9.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "libattr@2.4.46-12.amzn2.0.2.x86_64"}},
|
||||
{ID: "libcom_err@1.42.9-12.amzn2.0.2.x86_64", Name: "libcom_err", Version: "1.42.9", Release: "12.amzn2.0.2", Arch: "x86_64", SrcName: "e2fsprogs", SrcVersion: "1.42.9",
|
||||
SrcRelease: "12.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MIT"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "libcrypt@2.26-32.amzn2.0.1.x86_64", Name: "libcrypt", Version: "2.26", Release: "32.amzn2.0.1", Arch: "x86_64", SrcName: "glibc", SrcVersion: "2.26",
|
||||
SrcRelease: "32.amzn2.0.1", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+ and LGPLv2+ with exceptions and GPLv2+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "libcurl@7.61.1-9.amzn2.0.1.x86_64", Name: "libcurl", Version: "7.61.1", Release: "9.amzn2.0.1", Arch: "x86_64", SrcName: "curl", SrcVersion: "7.61.1",
|
||||
SrcRelease: "9.amzn2.0.1", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MIT"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "krb5-libs@1.15.1-20.amzn2.0.1.x86_64", "libcom_err@1.42.9-12.amzn2.0.2.x86_64", "libidn2@2.0.4-1.amzn2.0.2.x86_64", "libnghttp2@1.31.1-1.amzn2.0.2.x86_64", "libssh2@1.4.3-12.amzn2.2.x86_64", "nss-pem@1.0.3-5.amzn2.x86_64", "openldap@2.4.44-15.amzn2.x86_64", "openssl-libs@1.0.2k-16.amzn2.1.1.x86_64", "zlib@1.2.7-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "libdb@5.3.21-24.amzn2.0.3.x86_64", Name: "libdb", Version: "5.3.21", Release: "24.amzn2.0.3", Arch: "x86_64", SrcName: "libdb", SrcVersion: "5.3.21",
|
||||
SrcRelease: "24.amzn2.0.3", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"BSD and LGPLv2 and Sleepycat"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "libdb-utils@5.3.21-24.amzn2.0.3.x86_64", Name: "libdb-utils", Version: "5.3.21", Release: "24.amzn2.0.3", Arch: "x86_64", SrcName: "libdb", SrcVersion: "5.3.21",
|
||||
SrcRelease: "24.amzn2.0.3", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"BSD and LGPLv2 and Sleepycat"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "libdb@5.3.21-24.amzn2.0.3.x86_64"}},
|
||||
{ID: "libffi@3.0.13-18.amzn2.0.2.x86_64", Name: "libffi", Version: "3.0.13", Release: "18.amzn2.0.2", Arch: "x86_64", SrcName: "libffi", SrcVersion: "3.0.13",
|
||||
SrcRelease: "18.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MIT and Public Domain"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "libgcc@7.3.1-5.amzn2.0.2.x86_64", Name: "libgcc", Version: "7.3.1", Release: "5.amzn2.0.2", Arch: "x86_64", SrcName: "gcc", SrcVersion: "7.3.1",
|
||||
SrcRelease: "5.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv3+ and GPLv3+ with exceptions and GPLv2+ with exceptions and LGPLv2+ and BSD"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "libgcrypt@1.5.3-14.amzn2.0.2.x86_64", Name: "libgcrypt", Version: "1.5.3", Release: "14.amzn2.0.2", Arch: "x86_64", SrcName: "libgcrypt", SrcVersion: "1.5.3",
|
||||
SrcRelease: "14.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "libgpg-error@1.12-3.amzn2.0.3.x86_64"}},
|
||||
{ID: "libgpg-error@1.12-3.amzn2.0.3.x86_64", Name: "libgpg-error", Version: "1.12", Release: "3.amzn2.0.3", Arch: "x86_64", SrcName: "libgpg-error", SrcVersion: "1.12",
|
||||
SrcRelease: "3.amzn2.0.3", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "libidn2@2.0.4-1.amzn2.0.2.x86_64", Name: "libidn2", Version: "2.0.4", Release: "1.amzn2.0.2", Arch: "x86_64", SrcName: "libidn2", SrcVersion: "2.0.4",
|
||||
SrcRelease: "1.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"(GPLv2+ or LGPLv3+) and GPLv3+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "libunistring@0.9.3-9.amzn2.0.2.x86_64"}},
|
||||
{ID: "libmetalink@0.1.2-7.amzn2.0.2.x86_64", Name: "libmetalink", Version: "0.1.2", Release: "7.amzn2.0.2", Arch: "x86_64", SrcName: "libmetalink", SrcVersion: "0.1.2",
|
||||
SrcRelease: "7.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MIT"}, DependsOn: []string{"expat@2.1.0-10.amzn2.0.2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "libmount@2.30.2-2.amzn2.0.4.x86_64", Name: "libmount", Version: "2.30.2", Release: "2.amzn2.0.4", Arch: "x86_64", SrcName: "util-linux", SrcVersion: "2.30.2",
|
||||
SrcRelease: "2.amzn2.0.4", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "libblkid@2.30.2-2.amzn2.0.4.x86_64", "libselinux@2.5-12.amzn2.0.2.x86_64", "libuuid@2.30.2-2.amzn2.0.4.x86_64"}},
|
||||
{ID: "libnghttp2@1.31.1-1.amzn2.0.2.x86_64", Name: "libnghttp2", Version: "1.31.1", Release: "1.amzn2.0.2", Arch: "x86_64", SrcName: "nghttp2", SrcVersion: "1.31.1",
|
||||
SrcRelease: "1.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MIT"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "libselinux@2.5-12.amzn2.0.2.x86_64", Name: "libselinux", Version: "2.5", Release: "12.amzn2.0.2", Arch: "x86_64", SrcName: "libselinux", SrcVersion: "2.5",
|
||||
SrcRelease: "12.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"Public Domain"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "libsepol@2.5-8.1.amzn2.0.2.x86_64", "pcre@8.32-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "libsepol@2.5-8.1.amzn2.0.2.x86_64", Name: "libsepol", Version: "2.5", Release: "8.1.amzn2.0.2", Arch: "x86_64", SrcName: "libsepol", SrcVersion: "2.5",
|
||||
SrcRelease: "8.1.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "libssh2@1.4.3-12.amzn2.2.x86_64", Name: "libssh2", Version: "1.4.3", Release: "12.amzn2.2", Arch: "x86_64", SrcName: "libssh2", SrcVersion: "1.4.3",
|
||||
SrcRelease: "12.amzn2.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"BSD"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "openssl-libs@1.0.2k-16.amzn2.1.1.x86_64", "zlib@1.2.7-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "libstdc++@7.3.1-5.amzn2.0.2.x86_64", Name: "libstdc++", Version: "7.3.1", Release: "5.amzn2.0.2", Arch: "x86_64", SrcName: "gcc", SrcVersion: "7.3.1",
|
||||
SrcRelease: "5.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv3+ and GPLv3+ with exceptions and GPLv2+ with exceptions and LGPLv2+ and BSD"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "libgcc@7.3.1-5.amzn2.0.2.x86_64"}},
|
||||
{ID: "libtasn1@4.10-1.amzn2.0.2.x86_64", Name: "libtasn1", Version: "4.10", Release: "1.amzn2.0.2", Arch: "x86_64", SrcName: "libtasn1", SrcVersion: "4.10",
|
||||
SrcRelease: "1.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv3+ and LGPLv2+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "libunistring@0.9.3-9.amzn2.0.2.x86_64", Name: "libunistring", Version: "0.9.3", Release: "9.amzn2.0.2", Arch: "x86_64", SrcName: "libunistring", SrcVersion: "0.9.3",
|
||||
SrcRelease: "9.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv3+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "info@5.1-5.amzn2.x86_64"}},
|
||||
{ID: "libuuid@2.30.2-2.amzn2.0.4.x86_64", Name: "libuuid", Version: "2.30.2", Release: "2.amzn2.0.4", Arch: "x86_64", SrcName: "util-linux", SrcVersion: "2.30.2",
|
||||
SrcRelease: "2.amzn2.0.4", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"BSD"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "libverto@0.2.5-4.amzn2.0.2.x86_64", Name: "libverto", Version: "0.2.5", Release: "4.amzn2.0.2", Arch: "x86_64", SrcName: "libverto", SrcVersion: "0.2.5",
|
||||
SrcRelease: "4.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MIT"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "libxml2@2.9.1-6.amzn2.3.2.x86_64", Name: "libxml2", Version: "2.9.1", Release: "6.amzn2.3.2", Arch: "x86_64", SrcName: "libxml2", SrcVersion: "2.9.1",
|
||||
SrcRelease: "6.amzn2.3.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MIT"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "xz-libs@5.2.2-1.amzn2.0.2.x86_64", "zlib@1.2.7-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "lua@5.1.4-15.amzn2.0.2.x86_64", Name: "lua", Version: "5.1.4", Release: "15.amzn2.0.2", Arch: "x86_64", SrcName: "lua", SrcVersion: "5.1.4",
|
||||
SrcRelease: "15.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MIT"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "ncurses-libs@6.0-8.20170212.amzn2.1.2.x86_64", "readline@6.2-10.amzn2.0.2.x86_64"}},
|
||||
{ID: "ncurses@6.0-8.20170212.amzn2.1.2.x86_64", Name: "ncurses", Version: "6.0", Release: "8.20170212.amzn2.1.2", Arch: "x86_64", SrcName: "ncurses", SrcVersion: "6.0",
|
||||
SrcRelease: "8.20170212.amzn2.1.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MIT"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "ncurses-libs@6.0-8.20170212.amzn2.1.2.x86_64"}},
|
||||
{ID: "ncurses-base@6.0-8.20170212.amzn2.1.2.noarch", Name: "ncurses-base", Version: "6.0", Release: "8.20170212.amzn2.1.2", Arch: "noarch", SrcName: "ncurses", SrcVersion: "6.0",
|
||||
SrcRelease: "8.20170212.amzn2.1.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MIT"}},
|
||||
{ID: "ncurses-libs@6.0-8.20170212.amzn2.1.2.x86_64", Name: "ncurses-libs", Version: "6.0", Release: "8.20170212.amzn2.1.2", Arch: "x86_64", SrcName: "ncurses", SrcVersion: "6.0",
|
||||
SrcRelease: "8.20170212.amzn2.1.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MIT"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "ncurses-base@6.0-8.20170212.amzn2.1.2.noarch"}},
|
||||
{ID: "nspr@4.19.0-1.amzn2.x86_64", Name: "nspr", Version: "4.19.0", Release: "1.amzn2", Arch: "x86_64", SrcName: "nspr", SrcVersion: "4.19.0",
|
||||
SrcRelease: "1.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MPLv2.0"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "nss@3.36.0-7.amzn2.x86_64", Name: "nss", Version: "3.36.0", Release: "7.amzn2", Arch: "x86_64", SrcName: "nss", SrcVersion: "3.36.0",
|
||||
SrcRelease: "7.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MPLv2.0"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "nspr@4.19.0-1.amzn2.x86_64", "nss-pem@1.0.3-5.amzn2.x86_64", "nss-softokn@3.36.0-5.amzn2.x86_64", "nss-sysinit@3.36.0-7.amzn2.x86_64", "nss-util@3.36.0-1.amzn2.x86_64"}},
|
||||
{ID: "nss-pem@1.0.3-5.amzn2.x86_64", Name: "nss-pem", Version: "1.0.3", Release: "5.amzn2", Arch: "x86_64", SrcName: "nss-pem", SrcVersion: "1.0.3",
|
||||
SrcRelease: "5.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MPLv1.1"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "nspr@4.19.0-1.amzn2.x86_64", "nss-util@3.36.0-1.amzn2.x86_64", "nss@3.36.0-7.amzn2.x86_64"}},
|
||||
{ID: "nss-softokn@3.36.0-5.amzn2.x86_64", Name: "nss-softokn", Version: "3.36.0", Release: "5.amzn2", Arch: "x86_64", SrcName: "nss-softokn", SrcVersion: "3.36.0",
|
||||
SrcRelease: "5.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MPLv2.0"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "nspr@4.19.0-1.amzn2.x86_64", "nss-softokn-freebl@3.36.0-5.amzn2.x86_64", "nss-util@3.36.0-1.amzn2.x86_64", "sqlite@3.7.17-8.amzn2.0.2.x86_64"}},
|
||||
{ID: "nss-softokn-freebl@3.36.0-5.amzn2.x86_64", Name: "nss-softokn-freebl", Version: "3.36.0", Release: "5.amzn2", Arch: "x86_64", SrcName: "nss-softokn", SrcVersion: "3.36.0",
|
||||
SrcRelease: "5.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MPLv2.0"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "nspr@4.19.0-1.amzn2.x86_64", "nss-util@3.36.0-1.amzn2.x86_64"}},
|
||||
{ID: "nss-sysinit@3.36.0-7.amzn2.x86_64", Name: "nss-sysinit", Version: "3.36.0", Release: "7.amzn2", Arch: "x86_64", SrcName: "nss", SrcVersion: "3.36.0",
|
||||
SrcRelease: "7.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MPLv2.0"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "coreutils@8.22-21.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "nspr@4.19.0-1.amzn2.x86_64", "nss-util@3.36.0-1.amzn2.x86_64", "nss@3.36.0-7.amzn2.x86_64", "sed@4.2.2-5.amzn2.0.2.x86_64"}},
|
||||
{ID: "nss-tools@3.36.0-7.amzn2.x86_64", Name: "nss-tools", Version: "3.36.0", Release: "7.amzn2", Arch: "x86_64", SrcName: "nss", SrcVersion: "3.36.0",
|
||||
SrcRelease: "7.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MPLv2.0"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "nspr@4.19.0-1.amzn2.x86_64", "nss-softokn@3.36.0-5.amzn2.x86_64", "nss-util@3.36.0-1.amzn2.x86_64", "nss@3.36.0-7.amzn2.x86_64", "zlib@1.2.7-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "nss-util@3.36.0-1.amzn2.x86_64", Name: "nss-util", Version: "3.36.0", Release: "1.amzn2", Arch: "x86_64", SrcName: "nss-util", SrcVersion: "3.36.0",
|
||||
SrcRelease: "1.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MPLv2.0"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "nspr@4.19.0-1.amzn2.x86_64"}},
|
||||
{ID: "openldap@2.4.44-15.amzn2.x86_64", Name: "openldap", Version: "2.4.44", Release: "15.amzn2", Arch: "x86_64", SrcName: "openldap", SrcVersion: "2.4.44",
|
||||
SrcRelease: "15.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"OpenLDAP"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "coreutils@8.22-21.amzn2.x86_64", "cyrus-sasl-lib@2.1.26-23.amzn2.x86_64", "findutils@4.5.11-5.amzn2.0.2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "nspr@4.19.0-1.amzn2.x86_64", "nss-tools@3.36.0-7.amzn2.x86_64", "nss-util@3.36.0-1.amzn2.x86_64", "nss@3.36.0-7.amzn2.x86_64", "openssl-libs@1.0.2k-16.amzn2.1.1.x86_64", "rpm@4.11.3-25.amzn2.0.3.x86_64"}},
|
||||
{ID: "openssl-libs@1.0.2k-16.amzn2.1.1.x86_64", Name: "openssl-libs", Version: "1.0.2k", Release: "16.amzn2.1.1", Arch: "x86_64", SrcName: "openssl", SrcVersion: "1.0.2k",
|
||||
SrcRelease: "16.amzn2.1.1", Epoch: 1, SrcEpoch: 1, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"OpenSSL"}, DependsOn: []string{"ca-certificates@2018.2.22-70.0.amzn2.noarch", "glibc@2.26-32.amzn2.0.1.x86_64", "krb5-libs@1.15.1-20.amzn2.0.1.x86_64", "libcom_err@1.42.9-12.amzn2.0.2.x86_64", "zlib@1.2.7-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "p11-kit@0.23.5-3.amzn2.0.2.x86_64", Name: "p11-kit", Version: "0.23.5", Release: "3.amzn2.0.2", Arch: "x86_64", SrcName: "p11-kit", SrcVersion: "0.23.5",
|
||||
SrcRelease: "3.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"BSD"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "libffi@3.0.13-18.amzn2.0.2.x86_64"}},
|
||||
{ID: "p11-kit-trust@0.23.5-3.amzn2.0.2.x86_64", Name: "p11-kit-trust", Version: "0.23.5", Release: "3.amzn2.0.2", Arch: "x86_64", SrcName: "p11-kit", SrcVersion: "0.23.5",
|
||||
SrcRelease: "3.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"BSD"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "libffi@3.0.13-18.amzn2.0.2.x86_64", "libtasn1@4.10-1.amzn2.0.2.x86_64", "nss-softokn-freebl@3.36.0-5.amzn2.x86_64", "p11-kit@0.23.5-3.amzn2.0.2.x86_64"}},
|
||||
{ID: "pcre@8.32-17.amzn2.0.2.x86_64", Name: "pcre", Version: "8.32", Release: "17.amzn2.0.2", Arch: "x86_64", SrcName: "pcre", SrcVersion: "8.32",
|
||||
SrcRelease: "17.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"BSD"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "libgcc@7.3.1-5.amzn2.0.2.x86_64", "libstdc++@7.3.1-5.amzn2.0.2.x86_64"}},
|
||||
{ID: "pinentry@0.8.1-17.amzn2.0.2.x86_64", Name: "pinentry", Version: "0.8.1", Release: "17.amzn2.0.2", Arch: "x86_64", SrcName: "pinentry", SrcVersion: "0.8.1",
|
||||
SrcRelease: "17.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv2+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "ncurses-libs@6.0-8.20170212.amzn2.1.2.x86_64"}},
|
||||
{ID: "popt@1.13-16.amzn2.0.2.x86_64", Name: "popt", Version: "1.13", Release: "16.amzn2.0.2", Arch: "x86_64", SrcName: "popt", SrcVersion: "1.13",
|
||||
SrcRelease: "16.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MIT"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "pth@2.0.7-23.amzn2.0.2.x86_64", Name: "pth", Version: "2.0.7", Release: "23.amzn2.0.2", Arch: "x86_64", SrcName: "pth", SrcVersion: "2.0.7",
|
||||
SrcRelease: "23.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "pygpgme@0.3-9.amzn2.0.2.x86_64", Name: "pygpgme", Version: "0.3", Release: "9.amzn2.0.2", Arch: "x86_64", SrcName: "pygpgme", SrcVersion: "0.3",
|
||||
SrcRelease: "9.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "gpgme@1.3.2-5.amzn2.0.2.x86_64", "python-libs@2.7.14-58.amzn2.0.4.x86_64", "python@2.7.14-58.amzn2.0.4.x86_64"}},
|
||||
{ID: "pyliblzma@0.5.3-11.amzn2.0.2.x86_64", Name: "pyliblzma", Version: "0.5.3", Release: "11.amzn2.0.2", Arch: "x86_64", SrcName: "pyliblzma", SrcVersion: "0.5.3",
|
||||
SrcRelease: "11.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv3+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "python-libs@2.7.14-58.amzn2.0.4.x86_64", "python@2.7.14-58.amzn2.0.4.x86_64", "xz-libs@5.2.2-1.amzn2.0.2.x86_64"}},
|
||||
{ID: "python@2.7.14-58.amzn2.0.4.x86_64", Name: "python", Version: "2.7.14", Release: "58.amzn2.0.4", Arch: "x86_64", SrcName: "python", SrcVersion: "2.7.14",
|
||||
SrcRelease: "58.amzn2.0.4", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"Python"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "python-libs@2.7.14-58.amzn2.0.4.x86_64"}},
|
||||
{ID: "python-iniparse@0.4-9.amzn2.noarch", Name: "python-iniparse", Version: "0.4", Release: "9.amzn2", Arch: "noarch", SrcName: "python-iniparse", SrcVersion: "0.4",
|
||||
SrcRelease: "9.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"MIT"}, DependsOn: []string{"python@2.7.14-58.amzn2.0.4.x86_64"}},
|
||||
{ID: "python-libs@2.7.14-58.amzn2.0.4.x86_64", Name: "python-libs", Version: "2.7.14", Release: "58.amzn2.0.4", Arch: "x86_64", SrcName: "python", SrcVersion: "2.7.14",
|
||||
SrcRelease: "58.amzn2.0.4", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"Python"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "bzip2-libs@1.0.6-13.amzn2.0.2.x86_64", "expat@2.1.0-10.amzn2.0.2.x86_64", "gdbm@1.13-6.amzn2.0.2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "libcrypt@2.26-32.amzn2.0.1.x86_64", "libdb@5.3.21-24.amzn2.0.3.x86_64", "libffi@3.0.13-18.amzn2.0.2.x86_64", "ncurses-libs@6.0-8.20170212.amzn2.1.2.x86_64", "openssl-libs@1.0.2k-16.amzn2.1.1.x86_64", "readline@6.2-10.amzn2.0.2.x86_64", "sqlite@3.7.17-8.amzn2.0.2.x86_64", "zlib@1.2.7-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "python-pycurl@7.19.0-19.amzn2.0.2.x86_64", Name: "python-pycurl", Version: "7.19.0", Release: "19.amzn2.0.2", Arch: "x86_64", SrcName: "python-pycurl", SrcVersion: "7.19.0",
|
||||
SrcRelease: "19.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+ or MIT"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "keyutils-libs@1.5.8-3.amzn2.0.2.x86_64", "libcurl@7.61.1-9.amzn2.0.1.x86_64", "python-libs@2.7.14-58.amzn2.0.4.x86_64", "python@2.7.14-58.amzn2.0.4.x86_64"}},
|
||||
{ID: "python-urlgrabber@3.10-8.amzn2.noarch", Name: "python-urlgrabber", Version: "3.10", Release: "8.amzn2", Arch: "noarch", SrcName: "python-urlgrabber", SrcVersion: "3.10",
|
||||
SrcRelease: "8.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+"}, DependsOn: []string{"python-pycurl@7.19.0-19.amzn2.0.2.x86_64", "python@2.7.14-58.amzn2.0.4.x86_64"}},
|
||||
{ID: "pyxattr@0.5.1-5.amzn2.0.2.x86_64", Name: "pyxattr", Version: "0.5.1", Release: "5.amzn2.0.2", Arch: "x86_64", SrcName: "pyxattr", SrcVersion: "0.5.1",
|
||||
SrcRelease: "5.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "libattr@2.4.46-12.amzn2.0.2.x86_64", "python-libs@2.7.14-58.amzn2.0.4.x86_64", "python@2.7.14-58.amzn2.0.4.x86_64"}},
|
||||
{ID: "readline@6.2-10.amzn2.0.2.x86_64", Name: "readline", Version: "6.2", Release: "10.amzn2.0.2", Arch: "x86_64", SrcName: "readline", SrcVersion: "6.2",
|
||||
SrcRelease: "10.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv3+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "ncurses-libs@6.0-8.20170212.amzn2.1.2.x86_64"}},
|
||||
{ID: "rpm@4.11.3-25.amzn2.0.3.x86_64", Name: "rpm", Version: "4.11.3", Release: "25.amzn2.0.3", Arch: "x86_64", SrcName: "rpm", SrcVersion: "4.11.3",
|
||||
SrcRelease: "25.amzn2.0.3", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv2+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "bzip2-libs@1.0.6-13.amzn2.0.2.x86_64", "coreutils@8.22-21.amzn2.x86_64", "curl@7.61.1-9.amzn2.0.1.x86_64", "elfutils-libelf@0.170-4.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "libacl@2.2.51-14.amzn2.x86_64", "libcap@2.22-9.amzn2.0.2.x86_64", "libdb@5.3.21-24.amzn2.0.3.x86_64", "libselinux@2.5-12.amzn2.0.2.x86_64", "lua@5.1.4-15.amzn2.0.2.x86_64", "nss@3.36.0-7.amzn2.x86_64", "popt@1.13-16.amzn2.0.2.x86_64", "rpm-libs@4.11.3-25.amzn2.0.3.x86_64", "xz-libs@5.2.2-1.amzn2.0.2.x86_64", "zlib@1.2.7-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "rpm-build-libs@4.11.3-25.amzn2.0.3.x86_64", Name: "rpm-build-libs", Version: "4.11.3", Release: "25.amzn2.0.3", Arch: "x86_64", SrcName: "rpm", SrcVersion: "4.11.3",
|
||||
SrcRelease: "25.amzn2.0.3", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv2+ and LGPLv2+ with exceptions"}, DependsOn: []string{"bzip2-libs@1.0.6-13.amzn2.0.2.x86_64", "elfutils-libelf@0.170-4.amzn2.x86_64", "file-libs@5.11-33.amzn2.0.2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "libacl@2.2.51-14.amzn2.x86_64", "libcap@2.22-9.amzn2.0.2.x86_64", "libdb@5.3.21-24.amzn2.0.3.x86_64", "libselinux@2.5-12.amzn2.0.2.x86_64", "lua@5.1.4-15.amzn2.0.2.x86_64", "nss@3.36.0-7.amzn2.x86_64", "popt@1.13-16.amzn2.0.2.x86_64", "rpm-libs@4.11.3-25.amzn2.0.3.x86_64", "xz-libs@5.2.2-1.amzn2.0.2.x86_64", "zlib@1.2.7-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "rpm-libs@4.11.3-25.amzn2.0.3.x86_64", Name: "rpm-libs", Version: "4.11.3", Release: "25.amzn2.0.3", Arch: "x86_64", SrcName: "rpm", SrcVersion: "4.11.3",
|
||||
SrcRelease: "25.amzn2.0.3", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv2+ and LGPLv2+ with exceptions"}, DependsOn: []string{"bzip2-libs@1.0.6-13.amzn2.0.2.x86_64", "elfutils-libelf@0.170-4.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "libacl@2.2.51-14.amzn2.x86_64", "libcap@2.22-9.amzn2.0.2.x86_64", "libdb@5.3.21-24.amzn2.0.3.x86_64", "libselinux@2.5-12.amzn2.0.2.x86_64", "lua@5.1.4-15.amzn2.0.2.x86_64", "nss@3.36.0-7.amzn2.x86_64", "popt@1.13-16.amzn2.0.2.x86_64", "rpm@4.11.3-25.amzn2.0.3.x86_64", "xz-libs@5.2.2-1.amzn2.0.2.x86_64", "zlib@1.2.7-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "rpm-python@4.11.3-25.amzn2.0.3.x86_64", Name: "rpm-python", Version: "4.11.3", Release: "25.amzn2.0.3", Arch: "x86_64", SrcName: "rpm", SrcVersion: "4.11.3",
|
||||
SrcRelease: "25.amzn2.0.3", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv2+"}, DependsOn: []string{"bzip2-libs@1.0.6-13.amzn2.0.2.x86_64", "elfutils-libelf@0.170-4.amzn2.x86_64", "file-libs@5.11-33.amzn2.0.2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "libacl@2.2.51-14.amzn2.x86_64", "libcap@2.22-9.amzn2.0.2.x86_64", "libdb@5.3.21-24.amzn2.0.3.x86_64", "libselinux@2.5-12.amzn2.0.2.x86_64", "lua@5.1.4-15.amzn2.0.2.x86_64", "nss@3.36.0-7.amzn2.x86_64", "popt@1.13-16.amzn2.0.2.x86_64", "python-libs@2.7.14-58.amzn2.0.4.x86_64", "python@2.7.14-58.amzn2.0.4.x86_64", "rpm-build-libs@4.11.3-25.amzn2.0.3.x86_64", "rpm-libs@4.11.3-25.amzn2.0.3.x86_64", "rpm@4.11.3-25.amzn2.0.3.x86_64", "xz-libs@5.2.2-1.amzn2.0.2.x86_64", "zlib@1.2.7-17.amzn2.0.2.x86_64"}},
|
||||
{ID: "sed@4.2.2-5.amzn2.0.2.x86_64", Name: "sed", Version: "4.2.2", Release: "5.amzn2.0.2", Arch: "x86_64", SrcName: "sed", SrcVersion: "4.2.2",
|
||||
SrcRelease: "5.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv3+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "libselinux@2.5-12.amzn2.0.2.x86_64"}},
|
||||
{ID: "setup@2.8.71-10.amzn2.noarch", Name: "setup", Version: "2.8.71", Release: "10.amzn2", Arch: "noarch", SrcName: "setup", SrcVersion: "2.8.71",
|
||||
SrcRelease: "10.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"Public Domain"}, DependsOn: []string{"system-release@2-10.amzn2.x86_64"}},
|
||||
{ID: "shared-mime-info@1.8-4.amzn2.x86_64", Name: "shared-mime-info", Version: "1.8", Release: "4.amzn2", Arch: "x86_64", SrcName: "shared-mime-info", SrcVersion: "1.8",
|
||||
SrcRelease: "4.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv2+"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64", "coreutils@8.22-21.amzn2.x86_64", "glib2@2.54.2-2.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "libxml2@2.9.1-6.amzn2.3.2.x86_64"}},
|
||||
{ID: "sqlite@3.7.17-8.amzn2.0.2.x86_64", Name: "sqlite", Version: "3.7.17", Release: "8.amzn2.0.2", Arch: "x86_64", SrcName: "sqlite", SrcVersion: "3.7.17",
|
||||
SrcRelease: "8.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"Public Domain"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "ncurses-libs@6.0-8.20170212.amzn2.1.2.x86_64", "readline@6.2-10.amzn2.0.2.x86_64"}},
|
||||
{ID: "system-release@2-10.amzn2.x86_64", Name: "system-release", Version: "2", Release: "10.amzn2", Arch: "x86_64", SrcName: "system-release", SrcVersion: "2",
|
||||
SrcRelease: "10.amzn2", Epoch: 1, SrcEpoch: 1, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv2"}, DependsOn: []string{"bash@4.2.46-30.amzn2.x86_64"}},
|
||||
{ID: "tzdata@2018i-1.amzn2.noarch", Name: "tzdata", Version: "2018i", Release: "1.amzn2", Arch: "noarch", SrcName: "tzdata", SrcVersion: "2018i",
|
||||
SrcRelease: "1.amzn2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"Public Domain"}},
|
||||
{ID: "vim-minimal@7.4.160-4.amzn2.0.16.x86_64", Name: "vim-minimal", Version: "7.4.160", Release: "4.amzn2.0.16", Arch: "x86_64", SrcName: "vim", SrcVersion: "7.4.160",
|
||||
SrcRelease: "4.amzn2.0.16", Epoch: 2, SrcEpoch: 2, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"Vim"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64", "libacl@2.2.51-14.amzn2.x86_64", "libselinux@2.5-12.amzn2.0.2.x86_64", "ncurses-libs@6.0-8.20170212.amzn2.1.2.x86_64"}},
|
||||
{ID: "xz-libs@5.2.2-1.amzn2.0.2.x86_64", Name: "xz-libs", Version: "5.2.2", Release: "1.amzn2.0.2", Arch: "x86_64", SrcName: "xz", SrcVersion: "5.2.2",
|
||||
SrcRelease: "1.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"LGPLv2+"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
{ID: "yum@3.4.3-158.amzn2.0.2.noarch", Name: "yum", Version: "3.4.3", Release: "158.amzn2.0.2", Arch: "noarch", SrcName: "yum", SrcVersion: "3.4.3",
|
||||
SrcRelease: "158.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv2+"}, DependsOn: []string{"cpio@2.11-27.amzn2.x86_64", "diffutils@3.3-4.amzn2.0.2.x86_64", "pygpgme@0.3-9.amzn2.0.2.x86_64", "pyliblzma@0.5.3-11.amzn2.0.2.x86_64", "python-iniparse@0.4-9.amzn2.noarch", "python-urlgrabber@3.10-8.amzn2.noarch", "python@2.7.14-58.amzn2.0.4.x86_64", "pyxattr@0.5.1-5.amzn2.0.2.x86_64", "rpm-python@4.11.3-25.amzn2.0.3.x86_64", "rpm@4.11.3-25.amzn2.0.3.x86_64", "yum-metadata-parser@1.1.4-10.amzn2.0.2.x86_64"}},
|
||||
{ID: "yum-metadata-parser@1.1.4-10.amzn2.0.2.x86_64", Name: "yum-metadata-parser", Version: "1.1.4", Release: "10.amzn2.0.2", Arch: "x86_64", SrcName: "yum-metadata-parser", SrcVersion: "1.1.4",
|
||||
SrcRelease: "10.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv2"}, DependsOn: []string{"glib2@2.54.2-2.amzn2.x86_64", "glibc@2.26-32.amzn2.0.1.x86_64", "libxml2@2.9.1-6.amzn2.3.2.x86_64", "python-libs@2.7.14-58.amzn2.0.4.x86_64", "python@2.7.14-58.amzn2.0.4.x86_64", "sqlite@3.7.17-8.amzn2.0.2.x86_64"}},
|
||||
{ID: "yum-plugin-ovl@1.1.31-46.amzn2.0.1.noarch", Name: "yum-plugin-ovl", Version: "1.1.31", Release: "46.amzn2.0.1", Arch: "noarch", SrcName: "yum-utils", SrcVersion: "1.1.31",
|
||||
SrcRelease: "46.amzn2.0.1", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv2+"}, DependsOn: []string{"yum@3.4.3-158.amzn2.0.2.noarch"}},
|
||||
{ID: "yum-plugin-priorities@1.1.31-46.amzn2.0.1.noarch", Name: "yum-plugin-priorities", Version: "1.1.31", Release: "46.amzn2.0.1", Arch: "noarch", SrcName: "yum-utils", SrcVersion: "1.1.31",
|
||||
SrcRelease: "46.amzn2.0.1", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"GPLv2+"}, DependsOn: []string{"yum@3.4.3-158.amzn2.0.2.noarch"}},
|
||||
{ID: "zlib@1.2.7-17.amzn2.0.2.x86_64", Name: "zlib", Version: "1.2.7", Release: "17.amzn2.0.2", Arch: "x86_64", SrcName: "zlib", SrcVersion: "1.2.7",
|
||||
SrcRelease: "17.amzn2.0.2", Epoch: 0, SrcEpoch: 0, Maintainer: "Amazon Linux", Layer: types.Layer{}, Licenses: []string{"zlib and Boost"}, DependsOn: []string{"glibc@2.26-32.amzn2.0.1.x86_64"}},
|
||||
}
|
||||
@@ -110,6 +110,7 @@ const (
|
||||
ArtifactCycloneDX ArtifactType = "cyclonedx"
|
||||
ArtifactSPDX ArtifactType = "spdx"
|
||||
ArtifactAWSAccount ArtifactType = "aws_account"
|
||||
ArtifactVM ArtifactType = "vm"
|
||||
)
|
||||
|
||||
// ArtifactReference represents a reference of container image, local filesystem and repository
|
||||
|
||||
36
pkg/fanal/vm/disk/disk.go
Normal file
36
pkg/fanal/vm/disk/disk.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package disk
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/vm"
|
||||
)
|
||||
|
||||
var (
|
||||
vmDisks = []Disk{
|
||||
VMDK{},
|
||||
}
|
||||
)
|
||||
|
||||
// Disk defines virtual machine disk images like VMDK, VDI and VHD.
|
||||
type Disk interface {
|
||||
NewReader(rs io.ReadSeeker, cache vm.Cache) (*io.SectionReader, error)
|
||||
}
|
||||
|
||||
func New(rs io.ReadSeeker, cache vm.Cache) (*io.SectionReader, error) {
|
||||
for _, disk := range vmDisks {
|
||||
vreader, err := disk.NewReader(rs, cache)
|
||||
if err != nil {
|
||||
if errors.Is(err, vm.ErrInvalidSignature) {
|
||||
continue
|
||||
}
|
||||
return nil, xerrors.Errorf("open virtual machine error: %w", err)
|
||||
}
|
||||
|
||||
return vreader, nil
|
||||
}
|
||||
return nil, xerrors.New("virtual machine can not be detected")
|
||||
}
|
||||
43
pkg/fanal/vm/disk/disk_test.go
Normal file
43
pkg/fanal/vm/disk/disk_test.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package disk_test
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/vm"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/vm/disk"
|
||||
)
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
type args struct {
|
||||
rs io.ReadSeeker
|
||||
cache vm.Cache
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fileName string
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "invalid vm file",
|
||||
fileName: "testdata/invalid.vmdk",
|
||||
wantErr: "virtual machine can not be detected",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
f, err := os.Open(tt.fileName)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = disk.New(f, nil)
|
||||
if err == nil {
|
||||
assert.Fail(t, "required error test")
|
||||
}
|
||||
assert.ErrorContains(t, err, tt.wantErr)
|
||||
})
|
||||
}
|
||||
}
|
||||
0
pkg/fanal/vm/disk/testdata/invalid.vmdk
vendored
Normal file
0
pkg/fanal/vm/disk/testdata/invalid.vmdk
vendored
Normal file
36
pkg/fanal/vm/disk/vmdk.go
Normal file
36
pkg/fanal/vm/disk/vmdk.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package disk
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/masahiro331/go-vmdk-parser/pkg/virtualization/vmdk"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/vm"
|
||||
)
|
||||
|
||||
type VMDK struct{}
|
||||
|
||||
func (V VMDK) NewReader(rs io.ReadSeeker, cache vm.Cache) (*io.SectionReader, error) {
|
||||
if _, err := rs.Seek(0, io.SeekStart); err != nil {
|
||||
return nil, xerrors.Errorf("seek error: %w", err)
|
||||
}
|
||||
|
||||
if _, err := vmdk.Check(rs); err != nil {
|
||||
return nil, vm.ErrInvalidSignature
|
||||
}
|
||||
|
||||
if _, err := rs.Seek(0, io.SeekStart); err != nil {
|
||||
return nil, xerrors.Errorf("seek error: %w", err)
|
||||
}
|
||||
|
||||
reader, err := vmdk.Open(rs, cache)
|
||||
if err != nil {
|
||||
if errors.Is(err, vmdk.ErrUnSupportedType) {
|
||||
return nil, xerrors.Errorf("%s: %w", err.Error(), vm.ErrUnsupportedType)
|
||||
}
|
||||
return nil, xerrors.Errorf("failed to open vmdk: %w", err)
|
||||
}
|
||||
return reader, nil
|
||||
}
|
||||
41
pkg/fanal/vm/disk/vmdk_test.go
Normal file
41
pkg/fanal/vm/disk/vmdk_test.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package disk_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/vm/disk"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestVMDK_NewReader(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fileName string
|
||||
wantErr string
|
||||
}{
|
||||
// TODO: add valid tests
|
||||
{
|
||||
name: "invalid vmdk file",
|
||||
fileName: "testdata/invalid.vmdk",
|
||||
wantErr: "invalid signature error",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
v := disk.VMDK{}
|
||||
|
||||
f, err := os.Open(tt.fileName)
|
||||
require.NoError(t, err)
|
||||
defer f.Close()
|
||||
|
||||
_, err = v.NewReader(f, nil)
|
||||
if err == nil {
|
||||
assert.Fail(t, "required error test")
|
||||
}
|
||||
assert.ErrorContains(t, err, tt.wantErr)
|
||||
})
|
||||
}
|
||||
}
|
||||
34
pkg/fanal/vm/filesystem/ext4.go
Normal file
34
pkg/fanal/vm/filesystem/ext4.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package filesystem
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/fs"
|
||||
|
||||
"github.com/masahiro331/go-ext4-filesystem/ext4"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/vm"
|
||||
)
|
||||
|
||||
type EXT4 struct{}
|
||||
|
||||
func (e EXT4) New(sr io.SectionReader, cache vm.Cache) (fs.FS, error) {
|
||||
_, err := sr.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to seek offset error: %w", err)
|
||||
}
|
||||
ok := ext4.Check(&sr)
|
||||
if !ok {
|
||||
return nil, ErrInvalidHeader
|
||||
}
|
||||
|
||||
_, err = sr.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to seek offset error: %w", err)
|
||||
}
|
||||
f, err := ext4.NewFS(sr, cache)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("new ext4 filesystem error: %w", err)
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
51
pkg/fanal/vm/filesystem/filesystem.go
Normal file
51
pkg/fanal/vm/filesystem/filesystem.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package filesystem
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"io/fs"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/vm"
|
||||
)
|
||||
|
||||
const cacheSize = 2048
|
||||
|
||||
var (
|
||||
filesystems = []Filesystem{
|
||||
EXT4{},
|
||||
XFS{},
|
||||
}
|
||||
|
||||
ErrInvalidHeader = xerrors.New("invalid Header error")
|
||||
)
|
||||
|
||||
type Filesystem interface {
|
||||
New(sr io.SectionReader, cache vm.Cache) (fs.FS, error)
|
||||
}
|
||||
|
||||
func New(sr io.SectionReader) (fs.FS, func(), error) {
|
||||
var clean func()
|
||||
|
||||
// Initialize LRU cache for filesystem walking
|
||||
lruCache, err := lru.New(cacheSize)
|
||||
if err != nil {
|
||||
return nil, clean, xerrors.Errorf("failed to create a LRU cache: %w", err)
|
||||
}
|
||||
clean = lruCache.Purge
|
||||
|
||||
for _, filesystem := range filesystems {
|
||||
// TODO: implement LVM handler
|
||||
fsys, err := filesystem.New(sr, lruCache)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrInvalidHeader) {
|
||||
continue
|
||||
}
|
||||
return nil, clean, xerrors.Errorf("unexpected fs error: %w", err)
|
||||
}
|
||||
return fsys, clean, nil
|
||||
}
|
||||
return nil, clean, xerrors.New("unable to detect filesystem")
|
||||
}
|
||||
34
pkg/fanal/vm/filesystem/xfs.go
Normal file
34
pkg/fanal/vm/filesystem/xfs.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package filesystem
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/fs"
|
||||
|
||||
"github.com/masahiro331/go-xfs-filesystem/xfs"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/vm"
|
||||
)
|
||||
|
||||
type XFS struct{}
|
||||
|
||||
func (x XFS) New(sr io.SectionReader, cache vm.Cache) (fs.FS, error) {
|
||||
_, err := sr.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to seek offset error: %w", err)
|
||||
}
|
||||
ok := xfs.Check(&sr)
|
||||
if !ok {
|
||||
return nil, ErrInvalidHeader
|
||||
}
|
||||
|
||||
_, err = sr.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to seek offset error: %w", err)
|
||||
}
|
||||
f, err := xfs.NewFS(sr, cache)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("new xfs filesystem error: %w", err)
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
18
pkg/fanal/vm/vm.go
Normal file
18
pkg/fanal/vm/vm.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidSignature = xerrors.New("invalid signature error")
|
||||
ErrUnsupportedType = xerrors.New("unsupported type error")
|
||||
)
|
||||
|
||||
type Cache interface {
|
||||
// Add stores data in the cache
|
||||
Add(key, value interface{}) bool
|
||||
|
||||
// Get returns key's value from the cache
|
||||
Get(key interface{}) (value interface{}, ok bool)
|
||||
}
|
||||
85
pkg/fanal/walker/cached_file.go
Normal file
85
pkg/fanal/walker/cached_file.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package walker
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
dio "github.com/aquasecurity/go-dep-parser/pkg/io"
|
||||
)
|
||||
|
||||
// cachedFile represents a file cached in memory or storage according to the file size.
|
||||
type cachedFile struct {
|
||||
once sync.Once
|
||||
err error
|
||||
|
||||
size int64
|
||||
reader io.Reader
|
||||
|
||||
threshold int64 // Files larger than this threshold are written to file without being read into memory.
|
||||
|
||||
content []byte // It will be populated if this file is small
|
||||
filePath string // It will be populated if this file is large
|
||||
}
|
||||
|
||||
func newCachedFile(size int64, r io.Reader, threshold int64) *cachedFile {
|
||||
return &cachedFile{
|
||||
size: size,
|
||||
reader: r,
|
||||
threshold: threshold,
|
||||
}
|
||||
}
|
||||
|
||||
// Open opens a file and cache the file.
|
||||
// If the file size is greater than or equal to threshold, it copies the content to a temp file and opens it next time.
|
||||
// If the file size is less than threshold, it opens the file once and the content will be shared so that others analyzers can use the same data.
|
||||
func (o *cachedFile) Open() (dio.ReadSeekCloserAt, error) {
|
||||
o.once.Do(func() {
|
||||
// When the file is large, it will be written down to a temp file.
|
||||
if o.size >= o.threshold {
|
||||
f, err := os.CreateTemp("", "fanal-*")
|
||||
if err != nil {
|
||||
o.err = xerrors.Errorf("failed to create the temp file: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = io.Copy(f, o.reader); err != nil {
|
||||
o.err = xerrors.Errorf("failed to copy: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
o.filePath = f.Name()
|
||||
} else {
|
||||
b, err := io.ReadAll(o.reader)
|
||||
if err != nil {
|
||||
o.err = xerrors.Errorf("unable to read the file: %w", err)
|
||||
return
|
||||
}
|
||||
o.content = b
|
||||
}
|
||||
})
|
||||
if o.err != nil {
|
||||
return nil, xerrors.Errorf("failed to open: %w", o.err)
|
||||
}
|
||||
|
||||
return o.open()
|
||||
}
|
||||
|
||||
func (o *cachedFile) open() (dio.ReadSeekCloserAt, error) {
|
||||
if o.filePath != "" {
|
||||
f, err := os.Open(o.filePath)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to open the temp file: %w", err)
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
return dio.NopCloser(bytes.NewReader(o.content)), nil
|
||||
}
|
||||
|
||||
func (o *cachedFile) Clean() error {
|
||||
return os.Remove(o.filePath)
|
||||
}
|
||||
@@ -2,17 +2,12 @@ package walker
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
dio "github.com/aquasecurity/go-dep-parser/pkg/io"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -94,13 +89,13 @@ func (w LayerTar) Walk(layer io.Reader, analyzeFn WalkFunc) ([]string, []string,
|
||||
}
|
||||
|
||||
func (w LayerTar) processFile(filePath string, tr *tar.Reader, fi fs.FileInfo, analyzeFn WalkFunc) error {
|
||||
tf := newTarFile(fi.Size(), tr, w.threshold)
|
||||
cf := newCachedFile(fi.Size(), tr, w.threshold)
|
||||
defer func() {
|
||||
// nolint
|
||||
_ = tf.Clean()
|
||||
_ = cf.Clean()
|
||||
}()
|
||||
|
||||
if err := analyzeFn(filePath, fi, tf.Open); err != nil {
|
||||
if err := analyzeFn(filePath, fi, cf.Open); err != nil {
|
||||
return xerrors.Errorf("failed to analyze file: %w", err)
|
||||
}
|
||||
|
||||
@@ -119,76 +114,3 @@ func underSkippedDir(filePath string, skipDirs []string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// tarFile represents a file in a tar file.
|
||||
type tarFile struct {
|
||||
once sync.Once
|
||||
err error
|
||||
|
||||
size int64
|
||||
reader io.Reader
|
||||
|
||||
threshold int64 // Files larger than this threshold are written to file without being read into memory.
|
||||
|
||||
content []byte // It will be populated if this file is small
|
||||
filePath string // It will be populated if this file is large
|
||||
}
|
||||
|
||||
func newTarFile(size int64, r io.Reader, threshold int64) tarFile {
|
||||
return tarFile{
|
||||
size: size,
|
||||
reader: r,
|
||||
threshold: threshold,
|
||||
}
|
||||
}
|
||||
|
||||
// Open opens a file in the tar file.
|
||||
// If the file size is greater than or equal to threshold, it copies the content to a temp file and opens it next time.
|
||||
// If the file size is less than threshold, it opens the file once and the content will be shared so that others analyzers can use the same data.
|
||||
func (o *tarFile) Open() (dio.ReadSeekCloserAt, error) {
|
||||
o.once.Do(func() {
|
||||
// When the file is large, it will be written down to a temp file.
|
||||
if o.size >= o.threshold {
|
||||
f, err := os.CreateTemp("", "fanal-*")
|
||||
if err != nil {
|
||||
o.err = xerrors.Errorf("failed to create the temp file: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = io.Copy(f, o.reader); err != nil {
|
||||
o.err = xerrors.Errorf("failed to copy: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
o.filePath = f.Name()
|
||||
} else {
|
||||
b, err := io.ReadAll(o.reader)
|
||||
if err != nil {
|
||||
o.err = xerrors.Errorf("unable to read the file: %w", err)
|
||||
return
|
||||
}
|
||||
o.content = b
|
||||
}
|
||||
})
|
||||
if o.err != nil {
|
||||
return nil, xerrors.Errorf("failed to open: %w", o.err)
|
||||
}
|
||||
|
||||
return o.open()
|
||||
}
|
||||
|
||||
func (o *tarFile) open() (dio.ReadSeekCloserAt, error) {
|
||||
if o.filePath != "" {
|
||||
f, err := os.Open(o.filePath)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to open the temp file: %w", err)
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
return dio.NopCloser(bytes.NewReader(o.content)), nil
|
||||
}
|
||||
|
||||
func (o *tarFile) Clean() error {
|
||||
return os.Remove(o.filePath)
|
||||
}
|
||||
|
||||
229
pkg/fanal/walker/vm.go
Normal file
229
pkg/fanal/walker/vm.go
Normal file
@@ -0,0 +1,229 @@
|
||||
package walker
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/fs"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/masahiro331/go-disk"
|
||||
"github.com/masahiro331/go-disk/gpt"
|
||||
"github.com/masahiro331/go-disk/mbr"
|
||||
"github.com/masahiro331/go-disk/types"
|
||||
"golang.org/x/exp/slices"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
dio "github.com/aquasecurity/go-dep-parser/pkg/io"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/vm/filesystem"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
var requiredDiskName = []string{
|
||||
"Linux", // AmazonLinux image name
|
||||
"p.lxroot", // SLES image name
|
||||
"primary", // Common image name
|
||||
"0", // Common image name
|
||||
"1", // Common image name
|
||||
"2", // Common image name
|
||||
"3", // Common image name
|
||||
}
|
||||
|
||||
func AppendPermitDiskName(s ...string) {
|
||||
requiredDiskName = append(requiredDiskName, s...)
|
||||
}
|
||||
|
||||
type VM struct {
|
||||
walker
|
||||
threshold int64
|
||||
analyzeFn WalkFunc
|
||||
}
|
||||
|
||||
func NewVM(skipFiles, skipDirs []string, slow bool) VM {
|
||||
threshold := defaultSizeThreshold
|
||||
if slow {
|
||||
threshold = slowSizeThreshold
|
||||
}
|
||||
|
||||
return VM{
|
||||
walker: newWalker(skipFiles, skipDirs, slow),
|
||||
threshold: threshold,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *VM) Walk(vreader *io.SectionReader, root string, fn WalkFunc) error {
|
||||
// This function will be called on each file.
|
||||
w.analyzeFn = fn
|
||||
|
||||
driver, err := disk.NewDriver(vreader)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to new disk driver: %w", err)
|
||||
}
|
||||
|
||||
for {
|
||||
partition, err := driver.Next()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return xerrors.Errorf("failed to get a next partition: %w", err)
|
||||
}
|
||||
|
||||
// skip boot partition
|
||||
if shouldSkip(partition) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Walk each partition
|
||||
if err = w.diskWalk(root, partition); err != nil {
|
||||
log.Logger.Warnf("Partition error: %s", err.Error())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Inject disk partitioning processes from externally with diskWalk.
|
||||
func (w *VM) diskWalk(root string, partition types.Partition) error {
|
||||
log.Logger.Debugf("Found partition: %s", partition.Name())
|
||||
|
||||
sr := partition.GetSectionReader()
|
||||
|
||||
// Trivy does not support LVM scanning. It is skipped at the moment.
|
||||
foundLVM, err := w.detectLVM(sr)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("LVM detection error: %w", err)
|
||||
} else if foundLVM {
|
||||
log.Logger.Errorf("LVM is not supported, skip %s.img", partition.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
// Auto-detect filesystem such as ext4 and xfs
|
||||
fsys, clean, err := filesystem.New(sr)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("filesystem error: %w", err)
|
||||
}
|
||||
defer clean()
|
||||
|
||||
err = fs.WalkDir(fsys, root, func(path string, d fs.DirEntry, err error) error {
|
||||
// Walk filesystem
|
||||
return w.fsWalk(fsys, path, d, err)
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("filesystem walk error: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *VM) fsWalk(fsys fs.FS, path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return xerrors.Errorf("fs.Walk error: %w", err)
|
||||
}
|
||||
fi, err := d.Info()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("dir entry info error: %w", err)
|
||||
}
|
||||
pathName := strings.TrimPrefix(filepath.Clean(path), "/")
|
||||
if fi.IsDir() {
|
||||
if w.shouldSkipDir(pathName) {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
} else if !fi.Mode().IsRegular() {
|
||||
return nil
|
||||
} else if w.shouldSkipFile(pathName) {
|
||||
return nil
|
||||
} else if fi.Mode()&0x1000 == 0x1000 ||
|
||||
fi.Mode()&0x2000 == 0x2000 ||
|
||||
fi.Mode()&0x6000 == 0x6000 ||
|
||||
fi.Mode()&0xA000 == 0xA000 ||
|
||||
fi.Mode()&0xc000 == 0xc000 {
|
||||
// 0x1000: S_IFIFO (FIFO)
|
||||
// 0x2000: S_IFCHR (Character device)
|
||||
// 0x6000: S_IFBLK (Block device)
|
||||
// 0xA000: S_IFLNK (Symbolic link)
|
||||
// 0xC000: S_IFSOCK (Socket)
|
||||
return nil
|
||||
}
|
||||
|
||||
cvf := newCachedVMFile(fsys, pathName, w.threshold)
|
||||
defer cvf.Clean()
|
||||
|
||||
if err = w.analyzeFn(path, fi, cvf.Open); err != nil {
|
||||
return xerrors.Errorf("failed to analyze file: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type cachedVMFile struct {
|
||||
fs fs.FS
|
||||
filePath string
|
||||
threshold int64
|
||||
|
||||
cf *cachedFile
|
||||
}
|
||||
|
||||
func newCachedVMFile(fsys fs.FS, filePath string, threshold int64) *cachedVMFile {
|
||||
return &cachedVMFile{fs: fsys, filePath: filePath, threshold: threshold}
|
||||
}
|
||||
|
||||
func (cvf *cachedVMFile) Open() (dio.ReadSeekCloserAt, error) {
|
||||
if cvf.cf != nil {
|
||||
return cvf.cf.Open()
|
||||
}
|
||||
|
||||
f, err := cvf.fs.Open(cvf.filePath)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("file open error: %w", err)
|
||||
}
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("file stat error: %w", err)
|
||||
}
|
||||
|
||||
cvf.cf = newCachedFile(fi.Size(), f, cvf.threshold)
|
||||
return cvf.cf.Open()
|
||||
}
|
||||
|
||||
func (cvf *cachedVMFile) Clean() error {
|
||||
if cvf.cf == nil {
|
||||
return nil
|
||||
}
|
||||
return cvf.cf.Clean()
|
||||
}
|
||||
|
||||
func (w *VM) detectLVM(sr io.SectionReader) (bool, error) {
|
||||
buf := make([]byte, 512)
|
||||
_, err := sr.ReadAt(buf, 512)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("read header block error: %w", err)
|
||||
}
|
||||
_, err = sr.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("seek error: %w", err)
|
||||
}
|
||||
|
||||
// LABELONE is LVM signature
|
||||
if string(buf[:8]) == "LABELONE" {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func shouldSkip(partition types.Partition) bool {
|
||||
// skip empty partition
|
||||
if bytes.Equal(partition.GetType(), []byte{0x00}) {
|
||||
return true
|
||||
}
|
||||
|
||||
if !slices.Contains(requiredDiskName, partition.Name()) {
|
||||
return true
|
||||
}
|
||||
|
||||
switch p := partition.(type) {
|
||||
case *gpt.PartitionEntry:
|
||||
return p.Bootable()
|
||||
case *mbr.Partition:
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package log
|
||||
import (
|
||||
"os"
|
||||
|
||||
xlog "github.com/masahiro331/go-xfs-filesystem/log"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"golang.org/x/xerrors"
|
||||
@@ -36,6 +37,9 @@ func InitLogger(debug, disable bool) (err error) {
|
||||
// Set logger for fanal
|
||||
flog.SetLogger(Logger)
|
||||
|
||||
// Set logger for go-xfs-filesystem
|
||||
xlog.SetLogger(Logger)
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
flocal "github.com/aquasecurity/trivy/pkg/fanal/artifact/local"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact/remote"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact/sbom"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact/vm"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/image"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
@@ -64,6 +65,12 @@ var StandaloneSBOMSet = wire.NewSet(
|
||||
StandaloneSuperSet,
|
||||
)
|
||||
|
||||
// StandaloneVMSet binds vm dependencies
|
||||
var StandaloneVMSet = wire.NewSet(
|
||||
vm.NewArtifact,
|
||||
StandaloneSuperSet,
|
||||
)
|
||||
|
||||
/////////////////
|
||||
// Client/Server
|
||||
/////////////////
|
||||
@@ -88,6 +95,12 @@ var RemoteSBOMSet = wire.NewSet(
|
||||
RemoteSuperSet,
|
||||
)
|
||||
|
||||
// RemoteVMSet binds vm dependencies for client/server mode
|
||||
var RemoteVMSet = wire.NewSet(
|
||||
vm.NewArtifact,
|
||||
RemoteSuperSet,
|
||||
)
|
||||
|
||||
// RemoteDockerSet binds remote docker dependencies
|
||||
var RemoteDockerSet = wire.NewSet(
|
||||
aimage.NewArtifact,
|
||||
|
||||
30
pkg/semaphore/semaphore.go
Normal file
30
pkg/semaphore/semaphore.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package semaphore
|
||||
|
||||
import "golang.org/x/sync/semaphore"
|
||||
|
||||
const defaultSize = 5
|
||||
|
||||
type options struct {
|
||||
size int64
|
||||
}
|
||||
|
||||
type option func(*options)
|
||||
|
||||
func WithDefault(n int64) option {
|
||||
return func(opts *options) {
|
||||
opts.size = defaultSize
|
||||
}
|
||||
}
|
||||
|
||||
func New(slow bool, opts ...option) *semaphore.Weighted {
|
||||
o := &options{size: defaultSize}
|
||||
for _, opt := range opts {
|
||||
opt(o)
|
||||
}
|
||||
if slow {
|
||||
// Process in series
|
||||
return semaphore.NewWeighted(1)
|
||||
}
|
||||
// Process in parallel
|
||||
return semaphore.NewWeighted(o.size)
|
||||
}
|
||||
Reference in New Issue
Block a user