Skip to content

Commit 7999c5c

Browse files
authored
Merge pull request #13 from scality/feature/add-source-iso-for-image-sbom
Feature/add source iso for image SBOM
2 parents 26128f7 + 87b44ef commit 7999c5c

File tree

6 files changed

+107
-21
lines changed

6 files changed

+107
-21
lines changed

README.md

Lines changed: 82 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ using [Syft](https://github.com/anchore/syft).
99
## Basic Usage
1010

1111
```yaml
12-
- uses: scality/sbom@v1
12+
- uses: scality/sbom@v1.2.2
1313
with:
1414
target: ./
1515
```
1616
1717
This will create SBOM result files based on type, ex:
1818
1919
- repo_sbom_v1.1.0-4-gd6cdf1f.json
20-
- repo_sbom_v1.2.0.json
21-
- image_nginx_latest.json
20+
- repo_sbom_v1.2.2.json
21+
- image_myiso.iso_nginx_latest.json
2222
- iso_myiso.iso_128.json
2323
2424
If you want to scan a repository, you have to checkout it with `fetch-tags`.
@@ -39,9 +39,9 @@ The main [SBOM action](action.yml), responsible for generating SBOMs.
3939

4040
| Parameter | Description | Default |
4141
| --------------------------- | ------------------------------------------------------------------------------------- | ---------------------- |
42-
| `grype-version` | Grype version to use | 0.77.2 |
43-
| `sfyt-version` | Syft version to use | 1.2.0 |
44-
| `trivy-version` | Trivy version to use | 0.50.1 |
42+
| `grype-version` | Grype version to use | 0.77.3 |
43+
| `sfyt-version` | Syft version to use | 1.3.0 |
44+
| `trivy-version` | Trivy version to use | 0.51.1 |
4545
| `target` | A file/directory/iso on the filesystem to scan. | \<current directory> |
4646
| `format` | Format of SBOM file. | cyclonedx-json |
4747
| `name` | Name of the target, if you need to overwrite the detected. | |
@@ -57,7 +57,7 @@ The main [SBOM action](action.yml), responsible for generating SBOMs.
5757
Use the `path` parameter, relative to the repository root:
5858

5959
```yaml
60-
- uses: scality/sbom@v1
60+
- uses: scality/sbom@v1.2.2
6161
with:
6262
target: ./artifacts
6363
format: cyclonedx-json
@@ -69,7 +69,7 @@ Images created with Oras for example have custom mediatype and are not usable
6969
by Skopeo, they have to be excluded.
7070

7171
```yaml
72-
- uses: scality/sbom@v1
72+
- uses: scality/sbom@v1.2.2
7373
with:
7474
target: ./images
7575
exclude_mediatypes: "application/grafana-dashboard+json text/nginx-conf-template"
@@ -102,7 +102,7 @@ jobs:
102102
fetch-tags: true
103103
path: ${{ env.BASE_PATH }}/repo/myrepo
104104
- name: Generate sbom for repository
105-
uses: scality/sbom@v1.2.0
105+
uses: scality/sbom@v1.2.2
106106
with:
107107
target: ${{ env.BASE_PATH }}/repo/myrepo
108108
output-dir: ${{ env.SBOM_PATH }}
@@ -124,10 +124,10 @@ jobs:
124124
echo "Downloading my.iso from $ARTIFACTS_URL"
125125
curl -sSfL -o ${{ env.BASE_PATH }}/iso/my.iso -u $ARTIFACTS_USER:$ARTIFACTS_PASSWORD $ARTIFACTS_URL/my.iso
126126
- name: Generate sbom for ISO
127-
uses: scality/sbom@v1.2.0
127+
uses: scality/sbom@v1.2.2
128128
with:
129129
target: ${{ env.BASE_PATH }}/iso/my.iso
130-
version: "1.0.0" # Make sure to replace this with the actual ISO version
130+
version: "1.0.0" # Make sure to replace this with the actual ISO version to avoid undefined in you SBOM
131131
output-dir: ${{ env.SBOM_PATH }}
132132
- name: Generate archive
133133
shell: bash
@@ -151,6 +151,77 @@ jobs:
151151
source: artifacts
152152
```
153153

154+
## CycloneDX metadata
155+
156+
In generated SBOM you will find this metadata:
157+
158+
- for images contains in ISO:
159+
160+
```json
161+
{
162+
"$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
163+
"bomFormat": "CycloneDX",
164+
"specVersion": "1.5",
165+
"serialNumber": "urn:uuid:984d102d-0992-4dae-be80-ba551bc2079a",
166+
"version": 1,
167+
"metadata": {
168+
"timestamp": "2024-05-07T09:43:34Z",
169+
"tools": {
170+
"components": [
171+
{
172+
"type": "application",
173+
"author": "anchore",
174+
"name": "syft",
175+
"version": "1.3.0"
176+
}
177+
]
178+
},
179+
"component": {
180+
"bom-ref": "1b58496ca93cc57d",
181+
"type": "container",
182+
"name": "my.iso:alpine", // composed by iso_source_name:image_name
183+
"version": "1.1.1" // image_version
184+
}
185+
},
186+
...
187+
```
188+
189+
- for ISO:
190+
191+
```json
192+
{
193+
"$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
194+
"bomFormat": "CycloneDX",
195+
"specVersion": "1.5",
196+
"serialNumber": "urn:uuid:db2bc22b-a5e5-49a9-9d02-61a18480ead4",
197+
"version": 1,
198+
"metadata": {
199+
"timestamp": "2024-05-07T09:41:46Z",
200+
"tools": {
201+
"components": [
202+
{
203+
"type": "application",
204+
"author": "anchore",
205+
"name": "syft",
206+
"version": "1.3.0"
207+
}
208+
]
209+
},
210+
"component": {
211+
"bom-ref": "4a057776eee09e2f",
212+
"type": "file",
213+
"name": "my.iso", // ISO basename calculated by target var
214+
"version": "undefined" // for ISO if version is not provided, you will get undefined
215+
}
216+
}
217+
}
218+
```
219+
220+
-
221+
## Know issue
222+
223+
- scanning a repo present in `/tmp` will not work. Syft doesn't use right catalogers in this path. An issue is open [here](https://github.com/anchore/syft/issues/2847)
224+
154225
## References
155226

156227
HTML template for **Grype** results visualisation was slightly modified from [Grype Contrib](https://github.com/opt-nc/grype-contribs).

TODO.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# SBOM
2+
3+
Future releases will include this features.
4+
5+
### Todo
6+
7+
- [ ] Add detection of image directory
8+
- [ ] add detection in detect.py
9+
- [ ] switch to convert.py if necessary
10+
- [ ] migrate some code for image scanning in main.py to another module for cleanning code
11+
12+
### In Progress
13+
14+
### Done ✓

src/lib/detect.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ def is_git_repo(target):
1616
except exc.InvalidGitRepositoryError:
1717
return False
1818

19-
def get_repo_name():
19+
def get_repo_name(target):
2020
"""
2121
## Get the name of a git repository.
2222
### Args:
2323
target (str): The path to the git repository.
2424
"""
25-
name = Repo(".").remotes.origin.url.split(".git")[0].split("/")[-1]
25+
name = Repo(target).remotes.origin.url.split(".git")[0].split("/")[-1]
2626
return name
2727

2828
def get_repo_version(target):
@@ -55,9 +55,10 @@ def detect_target_type(target):
5555
elif os.path.isdir(target):
5656
target_type = "directory"
5757
print("Detected directory.")
58+
print(f"Provided target: {target}")
5859
if is_git_repo(target):
5960
version = get_repo_version(target)
60-
name = get_repo_name()
61+
name = get_repo_name(target)
6162
target_type = "git"
6263
print(f"Detected git repository: {name}, version: {version}")
6364
else:

src/lib/install.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from pyunpack import Archive
88

99
# Define the scanners and their versions
10-
scanners = {"syft": "1.2.0", "grype": "0.77.2", "trivy": "0.50.1"}
10+
scanners = {"syft": "1.3.0", "grype": "0.77.3", "trivy": "0.51.1"}
1111

1212
# Define the base URLs for the scanners
1313
ANCHORE_BASE_URL = (

src/lib/scan.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def __init__(
2626
self.output_file_prefix = output_file_prefix
2727
self.output_file = (
2828
f"{self.sbom_format}={self.output_dir}/"
29-
f"{self.output_file_prefix}_{self.name}_{self.version}.json"
29+
f"{self.output_file_prefix}_{self.name.replace(':', '_')}_{self.version}.json"
3030
)
3131

3232
def execute(self):

src/main.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@
133133
detect_image_origin(subdir_path)
134134
# get source iso basename
135135
source_iso = os.path.basename(extracted_dir)
136-
IMAGE_FILE_PREFIX=f"{OUTPUT_FILE_PREFIX}_{source_iso}"
136+
IMAGE_NAME_COMPLETE=f"{source_iso}:{image_name}"
137137
EXCLUDED = check_mediatype(
138138
subdir_path, excluded_mediatypes
139139
)
@@ -145,10 +145,10 @@
145145
scan_command = ScanCommand(
146146
target=f"{CONVERT_DIR}/{image_name}_{image_version}",
147147
target_type="oci-dir",
148-
name=image_name,
148+
name=IMAGE_NAME_COMPLETE,
149149
version=image_version,
150150
output_dir=OUTPUT_DIR,
151-
output_file_prefix=IMAGE_FILE_PREFIX,
151+
output_file_prefix=OUTPUT_FILE_PREFIX,
152152
sbom_format=SBOM_FORMAT,
153153
)
154154
scan_command.execute()
@@ -157,10 +157,10 @@
157157
scan_command = ScanCommand(
158158
target=f"{subdir_path}",
159159
target_type="dir",
160-
name=image_name,
160+
name=IMAGE_NAME_COMPLETE,
161161
version=image_version,
162162
output_dir=OUTPUT_DIR,
163-
output_file_prefix=IMAGE_FILE_PREFIX,
163+
output_file_prefix=OUTPUT_FILE_PREFIX,
164164
sbom_format=SBOM_FORMAT,
165165
)
166166
scan_command.execute()

0 commit comments

Comments
 (0)