From f4ebb93546557ec7afb1d40d8a684ed98470243b Mon Sep 17 00:00:00 2001 From: Arksine Date: Mon, 19 Apr 2021 20:45:37 -0400 Subject: [PATCH] docs: update documentation for the Authorization component USER_CHANGE: The "enable" and "api_key_file" options in the [authorizaton] section are now deprecated. A new API Key will be generated. Use the "fetch-apikey.sh" script to retrieve the new key. Signed-off-by: Eric Callahan --- README.md | 2 +- docs/configuration.md | 14 ++- docs/installation.md | 23 +++++ docs/user_changes.md | 13 +++ docs/web_api.md | 229 +++++++++++++++++++++++++++++++++++++----- 5 files changed, 246 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 5c713b0..73ac6c6 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ to see if any action is necessary on their part. The date of the most recent change is included. Users:\ -[user_changes.md](https://moonraker.readthedocs.io/en/latest/user_changes/) - March 10th 2021 +[user_changes.md](https://moonraker.readthedocs.io/en/latest/user_changes/) - April 19th 2021 Developers:\ [api_changes.md](https://moonraker.readthedocs.io/en/latest/api_changes/) - March 15th 2021 diff --git a/docs/configuration.md b/docs/configuration.md index 880296e..df5f476 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -54,19 +54,17 @@ gcode_store_size: 1000 ## `[authorization]` The `[authorization]` section provides configuration for Moonraker's -authorization module. This section is required. +authorization module. ```ini # moonraker.conf [authorization] -enabled: True -# Enables authorization. When set to true, requests must either contain -# a valid API key or originate from a trusted client. Default is True. -api_key_file: ~/.moonraker_api_key -# Path of the file that stores Moonraker's API key. The default is -# ~/.moonraker_api_key -trusted_clients: +login_timeout: +# The time, in days, after which a user is forced to re-enter their +# credentials to log in. This period begins when a logged out user +# first logs in. Successive logins without logging out will not +# renew the timeout. The default is 90 days. 192.168.1.30 192.168.1.0/24 # A list of newline separated ip addresses and/or ip ranges that are diff --git a/docs/installation.md b/docs/installation.md index fb75c19..260f844 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -178,6 +178,29 @@ These options may be changed by editing `/etc/systemd/system/moonraker.service`. The `install-moonraker.sh` script may also be used to modify the config file location. +### Retreiving the API Key + +Some clients may require an API Key to connect to Moonraker. After the +`[authorization]` component is first configured Moonraker will automatically +generate an API Key. There are two ways in which the key may be retreived +by the user: + +Retreive the API Key via the command line (SSH): +``` +cd ~/moonraker/scripts +./fetch-apikey.sh +``` + +Retreive the API Key via the browser from a trusted client: + +- Navigate to `http://{moonraker-host}/access/api_key`, where + `{moonraker-host}` is the host name or ip address of the desired + moonraker instance. +- The result will appear in the browser window in JSON format. Copy + The API Key without the quotes. + + {"result": "8ce6ae5d354a4365812b83140ed62e4b"} + ### Additional Notes - Make sure that Moonraker and Klipper both have read and write access to the diff --git a/docs/user_changes.md b/docs/user_changes.md index b321054..e0c51a1 100644 --- a/docs/user_changes.md +++ b/docs/user_changes.md @@ -2,6 +2,19 @@ This file will track changes that require user intervention, such as a configuration change or a reinstallation. +### April 19th 2021 +- The `[authorization]` module is now a component, thus is only + loaded if the user has it configured in `moonraker.conf`. This + deprecates the previous `enable` option, as it is enabled + if configured and disabled otherwise. +- The API Key is now stored in the database. This deprecates the + `api_key_file` option in the `[authorization]` module. Users can + no longer read the contents of the API Key file to retreive the + API Key. Instead, users can run `scripts/fetch-apikey.sh` to + print the API Key. Alternative a user can navigate to + `http://{moonraker-host}/access/api_key` from a trusted client + to retreive the API Key. + ### March 10th 2021 - The `cors_domain` option in the `[authoriztion]` section is now checked for dangerous entries. If a domain entry contains a diff --git a/docs/web_api.md b/docs/web_api.md index a9ac77f..27b2683 100644 --- a/docs/web_api.md +++ b/docs/web_api.md @@ -1431,9 +1431,209 @@ The requested file ### Authorization -Untrusted Clients must use a key to access the API by including it in the -`X-Api-Key` header for each HTTP Request. The APIs below allow authorized -clients to request or modify the current API Key. +The Authorization endpoints are enabled when the user has the +`[authorization]` component configured in `moonraker.conf`. + +Untrusted clients must use either a JSON Web Token or an API key to access +Moonraker's HTTP APIs. JWTs should be included in the `Authorization` +header as a `Bearer` type for each HTTP request. If using an API Key it +should be included in the `X-Api-Key` header for each HTTP Request. + +!!! warning + Clients should not use the query string to pass arguments to these + APIs. Arguments may be passed as part of the body either in JSON + format or as form-data. + +#### Login User +HTTP Request: +```http +POST /access/login +Content-Type: application/json + +{ + "username": "my_user", + "password": "my_password" +} +``` +JSON-RPC request: Not Available + +Returns: An object the logged in username, auth token, refresh token, +and action summary: +```json +{ + "username": "my_user", + "token": "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJpc3MiOiAiTW9vbnJha2VyIiwgImlhdCI6IDE2MTg4NzY4MDAuNDgxNjU1LCAiZXhwIjogMTYxODg4MDQwMC40ODE2NTUsICJ1c2VybmFtZSI6ICJteV91c2VyIiwgInRva2VuX3R5cGUiOiAiYXV0aCJ9.QdieeEskrU0FrH7rXKuPDSZxscM54kV_vH60uJqdU9g", + "refresh_token": "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJpc3MiOiAiTW9vbnJha2VyIiwgImlhdCI6IDE2MTg4NzY4MDAuNDgxNzUxNCwgImV4cCI6IDE2MjY2NTI4MDAuNDgxNzUxNCwgInVzZXJuYW1lIjogIm15X3VzZXIiLCAidG9rZW5fdHlwZSI6ICJyZWZyZXNoIn0.btJF0LJfymInhGJQ2xvPwkp2dFUqwgcw4OA_wE-EcCM", + "action": "user_logged_in" +} +``` +- The `token` field is a JSON Web Token used to authorize the user. It should + be included in the `Authorization` header as a `Bearer` type for all HTTP + requests. The `token` expires after 1 hour. +- The `refresh_token` field contains a JWT that can be used to generate new + tokens after they are expire. See the + [refresh token section](#refresh-json-web-token) for details. + +!!! Note + This endpoint may be accessed by unauthorized clients. A 401 would + only be returned if the username and/or password is invalid. + +#### Logout Current User +HTTP Request: +```http +POST /access/logout +``` +JSON-RPC request: Not Available + +Returns: An object containing the logged out username and action summary. +```json +{ + "username": "my_user", + "action": "user_logged_out" +} + +``` + +#### Get Current User +HTTP Request: +```http +GET /access/user +``` +JSON-RPC request: Not Available + +Returns: An object containing the currently logged in user name and +the date on which the user was created (in unix time). +```json +{ + "username": "my_user", + "created_on": 1618876783.8896716 +} +``` + +#### Create User +HTTP Request: +```http +POST /access/user +Content-Type: application/json + +{ + "username": "my_user", + "password": "my_password" +} +``` +JSON-RPC request: Not Available + +Returns: An object containing the created user name, an auth token, +a refresh token, and an action summary. Creating a user also effectively +logs the user in. +```json +{ + "username": "my_user", + "token": "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJpc3MiOiAiTW9vbnJha2VyIiwgImlhdCI6IDE2MTg4NzY3ODMuODkxNjE5LCAiZXhwIjogMTYxODg4MDM4My44OTE2MTksICJ1c2VybmFtZSI6ICJteV91c2VyIiwgInRva2VuX3R5cGUiOiAiYXV0aCJ9.oH0IShTL7mdlVs4kcx3BIs_-1j0Oe-qXezJKjo-9Xgo", + "refresh_token": "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJpc3MiOiAiTW9vbnJha2VyIiwgImlhdCI6IDE2MTg4NzY3ODMuODkxNzAyNCwgImV4cCI6IDE2MjY2NTI3ODMuODkxNzAyNCwgInVzZXJuYW1lIjogIm15X3VzZXIiLCAidG9rZW5fdHlwZSI6ICJyZWZyZXNoIn0.a6ZeRjk8RQQJDDH0JV-qGY_d_HIgfI3XpsqUlUaFT7c", + "action": "user_created" +} +``` +!!! note + Unlike `/access/login`, `/access/user` is a protected endpoint. To + create a new user a client must either be trusted, use the API Key, + or be logged in as another user. + +#### Delete User +Deletes the currently logged in user. + +HTTP Request: +```http +DELETE /access/user +Content-Type: application/json + +{ + "password": "my_password" +} +``` +JSON-RPC request: Not Available + +Returns: The username of the deleted user and an action summary. This +effectively logs the user out. +```json +{ + "username": "my_user", + "action": "user_deleted" +} +``` + +#### Reset User Password +HTTP Request: +```http +POST /access/user/password +Content-Type: application/json + +{ + "password": "my_current_password", + "new_password": "my_new_pass" +} +``` +JSON-RPC request: Not Available + +Returns: The username and action summary. +```json +{ + "username": "my_user", + "action": "user_password_reset" +} +``` + +#### Refresh JSON Web Token +This endpoint can be used to refresh an expired auth token. If this +request returns an error then the refresh token is no longer valid and +the user must login with their credentials. + +HTTP Request: +```http +POST /access/refresh_jwt +Content-Type: application/json + +{ + "refresh_token": "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJpc3MiOiAiTW9vbnJha2VyIiwgImlhdCI6IDE2MTg4Nzc0ODUuNzcyMjg5OCwgImV4cCI6IDE2MjY2NTM0ODUuNzcyMjg5OCwgInVzZXJuYW1lIjogInRlc3R1c2VyIiwgInRva2VuX3R5cGUiOiAicmVmcmVzaCJ9.Y5YxGuYSzwJN2WlunxlR7XNa2Y3GWK-2kt-MzHvLbP8" +} +``` + +JSON-RPC request: Not Available + +Returns: The username, new auth token, and action summary. +```json +{ + "username": "my_user", + "token": "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJpc3MiOiAiTW9vbnJha2VyIiwgImlhdCI6IDE2MTg4NzgyNDMuNTE2Nzc5MiwgImV4cCI6IDE2MTg4ODE4NDMuNTE2Nzc5MiwgInVzZXJuYW1lIjogInRlc3R1c2VyIiwgInRva2VuX3R5cGUiOiAiYXV0aCJ9.Ia_X_pf20RR4RAEXcxalZIOzOBOs2OwearWHfRnTSGU", + "action": "user_jwt_refresh" +} +``` +!!! Note + This endpoint may be accessed by unauthorized clients. A 401 would + only be returned if the refresh token is invalid. + +#### Generate a Oneshot Token + +Javascript is not capable of modifying the headers for some HTTP requests +(for example, the `websocket`), which is a requirement to apply JWT or API Key +authorization. To work around this clients may request a Oneshot Token and +pass it via the query string for these requests. Tokens expire in 5 seconds +and may only be used once, making them relatively safe for inclusion in the +query string. + +HTTP request: +```http +GET /access/oneshot_token +``` +JSON-RPC request: Not Available + +Returns: + +A temporary token that may be added to a request's query string for access +to any API endpoint. The query string should be added in the form of: +``` +?token={base32_ramdom_token} +``` #### Get the Current API Key HTTP request: @@ -1459,29 +1659,6 @@ The newly generated API key. This overwrites the previous key. Note that the API key change is applied immediately, all subsequent HTTP requests from untrusted clients must use the new key. -#### Generate a Oneshot Token - -Javascript is not capable of modifying the headers for some HTTP requests -(for example, the `websocket`), which is a requirement to apply `X-Api-Key` -authorization. To work around this clients may request a Oneshot Token and -pass it via the query string for these requests. Tokens expire in 5 seconds -and may only be used once, making them relatively safe for inclusion in the -query string. - -HTTP request: -```http -GET /access/oneshot_token -``` -JSON-RPC request: Not Available - -Returns: - -A temporary token that may be added to a request's query string for access -to any API endpoint. The query string should be added in the form of: -``` -?token={base32_ramdom_token} -``` - ### Database APIs The following endpoints provide access to Moonraker's ldbm database. The database is divided into `namespaces`. Each client may define its own