mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 08:23:15 +01:00
Upgrade generic cataloger (#1281)
* add second generation of generic cataloger Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * upgrade aplm cataloger to use generic.Cataloger Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * remove pacakge found-by attribute from the definition of a package ID Signed-off-by: Alex Goodman <alex.goodman@anchore.com> Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
parent
7a8b96abc2
commit
b44f441c82
@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"bomFormat": "CycloneDX",
|
"bomFormat": "CycloneDX",
|
||||||
"specVersion": "1.4",
|
"specVersion": "1.4",
|
||||||
"serialNumber": "urn:uuid:3ea3363f-3945-4859-9ba1-9a395983d248",
|
"serialNumber": "urn:uuid:f426926b-4867-4b52-9142-23997f685f2c",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"timestamp": "2022-05-23T12:05:00-07:00",
|
"timestamp": "2022-10-24T09:54:37-04:00",
|
||||||
"tools": [
|
"tools": [
|
||||||
{
|
{
|
||||||
"vendor": "anchore",
|
"vendor": "anchore",
|
||||||
@ -20,7 +20,7 @@
|
|||||||
},
|
},
|
||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
"bom-ref": "b85dbb4e6ece5082",
|
"bom-ref": "e624319940d8d36a",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"name": "package-1",
|
"name": "package-1",
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@ -57,7 +57,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bom-ref": "pkg:deb/debian/package-2@2.0.1?package-id=ceda99598967ae8d",
|
"bom-ref": "pkg:deb/debian/package-2@2.0.1?package-id=b8645f4ac2a0891e",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"name": "package-2",
|
"name": "package-2",
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"bomFormat": "CycloneDX",
|
"bomFormat": "CycloneDX",
|
||||||
"specVersion": "1.4",
|
"specVersion": "1.4",
|
||||||
"serialNumber": "urn:uuid:c825402b-bbfa-4ad5-81b1-6a8332a6a8b6",
|
"serialNumber": "urn:uuid:41bbbcc7-694d-4b07-a678-0afb67dabdf9",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"timestamp": "2022-05-23T12:05:01-07:00",
|
"timestamp": "2022-10-24T09:54:37-04:00",
|
||||||
"tools": [
|
"tools": [
|
||||||
{
|
{
|
||||||
"vendor": "anchore",
|
"vendor": "anchore",
|
||||||
@ -13,7 +13,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"component": {
|
"component": {
|
||||||
"bom-ref": "e779c1ed804ba529",
|
"bom-ref": "522dc6b135a55bb4",
|
||||||
"type": "container",
|
"type": "container",
|
||||||
"name": "user-image-input",
|
"name": "user-image-input",
|
||||||
"version": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368"
|
"version": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368"
|
||||||
@ -21,7 +21,7 @@
|
|||||||
},
|
},
|
||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
"bom-ref": "2a46171f91c8d4bc",
|
"bom-ref": "5ffee24fb164cffc",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"name": "package-1",
|
"name": "package-1",
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@ -53,7 +53,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "syft:location:0:layerID",
|
"name": "syft:location:0:layerID",
|
||||||
"value": "sha256:cd8f3884f1211d65c19ce5bbc5174bcd2ce8ba96b63e5b3693969a53279c4405"
|
"value": "sha256:fb6beecb75b39f4bb813dbf177e501edd5ddb3e69bb45cedeb78c676ee1b7a59"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "syft:location:0:path",
|
"name": "syft:location:0:path",
|
||||||
@ -62,7 +62,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bom-ref": "pkg:deb/debian/package-2@2.0.1?package-id=ae77680e9b1d087e",
|
"bom-ref": "pkg:deb/debian/package-2@2.0.1?package-id=8b16570b2b4155c3",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"name": "package-2",
|
"name": "package-2",
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
@ -83,7 +83,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "syft:location:0:layerID",
|
"name": "syft:location:0:layerID",
|
||||||
"value": "sha256:42d2ea51c688e6dc7be81a305acbe006d27a6ef0c26ae3888fd0d4ce44f69265"
|
"value": "sha256:319b588ce64253a87b533c8ed01cf0025e0eac98e7b516e12532957e1244fdec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "syft:location:0:path",
|
"name": "syft:location:0:path",
|
||||||
|
|||||||
Binary file not shown.
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<bom xmlns="http://cyclonedx.org/schema/bom/1.4" serialNumber="urn:uuid:a259c072-aaaf-4a3f-a707-49f691b1e9d9" version="1">
|
<bom xmlns="http://cyclonedx.org/schema/bom/1.4" serialNumber="urn:uuid:19df9583-d8b7-4683-81a6-e57cc8841321" version="1">
|
||||||
<metadata>
|
<metadata>
|
||||||
<timestamp>2022-05-23T12:02:41-07:00</timestamp>
|
<timestamp>2022-10-24T09:54:54-04:00</timestamp>
|
||||||
<tools>
|
<tools>
|
||||||
<tool>
|
<tool>
|
||||||
<vendor>anchore</vendor>
|
<vendor>anchore</vendor>
|
||||||
@ -14,7 +14,7 @@
|
|||||||
</component>
|
</component>
|
||||||
</metadata>
|
</metadata>
|
||||||
<components>
|
<components>
|
||||||
<component bom-ref="b85dbb4e6ece5082" type="library">
|
<component bom-ref="e624319940d8d36a" type="library">
|
||||||
<name>package-1</name>
|
<name>package-1</name>
|
||||||
<version>1.0.1</version>
|
<version>1.0.1</version>
|
||||||
<licenses>
|
<licenses>
|
||||||
@ -32,7 +32,7 @@
|
|||||||
<property name="syft:location:0:path">/some/path/pkg1</property>
|
<property name="syft:location:0:path">/some/path/pkg1</property>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<component bom-ref="pkg:deb/debian/package-2@2.0.1?package-id=ceda99598967ae8d" type="library">
|
<component bom-ref="pkg:deb/debian/package-2@2.0.1?package-id=b8645f4ac2a0891e" type="library">
|
||||||
<name>package-2</name>
|
<name>package-2</name>
|
||||||
<version>2.0.1</version>
|
<version>2.0.1</version>
|
||||||
<cpe>cpe:2.3:*:some:package:2:*:*:*:*:*:*:*</cpe>
|
<cpe>cpe:2.3:*:some:package:2:*:*:*:*:*:*:*</cpe>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<bom xmlns="http://cyclonedx.org/schema/bom/1.4" serialNumber="urn:uuid:155802bd-09e5-4b95-9485-826b94447495" version="1">
|
<bom xmlns="http://cyclonedx.org/schema/bom/1.4" serialNumber="urn:uuid:5342511c-3580-4cae-b373-20bbf14ba7a3" version="1">
|
||||||
<metadata>
|
<metadata>
|
||||||
<timestamp>2022-05-23T12:02:42-07:00</timestamp>
|
<timestamp>2022-10-24T09:54:54-04:00</timestamp>
|
||||||
<tools>
|
<tools>
|
||||||
<tool>
|
<tool>
|
||||||
<vendor>anchore</vendor>
|
<vendor>anchore</vendor>
|
||||||
@ -9,13 +9,13 @@
|
|||||||
<version>v0.42.0-bogus</version>
|
<version>v0.42.0-bogus</version>
|
||||||
</tool>
|
</tool>
|
||||||
</tools>
|
</tools>
|
||||||
<component bom-ref="e779c1ed804ba529" type="container">
|
<component bom-ref="522dc6b135a55bb4" type="container">
|
||||||
<name>user-image-input</name>
|
<name>user-image-input</name>
|
||||||
<version>sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368</version>
|
<version>sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368</version>
|
||||||
</component>
|
</component>
|
||||||
</metadata>
|
</metadata>
|
||||||
<components>
|
<components>
|
||||||
<component bom-ref="2a46171f91c8d4bc" type="library">
|
<component bom-ref="5ffee24fb164cffc" type="library">
|
||||||
<name>package-1</name>
|
<name>package-1</name>
|
||||||
<version>1.0.1</version>
|
<version>1.0.1</version>
|
||||||
<licenses>
|
<licenses>
|
||||||
@ -30,11 +30,11 @@
|
|||||||
<property name="syft:package:language">python</property>
|
<property name="syft:package:language">python</property>
|
||||||
<property name="syft:package:metadataType">PythonPackageMetadata</property>
|
<property name="syft:package:metadataType">PythonPackageMetadata</property>
|
||||||
<property name="syft:package:type">python</property>
|
<property name="syft:package:type">python</property>
|
||||||
<property name="syft:location:0:layerID">sha256:cd8f3884f1211d65c19ce5bbc5174bcd2ce8ba96b63e5b3693969a53279c4405</property>
|
<property name="syft:location:0:layerID">sha256:fb6beecb75b39f4bb813dbf177e501edd5ddb3e69bb45cedeb78c676ee1b7a59</property>
|
||||||
<property name="syft:location:0:path">/somefile-1.txt</property>
|
<property name="syft:location:0:path">/somefile-1.txt</property>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<component bom-ref="pkg:deb/debian/package-2@2.0.1?package-id=ae77680e9b1d087e" type="library">
|
<component bom-ref="pkg:deb/debian/package-2@2.0.1?package-id=8b16570b2b4155c3" type="library">
|
||||||
<name>package-2</name>
|
<name>package-2</name>
|
||||||
<version>2.0.1</version>
|
<version>2.0.1</version>
|
||||||
<cpe>cpe:2.3:*:some:package:2:*:*:*:*:*:*:*</cpe>
|
<cpe>cpe:2.3:*:some:package:2:*:*:*:*:*:*:*</cpe>
|
||||||
@ -43,7 +43,7 @@
|
|||||||
<property name="syft:package:foundBy">the-cataloger-2</property>
|
<property name="syft:package:foundBy">the-cataloger-2</property>
|
||||||
<property name="syft:package:metadataType">DpkgMetadata</property>
|
<property name="syft:package:metadataType">DpkgMetadata</property>
|
||||||
<property name="syft:package:type">deb</property>
|
<property name="syft:package:type">deb</property>
|
||||||
<property name="syft:location:0:layerID">sha256:42d2ea51c688e6dc7be81a305acbe006d27a6ef0c26ae3888fd0d4ce44f69265</property>
|
<property name="syft:location:0:layerID">sha256:319b588ce64253a87b533c8ed01cf0025e0eac98e7b516e12532957e1244fdec</property>
|
||||||
<property name="syft:location:0:path">/somefile-2.txt</property>
|
<property name="syft:location:0:path">/somefile-2.txt</property>
|
||||||
<property name="syft:metadata:installedSize">0</property>
|
<property name="syft:metadata:installedSize">0</property>
|
||||||
</properties>
|
</properties>
|
||||||
|
|||||||
Binary file not shown.
@ -3,18 +3,18 @@
|
|||||||
"name": "/some/path",
|
"name": "/some/path",
|
||||||
"spdxVersion": "SPDX-2.2",
|
"spdxVersion": "SPDX-2.2",
|
||||||
"creationInfo": {
|
"creationInfo": {
|
||||||
"created": "2022-05-23T19:10:22.25645Z",
|
"created": "2022-10-24T13:54:19.225779Z",
|
||||||
"creators": [
|
"creators": [
|
||||||
"Organization: Anchore, Inc",
|
"Organization: Anchore, Inc",
|
||||||
"Tool: syft-v0.42.0-bogus"
|
"Tool: syft-v0.42.0-bogus"
|
||||||
],
|
],
|
||||||
"licenseListVersion": "3.17"
|
"licenseListVersion": "3.18"
|
||||||
},
|
},
|
||||||
"dataLicense": "CC0-1.0",
|
"dataLicense": "CC0-1.0",
|
||||||
"documentNamespace": "https://anchore.com/syft/dir/some/path-81dbcbfa-251d-4ad5-9b01-be91afb16469",
|
"documentNamespace": "https://anchore.com/syft/dir/some/path-cd89c782-240b-461e-81a1-63863e02642f",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"SPDXID": "SPDXRef-b85dbb4e6ece5082",
|
"SPDXID": "SPDXRef-e624319940d8d36a",
|
||||||
"name": "package-1",
|
"name": "package-1",
|
||||||
"licenseConcluded": "MIT",
|
"licenseConcluded": "MIT",
|
||||||
"downloadLocation": "NOASSERTION",
|
"downloadLocation": "NOASSERTION",
|
||||||
@ -36,7 +36,7 @@
|
|||||||
"versionInfo": "1.0.1"
|
"versionInfo": "1.0.1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"SPDXID": "SPDXRef-ceda99598967ae8d",
|
"SPDXID": "SPDXRef-b8645f4ac2a0891e",
|
||||||
"name": "package-2",
|
"name": "package-2",
|
||||||
"licenseConcluded": "NONE",
|
"licenseConcluded": "NONE",
|
||||||
"downloadLocation": "NOASSERTION",
|
"downloadLocation": "NOASSERTION",
|
||||||
|
|||||||
@ -3,18 +3,18 @@
|
|||||||
"name": "user-image-input",
|
"name": "user-image-input",
|
||||||
"spdxVersion": "SPDX-2.2",
|
"spdxVersion": "SPDX-2.2",
|
||||||
"creationInfo": {
|
"creationInfo": {
|
||||||
"created": "2022-05-23T19:10:22.412847Z",
|
"created": "2022-10-24T13:54:19.477217Z",
|
||||||
"creators": [
|
"creators": [
|
||||||
"Organization: Anchore, Inc",
|
"Organization: Anchore, Inc",
|
||||||
"Tool: syft-v0.42.0-bogus"
|
"Tool: syft-v0.42.0-bogus"
|
||||||
],
|
],
|
||||||
"licenseListVersion": "3.17"
|
"licenseListVersion": "3.18"
|
||||||
},
|
},
|
||||||
"dataLicense": "CC0-1.0",
|
"dataLicense": "CC0-1.0",
|
||||||
"documentNamespace": "https://anchore.com/syft/image/user-image-input-c9945597-78ce-4e9b-89d2-68b8e4e4ccb9",
|
"documentNamespace": "https://anchore.com/syft/image/user-image-input-0b40ce75-7e54-4760-bd9d-4fa833b352dd",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"SPDXID": "SPDXRef-2a46171f91c8d4bc",
|
"SPDXID": "SPDXRef-5ffee24fb164cffc",
|
||||||
"name": "package-1",
|
"name": "package-1",
|
||||||
"licenseConcluded": "MIT",
|
"licenseConcluded": "MIT",
|
||||||
"downloadLocation": "NOASSERTION",
|
"downloadLocation": "NOASSERTION",
|
||||||
@ -36,7 +36,7 @@
|
|||||||
"versionInfo": "1.0.1"
|
"versionInfo": "1.0.1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"SPDXID": "SPDXRef-ae77680e9b1d087e",
|
"SPDXID": "SPDXRef-8b16570b2b4155c3",
|
||||||
"name": "package-2",
|
"name": "package-2",
|
||||||
"licenseConcluded": "NONE",
|
"licenseConcluded": "NONE",
|
||||||
"downloadLocation": "NOASSERTION",
|
"downloadLocation": "NOASSERTION",
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
"name": "user-image-input",
|
"name": "user-image-input",
|
||||||
"spdxVersion": "SPDX-2.2",
|
"spdxVersion": "SPDX-2.2",
|
||||||
"creationInfo": {
|
"creationInfo": {
|
||||||
"created": "2022-09-19T18:39:05.841331Z",
|
"created": "2022-10-24T13:54:19.48428Z",
|
||||||
"creators": [
|
"creators": [
|
||||||
"Organization: Anchore, Inc",
|
"Organization: Anchore, Inc",
|
||||||
"Tool: syft-v0.42.0-bogus"
|
"Tool: syft-v0.42.0-bogus"
|
||||||
@ -11,10 +11,10 @@
|
|||||||
"licenseListVersion": "3.18"
|
"licenseListVersion": "3.18"
|
||||||
},
|
},
|
||||||
"dataLicense": "CC0-1.0",
|
"dataLicense": "CC0-1.0",
|
||||||
"documentNamespace": "https://anchore.com/syft/image/user-image-input-6cf0595e-7d69-4990-aef5-8183b52023b9",
|
"documentNamespace": "https://anchore.com/syft/image/user-image-input-1a4dc179-1222-463c-b4e9-619131af7e97",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"SPDXID": "SPDXRef-2a46171f91c8d4bc",
|
"SPDXID": "SPDXRef-5ffee24fb164cffc",
|
||||||
"name": "package-1",
|
"name": "package-1",
|
||||||
"licenseConcluded": "MIT",
|
"licenseConcluded": "MIT",
|
||||||
"downloadLocation": "NOASSERTION",
|
"downloadLocation": "NOASSERTION",
|
||||||
@ -44,7 +44,7 @@
|
|||||||
"versionInfo": "1.0.1"
|
"versionInfo": "1.0.1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"SPDXID": "SPDXRef-ae77680e9b1d087e",
|
"SPDXID": "SPDXRef-8b16570b2b4155c3",
|
||||||
"name": "package-2",
|
"name": "package-2",
|
||||||
"licenseConcluded": "NONE",
|
"licenseConcluded": "NONE",
|
||||||
"downloadLocation": "NOASSERTION",
|
"downloadLocation": "NOASSERTION",
|
||||||
@ -118,32 +118,32 @@
|
|||||||
],
|
],
|
||||||
"relationships": [
|
"relationships": [
|
||||||
{
|
{
|
||||||
"spdxElementId": "SPDXRef-2a46171f91c8d4bc",
|
"spdxElementId": "SPDXRef-5ffee24fb164cffc",
|
||||||
"relationshipType": "CONTAINS",
|
"relationshipType": "CONTAINS",
|
||||||
"relatedSpdxElement": "SPDXRef-5265a4dde3edbf7c"
|
"relatedSpdxElement": "SPDXRef-5265a4dde3edbf7c"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"spdxElementId": "SPDXRef-2a46171f91c8d4bc",
|
"spdxElementId": "SPDXRef-5ffee24fb164cffc",
|
||||||
"relationshipType": "CONTAINS",
|
"relationshipType": "CONTAINS",
|
||||||
"relatedSpdxElement": "SPDXRef-839d99ee67d9d174"
|
"relatedSpdxElement": "SPDXRef-839d99ee67d9d174"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"spdxElementId": "SPDXRef-2a46171f91c8d4bc",
|
"spdxElementId": "SPDXRef-5ffee24fb164cffc",
|
||||||
"relationshipType": "CONTAINS",
|
"relationshipType": "CONTAINS",
|
||||||
"relatedSpdxElement": "SPDXRef-9c2f7510199b17f6"
|
"relatedSpdxElement": "SPDXRef-9c2f7510199b17f6"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"spdxElementId": "SPDXRef-2a46171f91c8d4bc",
|
"spdxElementId": "SPDXRef-5ffee24fb164cffc",
|
||||||
"relationshipType": "CONTAINS",
|
"relationshipType": "CONTAINS",
|
||||||
"relatedSpdxElement": "SPDXRef-c641caa71518099f"
|
"relatedSpdxElement": "SPDXRef-c641caa71518099f"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"spdxElementId": "SPDXRef-2a46171f91c8d4bc",
|
"spdxElementId": "SPDXRef-5ffee24fb164cffc",
|
||||||
"relationshipType": "CONTAINS",
|
"relationshipType": "CONTAINS",
|
||||||
"relatedSpdxElement": "SPDXRef-c6f5b29dca12661f"
|
"relatedSpdxElement": "SPDXRef-c6f5b29dca12661f"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"spdxElementId": "SPDXRef-2a46171f91c8d4bc",
|
"spdxElementId": "SPDXRef-5ffee24fb164cffc",
|
||||||
"relationshipType": "CONTAINS",
|
"relationshipType": "CONTAINS",
|
||||||
"relatedSpdxElement": "SPDXRef-f9e49132a4b96ccd"
|
"relatedSpdxElement": "SPDXRef-f9e49132a4b96ccd"
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@ -2,16 +2,16 @@ SPDXVersion: SPDX-2.2
|
|||||||
DataLicense: CC0-1.0
|
DataLicense: CC0-1.0
|
||||||
SPDXID: SPDXRef-DOCUMENT
|
SPDXID: SPDXRef-DOCUMENT
|
||||||
DocumentName: .
|
DocumentName: .
|
||||||
DocumentNamespace: https://anchore.com/syft/dir/bdb67358-651c-4dd8-b5ee-5318936eb16a
|
DocumentNamespace: https://anchore.com/syft/dir/4593d944-756e-49aa-af4e-b1a5acf09b97
|
||||||
LicenseListVersion: 3.17
|
LicenseListVersion: 3.18
|
||||||
Creator: Organization: Anchore, Inc
|
Creator: Organization: Anchore, Inc
|
||||||
Creator: Tool: syft-v0.42.0-bogus
|
Creator: Tool: syft-v0.42.0-bogus
|
||||||
Created: 2022-06-07T19:33:39Z
|
Created: 2022-10-24T13:53:53Z
|
||||||
|
|
||||||
##### Package: @at-sign
|
##### Package: @at-sign
|
||||||
|
|
||||||
PackageName: @at-sign
|
PackageName: @at-sign
|
||||||
SPDXID: SPDXRef-Package---at-sign-739e4f0d93fb8298
|
SPDXID: SPDXRef-Package---at-sign-fe69bc18c2698fc4
|
||||||
PackageDownloadLocation: NOASSERTION
|
PackageDownloadLocation: NOASSERTION
|
||||||
FilesAnalyzed: false
|
FilesAnalyzed: false
|
||||||
PackageLicenseConcluded: NONE
|
PackageLicenseConcluded: NONE
|
||||||
@ -21,7 +21,7 @@ PackageCopyrightText: NOASSERTION
|
|||||||
##### Package: some/slashes
|
##### Package: some/slashes
|
||||||
|
|
||||||
PackageName: some/slashes
|
PackageName: some/slashes
|
||||||
SPDXID: SPDXRef-Package--some-slashes-26db06648b24bff9
|
SPDXID: SPDXRef-Package--some-slashes-57ed206c09e6e5f4
|
||||||
PackageDownloadLocation: NOASSERTION
|
PackageDownloadLocation: NOASSERTION
|
||||||
FilesAnalyzed: false
|
FilesAnalyzed: false
|
||||||
PackageLicenseConcluded: NONE
|
PackageLicenseConcluded: NONE
|
||||||
@ -31,7 +31,7 @@ PackageCopyrightText: NOASSERTION
|
|||||||
##### Package: under_scores
|
##### Package: under_scores
|
||||||
|
|
||||||
PackageName: under_scores
|
PackageName: under_scores
|
||||||
SPDXID: SPDXRef-Package--under-scores-250cbfefcdea318b
|
SPDXID: SPDXRef-Package--under-scores-8b7505907fdaf19d
|
||||||
PackageDownloadLocation: NOASSERTION
|
PackageDownloadLocation: NOASSERTION
|
||||||
FilesAnalyzed: false
|
FilesAnalyzed: false
|
||||||
PackageLicenseConcluded: NONE
|
PackageLicenseConcluded: NONE
|
||||||
|
|||||||
@ -2,16 +2,16 @@ SPDXVersion: SPDX-2.2
|
|||||||
DataLicense: CC0-1.0
|
DataLicense: CC0-1.0
|
||||||
SPDXID: SPDXRef-DOCUMENT
|
SPDXID: SPDXRef-DOCUMENT
|
||||||
DocumentName: /some/path
|
DocumentName: /some/path
|
||||||
DocumentNamespace: https://anchore.com/syft/dir/some/path-c6b20d03-1478-4513-9feb-1ec427d4b547
|
DocumentNamespace: https://anchore.com/syft/dir/some/path-a4e58523-00d0-4135-9d21-cf586fbd340c
|
||||||
LicenseListVersion: 3.17
|
LicenseListVersion: 3.18
|
||||||
Creator: Organization: Anchore, Inc
|
Creator: Organization: Anchore, Inc
|
||||||
Creator: Tool: syft-v0.42.0-bogus
|
Creator: Tool: syft-v0.42.0-bogus
|
||||||
Created: 2022-05-24T22:51:02Z
|
Created: 2022-10-24T13:53:52Z
|
||||||
|
|
||||||
##### Package: package-2
|
##### Package: package-2
|
||||||
|
|
||||||
PackageName: package-2
|
PackageName: package-2
|
||||||
SPDXID: SPDXRef-Package-deb-package-2-ceda99598967ae8d
|
SPDXID: SPDXRef-Package-deb-package-2-b8645f4ac2a0891e
|
||||||
PackageVersion: 2.0.1
|
PackageVersion: 2.0.1
|
||||||
PackageDownloadLocation: NOASSERTION
|
PackageDownloadLocation: NOASSERTION
|
||||||
FilesAnalyzed: false
|
FilesAnalyzed: false
|
||||||
@ -24,7 +24,7 @@ ExternalRef: PACKAGE_MANAGER purl pkg:deb/debian/package-2@2.0.1
|
|||||||
##### Package: package-1
|
##### Package: package-1
|
||||||
|
|
||||||
PackageName: package-1
|
PackageName: package-1
|
||||||
SPDXID: SPDXRef-Package-python-package-1-b85dbb4e6ece5082
|
SPDXID: SPDXRef-Package-python-package-1-e624319940d8d36a
|
||||||
PackageVersion: 1.0.1
|
PackageVersion: 1.0.1
|
||||||
PackageDownloadLocation: NOASSERTION
|
PackageDownloadLocation: NOASSERTION
|
||||||
FilesAnalyzed: false
|
FilesAnalyzed: false
|
||||||
|
|||||||
@ -2,16 +2,16 @@ SPDXVersion: SPDX-2.2
|
|||||||
DataLicense: CC0-1.0
|
DataLicense: CC0-1.0
|
||||||
SPDXID: SPDXRef-DOCUMENT
|
SPDXID: SPDXRef-DOCUMENT
|
||||||
DocumentName: user-image-input
|
DocumentName: user-image-input
|
||||||
DocumentNamespace: https://anchore.com/syft/image/user-image-input-12a877bc-fe9b-40ef-aa9c-4d34f108d0d6
|
DocumentNamespace: https://anchore.com/syft/image/user-image-input-639f628a-5f8b-4050-a69e-90c85f0d7837
|
||||||
LicenseListVersion: 3.17
|
LicenseListVersion: 3.18
|
||||||
Creator: Organization: Anchore, Inc
|
Creator: Organization: Anchore, Inc
|
||||||
Creator: Tool: syft-v0.42.0-bogus
|
Creator: Tool: syft-v0.42.0-bogus
|
||||||
Created: 2022-05-24T22:51:02Z
|
Created: 2022-10-24T13:53:53Z
|
||||||
|
|
||||||
##### Package: package-2
|
##### Package: package-2
|
||||||
|
|
||||||
PackageName: package-2
|
PackageName: package-2
|
||||||
SPDXID: SPDXRef-Package-deb-package-2-ae77680e9b1d087e
|
SPDXID: SPDXRef-Package-deb-package-2-8b16570b2b4155c3
|
||||||
PackageVersion: 2.0.1
|
PackageVersion: 2.0.1
|
||||||
PackageDownloadLocation: NOASSERTION
|
PackageDownloadLocation: NOASSERTION
|
||||||
FilesAnalyzed: false
|
FilesAnalyzed: false
|
||||||
@ -24,7 +24,7 @@ ExternalRef: PACKAGE_MANAGER purl pkg:deb/debian/package-2@2.0.1
|
|||||||
##### Package: package-1
|
##### Package: package-1
|
||||||
|
|
||||||
PackageName: package-1
|
PackageName: package-1
|
||||||
SPDXID: SPDXRef-Package-python-package-1-2a46171f91c8d4bc
|
SPDXID: SPDXRef-Package-python-package-1-5ffee24fb164cffc
|
||||||
PackageVersion: 1.0.1
|
PackageVersion: 1.0.1
|
||||||
PackageDownloadLocation: NOASSERTION
|
PackageDownloadLocation: NOASSERTION
|
||||||
FilesAnalyzed: false
|
FilesAnalyzed: false
|
||||||
|
|||||||
Binary file not shown.
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"artifacts": [
|
"artifacts": [
|
||||||
{
|
{
|
||||||
"id": "b85dbb4e6ece5082",
|
"id": "e624319940d8d36a",
|
||||||
"name": "package-1",
|
"name": "package-1",
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"type": "python",
|
"type": "python",
|
||||||
@ -36,7 +36,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ceda99598967ae8d",
|
"id": "b8645f4ac2a0891e",
|
||||||
"name": "package-2",
|
"name": "package-2",
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"type": "deb",
|
"type": "deb",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"artifacts": [
|
"artifacts": [
|
||||||
{
|
{
|
||||||
"id": "b3fa3ee64756b0c6",
|
"id": "8373dcf05581b932",
|
||||||
"name": "package-1",
|
"name": "package-1",
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"type": "python",
|
"type": "python",
|
||||||
@ -31,7 +31,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "b324f4d9ee5413fe",
|
"id": "c3d4da40f387eec7",
|
||||||
"name": "package-2",
|
"name": "package-2",
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"type": "deb",
|
"type": "deb",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"artifacts": [
|
"artifacts": [
|
||||||
{
|
{
|
||||||
"id": "2a46171f91c8d4bc",
|
"id": "5ffee24fb164cffc",
|
||||||
"name": "package-1",
|
"name": "package-1",
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"type": "python",
|
"type": "python",
|
||||||
@ -9,7 +9,7 @@
|
|||||||
"locations": [
|
"locations": [
|
||||||
{
|
{
|
||||||
"path": "/somefile-1.txt",
|
"path": "/somefile-1.txt",
|
||||||
"layerID": "sha256:4965affaf42a7174561882c5fd87e2db6f0b07df532459ba86f98a8bd2af11de"
|
"layerID": "sha256:fb6beecb75b39f4bb813dbf177e501edd5ddb3e69bb45cedeb78c676ee1b7a59"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"licenses": [
|
"licenses": [
|
||||||
@ -32,7 +32,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ae77680e9b1d087e",
|
"id": "8b16570b2b4155c3",
|
||||||
"name": "package-2",
|
"name": "package-2",
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"type": "deb",
|
"type": "deb",
|
||||||
@ -40,7 +40,7 @@
|
|||||||
"locations": [
|
"locations": [
|
||||||
{
|
{
|
||||||
"path": "/somefile-2.txt",
|
"path": "/somefile-2.txt",
|
||||||
"layerID": "sha256:460c3e27be163efe75df048c4d4cf3a22e7e363f02521fa2e82a3bd257a682d4"
|
"layerID": "sha256:319b588ce64253a87b533c8ed01cf0025e0eac98e7b516e12532957e1244fdec"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"licenses": [],
|
"licenses": [],
|
||||||
@ -64,11 +64,11 @@
|
|||||||
],
|
],
|
||||||
"artifactRelationships": [],
|
"artifactRelationships": [],
|
||||||
"source": {
|
"source": {
|
||||||
"id": "00afea0209d754683fdfcdd47cfea94ec9f2e81286be444e297a8c776c4accbf",
|
"id": "1a678f111c8ddc66fd82687bb024e0dd6af61314404937a80e810c0cf317b796",
|
||||||
"type": "image",
|
"type": "image",
|
||||||
"target": {
|
"target": {
|
||||||
"userInput": "user-image-input",
|
"userInput": "user-image-input",
|
||||||
"imageID": "sha256:6b1b476e6dc187bb688566606cf7a59d7804d81169967d8c6bb121627b0a387f",
|
"imageID": "sha256:3c51b06feb0cda8ee62d0e3755ef2a8496a6b71f8a55b245f07f31c4bb813d31",
|
||||||
"manifestDigest": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368",
|
"manifestDigest": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368",
|
||||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -78,17 +78,17 @@
|
|||||||
"layers": [
|
"layers": [
|
||||||
{
|
{
|
||||||
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||||
"digest": "sha256:4965affaf42a7174561882c5fd87e2db6f0b07df532459ba86f98a8bd2af11de",
|
"digest": "sha256:fb6beecb75b39f4bb813dbf177e501edd5ddb3e69bb45cedeb78c676ee1b7a59",
|
||||||
"size": 22
|
"size": 22
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||||
"digest": "sha256:460c3e27be163efe75df048c4d4cf3a22e7e363f02521fa2e82a3bd257a682d4",
|
"digest": "sha256:319b588ce64253a87b533c8ed01cf0025e0eac98e7b516e12532957e1244fdec",
|
||||||
"size": 16
|
"size": 16
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"manifest": "eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjo2NzMsImRpZ2VzdCI6InNoYTI1Njo2YjFiNDc2ZTZkYzE4N2JiNjg4NTY2NjA2Y2Y3YTU5ZDc4MDRkODExNjk5NjdkOGM2YmIxMjE2MjdiMGEzODdmIn0sImxheWVycyI6W3sibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tlci5pbWFnZS5yb290ZnMuZGlmZi50YXIuZ3ppcCIsInNpemUiOjIwNDgsImRpZ2VzdCI6InNoYTI1Njo0OTY1YWZmYWY0MmE3MTc0NTYxODgyYzVmZDg3ZTJkYjZmMGIwN2RmNTMyNDU5YmE4NmY5OGE4YmQyYWYxMWRlIn0seyJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmltYWdlLnJvb3Rmcy5kaWZmLnRhci5nemlwIiwic2l6ZSI6MjA0OCwiZGlnZXN0Ijoic2hhMjU2OjQ2MGMzZTI3YmUxNjNlZmU3NWRmMDQ4YzRkNGNmM2EyMmU3ZTM2M2YwMjUyMWZhMmU4MmEzYmQyNTdhNjgyZDQifV19",
|
"manifest": "eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjo2NzMsImRpZ2VzdCI6InNoYTI1NjozYzUxYjA2ZmViMGNkYThlZTYyZDBlMzc1NWVmMmE4NDk2YTZiNzFmOGE1NWIyNDVmMDdmMzFjNGJiODEzZDMxIn0sImxheWVycyI6W3sibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tlci5pbWFnZS5yb290ZnMuZGlmZi50YXIuZ3ppcCIsInNpemUiOjIwNDgsImRpZ2VzdCI6InNoYTI1NjpmYjZiZWVjYjc1YjM5ZjRiYjgxM2RiZjE3N2U1MDFlZGQ1ZGRiM2U2OWJiNDVjZWRlYjc4YzY3NmVlMWI3YTU5In0seyJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmltYWdlLnJvb3Rmcy5kaWZmLnRhci5nemlwIiwic2l6ZSI6MjA0OCwiZGlnZXN0Ijoic2hhMjU2OjMxOWI1ODhjZTY0MjUzYTg3YjUzM2M4ZWQwMWNmMDAyNWUwZWFjOThlN2I1MTZlMTI1MzI5NTdlMTI0NGZkZWMifV19",
|
||||||
"config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiV29ya2luZ0RpciI6Ii8iLCJPbkJ1aWxkIjpudWxsfSwiY3JlYXRlZCI6IjIwMjItMTAtMDVUMTQ6MjQ6NTguNzc0NTY2MjM2WiIsImhpc3RvcnkiOlt7ImNyZWF0ZWQiOiIyMDIyLTEwLTA1VDE0OjI0OjU4Ljc0NDY3NTEyOVoiLCJjcmVhdGVkX2J5IjoiQUREIGZpbGUtMS50eHQgL3NvbWVmaWxlLTEudHh0ICMgYnVpbGRraXQiLCJjb21tZW50IjoiYnVpbGRraXQuZG9ja2VyZmlsZS52MCJ9LHsiY3JlYXRlZCI6IjIwMjItMTAtMDVUMTQ6MjQ6NTguNzc0NTY2MjM2WiIsImNyZWF0ZWRfYnkiOiJBREQgZmlsZS0yLnR4dCAvc29tZWZpbGUtMi50eHQgIyBidWlsZGtpdCIsImNvbW1lbnQiOiJidWlsZGtpdC5kb2NrZXJmaWxlLnYwIn1dLCJvcyI6ImxpbnV4Iiwicm9vdGZzIjp7InR5cGUiOiJsYXllcnMiLCJkaWZmX2lkcyI6WyJzaGEyNTY6NDk2NWFmZmFmNDJhNzE3NDU2MTg4MmM1ZmQ4N2UyZGI2ZjBiMDdkZjUzMjQ1OWJhODZmOThhOGJkMmFmMTFkZSIsInNoYTI1Njo0NjBjM2UyN2JlMTYzZWZlNzVkZjA0OGM0ZDRjZjNhMjJlN2UzNjNmMDI1MjFmYTJlODJhM2JkMjU3YTY4MmQ0Il19fQ==",
|
"config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiV29ya2luZ0RpciI6Ii8iLCJPbkJ1aWxkIjpudWxsfSwiY3JlYXRlZCI6IjIwMjItMDgtMDFUMjA6MDk6MjIuNTA5NDIxNzEyWiIsImhpc3RvcnkiOlt7ImNyZWF0ZWQiOiIyMDIyLTA4LTAxVDIwOjA5OjIyLjQ4Nzg5NTUxOVoiLCJjcmVhdGVkX2J5IjoiQUREIGZpbGUtMS50eHQgL3NvbWVmaWxlLTEudHh0ICMgYnVpbGRraXQiLCJjb21tZW50IjoiYnVpbGRraXQuZG9ja2VyZmlsZS52MCJ9LHsiY3JlYXRlZCI6IjIwMjItMDgtMDFUMjA6MDk6MjIuNTA5NDIxNzEyWiIsImNyZWF0ZWRfYnkiOiJBREQgZmlsZS0yLnR4dCAvc29tZWZpbGUtMi50eHQgIyBidWlsZGtpdCIsImNvbW1lbnQiOiJidWlsZGtpdC5kb2NrZXJmaWxlLnYwIn1dLCJvcyI6ImxpbnV4Iiwicm9vdGZzIjp7InR5cGUiOiJsYXllcnMiLCJkaWZmX2lkcyI6WyJzaGEyNTY6ZmI2YmVlY2I3NWIzOWY0YmI4MTNkYmYxNzdlNTAxZWRkNWRkYjNlNjliYjQ1Y2VkZWI3OGM2NzZlZTFiN2E1OSIsInNoYTI1NjozMTliNTg4Y2U2NDI1M2E4N2I1MzNjOGVkMDFjZjAwMjVlMGVhYzk4ZTdiNTE2ZTEyNTMyOTU3ZTEyNDRmZGVjIl19fQ==",
|
||||||
"repoDigests": [],
|
"repoDigests": [],
|
||||||
"architecture": "",
|
"architecture": "",
|
||||||
"os": ""
|
"os": ""
|
||||||
|
|||||||
Binary file not shown.
@ -55,30 +55,32 @@ var identityFiles = []parseEntry{
|
|||||||
|
|
||||||
// IdentifyRelease parses distro-specific files to discover and raise linux distribution release details.
|
// IdentifyRelease parses distro-specific files to discover and raise linux distribution release details.
|
||||||
func IdentifyRelease(resolver source.FileResolver) *Release {
|
func IdentifyRelease(resolver source.FileResolver) *Release {
|
||||||
|
logger := log.Nested("operation", "identify-release")
|
||||||
for _, entry := range identityFiles {
|
for _, entry := range identityFiles {
|
||||||
locations, err := resolver.FilesByPath(entry.path)
|
locations, err := resolver.FilesByPath(entry.path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("unable to get path locations from %s: %+v", entry.path, err)
|
logger.WithFields("error", err, "path", entry.path).Trace("unable to get path")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, location := range locations {
|
for _, location := range locations {
|
||||||
contentReader, err := resolver.FileContentsByLocation(location)
|
contentReader, err := resolver.FileContentsByLocation(location)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("unable to get contents from %s: %s", entry.path, err)
|
logger.WithFields("error", err, "path", location.RealPath).Trace("unable to get contents")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
content, err := io.ReadAll(contentReader)
|
content, err := io.ReadAll(contentReader)
|
||||||
internal.CloseAndLogError(contentReader, location.VirtualPath)
|
internal.CloseAndLogError(contentReader, location.VirtualPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("unable to read %q: %+v", location.RealPath, err)
|
logger.WithFields("error", err, "path", location.RealPath).Trace("unable to read contents")
|
||||||
break
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
release, err := entry.fn(string(content))
|
release, err := entry.fn(string(content))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("unable to parse %q", location.RealPath)
|
logger.WithFields("error", err, "path", location.RealPath).Trace("unable to parse contents")
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if release != nil {
|
if release != nil {
|
||||||
|
|||||||
@ -6,11 +6,11 @@ import (
|
|||||||
|
|
||||||
"github.com/scylladb/go-set/strset"
|
"github.com/scylladb/go-set/strset"
|
||||||
|
|
||||||
"github.com/anchore/packageurl-go"
|
|
||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
"github.com/anchore/syft/syft/linux"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var _ FileOwner = (*AlpmMetadata)(nil)
|
||||||
|
|
||||||
const AlpmDBGlob = "**/var/lib/pacman/local/**/desc"
|
const AlpmDBGlob = "**/var/lib/pacman/local/**/desc"
|
||||||
|
|
||||||
type AlpmMetadata struct {
|
type AlpmMetadata struct {
|
||||||
@ -40,34 +40,6 @@ type AlpmFileRecord struct {
|
|||||||
Digests []file.Digest `mapstructure:"digests" json:"digest,omitempty"`
|
Digests []file.Digest `mapstructure:"digests" json:"digest,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PackageURL returns the PURL for the specific Arch Linux package (see https://github.com/package-url/purl-spec)
|
|
||||||
func (m AlpmMetadata) PackageURL(distro *linux.Release) string {
|
|
||||||
qualifiers := map[string]string{
|
|
||||||
PURLQualifierArch: m.Architecture,
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.BasePackage != "" {
|
|
||||||
qualifiers[PURLQualifierUpstream] = m.BasePackage
|
|
||||||
}
|
|
||||||
|
|
||||||
distroID := ""
|
|
||||||
if distro != nil {
|
|
||||||
distroID = distro.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
return packageurl.NewPackageURL(
|
|
||||||
"alpm",
|
|
||||||
distroID,
|
|
||||||
m.Package,
|
|
||||||
m.Version,
|
|
||||||
purlQualifiers(
|
|
||||||
qualifiers,
|
|
||||||
distro,
|
|
||||||
),
|
|
||||||
"",
|
|
||||||
).ToString()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m AlpmMetadata) OwnedFiles() (result []string) {
|
func (m AlpmMetadata) OwnedFiles() (result []string) {
|
||||||
s := strset.New()
|
s := strset.New()
|
||||||
for _, f := range m.Files {
|
for _, f := range m.Files {
|
||||||
|
|||||||
@ -65,7 +65,7 @@ func (m ApkMetadata) PackageURL(distro *linux.Release) string {
|
|||||||
"",
|
"",
|
||||||
m.Package,
|
m.Package,
|
||||||
m.Version,
|
m.Version,
|
||||||
purlQualifiers(
|
PURLQualifiers(
|
||||||
qualifiers,
|
qualifiers,
|
||||||
distro,
|
distro,
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,48 +1,13 @@
|
|||||||
package alpm
|
package alpm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/anchore/syft/internal"
|
|
||||||
"github.com/anchore/syft/syft/artifact"
|
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
"github.com/anchore/syft/syft/source"
|
"github.com/anchore/syft/syft/pkg/cataloger/generic"
|
||||||
)
|
)
|
||||||
|
|
||||||
const catalogerName = "alpmdb-cataloger"
|
const catalogerName = "alpmdb-cataloger"
|
||||||
|
|
||||||
type Cataloger struct{}
|
func NewAlpmdbCataloger() *generic.Cataloger {
|
||||||
|
return generic.NewCataloger(catalogerName).
|
||||||
// NewAlpmdbCataloger returns a new ALPM DB cataloger object.
|
WithParserByGlobs(parseAlpmDB, pkg.AlpmDBGlob)
|
||||||
func NewAlpmdbCataloger() *Cataloger {
|
|
||||||
return &Cataloger{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns a string that uniquely describes a cataloger
|
|
||||||
func (c *Cataloger) Name() string {
|
|
||||||
return catalogerName
|
|
||||||
}
|
|
||||||
|
|
||||||
// Catalog is given an object to resolve file references and content, this function returns any discovered Packages after analyzing rpm db installation.
|
|
||||||
func (c *Cataloger) Catalog(resolver source.FileResolver) ([]pkg.Package, []artifact.Relationship, error) {
|
|
||||||
fileMatches, err := resolver.FilesByGlob(pkg.AlpmDBGlob)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("failed to find rpmdb's by glob: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var pkgs []pkg.Package
|
|
||||||
for _, location := range fileMatches {
|
|
||||||
dbContentReader, err := resolver.FileContentsByLocation(location)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
discoveredPkgs, err := parseAlpmDB(resolver, location.RealPath, dbContentReader)
|
|
||||||
internal.CloseAndLogError(dbContentReader, location.VirtualPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("unable to catalog package=%+v: %w", location.RealPath, err)
|
|
||||||
}
|
|
||||||
pkgs = append(pkgs, discoveredPkgs...)
|
|
||||||
}
|
|
||||||
return pkgs, nil, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
52
syft/pkg/cataloger/alpm/package.go
Normal file
52
syft/pkg/cataloger/alpm/package.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package alpm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/anchore/packageurl-go"
|
||||||
|
"github.com/anchore/syft/syft/linux"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/source"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newPackage(m pkg.AlpmMetadata, release *linux.Release, locations ...source.Location) pkg.Package {
|
||||||
|
p := pkg.Package{
|
||||||
|
Name: m.Package,
|
||||||
|
Version: m.Version,
|
||||||
|
Locations: source.NewLocationSet(locations...),
|
||||||
|
Type: pkg.AlpmPkg,
|
||||||
|
Licenses: strings.Split(m.License, " "),
|
||||||
|
PURL: packageURL(m, release),
|
||||||
|
MetadataType: pkg.AlpmMetadataType,
|
||||||
|
Metadata: m,
|
||||||
|
}
|
||||||
|
p.SetID()
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func packageURL(m pkg.AlpmMetadata, distro *linux.Release) string {
|
||||||
|
if distro == nil || distro.ID != "arch" {
|
||||||
|
// note: there is no namespace variation (like with debian ID_LIKE for ubuntu ID, for example)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
qualifiers := map[string]string{
|
||||||
|
pkg.PURLQualifierArch: m.Architecture,
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.BasePackage != "" {
|
||||||
|
qualifiers[pkg.PURLQualifierUpstream] = m.BasePackage
|
||||||
|
}
|
||||||
|
|
||||||
|
return packageurl.NewPackageURL(
|
||||||
|
"alpm", // `alpm` for Arch Linux and other users of the libalpm/pacman package manager. (see https://github.com/package-url/purl-spec/pull/164)
|
||||||
|
distro.ID,
|
||||||
|
m.Package,
|
||||||
|
m.Version,
|
||||||
|
pkg.PURLQualifiers(
|
||||||
|
qualifiers,
|
||||||
|
distro,
|
||||||
|
),
|
||||||
|
"",
|
||||||
|
).ToString()
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package pkg
|
package alpm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
@ -7,18 +7,32 @@ import (
|
|||||||
|
|
||||||
"github.com/anchore/packageurl-go"
|
"github.com/anchore/packageurl-go"
|
||||||
"github.com/anchore/syft/syft/linux"
|
"github.com/anchore/syft/syft/linux"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAlpmMetadata_pURL(t *testing.T) {
|
func Test_PackageURL(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
metadata AlpmMetadata
|
metadata pkg.AlpmMetadata
|
||||||
distro linux.Release
|
distro linux.Release
|
||||||
expected string
|
expected string
|
||||||
}{
|
}{
|
||||||
|
{
|
||||||
|
name: "bad distro id",
|
||||||
|
metadata: pkg.AlpmMetadata{
|
||||||
|
Package: "p",
|
||||||
|
Version: "v",
|
||||||
|
Architecture: "a",
|
||||||
|
},
|
||||||
|
distro: linux.Release{
|
||||||
|
ID: "something-else",
|
||||||
|
BuildID: "rolling",
|
||||||
|
},
|
||||||
|
expected: "",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "gocase",
|
name: "gocase",
|
||||||
metadata: AlpmMetadata{
|
metadata: pkg.AlpmMetadata{
|
||||||
Package: "p",
|
Package: "p",
|
||||||
Version: "v",
|
Version: "v",
|
||||||
Architecture: "a",
|
Architecture: "a",
|
||||||
@ -31,7 +45,7 @@ func TestAlpmMetadata_pURL(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "missing architecture",
|
name: "missing architecture",
|
||||||
metadata: AlpmMetadata{
|
metadata: pkg.AlpmMetadata{
|
||||||
Package: "p",
|
Package: "p",
|
||||||
Version: "v",
|
Version: "v",
|
||||||
},
|
},
|
||||||
@ -41,7 +55,7 @@ func TestAlpmMetadata_pURL(t *testing.T) {
|
|||||||
expected: "pkg:alpm/arch/p@v?distro=arch",
|
expected: "pkg:alpm/arch/p@v?distro=arch",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
metadata: AlpmMetadata{
|
metadata: pkg.AlpmMetadata{
|
||||||
Package: "python",
|
Package: "python",
|
||||||
Version: "3.10.0",
|
Version: "3.10.0",
|
||||||
Architecture: "any",
|
Architecture: "any",
|
||||||
@ -53,7 +67,7 @@ func TestAlpmMetadata_pURL(t *testing.T) {
|
|||||||
expected: "pkg:alpm/arch/python@3.10.0?arch=any&distro=arch-rolling",
|
expected: "pkg:alpm/arch/python@3.10.0?arch=any&distro=arch-rolling",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
metadata: AlpmMetadata{
|
metadata: pkg.AlpmMetadata{
|
||||||
Package: "g plus plus",
|
Package: "g plus plus",
|
||||||
Version: "v84",
|
Version: "v84",
|
||||||
Architecture: "x86_64",
|
Architecture: "x86_64",
|
||||||
@ -66,7 +80,7 @@ func TestAlpmMetadata_pURL(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "add source information as qualifier",
|
name: "add source information as qualifier",
|
||||||
metadata: AlpmMetadata{
|
metadata: pkg.AlpmMetadata{
|
||||||
Package: "p",
|
Package: "p",
|
||||||
Version: "v",
|
Version: "v",
|
||||||
Architecture: "a",
|
Architecture: "a",
|
||||||
@ -82,12 +96,17 @@ func TestAlpmMetadata_pURL(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
actual := test.metadata.PackageURL(&test.distro)
|
actual := packageURL(test.metadata, &test.distro)
|
||||||
if actual != test.expected {
|
if actual != test.expected {
|
||||||
dmp := diffmatchpatch.New()
|
dmp := diffmatchpatch.New()
|
||||||
diffs := dmp.DiffMain(test.expected, actual, true)
|
diffs := dmp.DiffMain(test.expected, actual, true)
|
||||||
t.Errorf("diff: %s", dmp.DiffPrettyText(diffs))
|
t.Errorf("diff: %s", dmp.DiffPrettyText(diffs))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if test.expected == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// verify packageurl can parse
|
// verify packageurl can parse
|
||||||
purl, err := packageurl.FromString(actual)
|
purl, err := packageurl.FromString(actual)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -13,11 +13,15 @@ import (
|
|||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
"github.com/vbatts/go-mtree"
|
"github.com/vbatts/go-mtree"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/artifact"
|
||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/pkg/cataloger/generic"
|
||||||
"github.com/anchore/syft/syft/source"
|
"github.com/anchore/syft/syft/source"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var _ generic.Parser = parseAlpmDB
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ignoredFiles = map[string]bool{
|
ignoredFiles = map[string]bool{
|
||||||
"/set": true,
|
"/set": true,
|
||||||
@ -27,16 +31,50 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func newAlpmDBPackage(d *pkg.AlpmMetadata) *pkg.Package {
|
func parseAlpmDB(resolver source.FileResolver, env *generic.Environment, reader source.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
return &pkg.Package{
|
metadata, err := parseAlpmDBEntry(reader)
|
||||||
Name: d.Package,
|
if err != nil {
|
||||||
Version: d.Version,
|
return nil, nil, err
|
||||||
FoundBy: catalogerName,
|
|
||||||
Type: "alpm",
|
|
||||||
Licenses: strings.Split(d.License, " "),
|
|
||||||
MetadataType: pkg.AlpmMetadataType,
|
|
||||||
Metadata: *d,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base := filepath.Dir(reader.RealPath)
|
||||||
|
r, err := getFileReader(filepath.Join(base, "mtree"), resolver)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
pkgFiles, err := parseMtree(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
// The replace the files found the the pacman database with the files from the mtree These contain more metadata and
|
||||||
|
// thus more useful.
|
||||||
|
metadata.Files = pkgFiles
|
||||||
|
|
||||||
|
// We only really do this to get any backup database entries from the files database
|
||||||
|
files := filepath.Join(base, "files")
|
||||||
|
_, err = getFileReader(files, resolver)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
filesMetadata, err := parseAlpmDBEntry(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
} else if filesMetadata != nil {
|
||||||
|
metadata.Backup = filesMetadata.Backup
|
||||||
|
}
|
||||||
|
|
||||||
|
return []pkg.Package{
|
||||||
|
newPackage(*metadata, env.LinuxRelease, reader.Location),
|
||||||
|
}, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseAlpmDBEntry(reader io.Reader) (*pkg.AlpmMetadata, error) {
|
||||||
|
scanner := newScanner(reader)
|
||||||
|
metadata, err := parseDatabase(scanner)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return metadata, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newScanner(reader io.Reader) *bufio.Scanner {
|
func newScanner(reader io.Reader) *bufio.Scanner {
|
||||||
@ -194,53 +232,3 @@ func parseMtree(r io.Reader) ([]pkg.AlpmFileRecord, error) {
|
|||||||
}
|
}
|
||||||
return entries, nil
|
return entries, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseAlpmDBEntry(reader io.Reader) (*pkg.AlpmMetadata, error) {
|
|
||||||
scanner := newScanner(reader)
|
|
||||||
metadata, err := parseDatabase(scanner)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if metadata == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return metadata, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseAlpmDB(resolver source.FileResolver, desc string, reader io.Reader) ([]pkg.Package, error) {
|
|
||||||
metadata, err := parseAlpmDBEntry(reader)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
base := filepath.Dir(desc)
|
|
||||||
mtree := filepath.Join(base, "mtree")
|
|
||||||
r, err := getFileReader(mtree, resolver)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pkgFiles, err := parseMtree(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// The replace the files found the the pacman database with the files from the mtree These contain more metadata and
|
|
||||||
// thus more useful.
|
|
||||||
metadata.Files = pkgFiles
|
|
||||||
|
|
||||||
// We only really do this to get any backup database entries from the files database
|
|
||||||
files := filepath.Join(base, "files")
|
|
||||||
_, err = getFileReader(files, resolver)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
filesMetadata, err := parseAlpmDBEntry(reader)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else if filesMetadata != nil {
|
|
||||||
metadata.Backup = filesMetadata.Backup
|
|
||||||
}
|
|
||||||
|
|
||||||
p := *newAlpmDBPackage(metadata)
|
|
||||||
p.SetID()
|
|
||||||
return []pkg.Package{p}, nil
|
|
||||||
}
|
|
||||||
|
|||||||
151
syft/pkg/cataloger/generic/cataloger.go
Normal file
151
syft/pkg/cataloger/generic/cataloger.go
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
package generic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/anchore/syft/internal"
|
||||||
|
"github.com/anchore/syft/internal/log"
|
||||||
|
"github.com/anchore/syft/syft/artifact"
|
||||||
|
"github.com/anchore/syft/syft/linux"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/source"
|
||||||
|
)
|
||||||
|
|
||||||
|
type processor func(resolver source.FileResolver, env Environment) []request
|
||||||
|
|
||||||
|
type request struct {
|
||||||
|
source.Location
|
||||||
|
Parser
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cataloger implements the Catalog interface and is responsible for dispatching the proper parser function for
|
||||||
|
// a given path or glob pattern. This is intended to be reusable across many package cataloger types.
|
||||||
|
type Cataloger struct {
|
||||||
|
processor []processor
|
||||||
|
upstreamCataloger string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cataloger) WithParserByGlobs(parser Parser, globs ...string) *Cataloger {
|
||||||
|
c.processor = append(c.processor,
|
||||||
|
func(resolver source.FileResolver, env Environment) []request {
|
||||||
|
var requests []request
|
||||||
|
for _, g := range globs {
|
||||||
|
// TODO: add more trace logging here
|
||||||
|
matches, err := resolver.FilesByGlob(g)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("unable to process glob=%q: %+v", g, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
requests = append(requests, makeRequests(parser, matches)...)
|
||||||
|
}
|
||||||
|
return requests
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cataloger) WithParserByMimeTypes(parser Parser, types ...string) *Cataloger {
|
||||||
|
c.processor = append(c.processor,
|
||||||
|
func(resolver source.FileResolver, env Environment) []request {
|
||||||
|
var requests []request
|
||||||
|
for _, t := range types {
|
||||||
|
// TODO: add more trace logging here
|
||||||
|
matches, err := resolver.FilesByMIMEType(t)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("unable to process mimetype=%q: %+v", t, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
requests = append(requests, makeRequests(parser, matches)...)
|
||||||
|
}
|
||||||
|
return requests
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cataloger) WithParserByPath(parser Parser, paths ...string) *Cataloger {
|
||||||
|
c.processor = append(c.processor,
|
||||||
|
func(resolver source.FileResolver, env Environment) []request {
|
||||||
|
var requests []request
|
||||||
|
for _, g := range paths {
|
||||||
|
// TODO: add more trace logging here
|
||||||
|
matches, err := resolver.FilesByPath(g)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("unable to process path=%q: %+v", g, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
requests = append(requests, makeRequests(parser, matches)...)
|
||||||
|
}
|
||||||
|
return requests
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeRequests(parser Parser, locations []source.Location) []request {
|
||||||
|
var requests []request
|
||||||
|
for _, l := range locations {
|
||||||
|
requests = append(requests, request{
|
||||||
|
Location: l,
|
||||||
|
Parser: parser,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return requests
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCataloger if provided path-to-parser-function and glob-to-parser-function lookups creates a Cataloger
|
||||||
|
func NewCataloger(upstreamCataloger string) *Cataloger {
|
||||||
|
return &Cataloger{
|
||||||
|
upstreamCataloger: upstreamCataloger,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns a string that uniquely describes the upstream cataloger that this Generic Cataloger represents.
|
||||||
|
func (c *Cataloger) Name() string {
|
||||||
|
return c.upstreamCataloger
|
||||||
|
}
|
||||||
|
|
||||||
|
// Catalog is given an object to resolve file references and content, this function returns any discovered Packages after analyzing the catalog source.
|
||||||
|
func (c *Cataloger) Catalog(resolver source.FileResolver) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
|
var packages []pkg.Package
|
||||||
|
var relationships []artifact.Relationship
|
||||||
|
|
||||||
|
logger := log.Nested("cataloger", c.upstreamCataloger)
|
||||||
|
|
||||||
|
env := Environment{
|
||||||
|
// TODO: consider passing into the cataloger, this would affect the cataloger interface (and all implementations). This can be deferred until later.
|
||||||
|
LinuxRelease: linux.IdentifyRelease(resolver),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, req := range c.selectFiles(resolver) {
|
||||||
|
location, parser := req.Location, req.Parser
|
||||||
|
|
||||||
|
contentReader, err := resolver.FileContentsByLocation(location)
|
||||||
|
if err != nil {
|
||||||
|
logger.WithFields("location", location.RealPath, "error", err).Warn("unable to fetch contents")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
discoveredPackages, discoveredRelationships, err := parser(resolver, &env, source.NewLocationReadCloser(location, contentReader))
|
||||||
|
internal.CloseAndLogError(contentReader, location.VirtualPath)
|
||||||
|
if err != nil {
|
||||||
|
logger.WithFields("location", location.RealPath, "error", err).Warnf("cataloger failed")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range discoveredPackages {
|
||||||
|
p.FoundBy = c.upstreamCataloger
|
||||||
|
packages = append(packages, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
relationships = append(relationships, discoveredRelationships...)
|
||||||
|
}
|
||||||
|
return packages, relationships, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// selectFiles takes a set of file trees and resolves and file references of interest for future cataloging
|
||||||
|
func (c *Cataloger) selectFiles(resolver source.FileResolver) []request {
|
||||||
|
var requests []request
|
||||||
|
for _, proc := range c.processor {
|
||||||
|
requests = append(requests, proc(resolver, Environment{})...)
|
||||||
|
}
|
||||||
|
return requests
|
||||||
|
}
|
||||||
87
syft/pkg/cataloger/generic/cataloger_test.go
Normal file
87
syft/pkg/cataloger/generic/cataloger_test.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package generic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/artifact"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/source"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Cataloger(t *testing.T) {
|
||||||
|
allParsedPaths := make(map[string]bool)
|
||||||
|
parser := func(resolver source.FileResolver, env *Environment, reader source.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
|
allParsedPaths[reader.AccessPath()] = true
|
||||||
|
contents, err := ioutil.ReadAll(reader)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if len(contents) == 0 {
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
p := pkg.Package{
|
||||||
|
Name: string(contents),
|
||||||
|
Locations: source.NewLocationSet(reader.Location),
|
||||||
|
}
|
||||||
|
r := artifact.Relationship{
|
||||||
|
From: p,
|
||||||
|
To: p,
|
||||||
|
Type: artifact.ContainsRelationship,
|
||||||
|
}
|
||||||
|
|
||||||
|
return []pkg.Package{p}, []artifact.Relationship{r}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream := "some-other-cataloger"
|
||||||
|
|
||||||
|
expectedSelection := []string{"test-fixtures/last/path.txt", "test-fixtures/another-path.txt", "test-fixtures/a-path.txt", "test-fixtures/empty.txt"}
|
||||||
|
resolver := source.NewMockResolverForPaths(expectedSelection...)
|
||||||
|
cataloger := NewCataloger(upstream).
|
||||||
|
WithParserByPath(parser, "test-fixtures/another-path.txt", "test-fixtures/last/path.txt").
|
||||||
|
WithParserByGlobs(parser, "**/a-path.txt", "**/empty.txt")
|
||||||
|
|
||||||
|
actualPkgs, relationships, err := cataloger.Catalog(resolver)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
expectedPkgs := make(map[string]pkg.Package)
|
||||||
|
for _, path := range expectedSelection {
|
||||||
|
require.True(t, allParsedPaths[path])
|
||||||
|
if path == "test-fixtures/empty.txt" {
|
||||||
|
continue // note: empty.txt won't become a package
|
||||||
|
}
|
||||||
|
expectedPkgs[path] = pkg.Package{
|
||||||
|
FoundBy: upstream,
|
||||||
|
Name: fmt.Sprintf("%s file contents!", path),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Len(t, allParsedPaths, len(expectedSelection))
|
||||||
|
assert.Len(t, actualPkgs, len(expectedPkgs))
|
||||||
|
assert.Len(t, relationships, len(actualPkgs))
|
||||||
|
|
||||||
|
for _, p := range actualPkgs {
|
||||||
|
ls := p.Locations.ToSlice()
|
||||||
|
require.NotEmpty(t, ls)
|
||||||
|
ref := ls[0]
|
||||||
|
exP, ok := expectedPkgs[ref.RealPath]
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("missing expected pkg: ref=%+v", ref)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// assigned by the generic cataloger
|
||||||
|
if p.FoundBy != exP.FoundBy {
|
||||||
|
t.Errorf("bad upstream: %s", p.FoundBy)
|
||||||
|
}
|
||||||
|
|
||||||
|
// assigned by the parser
|
||||||
|
if exP.Name != p.Name {
|
||||||
|
t.Errorf("bad contents mapping: %+v", p.Locations)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
syft/pkg/cataloger/generic/parser.go
Normal file
14
syft/pkg/cataloger/generic/parser.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package generic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/anchore/syft/syft/artifact"
|
||||||
|
"github.com/anchore/syft/syft/linux"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/source"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Environment struct {
|
||||||
|
LinuxRelease *linux.Release
|
||||||
|
}
|
||||||
|
|
||||||
|
type Parser func(source.FileResolver, *Environment, source.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error)
|
||||||
1
syft/pkg/cataloger/generic/test-fixtures/a-path.txt
Normal file
1
syft/pkg/cataloger/generic/test-fixtures/a-path.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
test-fixtures/a-path.txt file contents!
|
||||||
@ -0,0 +1 @@
|
|||||||
|
test-fixtures/another-path.txt file contents!
|
||||||
0
syft/pkg/cataloger/generic/test-fixtures/empty.txt
Normal file
0
syft/pkg/cataloger/generic/test-fixtures/empty.txt
Normal file
1
syft/pkg/cataloger/generic/test-fixtures/last/path.txt
Normal file
1
syft/pkg/cataloger/generic/test-fixtures/last/path.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
test-fixtures/last/path.txt file contents!
|
||||||
@ -65,7 +65,7 @@ func (m DpkgMetadata) PackageURL(distro *linux.Release) string {
|
|||||||
namespace,
|
namespace,
|
||||||
m.Package,
|
m.Package,
|
||||||
m.Version,
|
m.Version,
|
||||||
purlQualifiers(
|
PURLQualifiers(
|
||||||
qualifiers,
|
qualifiers,
|
||||||
distro,
|
distro,
|
||||||
),
|
),
|
||||||
|
|||||||
@ -17,7 +17,7 @@ type Package struct {
|
|||||||
id artifact.ID `hash:"ignore"`
|
id artifact.ID `hash:"ignore"`
|
||||||
Name string // the package name
|
Name string // the package name
|
||||||
Version string // the version of the package
|
Version string // the version of the package
|
||||||
FoundBy string `cyclonedx:"foundBy"` // the specific cataloger that discovered this package
|
FoundBy string `hash:"ignore" cyclonedx:"foundBy"` // the specific cataloger that discovered this package
|
||||||
Locations source.LocationSet // the locations that lead to the discovery of this package (note: this is not necessarily the locations that make up this package)
|
Locations source.LocationSet // the locations that lead to the discovery of this package (note: this is not necessarily the locations that make up this package)
|
||||||
Licenses []string // licenses discovered with the package metadata
|
Licenses []string // licenses discovered with the package metadata
|
||||||
Language Language `cyclonedx:"language"` // the language ecosystem this package belongs to (e.g. JavaScript, Python, etc)
|
Language Language `cyclonedx:"language"` // the language ecosystem this package belongs to (e.g. JavaScript, Python, etc)
|
||||||
|
|||||||
@ -190,14 +190,6 @@ func TestIDUniqueness(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expectedIDComparison: assert.NotEqual,
|
expectedIDComparison: assert.NotEqual,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "foundBy is reflected",
|
|
||||||
transform: func(pkg Package) Package {
|
|
||||||
pkg.FoundBy = "new!"
|
|
||||||
return pkg
|
|
||||||
},
|
|
||||||
expectedIDComparison: assert.NotEqual,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "metadata mutation is reflected",
|
name: "metadata mutation is reflected",
|
||||||
transform: func(pkg Package) Package {
|
transform: func(pkg Package) Package {
|
||||||
|
|||||||
@ -80,7 +80,7 @@ func (m RpmMetadata) PackageURL(distro *linux.Release) string {
|
|||||||
// for purl the epoch is a qualifier, not part of the version
|
// for purl the epoch is a qualifier, not part of the version
|
||||||
// see https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst under the RPM section
|
// see https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst under the RPM section
|
||||||
fmt.Sprintf("%s-%s", m.Version, m.Release),
|
fmt.Sprintf("%s-%s", m.Version, m.Release),
|
||||||
purlQualifiers(
|
PURLQualifiers(
|
||||||
qualifiers,
|
qualifiers,
|
||||||
distro,
|
distro,
|
||||||
),
|
),
|
||||||
|
|||||||
@ -67,7 +67,7 @@ func URL(p Package, release *linux.Release) string {
|
|||||||
).ToString()
|
).ToString()
|
||||||
}
|
}
|
||||||
|
|
||||||
func purlQualifiers(vars map[string]string, release *linux.Release) (q packageurl.Qualifiers) {
|
func PURLQualifiers(vars map[string]string, release *linux.Release) (q packageurl.Qualifiers) {
|
||||||
keys := make([]string, 0, len(vars))
|
keys := make([]string, 0, len(vars))
|
||||||
for k := range vars {
|
for k := range vars {
|
||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
|
|||||||
@ -200,24 +200,6 @@ func TestPackageURL(t *testing.T) {
|
|||||||
|
|
||||||
expected: "pkg:maven/g.id/a@v",
|
expected: "pkg:maven/g.id/a@v",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "alpm",
|
|
||||||
distro: &linux.Release{
|
|
||||||
ID: "arch",
|
|
||||||
BuildID: "rolling",
|
|
||||||
},
|
|
||||||
pkg: Package{
|
|
||||||
Name: "linux",
|
|
||||||
Version: "5.10.0",
|
|
||||||
Type: AlpmPkg,
|
|
||||||
Metadata: AlpmMetadata{
|
|
||||||
Package: "linux",
|
|
||||||
Version: "5.10.0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
expected: "pkg:alpm/arch/linux@5.10.0?distro=arch-rolling",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "cocoapods",
|
name: "cocoapods",
|
||||||
pkg: Package{
|
pkg: Package{
|
||||||
@ -288,6 +270,7 @@ func TestPackageURL(t *testing.T) {
|
|||||||
// testing microsoft packages is not valid for purl at this time
|
// testing microsoft packages is not valid for purl at this time
|
||||||
expectedTypes.Remove(string(KbPkg))
|
expectedTypes.Remove(string(KbPkg))
|
||||||
expectedTypes.Remove(string(PortagePkg))
|
expectedTypes.Remove(string(PortagePkg))
|
||||||
|
expectedTypes.Remove(string(AlpmPkg))
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
|||||||
@ -92,6 +92,13 @@ func NewVirtualLocationFromDirectory(responsePath, virtualResponsePath string, r
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l Location) AccessPath() string {
|
||||||
|
if l.VirtualPath != "" {
|
||||||
|
return l.VirtualPath
|
||||||
|
}
|
||||||
|
return l.RealPath
|
||||||
|
}
|
||||||
|
|
||||||
func (l Location) String() string {
|
func (l Location) String() string {
|
||||||
str := ""
|
str := ""
|
||||||
if l.ref.ID() != 0 {
|
if l.ref.ID() != 0 {
|
||||||
|
|||||||
15
syft/source/location_read_closer.go
Normal file
15
syft/source/location_read_closer.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package source
|
||||||
|
|
||||||
|
import "io"
|
||||||
|
|
||||||
|
type LocationReadCloser struct {
|
||||||
|
Location
|
||||||
|
io.ReadCloser
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLocationReadCloser(location Location, reader io.ReadCloser) LocationReadCloser {
|
||||||
|
return LocationReadCloser{
|
||||||
|
Location: location,
|
||||||
|
ReadCloser: reader,
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user