From 75a13ae8e885f9eed5ee173568b9502607b605e3 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Wed, 10 Nov 2021 12:39:10 +0100 Subject: [PATCH] Add keymanager-oapi.yaml --- keymanager-oapi.yaml | 229 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 keymanager-oapi.yaml diff --git a/keymanager-oapi.yaml b/keymanager-oapi.yaml new file mode 100644 index 0000000..a66fd15 --- /dev/null +++ b/keymanager-oapi.yaml @@ -0,0 +1,229 @@ +openapi: "3.0.3" + +info: + title: "Eth2 key manager API" + description: | + API specification for a key manager client, which enables users to manage keystores. + + The key manager API is served by the binary holding the validator keys. This binary may be a remote signer or a validator client. + + All routes SHOULD be exposed through a secure channel, such as with HTTPs, an SSH tunnel, a VPN, etc. + + All requests by default send and receive JSON, and as such should have either or both of the "Content-Type: application/json" + and "Accept: application/json" headers. + + All sensitive routes are to be authenticated with a token. This token should be provided by the user via a secure channel: + - Log the token to stdout when running the binary with the key manager API enabled + - Read the token from a file available to the binary + version: "Dev - Eth2Spec v1.0.1" + contact: + name: Ethereum Github + url: https://github.com/ethereum/eth2.0-apis/issues + license: + name: "Apache 2.0" + url: "https://www.apache.org/licenses/LICENSE-2.0.html" + +servers: + - url: "{server_url}" + variables: + server_url: + description: "key manager API url" + default: "https://public-mainnet-node.ethereum.org" + +paths: + /eth/v1/keystores: + get: + operationId: ListKeys + summary: List Keys. + description: | + List all validating pubkeys known to and decrypted by this keymanager binary + security: + - cookieAuth: [] + responses: + "200": + description: Success response + content: + application/json: + schema: + title: ListKeysResponse + type: object + properties: + data: + type: array + items: + type: object + properties: + validating_pubkey: + $ref: "#/components/types/Pubkey" + derivation_path: + type: string + description: The derivation path (if present in the imported keystore). + readonly: + type: boolean + required: false + description: The key associated with this pubkey cannot be deleted from the API + + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "500": + $ref: "#/components/responses/InternalError" + + post: + operationId: ImportKeystores + summary: Import Keystores. + description: | + Import keystores generated by the Eth2.0 deposit CLI tooling. `passwords[i]` must unlock `keystores[i]`. + + Users SHOULD send slashing_protection data associated with the imported pubkeys. MUST follow the format defined in + EIP-3076: Slashing Protection Interchange Format. + security: + - cookieAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + keystores: + type: array + description: JSON-encoded keystore files generated with the Launchpad. + items: + type: object + passwords: + type: array + description: Passwords to unlock imported keystore files. `passwords[i]` must unlock `keystores[i]`. + items: + type: string + slashing_protection: + type: object + required: false + description: Slashing protection of the imported keys data in EIP-3076 JSON format. + responses: + "200": + description: Success response + content: + application/json: + schema: + title: ImportKeystoresResponse + type: object + properties: + data: + type: array + description: Status result of each `request.keystores` with same length and order of `request.keystores` + items: + type: object + properties: + status: + type: string + description: | + - imported: Keystore successfully decrypted and imported to keymanager permanent storage + - duplicate: Keystore's pubkey is already known to the keymanager + - error: Any other status different to the above: decrypting error, I/O errors, etc. + enum: + - imported + - duplicate + - error + message: + type: string + description: error message if status == error + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "500": + $ref: "#/components/responses/InternalError" + + delete: + operationId: DeleteKeys + summary: Delete Keys. + description: | + DELETE must delete all keys from `request.pubkeys` that are known to the keymanager and exist in its + persistent storage. Additionally, DELETE must fetch the slashing protection data for the requested keys from + persistent storage, which must be retained (and not deleted) after the response has been sent. Therefore in the + case of two identical delete requests being made, both will have access to slashing protection data. + + In a single atomic sequential operation the keymanager must: + 1. Guarantee that key(s) can not produce any more signature; only then + 2. Delete key(s) and serialize its associated slashing protection data + + DELETE should never return a 404 response, even if all pubkeys from request.pubkeys have no extant keystores + nor slashing protection data. + security: + - cookieAuth: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + pubkeys: + type: array + description: List of public keys to delete. + items: + $ref: "#/components/types/Pubkey" + responses: + "200": + description: Success response + content: + application/json: + schema: + title: DeleteKeysResponse + type: object + properties: + data: + type: array + description: Deletion status of all keys in `request.pubkeys` in the same order. + items: + type: object + properties: + status: + type: string + description: | + - deleted: key was active and removed + - not_active: slashing protection data returned but key was not active + - not_found: key was not found to be removed, and no slashing data can be returned + - error: unexpected condition meant the key could not be removed (the key was actually found, but we couldn't stop using it) - this would be a sign that making it active elsewhere would almost certainly cause you headaches / slashing conditions etc. + enum: + - deleted + - not_active + - not_found + - error + message: + type: string + description: error message if status == error + slashing_protection: + type: object + description: | + JSON representation of the slash protection data in format defined in EIP-3076: Slashing + Protection Interchange Format. + + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/Forbidden" + "500": + $ref: "#/components/responses/InternalError" + +components: + responses: + Unauthorized: + $ref: "./types/http.yaml#/Unauthorized" + Forbidden: + $ref: "./types/http.yaml#/Forbidden" + InternalError: + $ref: "./types/http.yaml#/InternalError" + + securitySchemes: + cookieAuth: # arbitrary name for the security scheme; will be used in the "security" key later + type: apiKey + in: cookie + name: SESSION # cookie name + + types: + Pubkey: + type: string + pattern: "^0x[a-fA-F0-9]{96}$" + description: "The validator's BLS public key, uniquely identifying them. _48-bytes, hex encoded with 0x prefix, case insensitive._" + example: "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a"