From 50d0164b0cf9d305f4cc5af1f0a9787e67623ca9 Mon Sep 17 00:00:00 2001 From: Hank Donnay Date: Wed, 3 Sep 2025 12:39:12 -0500 Subject: [PATCH 1/3] types/v1: add JSON API v1 types and schemas Signed-off-by: Hank Donnay --- .../types/v1/affected_manifests.schema.json | 31 ++++++++ .../types/v1/bulk_delete.schema.json | 11 +++ httptransport/types/v1/cpe.schema.json | 20 +++++ httptransport/types/v1/digest.schema.json | 27 +++++++ .../types/v1/distribution.schema.json | 49 ++++++++++++ .../types/v1/environment.schema.json | 29 +++++++ httptransport/types/v1/error.schema.json | 20 +++++ .../types/v1/index_report.schema.json | 62 +++++++++++++++ .../types/v1/index_state.schema.json | 16 ++++ httptransport/types/v1/layer.schema.json | 40 ++++++++++ httptransport/types/v1/manifest.schema.json | 24 ++++++ .../types/v1/normalized_severity.schema.json | 14 ++++ .../types/v1/notification.schema.json | 34 ++++++++ .../types/v1/notification_page.schema.json | 39 ++++++++++ .../types/v1/notification_webhook.schema.json | 23 ++++++ httptransport/types/v1/package.schema.json | 55 +++++++++++++ httptransport/types/v1/range.schema.json | 19 +++++ httptransport/types/v1/repository.schema.json | 34 ++++++++ httptransport/types/v1/types.go | 11 +++ .../types/v1/update_diff.schema.json | 37 +++++++++ .../types/v1/update_operation.schema.json | 42 ++++++++++ .../types/v1/update_operations.schema.json | 13 ++++ .../types/v1/vulnerability.schema.json | 36 +++++++++ .../types/v1/vulnerability_core.schema.json | 75 ++++++++++++++++++ .../types/v1/vulnerability_report.schema.json | 77 +++++++++++++++++++ .../v1/vulnerability_summaries.schema.json | 11 +++ .../v1/vulnerability_summary.schema.json | 9 +++ 27 files changed, 858 insertions(+) create mode 100644 httptransport/types/v1/affected_manifests.schema.json create mode 100644 httptransport/types/v1/bulk_delete.schema.json create mode 100644 httptransport/types/v1/cpe.schema.json create mode 100644 httptransport/types/v1/digest.schema.json create mode 100644 httptransport/types/v1/distribution.schema.json create mode 100644 httptransport/types/v1/environment.schema.json create mode 100644 httptransport/types/v1/error.schema.json create mode 100644 httptransport/types/v1/index_report.schema.json create mode 100644 httptransport/types/v1/index_state.schema.json create mode 100644 httptransport/types/v1/layer.schema.json create mode 100644 httptransport/types/v1/manifest.schema.json create mode 100644 httptransport/types/v1/normalized_severity.schema.json create mode 100644 httptransport/types/v1/notification.schema.json create mode 100644 httptransport/types/v1/notification_page.schema.json create mode 100644 httptransport/types/v1/notification_webhook.schema.json create mode 100644 httptransport/types/v1/package.schema.json create mode 100644 httptransport/types/v1/range.schema.json create mode 100644 httptransport/types/v1/repository.schema.json create mode 100644 httptransport/types/v1/types.go create mode 100644 httptransport/types/v1/update_diff.schema.json create mode 100644 httptransport/types/v1/update_operation.schema.json create mode 100644 httptransport/types/v1/update_operations.schema.json create mode 100644 httptransport/types/v1/vulnerability.schema.json create mode 100644 httptransport/types/v1/vulnerability_core.schema.json create mode 100644 httptransport/types/v1/vulnerability_report.schema.json create mode 100644 httptransport/types/v1/vulnerability_summaries.schema.json create mode 100644 httptransport/types/v1/vulnerability_summary.schema.json diff --git a/httptransport/types/v1/affected_manifests.schema.json b/httptransport/types/v1/affected_manifests.schema.json new file mode 100644 index 0000000000..711cb60adc --- /dev/null +++ b/httptransport/types/v1/affected_manifests.schema.json @@ -0,0 +1,31 @@ +{ + "$id": "https://clairproject.org/api/http/v1/affected_manifests.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Affected Manifests", + "type": "object", + "description": "**This is an internal type, documented for completeness.**\n\nManifests affected by the specified vulnerability objects.", + "properties": { + "vulnerabilities": { + "type": "object", + "description": "Vulnerability objects.", + "additionalProperties": { + "$ref": "vulnerability.schema.json" + } + }, + "vulnerable_manifests": { + "type": "object", + "description": "Mapping of manifest digests to vulnerability identifiers.", + "additionalProperties": { + "type": "array", + "items": { + "type": "string", + "description": "An identifier to be used in the \"vulnerabilities\" object." + } + } + } + }, + "required": [ + "vulnerabilities", + "vulnerable_manifests" + ] +} diff --git a/httptransport/types/v1/bulk_delete.schema.json b/httptransport/types/v1/bulk_delete.schema.json new file mode 100644 index 0000000000..9306e2c893 --- /dev/null +++ b/httptransport/types/v1/bulk_delete.schema.json @@ -0,0 +1,11 @@ +{ + "$id": "https://clairproject.org/api/http/v1/bulk_delete.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Bulk Delete", + "type": "array", + "description": "Array of manifest digests to delete from the system.", + "items": { + "$ref": "digest.schema.json", + "description": "Manifest digest to delete from the system." + } +} diff --git a/httptransport/types/v1/cpe.schema.json b/httptransport/types/v1/cpe.schema.json new file mode 100644 index 0000000000..4675461b1b --- /dev/null +++ b/httptransport/types/v1/cpe.schema.json @@ -0,0 +1,20 @@ +{ + "$id": "https://clairproject.org/api/http/v1/cpe.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Common Platform Enumeration Name", + "description": "This is a CPE Name in either v2.2 \"URI\" form or v2.3 \"Formatted String\" form.", + "$comment": "Clair only produces v2.3 CPE Names. Any v2.2 Names will be normalized into v2.3 form.", + "type": "string", + "oneOf": [ + { + "description": "This is the CPE 2.2 regexp: https://cpe.mitre.org/specification/2.2/cpe-language_2.2.xsd", + "type": "string", + "pattern": "^[c][pP][eE]:/[AHOaho]?(:[A-Za-z0-9\\._\\-~%]*){0,6}$" + }, + { + "description": "This is the CPE 2.3 regexp: https://csrc.nist.gov/schema/cpe/2.3/cpe-naming_2.3.xsd", + "type": "string", + "pattern": "^cpe:2\\.3:[aho\\*\\-](:(((\\?*|\\*?)([a-zA-Z0-9\\-\\._]|(\\\\[\\\\\\*\\?!\"#$$%&'\\(\\)\\+,/:;<=>@\\[\\]\\^`\\{\\|}~]))+(\\?*|\\*?))|[\\*\\-])){5}(:(([a-zA-Z]{2,3}(-([a-zA-Z]{2}|[0-9]{3}))?)|[\\*\\-]))(:(((\\?*|\\*?)([a-zA-Z0-9\\-\\._]|(\\\\[\\\\\\*\\?!\"#$$%&'\\(\\)\\+,/:;<=>@\\[\\]\\^`\\{\\|}~]))+(\\?*|\\*?))|[\\*\\-])){4}$" + } + ] +} diff --git a/httptransport/types/v1/digest.schema.json b/httptransport/types/v1/digest.schema.json new file mode 100644 index 0000000000..31ff36a2f2 --- /dev/null +++ b/httptransport/types/v1/digest.schema.json @@ -0,0 +1,27 @@ +{ + "$id": "https://clairproject.org/api/http/v1/digest.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Digest", + "description": "A digest acts as a content identifier, enabling content addressability.", + "type": "string", + "anyOf": [ + { + "$comment": "SHA256: MUST be implemented", + "description": "SHA256", + "type": "string", + "pattern": "^sha256:[a-f0-9]{64}$" + }, + { + "$comment": "SHA512: MAY be implemented", + "description": "SHA512", + "type": "string", + "pattern": "^sha512:[a-f0-9]{128}$" + }, + { + "$comment": "BLAKE3: MAY be implemented", + "description": "BLAKE3\n\n**Currently not implemented.**", + "type": "string", + "pattern": "^blake3:[a-f0-9]{64}$" + } + ] +} diff --git a/httptransport/types/v1/distribution.schema.json b/httptransport/types/v1/distribution.schema.json new file mode 100644 index 0000000000..fa473bb4f6 --- /dev/null +++ b/httptransport/types/v1/distribution.schema.json @@ -0,0 +1,49 @@ +{ + "$id": "https://clairproject.org/api/http/v1/distribution.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Distribution", + "type": "object", + "description": "Distribution is the accompanying system context of a Package.", + "properties": { + "id": { + "description": "Unique ID for this Distribution. May be unique to the response document, not the whole system.", + "type": "string" + }, + "did": { + "description": "A lower-case string (no spaces or other characters outside of 0–9, a–z, \".\", \"_\", and \"-\") identifying the operating system, excluding any version information and suitable for processing by scripts or usage in generated filenames.", + "type": "string" + }, + "name": { + "description": "A string identifying the operating system.", + "type": "string" + }, + "version": { + "description": "A string identifying the operating system version, excluding any OS name information, possibly including a release code name, and suitable for presentation to the user.", + "type": "string" + }, + "version_code_name": { + "description": "A lower-case string (no spaces or other characters outside of 0–9, a–z, \".\", \"_\", and \"-\") identifying the operating system release code name, excluding any OS name information or release version, and suitable for processing by scripts or usage in generated filenames.", + "type": "string" + }, + "version_id": { + "description": "A lower-case string (mostly numeric, no spaces or other characters outside of 0–9, a–z, \".\", \"_\", and \"-\") identifying the operating system version, excluding any OS name information or release code name.", + "type": "string" + }, + "arch": { + "description": "A string identifying the OS architecture.", + "type": "string" + }, + "cpe": { + "description": "Common Platform Enumeration name.", + "$ref": "cpe.schema.json" + }, + "pretty_name": { + "description": "A pretty operating system name in a format suitable for presentation to the user.", + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "id" + ] +} diff --git a/httptransport/types/v1/environment.schema.json b/httptransport/types/v1/environment.schema.json new file mode 100644 index 0000000000..20d7a5f0b8 --- /dev/null +++ b/httptransport/types/v1/environment.schema.json @@ -0,0 +1,29 @@ +{ + "$id": "https://clairproject.org/api/http/v1/environment.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Environment", + "type": "object", + "description": "Environment describes the surrounding environment a package was discovered in.", + "properties": { + "package_db": { + "description": "The database the associated Package was discovered in.", + "type": "string" + }, + "distribution_id": { + "description": "The ID of the Distribution of the associated Package.", + "type": "string" + }, + "introduced_in": { + "description": "The Layer the associated Package was introduced in.", + "$ref": "digest.schema.json" + }, + "repository_ids": { + "description": "The IDs of the Repositories of the associated Package.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false +} diff --git a/httptransport/types/v1/error.schema.json b/httptransport/types/v1/error.schema.json new file mode 100644 index 0000000000..ffb1209425 --- /dev/null +++ b/httptransport/types/v1/error.schema.json @@ -0,0 +1,20 @@ +{ + "$id": "https://clairproject.org/api/http/v1/error.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Error", + "type": "object", + "description": "A general error response.", + "properties": { + "code": { + "type": "string", + "description": "a code for this particular error" + }, + "message": { + "type": "string", + "description": "a message with further detail" + } + }, + "required": [ + "message" + ] +} diff --git a/httptransport/types/v1/index_report.schema.json b/httptransport/types/v1/index_report.schema.json new file mode 100644 index 0000000000..f6fbb17f3f --- /dev/null +++ b/httptransport/types/v1/index_report.schema.json @@ -0,0 +1,62 @@ +{ + "$id": "https://clairproject.org/api/http/v1/index_report.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Index Report", + "type": "object", + "description": "An index of the contents of a Manifest.", + "properties": { + "manifest_hash": { + "$ref": "digest.schema.json", + "description": "The Manifest's digest." + }, + "state": { + "type": "string", + "description": "The current state of the index operation" + }, + "err": { + "type": "string", + "description": "An error message on event of unsuccessful index" + }, + "success": { + "type": "boolean", + "description": "A bool indicating succcessful index" + }, + "packages": { + "type": "object", + "description": "A map of Package objects indexed by a document-local identifier.", + "additionalProperties": { + "$ref": "package.schema.json" + } + }, + "distributions": { + "type": "object", + "description": "A map of Distribution objects indexed by a document-local identifier.", + "additionalProperties": { + "$ref": "distribution.schema.json" + } + }, + "repository": { + "type": "object", + "description": "A map of Repository objects indexed by a document-local identifier.", + "additionalProperties": { + "$ref": "repository.schema.json" + } + }, + "environments": { + "type": "object", + "description": "A map of Environment arrays indexed by a Package's identifier.", + "additionalProperties": { + "type": "array", + "items": { + "$ref": "environment.schema.json" + } + } + } + }, + "additionalProperties": false, + "required": [ + "manifest_hash", + "state", + "success" + ] +} diff --git a/httptransport/types/v1/index_state.schema.json b/httptransport/types/v1/index_state.schema.json new file mode 100644 index 0000000000..19645519cb --- /dev/null +++ b/httptransport/types/v1/index_state.schema.json @@ -0,0 +1,16 @@ +{ + "$id": "https://clairproject.org/api/http/v1/index_state.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Index State", + "type": "object", + "description": "Information on the state of the indexer system.", + "properties": { + "state": { + "type": "string", + "description": "an opaque token" + } + }, + "required": [ + "state" + ] +} diff --git a/httptransport/types/v1/layer.schema.json b/httptransport/types/v1/layer.schema.json new file mode 100644 index 0000000000..9166a9e0dc --- /dev/null +++ b/httptransport/types/v1/layer.schema.json @@ -0,0 +1,40 @@ +{ + "$id": "https://clairproject.org/api/http/v1/layer.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Layer", + "type": "object", + "description": "Layer is a description of a container layer. It should contain enough information to fetch the layer.", + "properties": { + "hash": { + "$ref": "digest.schema.json", + "description": "Digest of the layer blob." + }, + "uri": { + "type": "string", + "format": "uri", + "description": "A URI indicating where the layer blob can be downloaded from." + }, + "headers": { + "description": "Any additional HTTP-style headers needed for requesting layers.", + "type": "object", + "patternProperties": { + "^[a-zA-Z0-9\\-_]+$": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "media_type": { + "description": "The OCI Layer media type for this layer.", + "type": "string", + "pattern": "^application/vnd\\.oci\\.image\\.layer\\.v1\\.tar(\\+(gzip|zstd))?$" + } + }, + "additionalProperties": false, + "required": [ + "hash", + "uri" + ] +} diff --git a/httptransport/types/v1/manifest.schema.json b/httptransport/types/v1/manifest.schema.json new file mode 100644 index 0000000000..15face0a91 --- /dev/null +++ b/httptransport/types/v1/manifest.schema.json @@ -0,0 +1,24 @@ +{ + "$id": "https://clairproject.org/api/http/v1/manifest.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Manifest", + "type": "object", + "description": "A description of an OCI Image Manifest.", + "properties": { + "hash": { + "$ref": "digest.schema.json", + "description": "The OCI Image Manifest's digest.\n\nThis is used as an identifier throughout the system. This **SHOULD** be the same as the OCI Image Manifest's digest, but this is not enforced." + }, + "layers": { + "type": "array", + "description": "The OCI Layers making up the Image, in order.", + "items": { + "$ref": "layer.schema.json" + } + } + }, + "additionalProperties": false, + "required": [ + "hash" + ] +} diff --git a/httptransport/types/v1/normalized_severity.schema.json b/httptransport/types/v1/normalized_severity.schema.json new file mode 100644 index 0000000000..c3ef09d055 --- /dev/null +++ b/httptransport/types/v1/normalized_severity.schema.json @@ -0,0 +1,14 @@ +{ + "$id": "https://clairproject.org/api/http/v1/normalized_severity.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Normalized Severity", + "description": "Standardized severity values.", + "enum": [ + "Unknown", + "Negligible", + "Low", + "Medium", + "High", + "Critical" + ] +} diff --git a/httptransport/types/v1/notification.schema.json b/httptransport/types/v1/notification.schema.json new file mode 100644 index 0000000000..d9deb2d665 --- /dev/null +++ b/httptransport/types/v1/notification.schema.json @@ -0,0 +1,34 @@ +{ + "$id": "https://clairproject.org/api/http/v1/notification.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Notification", + "type": "object", + "description": "A change in a manifest affected by a vulnerability.", + "properties": { + "id": { + "description": "Unique identifier for this notification.", + "type": "string" + }, + "manifest": { + "$ref": "digest.schema.json", + "description": "The digest of the manifest affected by the provided vulnerability." + }, + "reason": { + "description": "The reason for the notifcation.", + "enum": [ + "added", + "removed" + ] + }, + "vulnerability": { + "$ref": "vulnerability_summary.schema.json" + } + }, + "additionalProperties": false, + "required": [ + "id", + "manifest", + "reason", + "vulnerability" + ] +} diff --git a/httptransport/types/v1/notification_page.schema.json b/httptransport/types/v1/notification_page.schema.json new file mode 100644 index 0000000000..daaf958364 --- /dev/null +++ b/httptransport/types/v1/notification_page.schema.json @@ -0,0 +1,39 @@ +{ + "$id": "https://clairproject.org/api/http/v1/notification_page.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Notification Page", + "type": "object", + "description": "A page description and list of notifications.", + "properties": { + "page": { + "description": "An object informing the client the next page to retrieve.", + "type": "object", + "properties": { + "size": { + "description": "The number of notifications contained in this page.", + "type": "integer" + }, + "next": { + "description": "The identififer to pass into the \"next\" parameter of a future GetNotification request.\n\nIf not present, there are no additional pages.", + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "size" + ] + }, + "notifications": { + "description": "Notifications within this page.", + "type": "array", + "items": { + "$ref": "notification.schema.json" + } + } + }, + "additionalProperties": false, + "required": [ + "page", + "notifications" + ] +} diff --git a/httptransport/types/v1/notification_webhook.schema.json b/httptransport/types/v1/notification_webhook.schema.json new file mode 100644 index 0000000000..c6958b47d2 --- /dev/null +++ b/httptransport/types/v1/notification_webhook.schema.json @@ -0,0 +1,23 @@ +{ + "$id": "https://clairproject.org/api/http/v1/notification_webhook.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Notification Webhook", + "type": "object", + "description": "Webhook sent to a configured service to begin retrieving notifications.", + "properties": { + "notification_id": { + "description": "Unique identifier for this notification.", + "type": "string" + }, + "callback": { + "description": "A URL to retrieve paginated Notification objects.", + "type": "string", + "format": "uri" + } + }, + "additionalProperties": false, + "required": [ + "notification_id", + "callback" + ] +} diff --git a/httptransport/types/v1/package.schema.json b/httptransport/types/v1/package.schema.json new file mode 100644 index 0000000000..a4a54cd9af --- /dev/null +++ b/httptransport/types/v1/package.schema.json @@ -0,0 +1,55 @@ +{ + "$id": "https://clairproject.org/api/http/v1/package.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Package", + "type": "object", + "description": "Description of installed software.", + "properties": { + "id": { + "description": "Unique ID for this Package. May be unique to the response document, not the whole system.", + "type": "string" + }, + "name": { + "description": "Identifier of this Package.\n\nThe uniqueness and scoping of this name depends on the packaging system.", + "type": "string" + }, + "version": { + "description": "Version of this Package, as reported by the packaging system.", + "type": "string" + }, + "kind": { + "description": "The \"kind\" of this Package.", + "enum": [ + "BINARY", + "SOURCE" + ], + "default": "BINARY" + }, + "source": { + "$ref": "#", + "description": "Source Package that produced the current binary Package, if known." + }, + "normalized_version": { + "description": "Normalized representation of the discoverd version.\n\nThe format is not specific, but is guarenteed to be forward compatible.", + "type": "string" + }, + "module": { + "description": "An identifier for intra-Repository grouping of packages.\n\nLikely only relevant on rpm-based systems.", + "type": "string" + }, + "arch": { + "description": "Native architecture for the Package.", + "type": "string", + "$comment": "This should become and enum in the future." + }, + "cpe": { + "$ref": "cpe.schema.json", + "description": "CPE Name for the Package." + } + }, + "additionalProperties": false, + "required": [ + "name", + "version" + ] +} diff --git a/httptransport/types/v1/range.schema.json b/httptransport/types/v1/range.schema.json new file mode 100644 index 0000000000..924a430f80 --- /dev/null +++ b/httptransport/types/v1/range.schema.json @@ -0,0 +1,19 @@ +{ + "$id": "https://clairproject.org/api/http/v1/range.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Range", + "type": "object", + "description": "A range of versions.", + "properties": { + "[": { + "type": "string", + "description": "Lower bound, inclusive." + }, + ")": { + "type": "string", + "description": "Upper bound, exclusive." + } + }, + "minProperties": 1, + "additionalProperties": false +} diff --git a/httptransport/types/v1/repository.schema.json b/httptransport/types/v1/repository.schema.json new file mode 100644 index 0000000000..1bb0bd9410 --- /dev/null +++ b/httptransport/types/v1/repository.schema.json @@ -0,0 +1,34 @@ +{ + "$id": "https://clairproject.org/api/http/v1/repository.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Repository", + "type": "object", + "description": "Description of a software repository", + "properties": { + "id": { + "description": "Unique ID for this Repository. May be unique to the response document, not the whole system.", + "type": "string" + }, + "name": { + "description": "Human-relevant name for the Repository.", + "type": "string" + }, + "key": { + "description": "Machine-relevant name for the Repository.", + "type": "string" + }, + "uri": { + "description": "URI describing the Repository.", + "type": "string", + "format": "uri" + }, + "cpe": { + "description": "CPE name for the Repository.", + "$ref": "cpe.schema.json" + } + }, + "additionalProperties": false, + "required": [ + "id" + ] +} diff --git a/httptransport/types/v1/types.go b/httptransport/types/v1/types.go new file mode 100644 index 0000000000..1257e33662 --- /dev/null +++ b/httptransport/types/v1/types.go @@ -0,0 +1,11 @@ +// Package types provides JSON Schemas for the HTTP API. +package types + +import ( + "embed" +) + +//go:generate sh -euc "for f in *.json; do <$DOLLAR{f} >$DOLLAR{f}_ jq -e .; mv $DOLLAR{f}_ $DOLLAR{f}; done" + +//go:embed *.schema.json +var Schema embed.FS diff --git a/httptransport/types/v1/update_diff.schema.json b/httptransport/types/v1/update_diff.schema.json new file mode 100644 index 0000000000..8edcd54a6e --- /dev/null +++ b/httptransport/types/v1/update_diff.schema.json @@ -0,0 +1,37 @@ +{ + "$id": "https://clairproject.org/api/http/v1/update_diff.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Update Difference", + "type": "object", + "description": "**This is an internal type, documented for completeness.**\n\nAn update difference describes changes between two Update Operations.", + "properties": { + "prev": { + "description": "The previous Update Operation.", + "$ref": "update_operation.schema.json" + }, + "cur": { + "description": "The current Update Operation.", + "$ref": "update_operation.schema.json" + }, + "added": { + "description": "Vulnerabilities present in \"cur\", but not \"prev\".", + "type": "array", + "items": { + "$ref": "vulnerability.schema.json" + } + }, + "removed": { + "description": "Vulnerabilities present in \"prev\", but not \"cur\".", + "type": "array", + "items": { + "$ref": "vulnerability.schema.json" + } + } + }, + "additionalProperties": false, + "required": [ + "cur", + "added", + "removed" + ] +} diff --git a/httptransport/types/v1/update_operation.schema.json b/httptransport/types/v1/update_operation.schema.json new file mode 100644 index 0000000000..5865a9b31d --- /dev/null +++ b/httptransport/types/v1/update_operation.schema.json @@ -0,0 +1,42 @@ +{ + "$id": "https://clairproject.org/api/http/v1/update_operation.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Update Operation", + "type": "object", + "description": "**This is an internal type, documented for completeness.**\n\nAn update operations describes an update of the internal vulnerability database.", + "properties": { + "ref": { + "type": "string", + "description": "A unique identifier for this update operation." + }, + "updater": { + "description": "The \"updater\" component that was run.", + "$comment": "This is not as useful as it could be: an end user needs to know too much about Clair(core)'s internals to make sense of it.", + "type": "string" + }, + "fingerprint": { + "description": "The stored \"fingerprint\" of this run.", + "type": "string" + }, + "date": { + "type": "string", + "description": "When this operation was run.", + "format": "date-time" + }, + "kind": { + "description": "The kind of data this operation updated.", + "enum": [ + "vulnerability", + "enrichment" + ] + } + }, + "additionalProperties": false, + "required": [ + "ref", + "updater", + "fingerprint", + "date", + "kind" + ] +} diff --git a/httptransport/types/v1/update_operations.schema.json b/httptransport/types/v1/update_operations.schema.json new file mode 100644 index 0000000000..2a8ad7948c --- /dev/null +++ b/httptransport/types/v1/update_operations.schema.json @@ -0,0 +1,13 @@ +{ + "$id": "https://clairproject.org/api/http/v1/update_operations.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Update Operations", + "type": "object", + "description": "**This is an internal type, documented for completeness.**\n\nA mapping of updater id to Update Operation(s).", + "additionalProperties": { + "type": "array", + "items": { + "$ref": "update_operation.schema.json" + } + } +} diff --git a/httptransport/types/v1/vulnerability.schema.json b/httptransport/types/v1/vulnerability.schema.json new file mode 100644 index 0000000000..2abf1ab356 --- /dev/null +++ b/httptransport/types/v1/vulnerability.schema.json @@ -0,0 +1,36 @@ +{ + "$id": "https://clairproject.org/api/http/v1/vulnerability.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Vulnerability", + "type": "object", + "description": "Description of a software flaw.", + "$ref": "vulnerability_core.schema.json", + "properties": { + "id": { + "description": "Unique ID for this Vulnerabiltity. May be unique to the response document, not the whole system.", + "type": "string" + }, + "updater": { + "description": "The updater component this Vulnerability came from.", + "type": "string" + }, + "description": { + "description": "A human-readable description of the vulnerability.", + "type": "string" + }, + "issued": { + "description": "The datetime this Vulnerability was issued, if known.", + "type": "string", + "format": "date-time" + }, + "links": { + "description": "Space-separated URIs to more information.", + "type": "string" + } + }, + "unevaluatedProperties": false, + "required": [ + "id", + "updater" + ] +} diff --git a/httptransport/types/v1/vulnerability_core.schema.json b/httptransport/types/v1/vulnerability_core.schema.json new file mode 100644 index 0000000000..b5f665b97d --- /dev/null +++ b/httptransport/types/v1/vulnerability_core.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://clairproject.org/api/http/v1/vulnerability_core.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Vulnerability Core", + "type": "object", + "description": "The core elements of vulnerabilities in the Clair system.", + "properties": { + "name": { + "type": "string", + "description": "Human-readable name, as presented in the vendor data." + }, + "fixed_in_version": { + "type": "string", + "description": "Version string, as presented in the vendor data." + }, + "severity": { + "type": "string", + "description": "Severity, as presented in the vendor data." + }, + "normalized_severity": { + "$ref": "normalized_severity.schema.json", + "description": "A well defined set of severity strings guaranteed to be present." + }, + "range": { + "$ref": "range.schema.json", + "description": "Range of versions the vulnerability applies to." + }, + "arch_op": { + "description": "Flag indicating how the referenced package's \"arch\" member should be interpreted.", + "enum": [ + "equals", + "not equals", + "pattern match" + ] + }, + "package": { + "$ref": "package.schema.json", + "description": "A package description" + }, + "distribution": { + "$ref": "distribution.schema.json", + "description": "A distribution description" + }, + "repository": { + "$ref": "repository.schema.json", + "description": "A repository description" + } + }, + "required": [ + "name", + "normalized_severity" + ], + "dependentRequired": { + "package": [ + "arch_op" + ] + }, + "anyOf": [ + { + "required": [ + "package" + ] + }, + { + "required": [ + "repository" + ] + }, + { + "required": [ + "distribution" + ] + } + ] +} diff --git a/httptransport/types/v1/vulnerability_report.schema.json b/httptransport/types/v1/vulnerability_report.schema.json new file mode 100644 index 0000000000..8f2658560d --- /dev/null +++ b/httptransport/types/v1/vulnerability_report.schema.json @@ -0,0 +1,77 @@ +{ + "$id": "https://clairproject.org/api/http/v1/vulnerability_report.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Vulnerability Report", + "type": "object", + "description": "A report with discovered packages, package environments, and package vulnerabilities within a Manifest.", + "properties": { + "manifest_hash": { + "$ref": "digest.schema.json", + "description": "The Manifest's digest." + }, + "packages": { + "type": "object", + "description": "A map of Package objects indexed by a document-local identifier.", + "additionalProperties": { + "$ref": "package.schema.json" + } + }, + "distributions": { + "type": "object", + "description": "A map of Distribution objects indexed by a document-local identifier.", + "additionalProperties": { + "$ref": "distribution.schema.json" + } + }, + "repository": { + "type": "object", + "description": "A map of Repository objects indexed by a document-local identifier.", + "additionalProperties": { + "$ref": "repository.schema.json" + } + }, + "environments": { + "type": "object", + "description": "A map of Environment arrays indexed by a Package's identifier.", + "additionalProperties": { + "type": "array", + "items": { + "$ref": "environment.schema.json" + } + } + }, + "vulnerabilities": { + "type": "object", + "description": "A map of Vulnerabilities indexed by a document-local identifier.", + "additionalProperties": { + "$ref": "vulnerability.schema.json" + } + }, + "package_vulnerabilities": { + "type": "object", + "description": "A mapping of Vulnerability identifier lists indexed by Package identifier.", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "enrichments": { + "type": "object", + "description": "A mapping of extra \"enrichment\" data by type", + "additionalProperties": { + "type": "array" + } + } + }, + "additionalProperties": false, + "required": [ + "distributions", + "environments", + "manifest_hash", + "packages", + "package_vulnerabilities", + "vulnerabilities" + ] +} diff --git a/httptransport/types/v1/vulnerability_summaries.schema.json b/httptransport/types/v1/vulnerability_summaries.schema.json new file mode 100644 index 0000000000..a3ffedda06 --- /dev/null +++ b/httptransport/types/v1/vulnerability_summaries.schema.json @@ -0,0 +1,11 @@ +{ + "$id": "https://clairproject.org/api/http/v1/vulnerability_summaries.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Vulnerability Summaries", + "type": "array", + "description": "**This is an internal type, documented for completeness.**\n\nThis is an array of pseudo-Vulnerability objects used for reverse-lookup.", + "items": { + "description": "Summary vulnerability objects.", + "$ref": "vulnerability_summary.schema.json" + } +} diff --git a/httptransport/types/v1/vulnerability_summary.schema.json b/httptransport/types/v1/vulnerability_summary.schema.json new file mode 100644 index 0000000000..8fac0115e5 --- /dev/null +++ b/httptransport/types/v1/vulnerability_summary.schema.json @@ -0,0 +1,9 @@ +{ + "$id": "https://clairproject.org/api/http/v1/vulnerability_summary.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Vulnerability Summary", + "type": "object", + "description": "A summary of a vulnerability.", + "$ref": "vulnerability_core.schema.json", + "unevaluatedProperties": false +} From 8c540b964f6b8afc99f6a82f60fede028fc739f1 Mon Sep 17 00:00:00 2001 From: Hank Donnay Date: Mon, 15 Sep 2025 16:06:29 -0500 Subject: [PATCH 2/3] openapi: rebuild OpenAPI spec Signed-off-by: Hank Donnay --- .gitattributes | 1 + Documentation/SUMMARY.md | 1 + Documentation/contribution.md | 1 + Documentation/contribution/openapi.md | 40 + Documentation/howto/api.md | 4 +- Documentation/reference/api.md | 2558 ++++++++++------- httptransport/api/.gitattributes | 3 + httptransport/api/lib/oapi.jq | 64 + httptransport/api/openapi.zsh | 96 + .../api/v1/examples/affected_manifests.json | 1 + .../api/v1/examples/bulk_delete.json | 3 + httptransport/api/v1/examples/cpe.json | 2 + httptransport/api/v1/examples/digest.json | 3 + .../api/v1/examples/distribution.json | 9 + .../api/v1/examples/environment.json | 7 + httptransport/api/v1/examples/manifest.json | 14 + .../api/v1/examples/notification_page.json | 43 + httptransport/api/v1/examples/package.json | 17 + .../api/v1/examples/vulnerability.json | 31 + .../v1/examples/vulnerability_summary.json | 24 + httptransport/api/v1/openapi.etag | 1 + httptransport/api/v1/openapi.jq | 487 ++++ httptransport/api/v1/openapi.json | 1831 ++++++++++++ httptransport/api/v1/openapi.yaml | 1334 +++++++++ httptransport/discoveryhandler.go | 47 +- httptransport/discoveryhandler_test.go | 130 +- httptransport/indexer_v1.go | 6 +- httptransport/matcher_v1.go | 5 +- httptransport/notification_v1.go | 3 +- httptransport/openapi.etag | 1 - httptransport/openapi.json | 1 - httptransport/openapigen.go | 83 - httptransport/server.go | 2 + openapi.yaml | 934 ------ 34 files changed, 5590 insertions(+), 2197 deletions(-) create mode 100644 Documentation/contribution/openapi.md create mode 100644 httptransport/api/.gitattributes create mode 100644 httptransport/api/lib/oapi.jq create mode 100755 httptransport/api/openapi.zsh create mode 100644 httptransport/api/v1/examples/affected_manifests.json create mode 100644 httptransport/api/v1/examples/bulk_delete.json create mode 100644 httptransport/api/v1/examples/cpe.json create mode 100644 httptransport/api/v1/examples/digest.json create mode 100644 httptransport/api/v1/examples/distribution.json create mode 100644 httptransport/api/v1/examples/environment.json create mode 100644 httptransport/api/v1/examples/manifest.json create mode 100644 httptransport/api/v1/examples/notification_page.json create mode 100644 httptransport/api/v1/examples/package.json create mode 100644 httptransport/api/v1/examples/vulnerability.json create mode 100644 httptransport/api/v1/examples/vulnerability_summary.json create mode 100644 httptransport/api/v1/openapi.etag create mode 100644 httptransport/api/v1/openapi.jq create mode 100644 httptransport/api/v1/openapi.json create mode 100644 httptransport/api/v1/openapi.yaml delete mode 100644 httptransport/openapi.etag delete mode 100644 httptransport/openapi.json delete mode 100644 httptransport/openapigen.go delete mode 100644 openapi.yaml diff --git a/.gitattributes b/.gitattributes index a2363ebf92..279878b8e4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ cmd/build.go export-subst *.go diff=golang +Documentation/reference/api.md linguist-generated diff --git a/Documentation/SUMMARY.md b/Documentation/SUMMARY.md index 11da1cd4b8..8899452eb3 100644 --- a/Documentation/SUMMARY.md +++ b/Documentation/SUMMARY.md @@ -18,6 +18,7 @@ - [Building](./contribution/building.md) - [Commit Style](./contribution/commit_style.md) - [Releases](./contribution/releases.md) + - [OpenAPI](./contribution/openapi.md) - [Reference](./reference.md) - [Api](./reference/api.md) - [Clairctl](./reference/clairctl.md) diff --git a/Documentation/contribution.md b/Documentation/contribution.md index 1f6f321e44..eb64fb6aff 100644 --- a/Documentation/contribution.md +++ b/Documentation/contribution.md @@ -4,3 +4,4 @@ The following sections provides information on how to contribute to Clair. - [Building](./contribution/building.md) - [Commit Style](./contribution/commit_style.md) - [Releases](./contribution/releases.md) +- [OpenAPI](./contribution/openapi.md) diff --git a/Documentation/contribution/openapi.md b/Documentation/contribution/openapi.md new file mode 100644 index 0000000000..6ff3fbe3fc --- /dev/null +++ b/Documentation/contribution/openapi.md @@ -0,0 +1,40 @@ +# OpenAPI + +The [OpenAPI specification] has moved from `openapi.yaml` to the `openapi.json` +and `openapi.yaml` files in `httptransport/api/v1`. + +These files are autogenerated from files in `httptransport/api` and +`httptransport/types` via the `httptransport/api/openapi.zsh` script. This +script requires `zsh` to run and `sha256sum`, `git`, `jq`, `yq`, and `npx` +commands in `PATH`. + +## Modifications + +To modify the OpenAPI spec, edit the relevant `httptransport/api/*/openapi.jq` +file (a [`jq`] script) or the `httptransport/api/lib/oapi.jq` library as needed, +then run `go generate ./httptransport`. + +The `go generate` command also needs to be run if files in `httptransport/types` +are modified. + +## Script + +The `openapi.zsh` script works by: +- for each `v*` directory under `httptransport/api`: + - for all [JSON Schema] files in the corresponding `httptransport/types/v*` directory: + - lint the schema + - slip-steam examples from the corresponding `examples` file + - amalgamate all the files from the previous step + - run the `openapi.jq` script with `null` input + - merge the outputs of the previous two steps + - ~~validate and lint the OpenAPI spec~~[^note] + - generate a `yaml` representation + - write out a `sha256` checksum in [Etag] format + +[^note]: The OpenAPI spec _should_ also be validated or linted, but there's not a known tool that handles JSON Schema [reference resolution] correctly. + +[OpenAPI specification]: https://spec.openapis.org/oas/v3.1.0.html +[`jq`]: https://jqlang.org/manual/ +[JSON Schema]: https://json-schema.org/ +[Etag]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/ETag +[reference resolution]: https://www.learnjsonschema.com/2020-12/core/ref/ diff --git a/Documentation/howto/api.md b/Documentation/howto/api.md index a922e561d2..f64f982b75 100644 --- a/Documentation/howto/api.md +++ b/Documentation/howto/api.md @@ -1,6 +1,6 @@ # API Definition -Clair provides its API definition via an OpenAPI specification. You can view our OpenAPI spec [here](https://raw.githubusercontent.com/quay/clair/main/openapi.yaml) +Clair provides its API definition via an OpenAPI specification. You can view our OpenAPI spec [here][openapi_v1]. The OpenAPI spec can be used in a variety of ways. * Generating http clients for your application @@ -11,3 +11,5 @@ The OpenAPI spec can be used in a variety of ways. See [Testing Clair](./testing.md) to learn how the local dev tooling starts a local swagger editor. This is handy for making changes to the spec in real time. See [API Reference](../reference/api.md) for a markdown rendered API reference. + +[openapi_v1]: https://github.com/quay/clair/tree/main/httptransport/api/v1 diff --git a/Documentation/reference/api.md b/Documentation/reference/api.md index ebc74ab43e..986fca82f0 100644 --- a/Documentation/reference/api.md +++ b/Documentation/reference/api.md @@ -1,5 +1,5 @@ --- -title: ClairV4 v1.1 +title: Clair Container Analyzer v1.2.0 language_tabs: - python: Python - go: Golang @@ -8,7 +8,8 @@ language_clients: - python: "" - go: "" - javascript: "" -toc_footers: [] +toc_footers: + - External documentation includes: [] search: false highlight_theme: darkula @@ -18,267 +19,30 @@ headingLevel: 2 -

ClairV4 v1.1

+

Clair Container Analyzer v1.2.0

> Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu. -ClairV4 is a set of cooperating microservices which scan, index, and match your container's content with known vulnerabilities. +Clair is a set of cooperating microservices which can index and match a container image's content with known vulnerabilities. -Email: Clair Team Web: Clair Team -License: Apache License 2.0 - -

Notifier

- -## DeleteNotification - - - -> Code samples - -```python -import requests -headers = { - 'Accept': 'application/json' -} - -r = requests.delete('/notifier/api/v1/notification/{notification_id}', headers = headers) - -print(r.json()) - -``` - -```go -package main - -import ( - "bytes" - "net/http" -) - -func main() { - - headers := map[string][]string{ - "Accept": []string{"application/json"}, - } - - data := bytes.NewBuffer([]byte{jsonReq}) - req, err := http.NewRequest("DELETE", "/notifier/api/v1/notification/{notification_id}", data) - req.Header = headers - - client := &http.Client{} - resp, err := client.Do(req) - // ... -} - -``` - -```javascript - -const headers = { - 'Accept':'application/json' -}; - -fetch('/notifier/api/v1/notification/{notification_id}', -{ - method: 'DELETE', - - headers: headers -}) -.then(function(res) { - return res.json(); -}).then(function(body) { - console.log(body); -}); - -``` - -`DELETE /notifier/api/v1/notification/{notification_id}` - -Issues a delete of the provided notification id and all associated notifications. After this delete clients will no longer be able to retrieve notifications. - -

Parameters

- -|Name|In|Type|Required|Description| -|---|---|---|---|---| -|notification_id|path|string|false|A notification ID returned by a callback| - -> Example responses - -> 400 Response - -```json -{ - "code": "string", - "message": "string" -} -``` - -

Responses

- -|Status|Meaning|Description|Schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|None| -|400|[Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)|Bad Request|[Error](#schemaerror)| -|405|[Method Not Allowed](https://tools.ietf.org/html/rfc7231#section-6.5.5)|Method Not Allowed|[Error](#schemaerror)| -|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|Internal Server Error|[Error](#schemaerror)| - - - -## Retrieve a paginated result of notifications for the provided id. - - - -> Code samples - -```python -import requests -headers = { - 'Accept': 'application/json' -} - -r = requests.get('/notifier/api/v1/notification/{notification_id}', headers = headers) - -print(r.json()) - -``` - -```go -package main - -import ( - "bytes" - "net/http" -) - -func main() { - - headers := map[string][]string{ - "Accept": []string{"application/json"}, - } - - data := bytes.NewBuffer([]byte{jsonReq}) - req, err := http.NewRequest("GET", "/notifier/api/v1/notification/{notification_id}", data) - req.Header = headers - - client := &http.Client{} - resp, err := client.Do(req) - // ... -} - -``` - -```javascript - -const headers = { - 'Accept':'application/json' -}; - -fetch('/notifier/api/v1/notification/{notification_id}', -{ - method: 'GET', - - headers: headers -}) -.then(function(res) { - return res.json(); -}).then(function(body) { - console.log(body); -}); - -``` - -`GET /notifier/api/v1/notification/{notification_id}` - -By performing a GET with a notification_id as a path parameter, the client will retrieve a paginated response of notification objects. - -

Parameters

+**Note:** Any endpoints tagged "internal" are documented for completeness but are considered exempt from versioning. -|Name|In|Type|Required|Description| -|---|---|---|---|---| -|notification_id|path|string|false|A notification ID returned by a callback| -|page_size|query|int|false|The maximum number of notifications to deliver in a single page.| -|next|query|string|false|The next page to fetch via id. Typically this number is provided on initial response in the page.next field. The first GET request may omit this field.| - -> Example responses +Email: Clair Team Web: Clair Team +License: Apache License 2.0 -> 200 Response +# Authentication -```json -{ - "page": { - "size": 100, - "next": "1b4d0db2-e757-4150-bbbb-543658144205" - }, - "notifications": [ - { - "id": "5e4b387e-88d3-4364-86fd-063447a6fad2", - "manifest": "sha256:35c102085707f703de2d9eaad8752d6fe1b8f02b5d2149f1d8357c9cc7fb7d0a", - "reason": "added", - "vulnerability": { - "name": "CVE-2009-5155", - "fixed_in_version": "v0.0.1", - "links": "http://link-to-advisory", - "description": "In the GNU C Library (aka glibc or libc6) before 2.28, parse_reg_exp in posix/regcomp.c misparses alternatives, which allows attackers to cause a denial of service (assertion failure and application exit) or trigger an incorrect result by attempting a regular-expression match.\"", - "normalized_severity": "Unknown", - "package": { - "id": "10", - "name": "libapt-pkg5.0", - "version": "1.6.11", - "kind": "binary", - "normalized_version": "", - "arch": "x86", - "module": "", - "cpe": "", - "source": { - "id": "9", - "name": "apt", - "version": "1.6.11", - "kind": "source", - "source": null - } - }, - "distribution": { - "id": "1", - "did": "ubuntu", - "name": "Ubuntu", - "version": "18.04.3 LTS (Bionic Beaver)", - "version_code_name": "bionic", - "version_id": "18.04", - "arch": "", - "cpe": "", - "pretty_name": "Ubuntu 18.04.3 LTS" - }, - "repository": { - "id": "string", - "name": "string", - "key": "string", - "uri": "string", - "cpe": "string" - } - } - } - ] -} -``` +- HTTP Authentication, scheme: bearer Clair's authentication scheme. -

Responses

+This is a [JWT](https://datatracker.ietf.org/doc/html/rfc7519) signed with a configured pre-shared key containing an allowlisted `iss` claim. -|Status|Meaning|Description|Schema| -|---|---|---|---| -|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|A paginated list of notifications|[PagedNotifications](#schemapagednotifications)| -|400|[Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)|Bad Request|[Error](#schemaerror)| -|405|[Method Not Allowed](https://tools.ietf.org/html/rfc7231#section-6.5.5)|Method Not Allowed|[Error](#schemaerror)| -|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|Internal Server Error|[Error](#schemaerror)| +

indexer

- +Indexer service endpoints. -

Indexer

+These are responsible for determining the contents of containers. -## Index the contents of a Manifest +## Index a Manifest @@ -287,8 +51,8 @@ This operation does not require authentication ```python import requests headers = { - 'Content-Type': 'application/json', - 'Accept': 'application/json' + 'Content-Type': 'application/vnd.clair.manifest.v1+json', + 'Accept': 'application/vnd.clair.index_report.v1+json' } r = requests.post('/indexer/api/v1/index_report', headers = headers) @@ -308,8 +72,8 @@ import ( func main() { headers := map[string][]string{ - "Content-Type": []string{"application/json"}, - "Accept": []string{"application/json"}, + "Content-Type": []string{"application/vnd.clair.manifest.v1+json"}, + "Accept": []string{"application/vnd.clair.index_report.v1+json"}, } data := bytes.NewBuffer([]byte{jsonReq}) @@ -328,22 +92,19 @@ const inputBody = '{ "hash": "sha256:fc84b5febd328eccaa913807716887b3eb5ed08bc22cc6933a9ebf82766725e3", "layers": [ { - "hash": "sha256:fc84b5febd328eccaa913807716887b3eb5ed08bc22cc6933a9ebf82766725e3", + "hash": "sha256:2f077db56abccc19f16f140f629ae98e904b4b7d563957a7fc319bd11b82ba36", "uri": "https://storage.example.com/blob/2f077db56abccc19f16f140f629ae98e904b4b7d563957a7fc319bd11b82ba36", "headers": { - "property1": [ - "string" - ], - "property2": [ - "string" + "Authoriztion": [ + "Bearer hunter2" ] } } ] }'; const headers = { - 'Content-Type':'application/json', - 'Accept':'application/json' + 'Content-Type':'application/vnd.clair.manifest.v1+json', + 'Accept':'application/vnd.clair.index_report.v1+json' }; fetch('/indexer/api/v1/index_report', @@ -371,14 +132,11 @@ By submitting a Manifest object to this endpoint Clair will fetch the layers, sc "hash": "sha256:fc84b5febd328eccaa913807716887b3eb5ed08bc22cc6933a9ebf82766725e3", "layers": [ { - "hash": "sha256:fc84b5febd328eccaa913807716887b3eb5ed08bc22cc6933a9ebf82766725e3", + "hash": "sha256:2f077db56abccc19f16f140f629ae98e904b4b7d563957a7fc319bd11b82ba36", "uri": "https://storage.example.com/blob/2f077db56abccc19f16f140f629ae98e904b4b7d563957a7fc319bd11b82ba36", "headers": { - "property1": [ - "string" - ], - "property2": [ - "string" + "Authoriztion": [ + "Bearer hunter2" ] } } @@ -386,11 +144,11 @@ By submitting a Manifest object to this endpoint Clair will fetch the layers, sc } ``` -

Parameters

+

Parameters

|Name|In|Type|Required|Description| |---|---|---|---|---| -|body|body|[Manifest](#schemamanifest)|true|none| +|body|body|[manifest](#schemamanifest)|true|Manifest to index.| > Example responses @@ -398,68 +156,45 @@ By submitting a Manifest object to this endpoint Clair will fetch the layers, sc ```json { - "manifest_hash": "sha256:fc84b5febd328eccaa913807716887b3eb5ed08bc22cc6933a9ebf82766725e3", - "state": "IndexFinished", - "packages": { - "10": { - "id": "10", - "name": "libapt-pkg5.0", - "version": "1.6.11", - "kind": "binary", - "normalized_version": "", - "arch": "x86", - "module": "", - "cpe": "", - "source": { - "id": "9", - "name": "apt", - "version": "1.6.11", - "kind": "source", - "source": null - } - } - }, - "distributions": { - "1": { - "id": "1", - "did": "ubuntu", - "name": "Ubuntu", - "version": "18.04.3 LTS (Bionic Beaver)", - "version_code_name": "bionic", - "version_id": "18.04", - "arch": "", - "cpe": "", - "pretty_name": "Ubuntu 18.04.3 LTS" - } - }, - "environments": { - "10": [ - { - "package_db": "var/lib/dpkg/status", - "introduced_in": "sha256:35c102085707f703de2d9eaad8752d6fe1b8f02b5d2149f1d8357c9cc7fb7d0a", - "distribution_id": "1" - } - ] - }, + "manifest_hash": null, + "state": "string", + "err": "string", "success": true, - "err": "" + "packages": {}, + "distributions": {}, + "repository": {}, + "environments": { + "property1": [], + "property2": [] + } } ``` -

Responses

+

Responses

|Status|Meaning|Description|Schema| |---|---|---|---| -|201|[Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)|IndexReport Created|[IndexReport](#schemaindexreport)| -|400|[Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)|Bad Request|[Error](#schemaerror)| -|405|[Method Not Allowed](https://tools.ietf.org/html/rfc7231#section-6.5.5)|Method Not Allowed|[Error](#schemaerror)| -|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|Internal Server Error|[Error](#schemaerror)| +|201|[Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)|IndexReport created. + +Clients may want to avoid reading the body if simply submitting the manifest for later vulnerability reporting.|[index_report](#schemaindex_report)| +|400|[Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)|Bad Request|[error](#schemaerror)| +|412|[Precondition Failed](https://tools.ietf.org/html/rfc7232#section-4.2)|Precondition Failed|None| +|415|[Unsupported Media Type](https://tools.ietf.org/html/rfc7231#section-6.5.13)|Unsupported Media Type|[error](#schemaerror)| +|default|Default|Internal Server Error|[error](#schemaerror)| + +### Response Headers + +|Status|Header|Type|Format|Description| +|---|---|---|---|---| +|201|Location|string||HTTP [Location header](https://httpwg.org/specs/rfc9110.html#field.location)| +|201|Link|string||Web Linking [Link header](https://httpwg.org/specs/rfc8288.html#header)| -