diff --git a/.wordlist.txt b/.wordlist.txt index 530502b..2da719b 100644 --- a/.wordlist.txt +++ b/.wordlist.txt @@ -1,7 +1,6 @@ amd apache API -apikey APIs artifacthub ASLR @@ -71,7 +70,6 @@ GitLab golang GPG graphQL -graphql gui haproxy hostname @@ -110,7 +108,6 @@ MacOS maxRetries md MERCHANTABILITY -Mgmt mgmt minify mkdocs @@ -122,14 +119,12 @@ nginx NodePort OAuth OCI -oci OIDC oidc onboarding Onboarding onDemand onlySigned -OpenAPI OpenID oras ORA diff --git a/docs/developer-guide/api-guide.md b/docs/developer-guide/api-guide.md deleted file mode 100644 index 7a55f61..0000000 --- a/docs/developer-guide/api-guide.md +++ /dev/null @@ -1,173 +0,0 @@ -# Using the zot API - -> :point_right: The zot API implements the [OCI Distribution endpoints](https://github.com/opencontainers/distribution-spec/blob/main/spec.md#endpoints) along with endpoints for the supported extensions. - -!!! note "Mike's Questions" - - Does the `ui` extension in the config file enable/disable the API? What is '/' in the API? - - Do we need to document the URL query parameters and API payloads here or should we link to the relevant articles for expanded details? - - Should we at least indicate in the API table that parameters or payloads are supported for each command? - - Is the API syntax finalized for uploading keys and certificates for cosign and notation? - - -## Viewing the OpenAPI documentation - -[OpenAPI](https://www.openapis.org/) (formerly Swagger) provides a standardized format for describing an API. An OpenAPI-conforming API document defines the structure and syntax of the API and can provide a sandbox for executing API commands. - -A zot registry incorporates a built-in OpenAPI document. To view the document, go to the following URL: - - http:///swagger/v2/ - -For example: - - http://localhost:8080/swagger/v2/ - -> :pencil2: You must include the trailing `/`. - -## API authentication - -When pushing and pulling images using API calls, your identity can be authenticated by either a password or an API key. An API key has advantages in situations where the primary zot authentication does not use the command line, such as a GUI login or social login. Also, you can reduce your security exposure by using an API key instead of your broader credentials, such as an LDAP username and password. - - -### Using API keys - -#### Enabling API keys - -To enable the use of API keys, you must set the `apikey` attribute to `true` in the zot configuration file, as shown in the following example: - -```json - "http": { - "auth": { - "apikey": true - } - } -``` - -#### Creating an API key - -Before you can create or revoke an API key, you must first log in using a different authentication mechanism, such as logging in through the zot GUI. Once you are logged in, you can create an API key for your identity with the following API command: - - POST /auth/apikey - -For example, using cURL: - - curl -u user:password -X POST http://localhost:8080/auth/apikey -d '{"label": "myAPIKEY", "scopes": ["repo1", "repo2"], "expirationDate": "2023-08-28T17:10:05+03:00"}' - -In this example, the command output would be: - -```json -{ - "createdAt":"2023-08-28T17:09:59.2603515+03:00", - "expirationDate":"2023-08-28T17:10:05+03:00", - "isExpired":false, - "creatorUa":"curl/7.68.0", - "generatedBy":"manual", - "lastUsed":"0001-01-01T00:00:00Z", - "label":"myAPIKEY", - "scopes": [ - "repo1", - "repo2" - ], - "uuid":"c931e635-a80d-4b52-b035-6b57be5f6e74", - "apiKey":"zak_ac55a8693d6b4370a2003fa9e10b3682" -} -``` - -> :pencil2: The API key (`apiKey`) is shown to the user only in the command output when it is created. It cannot be retrieved from zot with any other command. - -> :pencil2: The scopes and expiration date in this example are optional. By default, an API key has the same permissions as the user who created it. - -#### Using an API key in an API command - -The API key replaces a password in the API command, as shown in the following cURL example: - - curl -u user:zak_e77bcb9e9f634f1581756abbf9ecd269 http://localhost:8080/v2/_catalog - - -#### Removing an API key - -When logged in, you can revoke your own API key with the following API command: - - DELETE /auth/apikey?id=$uuid - -For example, using cURL: - - curl -u user:password -X DELETE http://localhost:8080/v2/auth/apikey?id=46a45ce7-5d92-498a-a9cb-9654b1da3da1 - - -#### Listing your current API keys - -When logged in, you can display a list of your API keys with the following API command: - - GET /auth/apikey - -For example, using cURL: - - curl -u user:password -X GET http://localhost:8080/auth/apikey - -The following command output example shows information about two keys for this user: - -```json -{ - "apiKeys": [ - { - "createdAt": "2023-05-05T15:39:28.420926+03:00", - "expirationDate": "0001-01-01T00:00:00Z", - "isExpired": true, - "creatorUa": "curl/7.68.0", - "generatedBy": "manual", - "lastUsed": "0001-01-01T00:00:00Z", - "label": "git", - "scopes": [ - "repo1", - "repo2" - ], - "uuid": "46a45ce7-5d92-498a-a9cb-9654b1da3da1" - }, - { - "createdAt": "2023-08-11T14:43:00.6459729+03:00", - "expirationDate": "2023-08-17T18:24:05+03:00", - "isExpired": false, - "creatorUa": "curl/7.68.0", - "generatedBy": "manual", - "lastUsed": "2023-08-11T14:43:47.5559998+03:00", - "label": "myAPIKEY", - "scopes": null, - "uuid": "294abf69-b62f-4e58-b214-dad2aec0bc52" - } - ] -} -``` - -> :pencil2: The actual API key (`apiKey`) is not shown. The key is shown to the user only when it is created. - - -## API endpoints reference - -The following is a list of zot API endpoints along with the conditions under which each endpoint is available. - -> :pencil2: Some API endpoints are available only when a specific extension is enabled in the zot configuration file, or when an extension build label is specified in the `make` command (for example, `make binary EXTENSIONS=ui`), or both. - -| Endpoint | Description | Availability | -| --- | ------------ | -------- | -| / | UI | Enabled by using the `ui` build label and enabling the `ui` extension in the configuration file. | -| /auth/login | With query parameters, opens an API session | Enabled by using the `ui` build label and enabling the `ui` extension in the configuration file. | -| /auth/logout | Ends an API session | Available when authentication is available. This includes not only OpenID, but all session-based authentication. | -| /auth/apikey | With query parameters, creates, lists, or deletes API keys | Available when API key authentication is enabled in the configuration file ("apikey": true). | -| /auth/callback | Redirects a login to a provider service | Available when OpenID authentication is enabled in the configuration file. | -| /oras/artifacts/v1/ | ORAS endpoints | Always enabled. | -| /metrics | Displays extended metrics | Available when the `metrics` build label is used and the `metrics` extension is enabled in the configuration file. | -| /swagger/v2/ | Displays the OpenAPI (formerly Swagger) documentation | Enabled by using the `debug` build label (`make binary-debug`). -| /v2/ | [OCI specification endpoints](https://github.com/opencontainers/distribution-spec/blob/main/spec.md#endpoints) | Always available. | -| /v2/_oci/ext/discover | Discover extensions per the OCI specification | Always available. | -| /v2/metrics | Displays basic metrics | Available when the `metrics` extension is disabled, whether or not the `metrics` build label was used. | -| /v2/_zot/ext/mgmt | Mgmt extension endpoints | Enabled by using the `mgmt` build label and enabling both the `search` and `ui` extensions in the configuration file. | -| /v2/_zot/ext/cosign | Uploads keys for signature verification | Enabled by using the `imagetrust` build label and enabling the `trust` extension with the `cosign` option enabled. | -| /v2/_zot/ext/notation | With query parameters, uploads certificates for signature verification | Enabled by using the `imagetrust` build label and enabling the `trust` extension with the `notation` option enabled. | -| /v2/_zot/ext/search | Enhanced search | Enabled by using the `search` build label and enabling the `search` extension in the configuration file. | -| /v2/_zot/ext/userprefs | User preferences endpoints | Enabled by using the `userprefs` build label and enabling both the `search` and the `ui` extensions in the configuration file. | -| /v2/_zot/debug/graphql-playground | [GraphQL](https://graphql.org/) playground | Enabled by using the `debug` build label. | - diff --git a/docs/developer-guide/api-reference.md b/docs/developer-guide/api-reference.md new file mode 100644 index 0000000..0d6fc42 --- /dev/null +++ b/docs/developer-guide/api-reference.md @@ -0,0 +1,1096 @@ +# zot API Command Reference + +> :point_right: This article describes the zot REST API commands, parameters, and responses. + +The information presented here is adapted from the interactive OpenAPI (formerly swagger) [JSON file](https://github.com/project-zot/zot/blob/main/swagger/swagger.json) in the zot Github project. + +For instructions and examples of how to use the zot API, see [Using the zot API](../developer-guide/api-user-guide.md). + + +## /auth/apikey + +### DELETE `/auth/apikey` + +Revokes one current user API key based on given key ID + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|id|query|string|true|api token id (UUID)| + +*Example responses* + +200 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|ok|string| +|400|[Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)|bad request|string| +|401|[Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1)|unauthorized|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error|string| + +This operation does not require authentication + +### GET `/auth/apikey` + +Get list of all API keys for a logged in user + +*Example responses* + +200 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|ok|string| +|401|[Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1)|unauthorized|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error|string| + +This operation does not require authentication + + +### POST `/auth/apikey` + +Can create an api key for a logged in user, based on the provided label and scopes. + +> Body parameter + +```json +{ + "expirationDate": "string", + "label": "string", + "scopes": [ + "string" + ] +} +``` + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|body|body|[api.APIKeyPayload](#schemaapi.apikeypayload)|true|api token id (UUID)| + +*Example responses* + +201 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|201|[Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)|created|string| +|400|[Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)|bad request|string| +|401|[Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1)|unauthorized|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error|string| + +This operation does not require authentication + +## `/auth/logout` + +### POST `/auth/logout` + +Logout by removing current session + +*Example responses* + +200 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|ok".|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error".|string| + +This operation does not require authentication + +## `/oras/artifacts/v1/{name}/manifests/{digest}/referrers` + +### GET `/oras/artifacts/v1/{name}/manifests/{digest}/referrers` + +Get references for an image given a digest and artifact type + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|name|path|string|true|repository name| +|digest|path|string|true|image digest| +|artifactType|query|string|true|artifact type| + +*Example responses* + +200 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|ok|string| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|not found|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error|string| + +This operation does not require authentication + +## `/v2/` + +### GET `/v2/` + +Check if this API version is supported + +*Example responses* + +200 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|ok".|string| + +This operation does not require authentication + +## `/v2/_catalog` + +### GET `/v2/_catalog` + +List all image repositories + +*Example responses* + +200 Response + +```json +{ + "repositories": [ + "string" + ] +} +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|[api.RepositoryList](#schemaapi.repositorylist)| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error|string| + +This operation does not require authentication + +## `/v2/_oci/ext/discover` + +### GET `/v2/_oci/ext/discover` + +List all extensions present on registry + +*Example responses* + +200 Response + +```json +{ + "extensions": [ + { + "description": "string", + "endpoints": [ + "string" + ], + "name": "string", + "url": "string" + } + ] +} +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|[api.ExtensionList](#schemaapi.extensionlist)| + +This operation does not require authentication + +## `/v2/_zot/ext/cosign` + +### POST `/v2/_zot/ext/cosign` + +Upload cosign public keys for verifying signatures + +> Body parameter + +```yaml +string + +``` + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|body|body|string|true|Public key content| + +*Example responses* + +200 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|ok|string| +|400|[Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)|bad request".|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error".|string| + +This operation does not require authentication + +## `/v2/_zot/ext/mgmt` + +### GET `/v2/_zot/ext/mgmt` + +Get current server configuration + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|resource|query|string|false|specify resource| + +*Enumerated Values* + +|Parameter|Value| +|---|---| +|resource|config| + +*Example responses* + +200 Response + +```json +{ + "binaryType": "string", + "distSpecVersion": "string", + "http": { + "auth": { + "bearer": { + "realm": "string", + "service": "string" + }, + "htpasswd": { + "path": "string" + }, + "ldap": { + "address": "string" + }, + "openid": { + "providers": { + "property1": { + "name": "string" + }, + "property2": { + "name": "string" + } + } + } + } + } +} +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|[extensions.StrippedConfig](#schemaextensions.strippedconfig)| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error".|string| + +This operation does not require authentication + +## `/v2/_zot/ext/notation` + +### POST `/v2/_zot/ext/notation` + +Upload notation certificates for verifying signatures + +> Body parameter + +```yaml +string + +``` + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|truststoreType|query|string|false|truststore type| +|body|body|string|true|Certificate content| + +*Example responses* + +200 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|ok|string| +|400|[Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)|bad request".|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error".|string| + +This operation does not require authentication + +## `/v2/_zot/ext/userprefs` + +### PUT `/v2/_zot/ext/userprefs` + +Add bookmarks/stars info + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|action|query|string|true|specify action| +|repo|query|string|true|repository name| + +*Enumerated Values* + +|Parameter|Value| +|---|---| +|action|toggleBookmark| +|action|toggleStar| + +*Example responses* + +200 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|ok|string| +|400|[Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)|bad request".|string| +|403|[Forbidden](https://tools.ietf.org/html/rfc7231#section-6.5.3)|forbidden|string| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|not found|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error|string| + +This operation does not require authentication + +## `/v2/{name}/blobs/{digest}` + +### DELETE `/v2/{name}/blobs/{digest}` + +Delete an image's blob/layer given a digest + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|name|path|string|true|repository name| +|digest|path|string|true|blob/layer digest| + +*Example responses* + +202 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|202|[Accepted](https://tools.ietf.org/html/rfc7231#section-6.3.3)|accepted|string| + +This operation does not require authentication + +### GET `/v2/{name}/blobs/{digest}` + +Get an image's blob/layer given a digest + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|name|path|string|true|repository name| +|digest|path|string|true|blob/layer digest| + +*Example responses* + +200 Response + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|[api.ImageManifest](#schemaapi.imagemanifest)| + +This operation does not require authentication + +### HEAD `/v2/{name}/blobs/{digest}` + +Check an image's blob/layer given a digest + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|name|path|string|true|repository name| +|digest|path|string|true|blob/layer digest| + +*Example responses* + +200 Response + +```json +{ + "annotations": { + "property1": "string", + "property2": "string" + }, + "artifactType": "string", + "config": { + "annotations": { + "property1": "string", + "property2": "string" + }, + "artifactType": "string", + "data": [ + 0 + ], + "digest": "string", + "mediaType": "string", + "platform": { + "architecture": "string", + "os": "string", + "os.features": [ + "string" + ], + "os.version": "string", + "variant": "string" + }, + "size": 0, + "urls": [ + "string" + ] + }, + "layers": [ + { + "annotations": { + "property1": "string", + "property2": "string" + }, + "artifactType": "string", + "data": [ + 0 + ], + "digest": "string", + "mediaType": "string", + "platform": { + "architecture": "string", + "os": "string", + "os.features": [ + "string" + ], + "os.version": "string", + "variant": "string" + }, + "size": 0, + "urls": [ + "string" + ] + } + ], + "mediaType": "string", + "schemaVersion": 0, + "subject": { + "annotations": { + "property1": "string", + "property2": "string" + }, + "artifactType": "string", + "data": [ + 0 + ], + "digest": "string", + "mediaType": "string", + "platform": { + "architecture": "string", + "os": "string", + "os.features": [ + "string" + ], + "os.version": "string", + "variant": "string" + }, + "size": 0, + "urls": [ + "string" + ] + } +} +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|[api.ImageManifest](#schemaapi.imagemanifest)| + +*Response Headers* + +|Status|Header|Type|Format|Description| +|---|---|---|---|---| +|200|constants.DistContentDigestKey|object||none| + +This operation does not require authentication + +## `/v2/{name}/blobs/uploads` + +### POST `/v2/{name}/blobs/uploads` + +Create a new image blob/layer upload + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|name|path|string|true|repository name| + +*Example responses* + +202 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|202|[Accepted](https://tools.ietf.org/html/rfc7231#section-6.3.3)|accepted|string| +|401|[Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1)|unauthorized|string| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|not found|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error|string| + +*Response Headers* + +|Status|Header|Type|Format|Description| +|---|---|---|---|---| +|202|Location|string||/v2/{name}/blobs/uploads/{session_id}| +|202|Range|string||0-0| + +This operation does not require authentication + +## `/v2/{name}/blobs/uploads/{session_id}` + +### DELETE `/v2/{name}/blobs/uploads/{session_id}` + +Delete an image's blob/layer given a digest + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|name|path|string|true|repository name| +|session_id|path|string|true|upload session_id| + +*Example responses* + +200 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|ok|string| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|not found|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error|string| + +This operation does not require authentication + +### GET `/v2/{name}/blobs/uploads/{session_id}` + +*Get an image's blob/layer upload given a session_id + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|name|path|string|true|repository name| +|session_id|path|string|true|upload session_id| + +*Example responses* + +204 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|204|[No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5)|no content|string| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|not found|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error|string| + +This operation does not require authentication + +### PATCH `/v2/{name}/blobs/uploads/{session_id}` + +Resume an image's blob/layer upload given an session_id + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|name|path|string|true|repository name| +|session_id|path|string|true|upload session_id| + +*Example responses* + +202 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|202|[Accepted](https://tools.ietf.org/html/rfc7231#section-6.3.3)|accepted|string| +|400|[Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)|bad request|string| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|not found|string| +|416|[Range Not Satisfiable](https://tools.ietf.org/html/rfc7233#section-4.4)|range not satisfiable|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error|string| + +*Response Headers* + +|Status|Header|Type|Format|Description| +|---|---|---|---|---| +|202|Location|string||/v2/{name}/blobs/uploads/{session_id}| +|202|Range|string||0-128| + +This operation does not require authentication + +### PUT `/v2/{name}/blobs/uploads/{session_id}` + +Update and finish an image's blob/layer upload given a digest + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|name|path|string|true|repository name| +|session_id|path|string|true|upload session_id| +|digest|query|string|true|blob/layer digest| + +*Example responses* + +201 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|201|[Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)|created|string| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|not found|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error|string| + +This operation does not require authentication + +## `/v2/{name}/manifests/{reference}` + +### DELETE `/v2/{name}/manifests/{reference}` + +Delete an image's manifest given a reference or a digest + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|name|path|string|true|repository name| +|reference|path|string|true|image reference or digest| + +*Example responses* + +200 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|ok|string| + +This operation does not require authentication + +### GET `/v2/{name}/manifests/{reference}` + +Get an image's manifest given a reference or a digest + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|name|path|string|true|repository name| +|reference|path|string|true|image reference or digest| + +*Example responses* + +200 Response + +```json +{ + "annotations": { + "property1": "string", + "property2": "string" + }, + "artifactType": "string", + "config": { + "annotations": { + "property1": "string", + "property2": "string" + }, + "artifactType": "string", + "data": [ + 0 + ], + "digest": "string", + "mediaType": "string", + "platform": { + "architecture": "string", + "os": "string", + "os.features": [ + "string" + ], + "os.version": "string", + "variant": "string" + }, + "size": 0, + "urls": [ + "string" + ] + }, + "layers": [ + { + "annotations": { + "property1": "string", + "property2": "string" + }, + "artifactType": "string", + "data": [ + 0 + ], + "digest": "string", + "mediaType": "string", + "platform": { + "architecture": "string", + "os": "string", + "os.features": [ + "string" + ], + "os.version": "string", + "variant": "string" + }, + "size": 0, + "urls": [ + "string" + ] + } + ], + "mediaType": "string", + "schemaVersion": 0, + "subject": { + "annotations": { + "property1": "string", + "property2": "string" + }, + "artifactType": "string", + "data": [ + 0 + ], + "digest": "string", + "mediaType": "string", + "platform": { + "architecture": "string", + "os": "string", + "os.features": [ + "string" + ], + "os.version": "string", + "variant": "string" + }, + "size20": 0, + "urls": [ + "string" + ] + } +} +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|[api.ImageManifest](#schemaapi.imagemanifest)| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|not found|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error|string| + +*Response Headers* + +|Status|Header|Type|Format|Description| +|---|---|---|---|---| +|200|constants.DistContentDigestKey|object||none| + +This operation does not require authentication + +### HEAD `/v2/{name}/manifests/{reference}` + +Check an image's manifest given a reference or a digest + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|name|path|string|true|repository name| +|reference|path|string|true|image reference or digest| + +*Example responses* + +200 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|ok|string| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|not found|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error".|string| + +*Response Headers* + +|Status|Header|Type|Format|Description| +|---|---|---|---|---| +|200|constants.DistContentDigestKey|object||none| + +This operation does not require authentication + +### PUT `/v2/{name}/manifests/{reference}` + +Update an image's manifest given a reference or a digest + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|name|path|string|true|repository name| +|reference|path|string|true|image reference or digest| + +*Example responses* + +201 Response + +```json +"string" +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|201|[Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)|created|string| +|400|[Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)|bad request|string| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|not found|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error|string| + +This operation does not require authentication + +## `/v2/{name}/referrers/{digest}` + +### GET `/v2/{name}/referrers/{digest}` + +Get referrers given a digest + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|name|path|string|true|repository name| +|digest|path|string|true|digest| +|artifactType|query|string|false|artifact type| + +*Example responses* + +200 Response + +```json +{ + "annotations": { + "property1": "string", + "property2": "string" + }, + "artifactType": "string", + "manifests": [ + { + "annotations": { + "property1": "string", + "property2": "string" + }, + "artifactType": "string", + "data": [ + 0 + ], + "digest": "string", + "mediaType": "string", + "platform": { + "architecture": "string", + "os": "string", + "os.features": [ + "string" + ], + "os.version": "string", + "variant": "string" + }, + "size": 0, + "urls": [ + "string" + ] + } + ], + "mediaType": "string", + "schemaVersion": 0, + "subject": { + "annotations": { + "property1": "string", + "property2": "string" + }, + "artifactType": "string", + "data": [ + 0 + ], + "digest": "string", + "mediaType": "string", + "platform": { + "architecture": "string", + "os": "string", + "os.features": [ + "string" + ], + "os.version": "string", + "variant": "string" + }, + "size": 0, + "urls": [ + "string" + ] + } +} +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|[api.ImageIndex](#schemaapi.imageindex)| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|not found|string| +|500|[Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1)|internal server error|string| + +This operation does not require authentication + +## `/v2/{name}/tags/list` + +### GET `/v2/{name}/tags/list` + +List all image tags in a repository + +*Parameters* + +|Name|In|Type|Required|Description| +|---|---|---|---|---| +|name|path|string|true|test| +|n|query|integer|true|limit entries for pagination| +|last|query|string|true|last tag value for pagination| + +*Example responses* + +200 Response + +```json +{ + "name": "string", + "tags": [ + "string" + ] +} +``` + +*Responses* + +|Status|Meaning|Description|Schema| +|---|---|---|---| +|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|[common.ImageTags](#schemacommon.imagetags)| +|400|[Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)|bad request".|string| +|404|[Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)|not found|string| + +This operation does not require authentication diff --git a/docs/developer-guide/api-user-guide.md b/docs/developer-guide/api-user-guide.md new file mode 100644 index 0000000..c7600d0 --- /dev/null +++ b/docs/developer-guide/api-user-guide.md @@ -0,0 +1,245 @@ +# Using the zot API + +> :point_right: This document describes how to use the zot REST API and provides a number of examples. + +For comprehensive details of all zot API commands, see [Viewing the complete zot API reference](#_find_reference). + +The zot API implements the [OCI Distribution endpoints](https://github.com/opencontainers/distribution-spec/blob/main/spec.md#endpoints) along with additional endpoints for supported extensions. You can access the REST API at the same URL and port number used by the GUI and by datapath tools. + +> :pencil2: The examples in this article assume that the zot registry is located at `localhost:8080`. + + +## Supported API endpoints + +The following is a list of zot API endpoints along with the conditions under which each endpoint is available. + +> :pencil2: Some API endpoints are available only when a specific extension is enabled in the zot configuration file, or when an extension build label is specified in the `make` command (for example, `make binary EXTENSIONS=ui`), or both. + +For comprehensive details of these zot API endpoints, see [Viewing the complete zot API reference](#_find_reference). + +| Endpoint | Actions | Description | Availability | +| --- | ------------ | -------- | --------| +| / | | Web interface | Enabled by using the `ui` build label and enabling the `ui` extension in the configuration file. | +| /auth/apikey| DELETE, GET, POST | Creates, lists, or deletes API keys | Available when API key authentication is enabled in the configuration file ("apikey": true). | +| /auth/logout| POST | Ends an API session | Available when authentication is available. This includes not only OpenID, but all session-based authentication. | +| /oras/artifacts/v1/_zot/ \ manifests/{digest}/referrers| GET | [OCI Registry As Storage (ORAS)](https://oras.land/) endpoints | Always enabled. | +| /v2/| GET | [OCI specification endpoints](https://github.com/opencontainers/distribution-spec/blob/main/spec.md#endpoints) | Always available. | +| /v2/_catalog| GET | | +| /v2/_oci/ext/discover| GET | Discover extensions per the OCI specification | Always available. | +| /v2/_zot/ext/cosign| POST | Uploads keys for signature verification | Enabled by using the `imagetrust` build label and enabling the `trust` extension with the `cosign` option enabled. | +| /v2/_zot/ext/mgmt| GET | Mgmt extension endpoints | Enabled by using the `mgmt` build label and enabling both the `search` and `ui` extensions in the configuration file. | +| /v2/_zot/ext/notation| POST | With query parameters, uploads certificates for signature verification | Enabled by using the `imagetrust` build label and enabling the `trust` extension with the `notation` option enabled. | +| /v2/_zot/ext/search | | Enhanced search | Enabled by using the `search` build label and enabling the `search` extension in the configuration file. | +| /v2/_zot/ext/userprefs| PUT | User preferences endpoints | Enabled by using the `userprefs` build label and enabling both the `search` and the `ui` extensions in the configuration file. | +| /v2/_zot/blobs/{digest}| DELETE, GET, HEAD | | +| /v2/_zot/blobs/uploads| POST | | +| /v2/_zot/blobs/uploads/{session_id}| DELETE, GET, PATCH, PUT | | +| /v2/_zot/manifests/{reference}| DELETE, GET, HEAD, PUT | | +| /v2/_zot/referrers/{digest}| GET | | + + + !!! REVIEW QUESTIONS: + + 1. Are these deprecated? + /auth/login + /auth/callback + /metrics + /swagger/v2/ + /v2/metrics + /v2/_zot/debug/graphql-playground + + 2. Can someone send me an API example (command and response) of uploading cosign OR notation credentials? + + +## API authentication + +> :pencil2: If [zot authentication](../articles/authn-authz.md) is not configured, any user can access the zot API. + +When pushing and pulling images using API calls, your identity can be authenticated by either a password or an API key. + +With a valid password, you can specify your credentials in a cURL request as shown in this example: + + curl -u : -X GET http:/// + +An API key has advantages in situations where the primary zot authentication does not use the command line, such as a GUI login or social login. Also, you can reduce your security exposure by using an API key instead of your broader credentials, such as an LDAP username and password. + + +### Using API keys + +#### Enabling API keys + +To enable the use of API keys, you must set the `apikey` attribute to `true` in the zot configuration file, as shown in the following example: + +```json + "http": { + "auth": { + "apikey": true + } + } +``` + +#### Creating your API key + +Before you can create or revoke an API key, you must first log in using a different authentication mechanism, such as logging in through the zot GUI. When you are logged in, you can create an API key for your identity using the following API command: + + POST /auth/apikey + +_cURL command example:_ + + curl -u user:password -X POST http://localhost:8080/auth/apikey -d '{"label": "myAPIKEY", "scopes": ["repo1", "repo2"], "expirationDate": "2023-08-28T17:10:05+03:00"}' + +> :pencil2: The scopes and expiration date in this example are optional. By default, an API key has the same permissions as the user who created it. + +_Command output:_ + +```json +{ + "createdAt":"2023-08-28T17:09:59.2603515+03:00", + "expirationDate":"2023-08-28T17:10:05+03:00", + "isExpired":false, + "creatorUa":"curl/7.68.0", + "generatedBy":"manual", + "lastUsed":"0001-01-01T00:00:00Z", + "label":"myAPIKEY", + "scopes": [ + "repo1", + "repo2" + ], + "uuid":"c931e635-a80d-4b52-b035-6b57be5f6e74", + "apiKey":"zak_ac55a8693d6b4370a2003fa9e10b3682" +} +``` + +> :pencil2: The API key (`apiKey`) is shown to the user only in the command output when the key is created. It cannot be later retrieved from zot with any other command. + + +#### Using your API key in an API command + +The API key replaces a password in the API command, as shown in the following cURL example: + + curl -u user:zak_e77bcb9e9f634f1581756abbf9ecd269 http://localhost:8080/v2/_catalog + + +#### Removing your API key + +When logged in, you can revoke your own API key with the following API command: + + DELETE /auth/apikey?id=$uuid + +_cURL command example:_ + + curl -u user:password -X DELETE http://localhost:8080/v2/auth/apikey?id=46a45ce7-5d92-498a-a9cb-9654b1da3da1 + + +#### Listing your current API keys + +When logged in, you can display a list of your API keys with the following API command: + + GET /auth/apikey + +_cURL command example:_ + + curl -u user:password -X GET http://localhost:8080/auth/apikey + +_Command output:_ + +```json +{ + "apiKeys": [ + { + "createdAt": "2023-05-05T15:39:28.420926+03:00", + "expirationDate": "0001-01-01T00:00:00Z", + "isExpired": true, + "creatorUa": "curl/7.68.0", + "generatedBy": "manual", + "lastUsed": "0001-01-01T00:00:00Z", + "label": "git", + "scopes": [ + "repo1", + "repo2" + ], + "uuid": "46a45ce7-5d92-498a-a9cb-9654b1da3da1" + }, + { + "createdAt": "2023-08-11T14:43:00.6459729+03:00", + "expirationDate": "2023-08-17T18:24:05+03:00", + "isExpired": false, + "creatorUa": "curl/7.68.0", + "generatedBy": "manual", + "lastUsed": "2023-08-11T14:43:47.5559998+03:00", + "label": "myAPIKEY", + "scopes": null, + "uuid": "294abf69-b62f-4e58-b214-dad2aec0bc52" + } + ] +} +``` + +This command output example shows an expired key and a current key for this user. + +> :pencil2: The actual API key (`apiKey`) is not shown. The key is shown to the user only when it is created. + +## API examples + +> :pencil2: The following examples assume that the zot registry is located at `localhost:8080`. + +### Listing repositories + +To get a list of all image repositories in the registry, use the following API endpoint: + + GET /v2/_catalog + +_cURL command example:_ + + curl -X GET http://localhost:8080/v2/_catalog + +_Command output:_ + +```json +{ + "repositories": ["alpine", "busybox"] +} + +``` + +### Discovering extension endpoints + +To list the installed and enabled zot extensions that can be accessed through the API, use the following OCI API endpoint: + + GET /v2/_oci/ext/discover + +_cURL command example:_ + + curl -X GET http://localhost:8080/v2/_oci/ext/discover + +_Command output:_ + +```json +{ + "extensions": [ + { + "name": "_zot", + "url": "https://github.com/project-zot/zot/blob//pkg/extensions/_zot.md", + "description": "zot registry extensions", + "endpoints": ["/v2/_zot/ext/search", "/v2/_zot/ext/userprefs", "/v2/_zot/ext/mgmt"] + }] +} + +``` + + + + +## Viewing the complete zot API reference + +You can find comprehensive details of all zot API commands in either of the following locations: + +- As text descriptions in the [zot API Command Reference](../developer-guide/api-reference.md) in the zot documentation. + +- As an interactive OpenAPI (swagger) [JSON file](https://github.com/project-zot/zot/blob/main/swagger/swagger.json) in the zot Github project. + + There are many ways to view a swagger file as an interactive document. If you have the `npm` package installed, for example, you can execute the following command: + + $ npx open-swagger-ui swagger.json + + This command creates a local web server at `localhost:3355` where you can interact with the API reference using a browser. diff --git a/mkdocs.yml b/mkdocs.yml index 0b42c94..8a194d4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -110,7 +110,8 @@ nav: - Developer Guide: - Onboarding: developer-guide/onboarding.md - Extensions: developer-guide/extensions-dev.md - - Using the API: developer-guide/api-guide.md + - Using the API: developer-guide/api-user-guide.md + - API Reference: developer-guide/api-reference.md - Contributing: developer-guide/contributing.md - Articles: - CI/CD Pipeline: articles/building-ci-cd-pipeline.md