From bddc031e8c0ab455c315a54fff01257204c84c57 Mon Sep 17 00:00:00 2001 From: Andrea Frittoli Date: Sat, 25 Nov 2023 17:07:22 +0000 Subject: [PATCH 1/2] Add an SBOM URI field to artifact events Artifact packaged and/or published events may include a link to a published SBOM. Since there is no default storage location for such SBOM documents, CDEvents may help linking the artifact with its SBOM by including a link to the SBOM in the artifact events. Partially-addresses: #132 Signed-off-by: Andrea Frittoli --- continuous-integration.md | 10 ++++++++-- examples/artifact_packaged.json | 5 +++-- examples/artifact_published.json | 6 ++++-- schemas/artifactpackaged.json | 9 +++++++-- schemas/artifactpublished.json | 12 +++++++++--- tools/verify-examples.sh | 13 +++++++------ 6 files changed, 38 insertions(+), 17 deletions(-) diff --git a/continuous-integration.md b/continuous-integration.md index 34daf71c..e6f5403f 100644 --- a/continuous-integration.md +++ b/continuous-integration.md @@ -47,6 +47,7 @@ An `artifact` is usually produced as output of a build process. Events need to b | type | `String` | See [type](spec.md#type-subject) | `artifact` | | change | `object` | The change (tag, commit, revision) of the repository which was used to build the artifact" | `{"id": "527d4a1aca5e8d0df24813df5ad65d049fc8d312", "source": "my-git.example/an-org/a-repo"}`, `{"id": "feature1234", "source": "my-git.example/an-org/a-repo"}` | | signature | `string` | The signature of the artifact | `MEYCIQCBT8U5ypDXWCjlNKfzTV4KH516/SK13NZSh8znnSMNkQIhAJ3XiQlc9PM1KyjITcZXHotdMB+J3NGua5T/yshmiPmp` | +| sbom-uri | `URI-Reference` | The URI of the Software Bill of Material (SBOM) associated with the artifact | `https://sbom.storage.service/my-projects/3A0b31b1c02ff458ad9b7b81cbdf8f028bd54699fa151f221d1e8de6817db93427.sbom` | ## Events @@ -96,8 +97,9 @@ This event represents a Build task that has finished. This event will eventually ### [`artifact packaged`](examples/artifact_packaged.json) The event represents an artifact that has been packaged for distribution; this artifact is now versioned with a fixed version. +This event is usually produced by the build system. If an SBOM URI is available at this stage, it should be included. -- Event Type: __`dev.cdevents.artifact.packaged.0.1.1`__ +- Event Type: __`dev.cdevents.artifact.packaged.0.2.0-draft`__ - Predicate: packaged - Subject: [`artifact`](#artifact) @@ -107,12 +109,15 @@ The event represents an artifact that has been packaged for distribution; this a | source | `URI-Reference` | See [source](spec.md#source-subject) | | | | type | `String` | See [type](spec.md#type-subject) | `artifact` | | | change | `object` | The change (tag, commit, revision) of the repository which was used to build the artifact" | `{"id": "527d4a1aca5e8d0df24813df5ad65d049fc8d312", "source": "my-git.example/an-org/a-repo"}`, `{"id": "feature1234", "source": "my-git.example/an-org/a-repo"}` | ✅ | +| sbom-uri | `URI-Reference` | The URI of the Software Bill of Material (SBOM) associated with the artifact | `https://sbom.storage.service/my-projects/3A0b31b1c02ff458ad9b7b81cbdf8f028bd54699fa151f221d1e8de6817db93427.sbom` | | ### [`artifact published`](examples/artifact_published.json) The event represents an artifact that has been published and it can be advertised for others to use. +This event may be produced both by the build system and by the artifact registry that received the artifact. +If an SBOM was published and the SBOM URI is available at this stage, it should be included. -- Event Type: __`dev.cdevents.artifact.published.0.1.1`__ +- Event Type: __`dev.cdevents.artifact.published.0.2.0-draft`__ - Predicate: published - Subject: [`artifact`](#artifact) @@ -121,6 +126,7 @@ The event represents an artifact that has been published and it can be advertise | id | `Purl` | See [id](spec.md#id-subject) | `pkg:oci/myapp@sha256%3A0b31b1c02ff458ad9b7b81cbdf8f028bd54699fa151f221d1e8de6817db93427?repository_url=mycr.io/myapp`, `pkg:golang/mygit.com/myorg/myapp@234fd47e07d1004f0aed9c` | ✅ | | source | `URI-Reference` | See [source](spec.md#source-subject) | | | | type | `String` | See [type](spec.md#type-subject) | `artifact` | | +| sbom-uri | `URI-Reference` | The URI of the Software Bill of Material (SBOM) associated with the artifact | `https://sbom.storage.service/my-projects/3A0b31b1c02ff458ad9b7b81cbdf8f028bd54699fa151f221d1e8de6817db93427.sbom` | ### [`artifact signed`](examples/artifact_signed.json) diff --git a/examples/artifact_packaged.json b/examples/artifact_packaged.json index c88744fa..59e36641 100644 --- a/examples/artifact_packaged.json +++ b/examples/artifact_packaged.json @@ -3,7 +3,7 @@ "version": "0.4.0-draft", "id": "271069a8-fc18-44f1-b38f-9d70a1695819", "source": "/event/source/123", - "type": "dev.cdevents.artifact.packaged.0.1.1", + "type": "dev.cdevents.artifact.packaged.0.2.0-draft", "timestamp": "2023-03-20T14:27:05.315384Z" }, "subject": { @@ -14,7 +14,8 @@ "change": { "id": "myChange123", "source": "my-git.example/an-org/a-repo" - } + }, + "sbom-uri": "https://sbom.repo/myorg/234fd47e07d1004f0aed9c.sbom" } } } diff --git a/examples/artifact_published.json b/examples/artifact_published.json index 43d94b74..1f42de48 100644 --- a/examples/artifact_published.json +++ b/examples/artifact_published.json @@ -3,13 +3,15 @@ "version": "0.4.0-draft", "id": "271069a8-fc18-44f1-b38f-9d70a1695819", "source": "/event/source/123", - "type": "dev.cdevents.artifact.published.0.1.1", + "type": "dev.cdevents.artifact.published.0.2.0-draft", "timestamp": "2023-03-20T14:27:05.315384Z" }, "subject": { "id": "pkg:golang/mygit.com/myorg/myapp@234fd47e07d1004f0aed9c", "source": "/event/source/123", "type": "artifact", - "content": {} + "content": { + "sbom-uri": "https://sbom.repo/myorg/234fd47e07d1004f0aed9c.sbom" + } } } diff --git a/schemas/artifactpackaged.json b/schemas/artifactpackaged.json index 27aca12b..fffd044e 100644 --- a/schemas/artifactpackaged.json +++ b/schemas/artifactpackaged.json @@ -20,9 +20,9 @@ "type": { "type": "string", "enum": [ - "dev.cdevents.artifact.packaged.0.1.1" + "dev.cdevents.artifact.packaged.0.2.0-draft" ], - "default": "dev.cdevents.artifact.packaged.0.1.1" + "default": "dev.cdevents.artifact.packaged.0.2.0-draft" }, "timestamp": { "type": "string", @@ -77,6 +77,11 @@ "required": [ "id" ] + }, + "sbom-uri": { + "type": "string", + "minLength": 1, + "format": "uri-reference" } }, "additionalProperties": false, diff --git a/schemas/artifactpublished.json b/schemas/artifactpublished.json index fc56f008..bd622608 100644 --- a/schemas/artifactpublished.json +++ b/schemas/artifactpublished.json @@ -20,9 +20,9 @@ "type": { "type": "string", "enum": [ - "dev.cdevents.artifact.published.0.1.1" + "dev.cdevents.artifact.published.0.2.0-draft" ], - "default": "dev.cdevents.artifact.published.0.1.1" + "default": "dev.cdevents.artifact.published.0.2.0-draft" }, "timestamp": { "type": "string", @@ -59,7 +59,13 @@ "default": "artifact" }, "content": { - "properties": {}, + "properties": { + "sbom-uri": { + "type": "string", + "minLength": 1, + "format": "uri-reference" + } + }, "additionalProperties": false, "type": "object" } diff --git a/tools/verify-examples.sh b/tools/verify-examples.sh index d7735363..522acbb6 100755 --- a/tools/verify-examples.sh +++ b/tools/verify-examples.sh @@ -44,20 +44,21 @@ go install github.com/neilpa/yajsv@v1.4.1 # - examples are subject_predicate.json # - schemas are subjectpredicate.json num_failed=0 -num_examples=$(ls "$EXAMPLES_FOLDER" | wc -l | awk '{ print $1 }') -for example in $(ls "$EXAMPLES_FOLDER"); do - SUBJECT_PREDICATE=$(basename $example .json) +num_examples=$(find "${EXAMPLES_FOLDER}" -type f -name '*json' | wc -l | awk '{ print $1 }') +for example in $(find "${EXAMPLES_FOLDER}" -type f -name '*json'); do + EXAMPLE_FILE=$(basename ${example}) + SUBJECT_PREDICATE=$(basename $EXAMPLE_FILE .json) splitArray=(${SUBJECT_PREDICATE//_/ }) SUBJECT=${splitArray[0]} PREDICATE=${splitArray[1]} - EXAMPLE_FILE=${EXAMPLES_FOLDER}/${example} SCHEMA_FILE=${SCHEMAS_FOLDER}/${SUBJECT}${PREDICATE}.json echo "==> $SUBJECT $PREDICATE" - yajsv -s "$SCHEMA_FILE" "$EXAMPLE_FILE" || num_failed=$(( num_failed + 1 )) + echo yajsv -s "$SCHEMA_FILE" "$example" + yajsv -s "$SCHEMA_FILE" "$example" || num_failed=$(( num_failed + 1 )) echo done if [ $num_failed -gt 0 ]; then echo "${num_failed} out of ${num_examples} examples failed validation" fi -exit $num_failed \ No newline at end of file +exit $num_failed From 85bdd0acaeda946366b3edb80df508324a4aa3b3 Mon Sep 17 00:00:00 2001 From: Andrea Frittoli Date: Fri, 15 Dec 2023 12:45:56 +0000 Subject: [PATCH 2/2] Convert the sbom-uri into an sbom object Signed-off-by: Andrea Frittoli --- continuous-integration.md | 16 +++++++++++++--- examples/artifact_packaged.json | 4 +++- examples/artifact_published.json | 4 +++- schemas/artifactpackaged.json | 17 +++++++++++++---- schemas/artifactpublished.json | 17 +++++++++++++---- 5 files changed, 45 insertions(+), 13 deletions(-) diff --git a/continuous-integration.md b/continuous-integration.md index e6f5403f..59f43841 100644 --- a/continuous-integration.md +++ b/continuous-integration.md @@ -47,7 +47,7 @@ An `artifact` is usually produced as output of a build process. Events need to b | type | `String` | See [type](spec.md#type-subject) | `artifact` | | change | `object` | The change (tag, commit, revision) of the repository which was used to build the artifact" | `{"id": "527d4a1aca5e8d0df24813df5ad65d049fc8d312", "source": "my-git.example/an-org/a-repo"}`, `{"id": "feature1234", "source": "my-git.example/an-org/a-repo"}` | | signature | `string` | The signature of the artifact | `MEYCIQCBT8U5ypDXWCjlNKfzTV4KH516/SK13NZSh8znnSMNkQIhAJ3XiQlc9PM1KyjITcZXHotdMB+J3NGua5T/yshmiPmp` | -| sbom-uri | `URI-Reference` | The URI of the Software Bill of Material (SBOM) associated with the artifact | `https://sbom.storage.service/my-projects/3A0b31b1c02ff458ad9b7b81cbdf8f028bd54699fa151f221d1e8de6817db93427.sbom` | +| sbom | [`sbom`](#sbom) | The Software Bill of Material (SBOM) associated with the artifact | `{"uri": "https://sbom.storage.service/my-projects/3A0b31b1c02ff458ad9b7b81cbdf8f028bd54699fa151f221d1e8de6817db93427.sbom"}` | ## Events @@ -109,7 +109,7 @@ This event is usually produced by the build system. If an SBOM URI is available | source | `URI-Reference` | See [source](spec.md#source-subject) | | | | type | `String` | See [type](spec.md#type-subject) | `artifact` | | | change | `object` | The change (tag, commit, revision) of the repository which was used to build the artifact" | `{"id": "527d4a1aca5e8d0df24813df5ad65d049fc8d312", "source": "my-git.example/an-org/a-repo"}`, `{"id": "feature1234", "source": "my-git.example/an-org/a-repo"}` | ✅ | -| sbom-uri | `URI-Reference` | The URI of the Software Bill of Material (SBOM) associated with the artifact | `https://sbom.storage.service/my-projects/3A0b31b1c02ff458ad9b7b81cbdf8f028bd54699fa151f221d1e8de6817db93427.sbom` | | +| sbom | [`sbom`](#sbom) | The Software Bill of Material (SBOM) associated with the artifact | `{"uri": "https://sbom.storage.service/my-projects/3A0b31b1c02ff458ad9b7b81cbdf8f028bd54699fa151f221d1e8de6817db93427.sbom"}` | | ### [`artifact published`](examples/artifact_published.json) @@ -126,7 +126,7 @@ If an SBOM was published and the SBOM URI is available at this stage, it should | id | `Purl` | See [id](spec.md#id-subject) | `pkg:oci/myapp@sha256%3A0b31b1c02ff458ad9b7b81cbdf8f028bd54699fa151f221d1e8de6817db93427?repository_url=mycr.io/myapp`, `pkg:golang/mygit.com/myorg/myapp@234fd47e07d1004f0aed9c` | ✅ | | source | `URI-Reference` | See [source](spec.md#source-subject) | | | | type | `String` | See [type](spec.md#type-subject) | `artifact` | | -| sbom-uri | `URI-Reference` | The URI of the Software Bill of Material (SBOM) associated with the artifact | `https://sbom.storage.service/my-projects/3A0b31b1c02ff458ad9b7b81cbdf8f028bd54699fa151f221d1e8de6817db93427.sbom` | +| sbom | [`sbom`](#sbom) | The Software Bill of Material (SBOM) associated with the artifact | `{"uri": "https://sbom.storage.service/my-projects/3A0b31b1c02ff458ad9b7b81cbdf8f028bd54699fa151f221d1e8de6817db93427.sbom"}` | | ### [`artifact signed`](examples/artifact_signed.json) @@ -143,3 +143,13 @@ An artifact may be signed after it has been packaged or sometimes after it has p | source | `URI-Reference` | See [source](spec.md#source-subject) | | | | type | `String` | See [type](spec.md#type-subject) | `artifact` | | | signature | `string` | The signature of the artifact | `MEYCIQCBT8U5ypDXWCjlNKfzTV4KH516/SK13NZSh8znnSMNkQIhAJ3XiQlc9PM1KyjITcZXHotdMB+J3NGua5T/yshmiPmp` | ✅ | + +## Objects + +### `sbom` + +Several events reference a Software Bill of Materials (SBOM). In CDEvents SBOMs are represented via the `sbom` object, which is a reference to an externally hosted SBOM. The `sbom` object includes a single `uri` field, and is defined as an object to allow for more fields to be added in a backwards compatible manner in future. + +| Field | Type | Description | Examples | +|-------|------|-------------|----------| +| `uri` | `URI-Reference` | Link to an externally hosted SBOM. | `https://sbom.storage.service/my-projects/3A0b31b1c02ff458ad9b7b81cbdf8f028bd54699fa151f221d1e8de6817db93427.sbom` | \ No newline at end of file diff --git a/examples/artifact_packaged.json b/examples/artifact_packaged.json index 59e36641..238e20bb 100644 --- a/examples/artifact_packaged.json +++ b/examples/artifact_packaged.json @@ -15,7 +15,9 @@ "id": "myChange123", "source": "my-git.example/an-org/a-repo" }, - "sbom-uri": "https://sbom.repo/myorg/234fd47e07d1004f0aed9c.sbom" + "sbom": { + "uri": "https://sbom.repo/myorg/234fd47e07d1004f0aed9c.sbom" + } } } } diff --git a/examples/artifact_published.json b/examples/artifact_published.json index 1f42de48..854e2d96 100644 --- a/examples/artifact_published.json +++ b/examples/artifact_published.json @@ -11,7 +11,9 @@ "source": "/event/source/123", "type": "artifact", "content": { - "sbom-uri": "https://sbom.repo/myorg/234fd47e07d1004f0aed9c.sbom" + "sbom": { + "uri": "https://sbom.repo/myorg/234fd47e07d1004f0aed9c.sbom" + } } } } diff --git a/schemas/artifactpackaged.json b/schemas/artifactpackaged.json index fffd044e..e293f617 100644 --- a/schemas/artifactpackaged.json +++ b/schemas/artifactpackaged.json @@ -78,10 +78,19 @@ "id" ] }, - "sbom-uri": { - "type": "string", - "minLength": 1, - "format": "uri-reference" + "sbom": { + "properties": { + "uri": { + "type": "string", + "minLength": 1, + "format": "uri-reference" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "uri" + ] } }, "additionalProperties": false, diff --git a/schemas/artifactpublished.json b/schemas/artifactpublished.json index bd622608..ae839a66 100644 --- a/schemas/artifactpublished.json +++ b/schemas/artifactpublished.json @@ -60,10 +60,19 @@ }, "content": { "properties": { - "sbom-uri": { - "type": "string", - "minLength": 1, - "format": "uri-reference" + "sbom": { + "properties": { + "uri": { + "type": "string", + "minLength": 1, + "format": "uri-reference" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "uri" + ] } }, "additionalProperties": false,