From d82cf3406b46ba4e0b24cb2ef3ff4dd7871f0cae Mon Sep 17 00:00:00 2001 From: Guillaume Mourier Date: Tue, 3 May 2022 15:59:15 +0200 Subject: [PATCH 01/17] Add an uid to make API Keys determinists, plus add a non-unique human readable name field to ease reading information --- open-api.yaml | 93 ++++--- text/0085-api-keys.md | 576 +++++++++++++++--------------------------- 2 files changed, 268 insertions(+), 401 deletions(-) diff --git a/open-api.yaml b/open-api.yaml index 28dad7d6..329d5fc1 100644 --- a/open-api.yaml +++ b/open-api.yaml @@ -562,9 +562,13 @@ components: title: key type: object properties: + uid: + type: string + description: A uuid v4 to identify the API Key. If not specified, it's generated by Meilisearch. + example: 01b4bc42-eb33-4041-b481-254d00cce834 key: type: string - description: The generated key. Generated by Meilisearch. + description: The derived key to use in the Authorization header to authorize requests. Generated by Meilisearch with a SHA-256 hash of the uid and the master key. example: d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4 readOnly: true actions: @@ -595,6 +599,12 @@ components: items: type: string example: movies + name: + type: + - string + - 'null' + description: A human-readable name for the key. null if empty. + default: null description: type: - string @@ -2574,12 +2584,14 @@ paths: example-1: value: results: - - key: d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4 + - uid: 01b4bc42-eb33-4041-b481-254d00cce834 + key: d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4 + name: An API Key + description: null actions: - documents.add indexes: - movies - description: An API Key expiresAt: '2022-11-12T10:00:00Z' createdAt: '2021-11-12T10:00:00Z' updatedAt: '2021-11-12T10:00:00Z' @@ -2591,32 +2603,33 @@ paths: parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/offset' - '/keys/{key}': - get: - summary: Get an API key - tags: - - Keys - security: - - apiKey: [] - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/key' - examples: - Fetch an API Key details: - value: - description: Indexing Products API key - key: d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4 - actions: - - documents.add - indexes: - - products - expiresAt: '2021-11-13T00:00:00Z' - createdAt: '2021-11-12T10:00:00Z' - updatedAt: '2021-11-12T10:00:00Z' + '/keys/{uid}': + summary: Get an API key from its uid + tags: + - Keys + security: + - apiKey: [] + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/key' + examples: + Fetch an API Key details: + value: + uid: 01b4bc42-eb33-4041-b481-254d00cce834 + key: d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4 + name: Indexing Products API key + description: null + actions: + - documents.add + indexes: + - products + expiresAt: '2021-11-13T00:00:00Z' + createdAt: '2021-11-12T10:00:00Z' + updatedAt: '2021-11-12T10:00:00Z' operationId: keys.get description: Get an API Key parameters: @@ -2654,8 +2667,10 @@ paths: examples: Patch an API Key Response: value: - description: Indexing Products API key + uid: 01b4bc42-eb33-4041-b481-254d00cce834 key: d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4 + name: Indexing Products API key + description: null actions: - documents.add indexes: @@ -2670,7 +2685,17 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/key' + type: object + properties: + name: + type: + - string + - 'null' + description: + type: + - string + - 'null' + additionalProperties: false examples: Patch an API Key Request: value: @@ -2692,8 +2717,10 @@ paths: examples: Create an API Key: value: - description: Indexing Products API key + uid: 01b4bc42-eb33-4041-b481-254d00cce834 key: d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4 + name: Indexing Products API key + description: null actions: - documents.add indexes: @@ -2711,7 +2738,7 @@ paths: examples: API Key Creation: value: - description: Indexing Products API key + name: Indexing Products API key actions: - documents.add indexes: diff --git a/text/0085-api-keys.md b/text/0085-api-keys.md index b14057ef..9ed9fc4c 100644 --- a/text/0085-api-keys.md +++ b/text/0085-api-keys.md @@ -1,89 +1,81 @@ -- Title: API Keys -- Start Date: 2021-10-15 -- Specification PR: [#85](https://github.com/meilisearch/specifications/pull/85) -- Discovery Issue: [#51](https://github.com/meilisearch/product/issues/51) - # API Keys -## 1. Functional Specification +## 1. Summary -### 1.1 Summary +API keys allows to define which actions and which indexes are accessible by the holder of an API key. The use of API keys allows to secure the access to the routes in a fine-grained manner of a Meilisearch instance. -Granular management of API keys is added to MeiliSearch. It is possible to restrict the access of an API key to certain actions on specific indexes. +## 2. Motivation -### 1.2 Motivation +To make Meilisearch more reliable for teams and more adapted to production cases, we extend the management and the possibilities of restrictions regarding write and read requests on a Meilisearch instance by introducing a way to manage custom API keys. -To make MeiliSearch more reliable for teams, we extend the management and the possibilities of restrictions for the management of a MeiliSearch instance by introducing a concrete API resource (`API Key`). Security is a critical need, often tricky to negotiate as the stakes are high for a company. +## 3. Functional Specification -### 1.3 Glossary +### 3.1. Glossary | Term | Definition | |--------------------|------------| -| Master Key | This is the master key that allows you to create other API keys. The master key is defined by the user when launching MeiliSearch, thus gives access to the `/keys` API endpoint. | -| API Key | API keys are stored and managed from the endpoint `/keys` by the master key holder. These are the keys used by the technical teams to interact with MeiliSearch at the level of the client code. | - -### 1.4 Personas +| Master Key | This is the master key that allows managing API keys. The master key is defined by the user when launching Meilisearch, thus gives access to the `/keys` API endpoint and requiring requests to be authorized. | +| API Key | API keys are stored and managed from the endpoint `/keys` by the master key holder. | -| Persona | Role | -|---------|------| -| Anna | Anna has an `ssh` access to the MeiliSearch instance and manages it on a daily basis. | -| Mark | Mark is a developer from the same company as Anna. He will implement the code to communicate with MeiliSearch to solve technical/product needs. | +### 3.2. Explanation -### 1.5 `API Key` Explanations +#### 3.2.1 Summary Key Points -#### 1.5.1 Summary Key Points +- API keys management is restricted to the master key holder. +- API keys must be provided via the `Authorization` header using the bearer method to authorize a request. +- The value of the `key` field of an API Key is generated from its `uid` and the master key. +- When a master key is set at Meilisearch first-launch, it generate two pre-configured default `API Key` resources. A `Default Search API Key` authorizing the search action on all indexes and a `Default Admin API Key` authorizing all actions on all indexes (except managing `/keys` resource). +- If the master-key changes, all `key` field are re-generated. +- Default API keys can be modified/deleted from the `/keys` endpoints but are not re-created if Meilisearch has already created them. +- The master key can only be used to manage API keys. Using the master-key for any other request other than on `/keys` returns an authorization error. +- API keys can have restrictions on which methods can be accessed via an `actions` list; they also `expiresAt` a specific date time and are restricted to a specific set of `indexes`. +- `name` and `description` fields are the only editable fields of an API key. +- API key resources are propagated to snapshots and dumps. -- `X-MEILI-API-KEY` header is replaced by the `Authorization` header. `API keys` must be specified with the bearer authorization method. See examples. -- `/keys` management is restricted to the master key. -- When a master key is set at MeiliSearch first-launch, we generate two pre-configured default `API Key` resources. A `Default Search API Key` restricted to the search action and a `Default Admin API Key` to handle all operations (except managing `/keys` resource) on MeiliSearch. -- If the master-key changes, all `API Keys` are re-generated. -- These default API Keys can be modified/deleted with the `/keys` endpoint but are not re-created if MeiliSearch has already created them. -- New endpoints are added to manage the `API Key` resource. -- `API keys` can have restrictions on which methods can be accessed via an `actions` list; they can also `expiresAt` a specific date time and be restricted to a specific set of `indexes`. -- There is no possibility to regenerate the value of the `key` field for a specific `API key` in this first iteration. -- New errors are added and the `missing_authorization_header` message is updated. -- The current state of the `API Keys` resource is propagated to snapshots and dumps. +#### 3.2.2. Master Key -#### 1.5.2 Master Key +The master key exists to secure a Meilisearch instance. As soon as a master key is set via the `MEILI_MASTER_KEY` environment variable or the `--master-key` CLI option, the endpoint `/keys` is accessible for the master key holder. It can be seen as a super admin key; It must be securely shared only with people who have to manage the security of a Meilisearch instance. -The master key exists to secure a MeiliSearch instance. As soon as a master key is set via the `MEILI_MASTER_KEY` environment variable or the `--master-key` CLI option , the endpoint `/keys` is accessible only for the master key holder. It can be seen as a super admin key; It must be shared only with people who have to manage the security of a MeiliSearch instance. +This master key is not an API key, thus is not stored and fetchable from the `/keys` API endpoint. It must be seen as a runtime lock that activates the security of Meilisearch as soon as an instance is launched with it. The master key can only be used to manage API Keys. Using the master key for any other request other than on `/keys` returns an authorization error. -This master key is not an API Key, thus is not stored and fetchable from the `/keys` API endpoint. It must be seen as a runtime lock that activates the security of MeiliSearch as soon as an instance is launched with it. +At the first launch of Meilisearch with a master key, Meilisearch automatically generates two default API keys to cover the basic needs a user may encounter. It generates a `Default Search API Key` dedicated to the search that can be used on the client-side and a `Default Admin API Key` to manipulate a MeiliSearch instance from a backend side. -At the first launch of MeiliSearch with a master key, MeiliSearch automatically generates two default API keys (See the `GET - /keys` example) to cover many of the most basic needs. It generates a `Default Search API Key` dedicated to the search that can be used on the client-side and a `Default Admin API Key` to manipulate a MeiliSearch instance from a backend side. +If the master key is removed at Meilisearch launch, the previously generated API keys no longer secure the Meilisearch instance. -If the master key is removed at MeiliSearch launch, the previously generated API keys no longer secure the MeiliSearch instance. +If Meilisearch is launched with the `production` value for the `MEILI_ENV` environment variable or the `--env` CLI option, a master key is mandatory. If the master key is omitted in that particular case, MeiliSearch launch is aborted and displays an error: -If MeiliSearch is launched with the `production` value for the `MEILI_ENV` environment variable or the `--env` CLI option, a master key is mandatory to force the user to secure his instance. If the master key is omitted in that particular case, MeiliSearch launch is aborted and displays the `Error: In production mode, the environment variable MEILI_MASTER_KEY is mandatory` error in stdout. +`Error: In production mode, the environment variable MEILI_MASTER_KEY is mandatory` -The master key must be composed of valid utf-8 characters. It is advisable to enclose it in `'` when specified via the --master-key option. +The master key must be composed of valid utf-8 characters. It is advisable to enclose it in `'` when specified via the `--master-key` option. -> 🚨 A user coming from a version prior to v0.25.0 and having a master-key will have to update their code to use the newly generated default keys replacing the public and private, since we changed the previous `public` and `private` API Key generation, is it mandatory for that specific version upgrade. Now, a prefix of an API Key is generated uniquely and the final value of the `key` field is a hash of that randomized prefix with the master-key. See 2.1 API Key Generation part. +> 🚨 The master key should never be exposed to the public as it may compromise a Meilisearch instance. -> 🚨 The master-key should never be exposed to the public or bad-intentioned persons for security measures as it may compromise a MeiliSearch instance. +> 🚨 If the value of the master key changes, all the previously generated `API Keys` changes, thus allows to invalidate the set of API keys previously generated by regenerating a different value for their `key` field. This is particularly useful in the case where the master key might have been leaked and the user need to re-generate the whole set of keys at once to re-secure the instance. -> 🚨 If the value of the master key changes, all the previously generated `API Keys` changes, thus allows to invalidate the set of keys previously generated by regenerating to a different value for the `key` field. This is particularly useful in the case where the master key might have been leaked and the user need to re-generate the whole set of keys at once to re-secure the instance. +> The master key does not appear on the `/keys` endpoints and can't be used to authorize requests other than on the `/keys` endpoint. -> Note that the master key does not appear on the `/keys` endpoints. +> The only route not secured in the presence of a master key is the `/health` route. -#### 1.5.3 Default API Keys +#### 3.2.3. Default API Keys -When the user accessing the machine launches MeiliSearch with a `master` key the first time, MeiliSearch will generate two API keys described below, as it did before with the `public` and `private` key. +The first time a Meilisearch is launched with a `master key`, Meilisearch will generate two API keys described below. -If the user changes the value of the `master` key later, these two default keys are not created again but re-generated with a different `key` field. However, these two API keys can be changed using the `/keys` endpoints. +If the user changes the value of the master key later, these two default keys are not created again but re-generated with a different `key` field. However, these two API keys can be updated/deleted using the `/keys` endpoints. -MeiliSearch must know that it has already generated these Default API Keys internally so if the user delete them, the engine should not create them again when MeiliSearch is launched again with a `master` key. +If these API keys are deleted, the engine should not create them again when Meilisearch is launched again with a master key. -##### 1.5.3.1 Default Search API Key +##### 3.2.3.1. Default Search API Key -The `Default Search API key` gives access to the same rights as the old `public` key. +The `Default Search API key` gives access to the search endpoints on all indexes. Here is how the `Default Search API Key` is represented after its generation. -```json +```jsonc { - "description": "Default Search API Key (Use it to search from the frontend)", - "key": "0a6e572506c52ab0bd6195921575d23092b7f0c284ab4ac86d12346c33057f99", //example + "uid": "01b4bc42-eb33-4041-b481-254d00cce834", //auto-generated value + "key": "0a6e572506c52ab0bd6195921575d23092b7f0c284ab4ac86d12346c33057f99", //auto-generated value + "name": "Default Search API Key", + "description": "(Use it to search from the frontend)", "actions": [ "search" ], @@ -91,21 +83,23 @@ Here is how the `Default Search API Key` is represented after its generation. "*" ], "expiresAt": null, - "createdAt": "2021-08-11T10:00:00Z", //example + "createdAt": "2021-08-11T10:00:00Z", "updatedAt": "2021-08-11T10:00:00Z" } ``` -##### 1.5.3.2 Default Admin API Key +##### 3.2.3.2. Default Admin API Key -The `Default Admin API key` gives access to the same rights as the old `private` key. +The `Default Admin API key` gives access to all actions on all indexes except managing the API Keys. Here is how the `Default Admin API Key` is represented after its generation. -```json +```jsonc { - "description": "Default Admin API Key (Use it for all other operations. Caution! Do not use it on a public frontend)", - "key": "380689dd379232519a54d15935750cc7625620a2ea2fc06907cb40ba5b421b6f", //example + "uid": "ac06a7e1-6956-4699-bb04-dbeb72a231df", //auto-generated value + "key": "380689dd379232519a54d15935750cc7625620a2ea2fc06907cb40ba5b421b6f", //auto-generated value + "name": "Default Admin API Key", + "description": "(Use it for all other than search operations. Caution! Do not expose it on a public frontend)", "actions": [ "*" ], @@ -113,261 +107,34 @@ Here is how the `Default Admin API Key` is represented after its generation. "*" ], "expiresAt": null, - "createdAt": "2021-08-11T10:00:00Z", //example + "createdAt": "2021-08-11T10:00:00Z", "updatedAt": "2021-08-11T10:00:00Z" } ``` -#### 1.5.3 Managing `API Key` - -![](https://i.imgur.com/mAUFnNb.png) - -`Anna` manages the MeiliSearch instance; she uses the master key she defined at startup to generate an `API Key` resource for `Mark` to use in his client code to communicate with the MeiliSearch instance. - -`Anna` can define access rights to certain indexes to define an expiration date and also authorized `actions` for an `API Key` (See API Key Actions List Definition Part). +#### 3.2.4. API Endpoints Definition -Only the master key allows managing the API keys. +Manipulate API keys of a Meilisearch instance. `/keys` endpoints are **only accessible by the master key holder.** -#### 1.5.4 `API Key` object representation +##### 3.2.4.1. `API Key` Resource Representation | field | type | description | |-------------|---------|--------------------------------------------------| +| uid | string | A unique identifier represented by a uuid v4. Can be specified at creation or generated by Meilisearch if ommited. | +| key | string | The generated key to use when in the Authorization header when making requests. **Generated by MeiliSearch by a combination of uid and the master key**. | +| name | string | A non unique human readable name to ease identification of the API key. `null` if empty. | | description | string | A description for the key. `null` if empty. | -| key | string | The generated key. **Generated by MeiliSearch**. | -| actions | array | A list of actions permitted for the key. `["*"]` for all actions. See Actions list definition part. | +| actions | array | A list of actions permitted for the key. `["*"]` for all actions. See Actions List Definition part. | | indexes | array | A list of indexes permitted for the key. `["*"]` for all indexes. | | expiresAt | string | Represent the expiration date and time as `RFC 3339` format. `null` equals to no expiration time. | | createdAt | string | Represent the date and time as `RFC 3339` format when the API key has been created. **Generated by MeiliSearch** | | updatedAt | string | Represent the date and time as `RFC 3339` format when the API key has been updated. **Default**: Value of `createdAt`. **Generated by MeiliSearch** | -#### 1.5.5 `POST`/ `PATCH` - `/keys` - API Key object payload definition - -| field | type | required |description | -|-------------|---------|----------|--------------------------------| -| indexes | array | Required | `[*]` for all indexes. **Default**: `No Default` | -| description | string | Optional | A description for the API key. **Default**: `null` | -| actions | array | Required | A list of actions permitted for the API key. `["*"]` for all actions. **See Actions list definition part**. `*` character can be used as a wildcard. e.g. `documents.*` to authorize access on all documents endpoints. **Default**: `No default` | -| expiresAt | string | Required | The expiration date and time as `RFC 3339` format. `null` equals to no expiration time. Sending only the date part e.g `2021-12-01` leads to having an `expiresAt` value set to `2021-12-01T00:00:00`. **Default**: `No Default` | - - -#### 1.5.6 Actions List Definition - -> `:authorizedIndexes` can be any value extracted from the `indexes` field of an `API key` resource. - -| name | description | -|---------|-------------| -| search | Provides access to `GET` and `POST` methods on `/indexes/:authorizedIndexes/search` routes. | -| documents.add | Provides access to `POST` and `PUT` on `/indexes/:authorizedIndexes/documents` routes. | -| documents.get | Provides access to `GET` methods on `/indexes/:authorizedIndexes/documents` and `/indexes/:authorizedIndexes/documents/:documentId` routes. | -| documents.delete | Provides access to `DELETE` method on `/indexes/:authorizedIndexes/documents/:documentId`, `indexes/:authorizedIndexes/documents/:documentId` and `POST` method on `/indexes/:authorizedIndexes/documents/delete-batch` routes. | -| indexes.create | Provides access to `POST` `/indexes`. **⚠️ `indexes` field should indicate the newly created index or having `[*]` to permits access on it.**. | -| indexes.get | Provides access to `GET` `/indexes` and `/indexes/:authorizedIndexes`. **⚠️Non-authorized `indexes` are omitted from the response on `/indexes`**. | -| indexes.update | Provides access to `PUT` `/indexes/:authorizedIndexes`. | -| indexes.delete | Provides access to `DELETE` `/indexes/:authorizedIndexes`. | -| tasks.get | Provides access to `GET` `/tasks`. **⚠️Non-authorized `indexes` are omitted from the response on `/tasks`**. Also add access to `GET` `/indexes/:authorizedIndexes/tasks` routes. | -| settings.get | Provides access to `GET` `/indexes/:authorizedIndexes/settings` and `/indexes/:authorizedIndexes/settings/*` routes. | -| settings.update | Provides access to `POST / DELETE` `/indexes/:authorizedIndexes/settings` and `/indexes/:authorizedIndexes/settings/*` routes. | -| stats.get | Provides access to `GET` `/stats/`. **⚠️Non-authorized `indexes` are omitted from the response on `/stats`**. Also add access to `GET` `/indexes/:authorizedIndexes/stats`. | -| dumps.create | Provides access to `POST` `/dumps` route. **As dumps are not scoped by indexes, a restriction on `indexes` does not affect this action.** | -| version | Provides access to `GET` `/version` route. - ---- - -#### **As `Anna πŸ‘©`, I want to create an `API key` for `Mark πŸ‘¨πŸ»` client-code, so that he can index some documents into MeiliSearch** - -##### Request Definition - -`POST` - `/keys` - -##### Headers - -``` -"Authorization: Bearer :masterKey" -"Content-Type: application/json" -``` - -##### Body Payload - -```json -{ - "description": "Indexing Products API key", - "actions": [ - "documents.add" - ], - "indexes": ["products"], - "expiresAt": "2021-11-13T00:00:00Z" -} -``` - -##### Response - -`201 Created` - -```json -{ - "description": "Indexing Products API key", - "key": "d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4", - "actions": [ - "documents.add" - ], - "indexes": ["products"], - "expiresAt": "2021-11-13T00:00:00Z", - "createdAt": "2021-11-12T10:00:00Z", - "updatedAt": "2021-11-12T10:00:00Z" -} -``` - -##### Requirements - -- `actions` is mandatory and should be an array of valid `actions`. -- `indexes` is mandatory and should be an array of string. -- `expiresAt` is mandatory and must be a valid `RFC 3339` datetime in the future or `null`. -- If set, `description` should be a string or `null`. - -##### Errors - -- πŸ”΄ Accessing this route without the `Authorization` header returns a [missing_authorization_header](0061-error-format-and-definitions.md#missing_authorization_header) error. -- πŸ”΄ Accessing this route with a key that does not have permissions (i.e. other than the master-key) returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. -- πŸ”΄ Omitting Content-Type header returns a [missing_content_type](0061-error-format-and-definitions.md#missing_content_type) error. -- πŸ”΄ Sending an empty Content-Type returns an [invalid_content_type](0061-error-format-and-definitions.md#invalid_content_type) error. -- πŸ”΄ Sending a different Content-Type than `application/json` returns an [invalid_content_type](0061-error-format-and-definitions.md#invalid_content_type) error. -- πŸ”΄ Sending an empty payload returns a [missing_payload](0061-error-format-and-definitions.md#missing_payload) error. -- πŸ”΄ Sending a different payload type than the Content-Type header returns a [malformed_payload](0061-error-format-and-definitions.md#malformed_payload) error. -- πŸ”΄ Sending an invalid json format returns a [malformed_payload](0061-error-format-and-definitions.md#malformed_payload) error. -- πŸ”΄ Omitting `actions` field from the payload returns a [missing_parameter](0061-error-format-and-definitions.md#missing_parameter) error. -- πŸ”΄ Omitting `indexes` field from the payload returns a [missing_parameter](0061-error-format-and-definitions.md#missing_parameter) error. -- πŸ”΄ Omitting `expiresAt` field from the payload returns a [missing_parameter](0061-error-format-and-definitions.md#missing_parameter) error. -- πŸ”΄ Sending an invalid value for the `actions` field returns an [invalid_api_key_actions](0061-error-format-and-definitions.md#invalid_api_key_actions) error. -- πŸ”΄ Sending an invalid value for the `indexes` field returns an [invalid_api_key_indexes](0061-error-format-and-definitions.md#invalid_api_key_indexes) error. -- πŸ”΄ Sending an invalid value for the `expiresAt` field returns an [invalid_api_key_expires_at](0061-error-format-and-definitions.md#invalid_api_key_expires_at) error. -- πŸ”΄ Sending an invalid value for the `description` field returns an [invalid_api_key_description](0061-error-format-and-definitions.md#invalid_api_key_description) error. - ---- - -#### **As `Anna πŸ‘©`, I want to get details about an `API Key`** - -##### Request Definition - -`GET` - `/keys/:key` - -##### Headers - -``` -"Authorization: Bearer :masterKey" -``` - -##### Response - -`200 Success` - -```json -{ - "description": "Indexing API key", - "key": "d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4", - "actions": [ - "documents.add" - ], - "indexes": [ - "products" - ], - "expiresAt": "2021-11-13T00:00:00Z", - "createdAt": "2021-11-12T10:00:00Z", - "updatedAt": "2021-11-12T10:00:00Z" -} -``` - -##### Errors - -- πŸ”΄ Accessing this route without the `Authorization` header returns a [missing_authorization_header](0061-error-format-and-definitions.md#missing_authorization_header) error. -- πŸ”΄ Accessing this route with a key that does not have permissions (i.e. other than the master-key) returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. -- πŸ”΄ Attempting to access an API key that does not exist returns an [api_key_not_found](0061-error-format-and-definitions.md#api_key_not_found) error. - ---- - -#### **As `Anna πŸ‘©`, I want to update API key to change its restrictions** - -##### Request Definition - -`PATCH` - `/keys/:key` - -##### Headers - -``` -"Authorization: Bearer :masterKey" -"Content-Type: application/json" -``` - -##### Body Payload - -> PATCH method allows making partial changes to an existing resource. Thus the user is not obliged to send the complete API resource for each update. - -```json -{ - "description": "Manage Products/Reviews Documents API key", //Update the description to specify the API Key purposes. - "actions": [ - "documents.add", - "documents.delete" //Has now access to documents deletion - ], - "indexes": [ - "products", - "reviews" - ], //Has now access to reviews - "expiresAt": "2021-12-31T23:59:59Z" //Extended to the end of the year -} -``` - -##### Response - -`200 Success` - -```json -{ - "description": "Manage Products/Reviews Documents API key", - "key": "d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4", - "actions": [ - "documents.add", - "documents.delete" - ], - "indexes": [ - "products", - "reviews" - ], - "expiresAt": "2021-12-31T23:59:59Z", - "createdAt": "2021-11-12T10:00:00Z", - "updatedAt": "2021-10-12T15:00:00Z" -} -``` - -##### Errors - -- πŸ”΄ Accessing this route without the `Authorization` header returns a [missing_authorization_header](0061-error-format-and-definitions.md#missing_authorization_header) error. -- πŸ”΄ Accessing this route with a key that does not have permissions (i.e. other than the master-key) returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. -- πŸ”΄ Attempting to access an API key that does not exist returns a [api_key_not_found](0061-error-format-and-definitions.md#api_key_not_found) error. -- πŸ”΄ Omitting Content-Type header returns a [missing_content_type](0061-error-format-and-definitions.md#missing_content_type) error. -- πŸ”΄ Sending an empty Content-Type returns an [invalid_content_type](0061-error-format-and-definitions.md#invalid_content_type) error. -- πŸ”΄ Sending a different Content-Type than `application/json` returns an [invalid_content_type](0061-error-format-and-definitions.md#invalid_content_type) error. -- πŸ”΄ Sending an empty payload returns a [missing_payload](0061-error-format-and-definitions.md#missing_payload) error. -- πŸ”΄ Sending a different payload type than the Content-Type header returns a [malformed_payload](0061-error-format-and-definitions.md#malformed_payload) error. -- πŸ”΄ Sending an invalid json format returns a [malformed_payload](0061-error-format-and-definitions.md#malformed_payload) error. -- πŸ”΄ Sending an invalid value for the `actions` field returns an [invalid_api_key_actions](0061-error-format-and-definitions.md#invalid_api_key_actions) error. -- πŸ”΄ Sending an invalid value for the `indexes` field returns an [invalid_api_key_indexes](0061-error-format-and-definitions.md#invalid_api_key_indexes) error. -- πŸ”΄ Sending an invalid value for the `expiresAt` field returns an [invalid_api_key_expires_at](0061-error-format-and-definitions.md#invalid_api_key_expires_at) error. -- πŸ”΄ Sending an invalid value for the `description` field returns an [invalid_api_key_description](0061-error-format-and-definitions.md#invalid_api_key_description) error. - ---- - -#### **As `Anna πŸ‘©`, I want to list the API Keys** - -##### Request Definition +##### 3.2.4.2. `GET` - `/keys` -`GET` - `/keys` +Fetch the API keys of a Meilisearch instance. -##### Headers - -``` -"Authorization: Bearer :masterKey" -``` -##### Query Parameters +###### 3.2.4.2.1. Query Parameter Definition | Field | Type | Required | |--------------------------|--------------------------|----------| @@ -390,18 +157,20 @@ Sets the starting point in the results, effectively skipping over a given number Sets the maximum number of documents to be returned by the current request. -##### Response Definition +###### 3.2.4.2.2. Response Definition -| Field | Type | Required | -|--------------------------|--------------------------|----------| -| `result` | Array[Key] | true | -| `offset` | Integer | true | -| `limit` | Integer | true | -| `total` | Integer | true | +Returns a `200 Success` HTTP code when the request is successful. + +| Field | Type | Required | +|-----------|----------------------------------------------------------|----------| +| `results` | Array of [APIKey](#3241-api-key-resource-representation) | true | +| `offset` | Integer | true | +| `limit` | Integer | true | +| `total` | Integer | true | ###### `results` -- Type: Array[Key] +- Type: Array[APIKey] - Required: True An array containing the fetched API keys. @@ -427,7 +196,16 @@ Gives the `limit` parameter used for the query. Gives the total number of API keys that can be browsed. -###### Example +> API Keys are ordered by `createdAt` in `desc` order. (Most recent first) + +> Expired API keys can be found on the `/keys` endpoints. An archiving system or a filter could allow to not display them by default. See Future Possibilities part. + +###### 3.2.4.2.3. Errors + +- πŸ”΄ Accessing this route without the `Authorization` header returns a [missing_authorization_header](0061-error-format-and-definitions.md#missing_authorization_header) error. +- πŸ”΄ Accessing this route without the master key returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. + +###### 3.2.4.2.4. Example `200 Success` @@ -436,7 +214,8 @@ Gives the total number of API keys that can be browsed. "results": [ { "description": "Manage Products/Reviews Documents API key", - "key": "d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4", + "uid": "ac06a7e1-6956-4699-bb04-dbeb72a231df", + "key": "2fcdddd16ab75a4aeea6b74577874bc2888938a69ffafe3d05547560fa72e15b", "actions": [ "documents.add", "documents.delete" @@ -451,7 +230,8 @@ Gives the total number of API keys that can be browsed. }, { "description": "Default Search API Key (Use it to search from the frontend code)", - "key": "0a6e572506c52ab0bd6195921575d23092b7f0c284ab4ac86d12346c33057f99", + "uid": "87861fb0-e948-41da-ae7f-89617d57d5f5", + "key": "0fe6fc6d94a21b5ca0b5a714bcb338865108039efc048e99e5ba2e7a976fa330", "actions": [ "search" ], @@ -464,7 +244,8 @@ Gives the total number of API keys that can be browsed. }, { "description": "Default Admin API Key (Use it for all other operations. Caution! Do not share it on the client side)", - "key": "380689dd379232519a54d15935750cc7625620a2ea2fc06907cb40ba5b421b6f", + "uid": "ad9af94e-d2db-420f-9ee3-9375f091e565", + "key": "1846b591d7fd0454bc2b7f1c7ad80c411b1cfe46a51b0d44e6554a30f4bc0a18", "actions": [ "*" ], @@ -482,130 +263,189 @@ Gives the total number of API keys that can be browsed. } ``` -> Expired API keys can be found on the `/keys` endpoints. An archiving system or a filter could allow to not display them by default. See Future Possibilities part. - > πŸ‘‰ Note the two default generated API keys here. When a master key is set at MeiliSearch's launch, it generates two pre-configured `API Keys`. A Default Search API Key restricted to the search action on all indexes and a Default Admin API Key on all indexes to handle all operations (except managing API Keys). -##### List details +##### 3.2.4.3. `GET` - `/keys/:uid` -- `API Key` objects are returned in a `results` array. -- `API Keys` are ordered by `createdAt` in `desc` order. (Most recent first) -- No pagination yet. See Future Possibilities part. +Fetch a specific API key of a Meilisearch instance from it's `uid` field. -##### Errors +###### 3.2.4.3.1. Query Parameter Definition +n/a + +###### 3.2.4.3.2. Response Definition + +Returns a `200 Success` HTTP code when the request is successful. + +See [API Key Resource Representation](#3241-api-key-resource-representation) section for the response body. + +###### 3.2.4.3.3. Errors - πŸ”΄ Accessing this route without the `Authorization` header returns a [missing_authorization_header](0061-error-format-and-definitions.md#missing_authorization_header) error. -- πŸ”΄ Accessing this route with a key that does not have permissions (i.e. other than the master-key) returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. +- πŸ”΄ Accessing this route without the master key returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. ---- +##### 3.2.4.4. `POST` - `/keys` -#### **As `Anna πŸ‘©`, I want to delete an `API Key`** +Create an API key. + +###### 3.2.4.4.1. Payload Definition + +| field | type | required |description | +|-------------|---------|----------|--------------------------------| +| uid | string | Optional | A unique identifier represented by uuid v4. Specified at creation or generated by Meilisearch if ommited. | +| name | string | Optional | A non unique human readable name to ease identification of the API key. **Default**: `null` | +| description | string | Optional | A description for the API key. **Default**: `null` | +| actions | array | Required | A list of actions permitted for the API key. `["*"]` for all actions. **See Actions list definition part**. `*` character can be used as a wildcard. e.g. `documents.*` to authorize access on all documents endpoints. **Default**: `No default` | +| indexes | array | Required | `[*]` for all indexes. **Default**: `No Default` | +| expiresAt | string | Required | The expiration date and time as `RFC 3339` format. `null` equals to no expiration time. Sending only the date part e.g `2021-12-01` leads to having an `expiresAt` value set to `2021-12-01T00:00:00`. **Default**: `No Default` | -##### Request Definition +###### 3.2.4.4.2. `actions` List Definition -`DELETE` - `/keys/:key` +> `:authorizedIndexes` can be any value extracted from the `indexes` field of an API key resource. -##### Headers +| name | description | +|---------|-------------| +| search | Provides access to `GET` and `POST` methods on `/indexes/:authorizedIndexes/search` routes. | +| documents.add | Provides access to `POST` and `PUT` on `/indexes/:authorizedIndexes/documents` routes. | +| documents.get | Provides access to `GET` methods on `/indexes/:authorizedIndexes/documents` and `/indexes/:authorizedIndexes/documents/:documentId` routes. | +| documents.delete | Provides access to `DELETE` method on `/indexes/:authorizedIndexes/documents/:documentId`, `indexes/:authorizedIndexes/documents/:documentId` and `POST` method on `/indexes/:authorizedIndexes/documents/delete-batch` routes. | +| indexes.create | Provides access to `POST` `/indexes`. **⚠️ `indexes` field should indicate the newly created index or having `[*]` to permits access on it.**. | +| indexes.get | Provides access to `GET` `/indexes` and `/indexes/:authorizedIndexes`. **⚠️Non-authorized `indexes` are omitted from the response on `/indexes`**. | +| indexes.update | Provides access to `PUT` `/indexes/:authorizedIndexes`. | +| indexes.delete | Provides access to `DELETE` `/indexes/:authorizedIndexes`. | +| tasks.get | Provides access to `GET` `/tasks`. **⚠️Non-authorized `indexes` are omitted from the response on `/tasks`**. Also add access to `GET` `/indexes/:authorizedIndexes/tasks` routes. | +| settings.get | Provides access to `GET` `/indexes/:authorizedIndexes/settings` and `/indexes/:authorizedIndexes/settings/*` routes. | +| settings.update | Provides access to `POST / DELETE` `/indexes/:authorizedIndexes/settings` and `/indexes/:authorizedIndexes/settings/*` routes. | +| stats.get | Provides access to `GET` `/stats/`. **⚠️Non-authorized `indexes` are omitted from the response on `/stats`**. Also add access to `GET` `/indexes/:authorizedIndexes/stats`. | +| dumps.create | Provides access to `POST` `/dumps` route. **As dumps are not scoped by indexes, a restriction on `indexes` does not affect this action.** | +| version | Provides access to `GET` `/version` route. -``` -"Authorization: Bearer :masterKey" -``` +###### 3.2.4.4.3. Response Definition -##### Response +Returns a `201 Created` HTTP code when the request is successful. -`204 No-Content` +See [API Key Resource Representation](#3241-api-key-resource-representation) section for the response body. -##### Errors +###### 3.2.4.4.3. Errors - πŸ”΄ Accessing this route without the `Authorization` header returns a [missing_authorization_header](0061-error-format-and-definitions.md#missing_authorization_header) error. -- πŸ”΄ Accessing this route with a key that does not have permissions (i.e. other than the master-key) returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. -- πŸ”΄ Attempting to access an API key that does not exist returns a `api_key_not_found`. +- πŸ”΄ Accessing this route without the master key returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. +- πŸ”΄ Omitting Content-Type header returns a [missing_content_type](0061-error-format-and-definitions.md#missing_content_type) error. +- πŸ”΄ Sending an empty Content-Type returns an [invalid_content_type](0061-error-format-and-definitions.md#invalid_content_type) error. +- πŸ”΄ Sending a different Content-Type than `application/json` returns an [invalid_content_type](0061-error-format-and-definitions.md#invalid_content_type) error. +- πŸ”΄ Sending an empty payload returns a [missing_payload](0061-error-format-and-definitions.md#missing_payload) error. +- πŸ”΄ Sending a different payload type than the Content-Type header returns a [malformed_payload](0061-error-format-and-definitions.md#malformed_payload) error. +- πŸ”΄ Sending an invalid json format returns a [malformed_payload](0061-error-format-and-definitions.md#malformed_payload) error. +- πŸ”΄ Omitting `actions` field from the payload returns a [missing_parameter](0061-error-format-and-definitions.md#missing_parameter) error. +- πŸ”΄ Omitting `indexes` field from the payload returns a [missing_parameter](0061-error-format-and-definitions.md#missing_parameter) error. +- πŸ”΄ Omitting `expiresAt` field from the payload returns a [missing_parameter](0061-error-format-and-definitions.md#missing_parameter) error. +- πŸ”΄ Sending an invalid value for the `uid` field returns an [invalid_api_key_uid](0061-error-format-and-definitions.md#invalid_api_key_uid). +- πŸ”΄ Sending an invalid value for the `actions` field returns an [invalid_api_key_actions](0061-error-format-and-definitions.md#invalid_api_key_actions) error. +- πŸ”΄ Sending an invalid value for the `indexes` field returns an [invalid_api_key_indexes](0061-error-format-and-definitions.md#invalid_api_key_indexes) error. +- πŸ”΄ Sending an invalid value for the `expiresAt` field returns an [invalid_api_key_expires_at](0061-error-format-and-definitions.md#invalid_api_key_expires_at) error. +- πŸ”΄ Sending an invalid value for the `name` field returns an [invalid_api_key_name](0061-error-format-and-definitions.md#invalid_api_key_name) error. +- πŸ”΄ Sending an invalid value for the `description` field returns an [invalid_api_key_description](0061-error-format-and-definitions.md#invalid_api_key_description) error. ---- +##### 3.2.4.5. `PATCH` - `/keys/:uid` -#### Using `API Key` on client-code +Update an API key found by its `uid`. Only the `name` and `description` fields of an API key can be modified. -![](https://i.imgur.com/kRKcB43.png) +###### 3.2.4.5.1. Payload Definition -`Mark πŸ‘¨πŸ»` receives the `API Key` transmitted by `Anna πŸ‘©` on a secured channel of their choice. He uses it to authenticate requests from the client code to MeiliSearch. +| field | type | required |description | +|-------------|---------|----------|--------------------------------| +| name | string | Optional | A name for the API Key. **Default**: `null` | +| description | string | Optional | A description for the API key. **Default**: `null` | -#### **As `Mark πŸ‘¨πŸ»`, I am using an expired/deleted API Key** +###### 3.2.4.5.2. Response Definition -#### Request example +Returns a `200 Success` HTTP code when the request is successful. -`POST` - `/indexes/movies/search` +See [API Key Resource Representation](#3241-api-key-resource-representation) section for the response body. -#### Headers +###### 3.2.4.5.3. Errors -``` - "Authorization: Bearer :apiKey" - "Content-Type: application/json" -``` +- πŸ”΄ Accessing this route without the `Authorization` header returns a [missing_authorization_header](0061-error-format-and-definitions.md#missing_authorization_header) error. +- πŸ”΄ Accessing this route without the master key returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. +- πŸ”΄ Attempting to access an API key that does not exist returns a [api_key_not_found](0061-error-format-and-definitions.md#api_key_not_found) error. +- πŸ”΄ Omitting Content-Type header returns a [missing_content_type](0061-error-format-and-definitions.md#missing_content_type) error. +- πŸ”΄ Sending an empty Content-Type returns an [invalid_content_type](0061-error-format-and-definitions.md#invalid_content_type) error. +- πŸ”΄ Sending a different Content-Type than `application/json` returns an [invalid_content_type](0061-error-format-and-definitions.md#invalid_content_type) error. +- πŸ”΄ Sending an empty payload returns a [missing_payload](0061-error-format-and-definitions.md#missing_payload) error. +- πŸ”΄ Sending a different payload type than the Content-Type header returns a [malformed_payload](0061-error-format-and-definitions.md#malformed_payload) error. +- πŸ”΄ Sending an invalid json format returns a [malformed_payload](0061-error-format-and-definitions.md#malformed_payload) error. +- πŸ”΄ Sending an invalid value for the `name` field returns an [invalid_api_key_name](0061-error-format-and-definitions.md#invalid_api_key_name) error. +- πŸ”΄ Sending an invalid value for the `description` field returns an [invalid_api_key_description](0061-error-format-and-definitions.md#invalid_api_key_description) error. -#### Response +##### 3.2.4.6. `DELETE` - `/keys/:uid` -- πŸ”΄ Accessing this route with an `API Key` that has expired or, been deleted returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. +Delete an API key found by its `uid`. ---- +###### 3.2.4.6.1. Payload Definition +n/a -### **As `Mark πŸ‘¨πŸ»`, I am using a valid API Key, but the permission set is not sufficient to access the requested API resource** +###### 3.2.4.6.2. Response Definition -#### Request example +Returns a `204 No-Content` HTTP code when the request is successful. -`POST` - `/indexes/movies/search` +###### 3.2.4.6.3. Errors + +- πŸ”΄ Accessing this route without the `Authorization` header returns a [missing_authorization_header](0061-error-format-and-definitions.md#missing_authorization_header) error. +- πŸ”΄ Accessing this route without the master key returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. +- πŸ”΄ Attempting to access an API key that does not exist returns a [`api_key_not_found`](0061-error-format-and-definitions.md#api_key_not_found) error. -#### Headers +##### 3.2.4.7. Using an API key on client-code + +###### 3.2.4.7.1 Authorization Bearer Header + +When the Meilisearch API is secured by the presence of a master key, the `Authorization` header must be used with a bearer to authorize requests. The specified value must be the value of the `key` field of an API key. ``` - "Authorization: Bearer :apiKey" + "Authorization: Bearer `:key`" "Content-Type: application/json" ``` -#### Response - -- πŸ”΄ Accessing this route with an `API Key` that don't have sufficient permissions to access it returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. +- πŸ”΄ Accessing a route with an `API Key` that has expired, been deleted or don't have sufficient permissions returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. -## 2. Technical Aspects +## 4. Technical Aspects -### 2.1 API Key generation +### 4.1. API Key generation -A prefix of 8 characters is randomly generated per key and is stored within the instance. +An `uid` representing an uuid v4 is generated if not specified at creation by the user. -The final key is then a SHA-2556 hash made of the prefix and the master-key concatenation. +The final key is then a SHA-2556 hash made of the `uid` and the master key concatenation. -`SHA-256(:randomizedPrefix, :master-key)` gives the final `key` field to use. +`SHA-256(:uid, :master-key)` gives the final `key` field to use when authorizing requests. -### 2.2 Synchronous write of `API Key` resources +### 4.2. Synchronous write of `API Key` resources -Writing to `/keys` endpoints are synchronous in order to return errors directly to the user when he performs an operation on them. +Writing to `/keys` endpoints are synchronous in order to return errors directly to the user when he performs an operation on them. This means that API key management operations do not appear as a task on `/tasks`. -### 2.3 Propagating `API Key` to a dump. +### 4.3. Propagating `API Key` to dumps. The generated API keys must also transit within a dump to facilitate the upgrade of a MeiliSearch instance. > 🚨 As a reminder, dumps must be stored in secure areas not accessible to the public or unaccredited persons. In general, you should avoid moving them off the host machine or do so via a secure channel as a security measure. -If the dumps ever leak, the api keys cannot be spoofed from the dump inspection because it needs the master-key to have the full value of a valid API key. Only the randomized prefixes are propagated in the dumps. +If the dumps ever leak, the api keys cannot be spoofed from the dump inspection because it needs the master key to have the full value of a valid API key. Only the `uid` value is propagated in the dumps. -### 2.4 Propagating `API Key` to snapshots. +### 4.4. Propagating `API Key` to snapshots. The generated API keys must also transit within a snapshot to facilitate the recovery of a MeiliSearch instance. > 🚨 As a reminder, snapshots must be stored in secure areas not accessible to the public or unaccredited persons. In general, you should avoid moving them off the host machine or do so via a secure channel as a security measure. -If the snapshot ever leak, the `API Keys` cannot be spoofed from the snapshot inspection because it needs the master-key to have the full value of a valid `API key`. Only the randomized prefixes are propagated in the snapshots. +If the snapshot ever leak, the `API keys` cannot be spoofed from the snapshot inspection because it needs the master key to have the full value of a valid `API key`. Only the `uid` value is propagated in the snapshots. -### 2.5 API Keys storage size limit +### 4.5. API Keys storage size limit -The maximum size of the API key storage is `100GB`. +The maximum size of the API key storage layer is `100GB`. -## 3. Future Possibilities +## 5. Future Possibilities - Regenerate a specific `API Key`. -- Add a generated id field to paginate the list of API Key. -- Have a filer/dedicated route to fetch expired key if MeiliSearch do not display them by default on `/keys` in the future. - Have an "archive" state where manually deleted API Keys can be restored for a certain amount of time. - Add rate-limiting per API Key. - A restriction on the maximum offset/limit. - Add search parameters restrictions for an API Key. -- Add rfc2822 format expression for `expiredAt` field. e.g. `Wed, 18 Feb 2022 23:16:09 GMT` \ No newline at end of file +- Add rfc2822 format expression for `expiredAt` field. e.g. `Wed, 18 Feb 2022 23:16:09 GMT` +- Add an alias that can only be associated to one API Key to retrieve it easily on client side. e.g. `GET /keys/:uid_or_alias` \ No newline at end of file From 875dcc1afd1b9c2cb43a6bd228d37b91eab6e1bc Mon Sep 17 00:00:00 2001 From: Guillaume Mourier Date: Mon, 23 May 2022 15:08:20 +0200 Subject: [PATCH 02/17] Describe errors for uid and name fields --- text/0061-error-format-and-definitions.md | 67 +++++++++++++++++++++++ text/0085-api-keys.md | 4 +- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/text/0061-error-format-and-definitions.md b/text/0061-error-format-and-definitions.md index fdd7c301..3dd05f3a 100644 --- a/text/0061-error-format-and-definitions.md +++ b/text/0061-error-format-and-definitions.md @@ -122,6 +122,73 @@ HTTP Code: `400 Bad Request` --- +## invalid_api_key_uid + +`Synchronous` + +### Context + +This error happens when the `uid` field for an `API Key` resource is invalid. The error may occur when the format given for the `uid` field is not valid or if an API key with this `uid` already exists. + +### Error Definition + +#### Variant: Sending an invalid uuid v4 format + +HTTP Code: `400 Bad Request` + +```json +{ + "message": "`uid` field value `:value` is invalid. It should be a valid uuidv4 string or ommited.", + "code": "invalid_api_key_uid", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid_api_key_uid" +} +``` + +- The `:value` is inferred when the message is generated. + +#### Variant: Sending an `uid` that already exists + +HTTP Code: `409 Conflict` + +```json +{ + "message": "`uid` field value `:value` already exists for an API key.", + "code": "invalid_api_key_uid", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid_api_key_uid" +} +``` + +- The `:value` is inferred when the message is generated. + +--- + +## invalid_api_key_name + +`Synchronous` + +### Context + +This error happens when the `name` field for an `API Key` resource is invalid. + +### Error Definition + +HTTP Code: `400 Bad Request` + +```json +{ + "message": "`name` field value `:value` is invalid. It should be a string or specified as a null value.", + "code": "invalid_api_key_name", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid_api_key_name" +} +``` + +- The `:value` is inferred when the message is generated. + +--- + ## invalid_api_key_description `Synchronous` diff --git a/text/0085-api-keys.md b/text/0085-api-keys.md index 9ed9fc4c..ff2816f1 100644 --- a/text/0085-api-keys.md +++ b/text/0085-api-keys.md @@ -291,7 +291,7 @@ Create an API key. | field | type | required |description | |-------------|---------|----------|--------------------------------| -| uid | string | Optional | A unique identifier represented by uuid v4. Specified at creation or generated by Meilisearch if ommited. | +| uid | string | Optional | A unique identifier represented by a [uuid v4](https://fr.wikipedia.org/wiki/Universally_unique_identifier). Specified at creation or generated by Meilisearch if ommited. | | name | string | Optional | A non unique human readable name to ease identification of the API key. **Default**: `null` | | description | string | Optional | A description for the API key. **Default**: `null` | | actions | array | Required | A list of actions permitted for the API key. `["*"]` for all actions. **See Actions list definition part**. `*` character can be used as a wildcard. e.g. `documents.*` to authorize access on all documents endpoints. **Default**: `No default` | @@ -410,7 +410,7 @@ When the Meilisearch API is secured by the presence of a master key, the `Author ### 4.1. API Key generation -An `uid` representing an uuid v4 is generated if not specified at creation by the user. +An `uid` representing by a uuid v4 is generated if not specified at creation by the user. The final key is then a SHA-2556 hash made of the `uid` and the master key concatenation. From b11c8ff7fe0ee2598fd005fb3492f10775dce84d Mon Sep 17 00:00:00 2001 From: Guillaume Mourier Date: Mon, 23 May 2022 15:10:34 +0200 Subject: [PATCH 03/17] Apply suggestions from code review Co-authored-by: Bruno Casali --- text/0085-api-keys.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text/0085-api-keys.md b/text/0085-api-keys.md index ff2816f1..6ebc1ac4 100644 --- a/text/0085-api-keys.md +++ b/text/0085-api-keys.md @@ -42,7 +42,7 @@ At the first launch of Meilisearch with a master key, Meilisearch automatically If the master key is removed at Meilisearch launch, the previously generated API keys no longer secure the Meilisearch instance. -If Meilisearch is launched with the `production` value for the `MEILI_ENV` environment variable or the `--env` CLI option, a master key is mandatory. If the master key is omitted in that particular case, MeiliSearch launch is aborted and displays an error: +If Meilisearch is launched with the `production` value for the `MEILI_ENV` environment variable or the `--env` CLI option, a master key is mandatory. If the master key is omitted in that particular case, Meilisearch launch is aborted and displays an error: `Error: In production mode, the environment variable MEILI_MASTER_KEY is mandatory` @@ -58,7 +58,7 @@ The master key must be composed of valid utf-8 characters. It is advisable to en #### 3.2.3. Default API Keys -The first time a Meilisearch is launched with a `master key`, Meilisearch will generate two API keys described below. +The first time a Meilisearch instance is launched with a `master key`, Meilisearch will generate two API keys described below. If the user changes the value of the master key later, these two default keys are not created again but re-generated with a different `key` field. However, these two API keys can be updated/deleted using the `/keys` endpoints. @@ -412,7 +412,7 @@ When the Meilisearch API is secured by the presence of a master key, the `Author An `uid` representing by a uuid v4 is generated if not specified at creation by the user. -The final key is then a SHA-2556 hash made of the `uid` and the master key concatenation. +The final key is then an SHA-256 hash made of the `uid` and the master key concatenation. `SHA-256(:uid, :master-key)` gives the final `key` field to use when authorizing requests. From a92091d13ad28e3694e612212a51d880a2daaab8 Mon Sep 17 00:00:00 2001 From: Guillaume Mourier Date: Mon, 23 May 2022 15:13:34 +0200 Subject: [PATCH 04/17] misc: add precisions --- text/0085-api-keys.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text/0085-api-keys.md b/text/0085-api-keys.md index 6ebc1ac4..ca67970a 100644 --- a/text/0085-api-keys.md +++ b/text/0085-api-keys.md @@ -25,7 +25,7 @@ To make Meilisearch more reliable for teams and more adapted to production cases - API keys must be provided via the `Authorization` header using the bearer method to authorize a request. - The value of the `key` field of an API Key is generated from its `uid` and the master key. - When a master key is set at Meilisearch first-launch, it generate two pre-configured default `API Key` resources. A `Default Search API Key` authorizing the search action on all indexes and a `Default Admin API Key` authorizing all actions on all indexes (except managing `/keys` resource). -- If the master-key changes, all `key` field are re-generated. +- If the master-key changes, the `key` field is re-generated. - Default API keys can be modified/deleted from the `/keys` endpoints but are not re-created if Meilisearch has already created them. - The master key can only be used to manage API keys. Using the master-key for any other request other than on `/keys` returns an authorization error. - API keys can have restrictions on which methods can be accessed via an `actions` list; they also `expiresAt` a specific date time and are restricted to a specific set of `indexes`. @@ -60,7 +60,7 @@ The master key must be composed of valid utf-8 characters. It is advisable to en The first time a Meilisearch instance is launched with a `master key`, Meilisearch will generate two API keys described below. -If the user changes the value of the master key later, these two default keys are not created again but re-generated with a different `key` field. However, these two API keys can be updated/deleted using the `/keys` endpoints. +If the user changes the value of the master key later, these two default keys are not created again but the `key` field is re-generated. However, these two API keys can be updated/deleted using the `/keys` endpoints. If these API keys are deleted, the engine should not create them again when Meilisearch is launched again with a master key. @@ -75,7 +75,7 @@ Here is how the `Default Search API Key` is represented after its generation. "uid": "01b4bc42-eb33-4041-b481-254d00cce834", //auto-generated value "key": "0a6e572506c52ab0bd6195921575d23092b7f0c284ab4ac86d12346c33057f99", //auto-generated value "name": "Default Search API Key", - "description": "(Use it to search from the frontend)", + "description": "Use it to search from the frontend", "actions": [ "search" ], @@ -99,7 +99,7 @@ Here is how the `Default Admin API Key` is represented after its generation. "uid": "ac06a7e1-6956-4699-bb04-dbeb72a231df", //auto-generated value "key": "380689dd379232519a54d15935750cc7625620a2ea2fc06907cb40ba5b421b6f", //auto-generated value "name": "Default Admin API Key", - "description": "(Use it for all other than search operations. Caution! Do not expose it on a public frontend)", + "description": "Use it for all other than search operations. Caution! Do not expose it on a public frontend", "actions": [ "*" ], From aba73b1f18c99a035f438d77fe9cf7d9f443ad0b Mon Sep 17 00:00:00 2001 From: Guillaume Mourier Date: Mon, 23 May 2022 15:34:12 +0200 Subject: [PATCH 05/17] Reorganize route descriptions --- open-api.yaml | 88 +++++++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/open-api.yaml b/open-api.yaml index 329d5fc1..8460fd86 100644 --- a/open-api.yaml +++ b/open-api.yaml @@ -2603,6 +2603,50 @@ paths: parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/offset' + post: + summary: Create an API Key + operationId: keys.create + tags: + - Keys + security: + - apiKey: [] + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/key' + examples: + Create an API Key: + value: + uid: 01b4bc42-eb33-4041-b481-254d00cce834 + key: d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4 + name: Indexing Products API key + description: null + actions: + - documents.add + indexes: + - products + expiresAt: '2021-11-13T00:00:00Z' + createdAt: '2021-11-12T10:00:00Z' + updatedAt: '2021-11-12T10:00:00Z' + parameters: + - $ref: '#/components/parameters/Content-Type' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/key' + examples: + API Key Creation: + value: + name: Indexing Products API key + actions: + - documents.add + indexes: + - products + expiresAt: '2021-11-13T00:00:00Z' '/keys/{uid}': summary: Get an API key from its uid tags: @@ -2700,50 +2744,6 @@ paths: Patch an API Key Request: value: description: Indexing Products API key - post: - summary: Create an API Key - operationId: keys.create - tags: - - Keys - security: - - apiKey: [] - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/key' - examples: - Create an API Key: - value: - uid: 01b4bc42-eb33-4041-b481-254d00cce834 - key: d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4 - name: Indexing Products API key - description: null - actions: - - documents.add - indexes: - - products - expiresAt: '2021-11-13T00:00:00Z' - createdAt: '2021-11-12T10:00:00Z' - updatedAt: '2021-11-12T10:00:00Z' - parameters: - - $ref: '#/components/parameters/Content-Type' - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/key' - examples: - API Key Creation: - value: - name: Indexing Products API key - actions: - - documents.add - indexes: - - products - expiresAt: '2021-11-13T00:00:00Z' /stats: get: operationId: stats.list From fe49c07897fe133e21fe514cf5f724bf3d4f0def Mon Sep 17 00:00:00 2001 From: Guillaume Mourier Date: Mon, 23 May 2022 18:53:42 +0200 Subject: [PATCH 06/17] Update error_code when API Key already exists for a given uid --- text/0061-error-format-and-definitions.md | 29 ++++++++++++++--------- text/0085-api-keys.md | 3 ++- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/text/0061-error-format-and-definitions.md b/text/0061-error-format-and-definitions.md index 3dd05f3a..1f586c29 100644 --- a/text/0061-error-format-and-definitions.md +++ b/text/0061-error-format-and-definitions.md @@ -122,38 +122,45 @@ HTTP Code: `400 Bad Request` --- -## invalid_api_key_uid +## api_key_already_exists `Synchronous` ### Context -This error happens when the `uid` field for an `API Key` resource is invalid. The error may occur when the format given for the `uid` field is not valid or if an API key with this `uid` already exists. +This error happens when a user tries to create an API Key that already exists for the given `uid`. ### Error Definition -#### Variant: Sending an invalid uuid v4 format - -HTTP Code: `400 Bad Request` +HTTP Code: `409 Conflict` ```json { - "message": "`uid` field value `:value` is invalid. It should be a valid uuidv4 string or ommited.", - "code": "invalid_api_key_uid", + "message": "`uid` field value `:value` already exists for an API key.", + "code": "api_key_already_exists", "type": "invalid_request", - "link": "https://docs.meilisearch.com/errors#invalid_api_key_uid" + "link": "https://docs.meilisearch.com/errors#api_key_already_exists" } ``` - The `:value` is inferred when the message is generated. -#### Variant: Sending an `uid` that already exists +--- +## invalid_api_key_uid -HTTP Code: `409 Conflict` +`Synchronous` + +### Context + +This error happens when the `uid` field for an `API Key` resource is invalid. + +### Error Definition + +HTTP Code: `400 Bad Request` ```json { - "message": "`uid` field value `:value` already exists for an API key.", + "message": "`uid` field value `:value` is invalid. It should be a valid uuidv4 string or ommited.", "code": "invalid_api_key_uid", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid_api_key_uid" diff --git a/text/0085-api-keys.md b/text/0085-api-keys.md index ca67970a..32021f98 100644 --- a/text/0085-api-keys.md +++ b/text/0085-api-keys.md @@ -338,7 +338,8 @@ See [API Key Resource Representation](#3241-api-key-resource-representation) sec - πŸ”΄ Omitting `actions` field from the payload returns a [missing_parameter](0061-error-format-and-definitions.md#missing_parameter) error. - πŸ”΄ Omitting `indexes` field from the payload returns a [missing_parameter](0061-error-format-and-definitions.md#missing_parameter) error. - πŸ”΄ Omitting `expiresAt` field from the payload returns a [missing_parameter](0061-error-format-and-definitions.md#missing_parameter) error. -- πŸ”΄ Sending an invalid value for the `uid` field returns an [invalid_api_key_uid](0061-error-format-and-definitions.md#invalid_api_key_uid). +- πŸ”΄ Sending an `uid` field that already exists returns an [api_key_already_exists](0061-error-format-and-definitions.md#api_key_already_exists) error. +- πŸ”΄ Sending an invalid value for the `uid` field returns an [invalid_api_key_uid](0061-error-format-and-definitions.md#invalid_api_key_uid) error. - πŸ”΄ Sending an invalid value for the `actions` field returns an [invalid_api_key_actions](0061-error-format-and-definitions.md#invalid_api_key_actions) error. - πŸ”΄ Sending an invalid value for the `indexes` field returns an [invalid_api_key_indexes](0061-error-format-and-definitions.md#invalid_api_key_indexes) error. - πŸ”΄ Sending an invalid value for the `expiresAt` field returns an [invalid_api_key_expires_at](0061-error-format-and-definitions.md#invalid_api_key_expires_at) error. From ab5b25aaca43b5503c7091ff15351d80b96ed578 Mon Sep 17 00:00:00 2001 From: Guillaume Mourier Date: Wed, 1 Jun 2022 11:01:28 +0200 Subject: [PATCH 07/17] Apply suggestions from code review Co-authored-by: Many the fish --- text/0061-error-format-and-definitions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/0061-error-format-and-definitions.md b/text/0061-error-format-and-definitions.md index 1f586c29..e940aae9 100644 --- a/text/0061-error-format-and-definitions.md +++ b/text/0061-error-format-and-definitions.md @@ -136,7 +136,7 @@ HTTP Code: `409 Conflict` ```json { - "message": "`uid` field value `:value` already exists for an API key.", + "message": "`uid` field value `:value` is already an existing API key.", "code": "api_key_already_exists", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#api_key_already_exists" @@ -160,7 +160,7 @@ HTTP Code: `400 Bad Request` ```json { - "message": "`uid` field value `:value` is invalid. It should be a valid uuidv4 string or ommited.", + "message": "`uid` field value `:value` is invalid. It should be a valid UUID v4 string or omitted.", "code": "invalid_api_key_uid", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid_api_key_uid" From bbd5a55e57e4b9226c308cb7953bb78e07853ea6 Mon Sep 17 00:00:00 2001 From: Guillaume Mourier Date: Wed, 1 Jun 2022 12:00:20 +0200 Subject: [PATCH 08/17] Add new keys actions, remove master-key changes, introduce a new error for immutable field and update tenant token --- open-api.yaml | 4 +- text/0061-error-format-and-definitions.md | 25 +++++ text/0085-api-keys.md | 107 +++++++++++----------- text/0089-tenant-tokens.md | 10 +- 4 files changed, 88 insertions(+), 58 deletions(-) diff --git a/open-api.yaml b/open-api.yaml index 8460fd86..2fd13944 100644 --- a/open-api.yaml +++ b/open-api.yaml @@ -632,7 +632,7 @@ components: - actions - indexes - expiresAt - description: API keys are stored and managed by the master key holder. These are the keys used by the technical teams to interact with Meilisearch at the level of the client/server code. API keys can have restrictions on which methods can be accessed via an actions list; they can also expiresAt a specific date time and be restricted to a specific set of indexes. + description: API keys are stored and managed by the master key holder and the default admin key holder. These are the keys used by the technical teams to interact with Meilisearch at the level of the client/server code. API keys can have restrictions on which methods can be accessed via an actions list; they can also expiresAt a specific date time and be restricted to a specific set of indexes. parameters: indexUid: name: indexUid @@ -945,7 +945,7 @@ tags: - name: Keys description: | Manage API `keys` for a Meilisearch instance. Each key has a given set of permissions. - You must have the master key to access the `keys` route. + You must have the master key or the default admin key to access the `keys` route. [More information about the keys and their rights](https://docs.meilisearch.com/reference/features/security.html). - name: Settings description: | diff --git a/text/0061-error-format-and-definitions.md b/text/0061-error-format-and-definitions.md index e940aae9..d287f99c 100644 --- a/text/0061-error-format-and-definitions.md +++ b/text/0061-error-format-and-definitions.md @@ -122,6 +122,31 @@ HTTP Code: `400 Bad Request` --- +## immutable_field + +`Synchronous` / `Asynchronous` + +### Context + +This error happens when an immutable field is given in a payload dedicated to modify a resource. + +### Error Definition + +HTTP Code: `400 Bad Request` + +```json +{ + "message": "`:fieldName` cannot be modified for the given resource.", + "code": "immutable_field", + "type": "invalid_request", + "link":"https://docs.meilisearch.com/errors#immutable_field" +} +``` + +- The `:fieldName` is inferred when the message is generated. + +-- + ## api_key_already_exists `Synchronous` diff --git a/text/0085-api-keys.md b/text/0085-api-keys.md index 32021f98..bf834019 100644 --- a/text/0085-api-keys.md +++ b/text/0085-api-keys.md @@ -12,22 +12,21 @@ To make Meilisearch more reliable for teams and more adapted to production cases ### 3.1. Glossary -| Term | Definition | -|--------------------|------------| -| Master Key | This is the master key that allows managing API keys. The master key is defined by the user when launching Meilisearch, thus gives access to the `/keys` API endpoint and requiring requests to be authorized. | -| API Key | API keys are stored and managed from the endpoint `/keys` by the master key holder. | +| Term | Definition | +|------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Master Key | This is the master key that allows managing API keys. The master key is defined by the user when launching Meilisearch, thus gives access to the `/keys` API endpoint and requiring requests to be authorized. | +| API Key | API keys are stored and managed from the endpoint `/keys` by the master key holder. | ### 3.2. Explanation #### 3.2.1 Summary Key Points -- API keys management is restricted to the master key holder. +- API keys management is restricted to the master key or API keys having `keys.get`, `keys.create`, `keys.update`, `keys.delete` actions. - API keys must be provided via the `Authorization` header using the bearer method to authorize a request. - The value of the `key` field of an API Key is generated from its `uid` and the master key. - When a master key is set at Meilisearch first-launch, it generate two pre-configured default `API Key` resources. A `Default Search API Key` authorizing the search action on all indexes and a `Default Admin API Key` authorizing all actions on all indexes (except managing `/keys` resource). - If the master-key changes, the `key` field is re-generated. - Default API keys can be modified/deleted from the `/keys` endpoints but are not re-created if Meilisearch has already created them. -- The master key can only be used to manage API keys. Using the master-key for any other request other than on `/keys` returns an authorization error. - API keys can have restrictions on which methods can be accessed via an `actions` list; they also `expiresAt` a specific date time and are restricted to a specific set of `indexes`. - `name` and `description` fields are the only editable fields of an API key. - API key resources are propagated to snapshots and dumps. @@ -36,7 +35,7 @@ To make Meilisearch more reliable for teams and more adapted to production cases The master key exists to secure a Meilisearch instance. As soon as a master key is set via the `MEILI_MASTER_KEY` environment variable or the `--master-key` CLI option, the endpoint `/keys` is accessible for the master key holder. It can be seen as a super admin key; It must be securely shared only with people who have to manage the security of a Meilisearch instance. -This master key is not an API key, thus is not stored and fetchable from the `/keys` API endpoint. It must be seen as a runtime lock that activates the security of Meilisearch as soon as an instance is launched with it. The master key can only be used to manage API Keys. Using the master key for any other request other than on `/keys` returns an authorization error. +This master key is not an API key, thus is not stored and fetchable from the `/keys` API endpoint. It must be seen as a runtime lock that activates the security of Meilisearch as soon as an instance is launched with it. The master key should only be used to fetch API Keys the first time. The default Admin API key should be preferred to manage the API keys resources. At the first launch of Meilisearch with a master key, Meilisearch automatically generates two default API keys to cover the basic needs a user may encounter. It generates a `Default Search API Key` dedicated to the search that can be used on the client-side and a `Default Admin API Key` to manipulate a MeiliSearch instance from a backend side. @@ -118,17 +117,17 @@ Manipulate API keys of a Meilisearch instance. `/keys` endpoints are **only acce ##### 3.2.4.1. `API Key` Resource Representation -| field | type | description | -|-------------|---------|--------------------------------------------------| -| uid | string | A unique identifier represented by a uuid v4. Can be specified at creation or generated by Meilisearch if ommited. | -| key | string | The generated key to use when in the Authorization header when making requests. **Generated by MeiliSearch by a combination of uid and the master key**. | -| name | string | A non unique human readable name to ease identification of the API key. `null` if empty. | -| description | string | A description for the key. `null` if empty. | -| actions | array | A list of actions permitted for the key. `["*"]` for all actions. See Actions List Definition part. | -| indexes | array | A list of indexes permitted for the key. `["*"]` for all indexes. | -| expiresAt | string | Represent the expiration date and time as `RFC 3339` format. `null` equals to no expiration time. | -| createdAt | string | Represent the date and time as `RFC 3339` format when the API key has been created. **Generated by MeiliSearch** | -| updatedAt | string | Represent the date and time as `RFC 3339` format when the API key has been updated. **Default**: Value of `createdAt`. **Generated by MeiliSearch** | +| field | type | description | +|-------------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------| +| uid | string | A unique identifier represented by a uuid v4. Can be specified at creation or generated by Meilisearch if ommited. | +| key | string | The generated key to use when in the Authorization header when making requests. **Generated by MeiliSearch by a combination of uid and the master key**. | +| name | string | A non unique human readable name to ease identification of the API key. `null` if empty. | +| description | string | A description for the key. `null` if empty. | +| actions | array | A list of actions permitted for the key. `["*"]` for all actions. See Actions List Definition part. | +| indexes | array | A list of indexes permitted for the key. `["*"]` for all indexes. | +| expiresAt | string | Represent the expiration date and time as `RFC 3339` format. `null` equals to no expiration time. | +| createdAt | string | Represent the date and time as `RFC 3339` format when the API key has been created. **Generated by MeiliSearch** | +| updatedAt | string | Represent the date and time as `RFC 3339` format when the API key has been updated. **Default**: Value of `createdAt`. **Generated by MeiliSearch** | ##### 3.2.4.2. `GET` - `/keys` @@ -265,9 +264,9 @@ Gives the total number of API keys that can be browsed. > πŸ‘‰ Note the two default generated API keys here. When a master key is set at MeiliSearch's launch, it generates two pre-configured `API Keys`. A Default Search API Key restricted to the search action on all indexes and a Default Admin API Key on all indexes to handle all operations (except managing API Keys). -##### 3.2.4.3. `GET` - `/keys/:uid` +##### 3.2.4.3. `GET` - `/keys/:uid_or_key` -Fetch a specific API key of a Meilisearch instance from it's `uid` field. +Fetch a specific API key of a Meilisearch instance from it's `uid` or `key` field. ###### 3.2.4.3.1. Query Parameter Definition n/a @@ -281,7 +280,7 @@ See [API Key Resource Representation](#3241-api-key-resource-representation) sec ###### 3.2.4.3.3. Errors - πŸ”΄ Accessing this route without the `Authorization` header returns a [missing_authorization_header](0061-error-format-and-definitions.md#missing_authorization_header) error. -- πŸ”΄ Accessing this route without the master key returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. +- πŸ”΄ Accessing this route without the master key or an API key missing the `keys.get` permission returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. ##### 3.2.4.4. `POST` - `/keys` @@ -289,35 +288,39 @@ Create an API key. ###### 3.2.4.4.1. Payload Definition -| field | type | required |description | -|-------------|---------|----------|--------------------------------| -| uid | string | Optional | A unique identifier represented by a [uuid v4](https://fr.wikipedia.org/wiki/Universally_unique_identifier). Specified at creation or generated by Meilisearch if ommited. | -| name | string | Optional | A non unique human readable name to ease identification of the API key. **Default**: `null` | -| description | string | Optional | A description for the API key. **Default**: `null` | -| actions | array | Required | A list of actions permitted for the API key. `["*"]` for all actions. **See Actions list definition part**. `*` character can be used as a wildcard. e.g. `documents.*` to authorize access on all documents endpoints. **Default**: `No default` | -| indexes | array | Required | `[*]` for all indexes. **Default**: `No Default` | -| expiresAt | string | Required | The expiration date and time as `RFC 3339` format. `null` equals to no expiration time. Sending only the date part e.g `2021-12-01` leads to having an `expiresAt` value set to `2021-12-01T00:00:00`. **Default**: `No Default` | +| field | type | required | description | +|-------------|--------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| uid | string | Optional | A unique identifier represented by a [uuid v4](https://fr.wikipedia.org/wiki/Universally_unique_identifier). Specified at creation or generated by Meilisearch if ommited. | +| name | string | Optional | A non unique human readable name to ease identification of the API key. **Default**: `null` | +| description | string | Optional | A description for the API key. **Default**: `null` | +| actions | array | Required | A list of actions permitted for the API key. `["*"]` for all actions. **See Actions list definition part**. `*` character can be used as a wildcard. e.g. `documents.*` to authorize access on all documents endpoints. **Default**: `No default` | +| indexes | array | Required | `[*]` for all indexes. **Default**: `No Default` | +| expiresAt | string | Required | The expiration date and time as `RFC 3339` format. `null` equals to no expiration time. Sending only the date part e.g `2021-12-01` leads to having an `expiresAt` value set to `2021-12-01T00:00:00`. **Default**: `No Default` | ###### 3.2.4.4.2. `actions` List Definition > `:authorizedIndexes` can be any value extracted from the `indexes` field of an API key resource. -| name | description | -|---------|-------------| -| search | Provides access to `GET` and `POST` methods on `/indexes/:authorizedIndexes/search` routes. | -| documents.add | Provides access to `POST` and `PUT` on `/indexes/:authorizedIndexes/documents` routes. | -| documents.get | Provides access to `GET` methods on `/indexes/:authorizedIndexes/documents` and `/indexes/:authorizedIndexes/documents/:documentId` routes. | +| name | description | +|------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| search | Provides access to `GET` and `POST` methods on `/indexes/:authorizedIndexes/search` routes. | +| documents.add | Provides access to `POST` and `PUT` on `/indexes/:authorizedIndexes/documents` routes. | +| documents.get | Provides access to `GET` methods on `/indexes/:authorizedIndexes/documents` and `/indexes/:authorizedIndexes/documents/:documentId` routes. | | documents.delete | Provides access to `DELETE` method on `/indexes/:authorizedIndexes/documents/:documentId`, `indexes/:authorizedIndexes/documents/:documentId` and `POST` method on `/indexes/:authorizedIndexes/documents/delete-batch` routes. | -| indexes.create | Provides access to `POST` `/indexes`. **⚠️ `indexes` field should indicate the newly created index or having `[*]` to permits access on it.**. | -| indexes.get | Provides access to `GET` `/indexes` and `/indexes/:authorizedIndexes`. **⚠️Non-authorized `indexes` are omitted from the response on `/indexes`**. | -| indexes.update | Provides access to `PUT` `/indexes/:authorizedIndexes`. | -| indexes.delete | Provides access to `DELETE` `/indexes/:authorizedIndexes`. | -| tasks.get | Provides access to `GET` `/tasks`. **⚠️Non-authorized `indexes` are omitted from the response on `/tasks`**. Also add access to `GET` `/indexes/:authorizedIndexes/tasks` routes. | -| settings.get | Provides access to `GET` `/indexes/:authorizedIndexes/settings` and `/indexes/:authorizedIndexes/settings/*` routes. | -| settings.update | Provides access to `POST / DELETE` `/indexes/:authorizedIndexes/settings` and `/indexes/:authorizedIndexes/settings/*` routes. | -| stats.get | Provides access to `GET` `/stats/`. **⚠️Non-authorized `indexes` are omitted from the response on `/stats`**. Also add access to `GET` `/indexes/:authorizedIndexes/stats`. | -| dumps.create | Provides access to `POST` `/dumps` route. **As dumps are not scoped by indexes, a restriction on `indexes` does not affect this action.** | -| version | Provides access to `GET` `/version` route. +| indexes.create | Provides access to `POST` `/indexes`. **⚠️ `indexes` field should indicate the newly created index or having `[*]` to permits access on it.**. | +| indexes.get | Provides access to `GET` `/indexes` and `/indexes/:authorizedIndexes`. **⚠️Non-authorized `indexes` are omitted from the response on `/indexes`**. | +| indexes.update | Provides access to `PUT` `/indexes/:authorizedIndexes`. | +| indexes.delete | Provides access to `DELETE` `/indexes/:authorizedIndexes`. | +| tasks.get | Provides access to `GET` `/tasks`. **⚠️Non-authorized `indexes` are omitted from the response on `/tasks`**. Also add access to `GET` `/indexes/:authorizedIndexes/tasks` routes. | +| settings.get | Provides access to `GET` `/indexes/:authorizedIndexes/settings` and `/indexes/:authorizedIndexes/settings/*` routes. | +| settings.update | Provides access to `POST / DELETE` `/indexes/:authorizedIndexes/settings` and `/indexes/:authorizedIndexes/settings/*` routes. | +| stats.get | Provides access to `GET` `/stats/`. **⚠️Non-authorized `indexes` are omitted from the response on `/stats`**. Also add access to `GET` `/indexes/:authorizedIndexes/stats`. | +| dumps.create | Provides access to `POST` `/dumps` route. **As dumps are not scoped by indexes, a restriction on `indexes` does not affect this action.** | +| version | Provides access to `GET` `/version` route. | +| keys.get | Provides access to `GET` `/keys` route. | +| keys.create | Provides access to `POST` `/keys` route. | +| keys.update | Provides access to `PATCH` `/keys` routes. | +| keys.delete | Provides access to `DELETE` `/keys` routes. | ###### 3.2.4.4.3. Response Definition @@ -328,7 +331,7 @@ See [API Key Resource Representation](#3241-api-key-resource-representation) sec ###### 3.2.4.4.3. Errors - πŸ”΄ Accessing this route without the `Authorization` header returns a [missing_authorization_header](0061-error-format-and-definitions.md#missing_authorization_header) error. -- πŸ”΄ Accessing this route without the master key returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. +- πŸ”΄ Accessing this route without the master key or an API key missing the `keys.create` permission returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. - πŸ”΄ Omitting Content-Type header returns a [missing_content_type](0061-error-format-and-definitions.md#missing_content_type) error. - πŸ”΄ Sending an empty Content-Type returns an [invalid_content_type](0061-error-format-and-definitions.md#invalid_content_type) error. - πŸ”΄ Sending a different Content-Type than `application/json` returns an [invalid_content_type](0061-error-format-and-definitions.md#invalid_content_type) error. @@ -352,10 +355,10 @@ Update an API key found by its `uid`. Only the `name` and `description` fields o ###### 3.2.4.5.1. Payload Definition -| field | type | required |description | -|-------------|---------|----------|--------------------------------| -| name | string | Optional | A name for the API Key. **Default**: `null` | -| description | string | Optional | A description for the API key. **Default**: `null` | +| field | type | required | description | +|-------------|--------|----------|----------------------------------------------------| +| name | string | Optional | A name for the API Key. **Default**: `null` | +| description | string | Optional | A description for the API key. **Default**: `null` | ###### 3.2.4.5.2. Response Definition @@ -366,7 +369,7 @@ See [API Key Resource Representation](#3241-api-key-resource-representation) sec ###### 3.2.4.5.3. Errors - πŸ”΄ Accessing this route without the `Authorization` header returns a [missing_authorization_header](0061-error-format-and-definitions.md#missing_authorization_header) error. -- πŸ”΄ Accessing this route without the master key returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. +- πŸ”΄ Accessing this route without the master key or an API key missing the `keys.update` permission returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. - πŸ”΄ Attempting to access an API key that does not exist returns a [api_key_not_found](0061-error-format-and-definitions.md#api_key_not_found) error. - πŸ”΄ Omitting Content-Type header returns a [missing_content_type](0061-error-format-and-definitions.md#missing_content_type) error. - πŸ”΄ Sending an empty Content-Type returns an [invalid_content_type](0061-error-format-and-definitions.md#invalid_content_type) error. @@ -376,6 +379,8 @@ See [API Key Resource Representation](#3241-api-key-resource-representation) sec - πŸ”΄ Sending an invalid json format returns a [malformed_payload](0061-error-format-and-definitions.md#malformed_payload) error. - πŸ”΄ Sending an invalid value for the `name` field returns an [invalid_api_key_name](0061-error-format-and-definitions.md#invalid_api_key_name) error. - πŸ”΄ Sending an invalid value for the `description` field returns an [invalid_api_key_description](0061-error-format-and-definitions.md#invalid_api_key_description) error. +- πŸ”΄ Sending `uid`, `key`, `actions`, `indexes`, `expiresAt`, `createdAt`, `updatedAt` in the payload request returns an [immutable_field](0061-error-format-and-definitions.md#immutable_field) error. + ##### 3.2.4.6. `DELETE` - `/keys/:uid` @@ -391,7 +396,7 @@ Returns a `204 No-Content` HTTP code when the request is successful. ###### 3.2.4.6.3. Errors - πŸ”΄ Accessing this route without the `Authorization` header returns a [missing_authorization_header](0061-error-format-and-definitions.md#missing_authorization_header) error. -- πŸ”΄ Accessing this route without the master key returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. +- πŸ”΄ Accessing this route without the master key or an API key missing the `keys.delete` permission returns an [invalid_api_key](0061-error-format-and-definitions.md#invalid_api_key) error. - πŸ”΄ Attempting to access an API key that does not exist returns a [`api_key_not_found`](0061-error-format-and-definitions.md#api_key_not_found) error. ##### 3.2.4.7. Using an API key on client-code diff --git a/text/0089-tenant-tokens.md b/text/0089-tenant-tokens.md index 8e53977f..69dc84b5 100644 --- a/text/0089-tenant-tokens.md +++ b/text/0089-tenant-tokens.md @@ -76,14 +76,14 @@ Meilisearch needs information within the tenant token to check its validity and | Fields | Required | Description | Comments | | -------- |----------- | ----------- | -------- | -| `apiKeyPrefix` (Custom claim) | Required | Must contain the first 8 characters of the signing `Meilisearch API key` used to generate the JWT | | +| `apiKeyUid` (Custom claim) | Required | Must contain the `uid` field value of the signing `Meilisearch API key` used to generate the JWT | | | `exp` (Expiration Time claim) | Optional | A JSON numeric value representing the number of seconds from 1970-01-01T00:00:00Z UTC until the specified UTC date/time. | If the signing API key expires, the Tenant Token also expires. Thus said, the `exp` can't be greater than the expiration date of the signing API key. | -###### 3.2.2.1.1. `apiKeyPrefix` field +###### 3.2.2.1.1. `apiKeyUid` field -`apiKeyPrefix` permits to verify that the signing API key of the Token is known and valid within Meilisearch. It must contain the first 8 characters of the Meilisearch API key that generates and signs the Tenant Token. +`apiKeyUid` permits to verify that the signing API key of the Token is known and valid within Meilisearch. It must contain the `uid` field value of the Meilisearch API key that generates and signs the Tenant Token. -The `apiKeyPrefix` can't be generated from a master key, and the `API Key` must have the `search` action defined. +The `apiKeyUid` can't be generated from the master key, and the `API Key` must have the `search` action defined to generate a usable tenant token. ###### 3.2.2.1.2. `exp` field @@ -235,7 +235,7 @@ e.g. `Meilisearch API key: rkDxFUHd02193e120218f72cc51a9db62729fdb4003e271f960d1 ```jsonc { - "apiKeyPrefix": "rkDxFUHd", // The first 8 characters of the signing Meilisearch API Key + "apiKeyUid": "f0ec9882-0184-4303-89f0-d4c4d6912bcf", // The uid field value of the signing Meilisearch API Key "exp": 1641835850, // An expiration date in seconds from 1970-01-01T00:00:00Z UTC "searchRules": { // The searchRules Json Object definition "*": { From 14048c7a31f68e05de0cba7a380123ee128bcb1a Mon Sep 17 00:00:00 2001 From: Guillaume Mourier Date: Wed, 1 Jun 2022 12:01:28 +0200 Subject: [PATCH 09/17] Update open-api spec --- open-api.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/open-api.yaml b/open-api.yaml index 2fd13944..61ef4b5f 100644 --- a/open-api.yaml +++ b/open-api.yaml @@ -593,6 +593,10 @@ components: - stats.get - dumps.create - version + - keys.get + - keys.create + - keys.update + - keys.delete indexes: type: array description: 'A list of accesible indexes permitted for the key. ["*"] for all indexes.' From 3910d80f445b7518e5870e708d14506681b66e0f Mon Sep 17 00:00:00 2001 From: Guillaume Mourier Date: Wed, 1 Jun 2022 16:34:44 +0200 Subject: [PATCH 10/17] Update immutable_field error message --- text/0061-error-format-and-definitions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0061-error-format-and-definitions.md b/text/0061-error-format-and-definitions.md index d287f99c..71bd9c79 100644 --- a/text/0061-error-format-and-definitions.md +++ b/text/0061-error-format-and-definitions.md @@ -136,7 +136,7 @@ HTTP Code: `400 Bad Request` ```json { - "message": "`:fieldName` cannot be modified for the given resource.", + "message": "The `:fieldName` field cannot be modified for the given resource.", "code": "immutable_field", "type": "invalid_request", "link":"https://docs.meilisearch.com/errors#immutable_field" From 68adaa96437f44d843e23e2f1eae39e25e49a263 Mon Sep 17 00:00:00 2001 From: Guillaume Mourier Date: Mon, 13 Jun 2022 13:55:47 +0200 Subject: [PATCH 11/17] Apply suggestions from code review Co-authored-by: Many the fish --- open-api.yaml | 2 +- text/0085-api-keys.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/open-api.yaml b/open-api.yaml index 61ef4b5f..c1aa76b8 100644 --- a/open-api.yaml +++ b/open-api.yaml @@ -568,7 +568,7 @@ components: example: 01b4bc42-eb33-4041-b481-254d00cce834 key: type: string - description: The derived key to use in the Authorization header to authorize requests. Generated by Meilisearch with a SHA-256 hash of the uid and the master key. + description: The derived key to use in the Authorization header to authorize requests. Generated by Meilisearch with an HMAC, using an SHA-256 hash, of the uid and the master key. example: d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4 readOnly: true actions: diff --git a/text/0085-api-keys.md b/text/0085-api-keys.md index bf834019..19af9ef3 100644 --- a/text/0085-api-keys.md +++ b/text/0085-api-keys.md @@ -418,9 +418,9 @@ When the Meilisearch API is secured by the presence of a master key, the `Author An `uid` representing by a uuid v4 is generated if not specified at creation by the user. -The final key is then an SHA-256 hash made of the `uid` and the master key concatenation. +The final key is then an HMAC with the master key, pre-hashed by an SHA-256 algorithm, as the secret and the `uid` as the data. HMAC uses an SHA-256 algorithm internally. -`SHA-256(:uid, :master-key)` gives the final `key` field to use when authorizing requests. +`HMAC(secret: SHA-256(:master-key), data: :uid)` gives the final `key` field to use when authorizing requests. ### 4.2. Synchronous write of `API Key` resources From f82d6559089afefb8361d321020e920675836264 Mon Sep 17 00:00:00 2001 From: Guillaume Mourier Date: Mon, 20 Jun 2022 13:06:43 +0200 Subject: [PATCH 12/17] Mention that the Default Admin API Key can manage keys --- text/0085-api-keys.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text/0085-api-keys.md b/text/0085-api-keys.md index 19af9ef3..ed8d4943 100644 --- a/text/0085-api-keys.md +++ b/text/0085-api-keys.md @@ -21,10 +21,10 @@ To make Meilisearch more reliable for teams and more adapted to production cases #### 3.2.1 Summary Key Points -- API keys management is restricted to the master key or API keys having `keys.get`, `keys.create`, `keys.update`, `keys.delete` actions. +- API keys management is restricted to the master key or API keys having `keys.get`, `keys.create`, `keys.update`, `keys.delete` or `*` actions. - API keys must be provided via the `Authorization` header using the bearer method to authorize a request. - The value of the `key` field of an API Key is generated from its `uid` and the master key. -- When a master key is set at Meilisearch first-launch, it generate two pre-configured default `API Key` resources. A `Default Search API Key` authorizing the search action on all indexes and a `Default Admin API Key` authorizing all actions on all indexes (except managing `/keys` resource). +- When a master key is set at Meilisearch first-launch, it generate two pre-configured default `API Key` resources. A `Default Search API Key` authorizing the search action on all indexes and a `Default Admin API Key` authorizing all actions. - If the master-key changes, the `key` field is re-generated. - Default API keys can be modified/deleted from the `/keys` endpoints but are not re-created if Meilisearch has already created them. - API keys can have restrictions on which methods can be accessed via an `actions` list; they also `expiresAt` a specific date time and are restricted to a specific set of `indexes`. @@ -89,7 +89,7 @@ Here is how the `Default Search API Key` is represented after its generation. ##### 3.2.3.2. Default Admin API Key -The `Default Admin API key` gives access to all actions on all indexes except managing the API Keys. +The `Default Admin API key` gives access to all actions by default. Here is how the `Default Admin API Key` is represented after its generation. From d917b172fad1b34f87adcaedfe30b2e78a045ecd Mon Sep 17 00:00:00 2001 From: Kerollmops Date: Wed, 22 Jun 2022 16:11:44 +0200 Subject: [PATCH 13/17] Specify that the JWT Tenant Token must be enrypted with the API Key value --- text/0089-tenant-tokens.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/text/0089-tenant-tokens.md b/text/0089-tenant-tokens.md index 69dc84b5..1a467dfd 100644 --- a/text/0089-tenant-tokens.md +++ b/text/0089-tenant-tokens.md @@ -68,6 +68,8 @@ e.g. With `HS256` } ``` +The secret key that is used to encrypt the JWT token must be the original API Key value (not the UID). + #### 3.2.2. Payload: Data Meilisearch needs information within the tenant token to check its validity and use it to authorize and perform end-user search requests. @@ -265,4 +267,4 @@ Another much more drastic method is to modify the `master key` of the Meilisearc - Handle more signing methods for the Tenant Token. - Handle more search parameters restrictions in `searchRules`. - Add a possibility to revoke a specific Tenant Token. -- Introduce an endpoint to generate tenant tokens on the Meilisearch side. \ No newline at end of file +- Introduce an endpoint to generate tenant tokens on the Meilisearch side. From eb47df57d388ace37510c4b07e7a8a31383bc0c0 Mon Sep 17 00:00:00 2001 From: Guillaume Mourier Date: Mon, 27 Jun 2022 18:29:45 +0200 Subject: [PATCH 14/17] Update the spec regarding the description of the Admin API Key to be up-to-date --- text/0085-api-keys.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0085-api-keys.md b/text/0085-api-keys.md index ed8d4943..43ed68f4 100644 --- a/text/0085-api-keys.md +++ b/text/0085-api-keys.md @@ -98,7 +98,7 @@ Here is how the `Default Admin API Key` is represented after its generation. "uid": "ac06a7e1-6956-4699-bb04-dbeb72a231df", //auto-generated value "key": "380689dd379232519a54d15935750cc7625620a2ea2fc06907cb40ba5b421b6f", //auto-generated value "name": "Default Admin API Key", - "description": "Use it for all other than search operations. Caution! Do not expose it on a public frontend", + "description": "Use it for anything that is not a search operation. Caution! Do not expose it on a public frontend", "actions": [ "*" ], From 510f7d744ebc5aff7ff094a2ef4b8f000192f7f6 Mon Sep 17 00:00:00 2001 From: Guillaume Mourier Date: Tue, 28 Jun 2022 11:44:29 +0200 Subject: [PATCH 15/17] Add uid_or_key url param to update and delete a key --- open-api.yaml | 73 ++++++++++++++++++++++--------------------- text/0085-api-keys.md | 8 ++--- 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/open-api.yaml b/open-api.yaml index c1aa76b8..99a25608 100644 --- a/open-api.yaml +++ b/open-api.yaml @@ -2651,44 +2651,45 @@ paths: indexes: - products expiresAt: '2021-11-13T00:00:00Z' - '/keys/{uid}': - summary: Get an API key from its uid - tags: - - Keys - security: - - apiKey: [] - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/key' - examples: - Fetch an API Key details: - value: - uid: 01b4bc42-eb33-4041-b481-254d00cce834 - key: d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4 - name: Indexing Products API key - description: null - actions: - - documents.add - indexes: - - products - expiresAt: '2021-11-13T00:00:00Z' - createdAt: '2021-11-12T10:00:00Z' - updatedAt: '2021-11-12T10:00:00Z' + '/keys/{uid_or_key}': + get: + summary: Get an API key from its uid or key field. + tags: + - Keys + security: + - apiKey: [] + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/key' + examples: + Fetch an API Key details: + value: + uid: 01b4bc42-eb33-4041-b481-254d00cce834 + key: d0552b41536279a0ad88bd595327b96f01176a60c2243e906c52ac02375f9bc4 + name: Indexing Products API key + description: null + actions: + - documents.add + indexes: + - products + expiresAt: '2021-11-13T00:00:00Z' + createdAt: '2021-11-12T10:00:00Z' + updatedAt: '2021-11-12T10:00:00Z' operationId: keys.get description: Get an API Key - parameters: - - schema: - type: string - name: key - in: path - required: true - description: The API key value + parameters: + - schema: + type: string + name: uidOrKey + in: path + required: true + description: The uid or the key field value of the API Key. delete: - summary: Delete an API key + summary: Delete an API key specified by its uid or key field. operationId: keys.delete tags: - Keys @@ -2699,7 +2700,7 @@ paths: $ref: '#/components/responses/204' description: '' patch: - summary: Update an API key + summary: Update an API key specified by its uid or key field. operationId: keys.update tags: - Keys diff --git a/text/0085-api-keys.md b/text/0085-api-keys.md index 43ed68f4..510d95d2 100644 --- a/text/0085-api-keys.md +++ b/text/0085-api-keys.md @@ -349,9 +349,9 @@ See [API Key Resource Representation](#3241-api-key-resource-representation) sec - πŸ”΄ Sending an invalid value for the `name` field returns an [invalid_api_key_name](0061-error-format-and-definitions.md#invalid_api_key_name) error. - πŸ”΄ Sending an invalid value for the `description` field returns an [invalid_api_key_description](0061-error-format-and-definitions.md#invalid_api_key_description) error. -##### 3.2.4.5. `PATCH` - `/keys/:uid` +##### 3.2.4.5. `PATCH` - `/keys/:uid_or_key` -Update an API key found by its `uid`. Only the `name` and `description` fields of an API key can be modified. +Update an API key found by it's `uid` or `key` field. Only the `name` and `description` fields of an API key can be modified. ###### 3.2.4.5.1. Payload Definition @@ -382,9 +382,9 @@ See [API Key Resource Representation](#3241-api-key-resource-representation) sec - πŸ”΄ Sending `uid`, `key`, `actions`, `indexes`, `expiresAt`, `createdAt`, `updatedAt` in the payload request returns an [immutable_field](0061-error-format-and-definitions.md#immutable_field) error. -##### 3.2.4.6. `DELETE` - `/keys/:uid` +##### 3.2.4.6. `DELETE` - `/keys/:uid_or_key` -Delete an API key found by its `uid`. +Delete an API key found by it's `uid` or `key` field. ###### 3.2.4.6.1. Payload Definition n/a From 1663ec877c29eb76cd4c5e850277452f4ed80779 Mon Sep 17 00:00:00 2001 From: Guillaume Mourier Date: Tue, 5 Jul 2022 19:01:42 +0200 Subject: [PATCH 16/17] Update text/0085-api-keys.md Co-authored-by: Many the fish --- text/0085-api-keys.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0085-api-keys.md b/text/0085-api-keys.md index 510d95d2..6210b327 100644 --- a/text/0085-api-keys.md +++ b/text/0085-api-keys.md @@ -418,7 +418,7 @@ When the Meilisearch API is secured by the presence of a master key, the `Author An `uid` representing by a uuid v4 is generated if not specified at creation by the user. -The final key is then an HMAC with the master key, pre-hashed by an SHA-256 algorithm, as the secret and the `uid` as the data. HMAC uses an SHA-256 algorithm internally. +The final key is then an HMAC with the master key, as the secret, and the `uid`, a hyphenated Uuidv4, as the data. HMAC uses an SHA-256 algorithm internally. `HMAC(secret: SHA-256(:master-key), data: :uid)` gives the final `key` field to use when authorizing requests. From 826bfb59debe3776ffee8df49f592d5d3e9c1f9a Mon Sep 17 00:00:00 2001 From: Guillaume Mourier Date: Tue, 5 Jul 2022 19:01:51 +0200 Subject: [PATCH 17/17] Update text/0085-api-keys.md Co-authored-by: Many the fish --- text/0085-api-keys.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/text/0085-api-keys.md b/text/0085-api-keys.md index 6210b327..3bd8793b 100644 --- a/text/0085-api-keys.md +++ b/text/0085-api-keys.md @@ -420,7 +420,10 @@ An `uid` representing by a uuid v4 is generated if not specified at creation by The final key is then an HMAC with the master key, as the secret, and the `uid`, a hyphenated Uuidv4, as the data. HMAC uses an SHA-256 algorithm internally. -`HMAC(secret: SHA-256(:master-key), data: :uid)` gives the final `key` field to use when authorizing requests. +The final key could be generated with openssl as below: + + echo -n $HYPHENATED_UUID | openssl dgst -sha256 -hmac $MASTER_KEY + ### 4.2. Synchronous write of `API Key` resources