From c3d01d372c39440c36b8ac7c957ff62ceb198035 Mon Sep 17 00:00:00 2001 From: Vignesh Rao Date: Sun, 11 Aug 2024 08:18:18 -0500 Subject: [PATCH] Enable remote execution optionally --- .pre-commit-config.yaml | 2 +- README.md | 5 ++ doc_gen/index.rst | 8 +-- docs/README.html | 4 ++ docs/README.md | 5 ++ docs/_sources/README.md.txt | 5 ++ docs/_sources/index.rst.txt | 8 +-- docs/genindex.html | 30 +++++++-- docs/index.html | 107 ++++++++++++++++++++------------ docs/objects.inv | Bin 584 -> 608 bytes docs/searchindex.js | 2 +- pyninja/routers.py | 120 ++++++++++++++++++++++++++++++------ pyninja/squire.py | 14 +++-- 13 files changed, 233 insertions(+), 77 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 71723af..da8cd0d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -36,7 +36,7 @@ repos: additional_dependencies: - flake8-docstrings - flake8-sfs - args: [ --max-line-length=120, --extend-ignore=SFS3 D107 SFS301 D100 D104 D401 SFS101 SFS201 D412 ] + args: [ --max-line-length=120, --extend-ignore=SFS3 D107 SFS301 D100 D104 D401 SFS101 SFS201 D412 D400 ] - repo: https://github.com/PyCQA/isort rev: 5.13.2 diff --git a/README.md b/README.md index 124d18f..6471aa4 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,13 @@ pyninja start - **NINJA_HOST** - Hostname for the API server. - **NINJA_PORT** - Port number for the API server. - **WORKERS** - Number of workers for the uvicorn server. +- **COMMAND_TIMEOUT** - Number of seconds for a command to timeout. +- **API_SECRET** - Secret access key for running commands on server remotely. - **APIKEY** - API Key for authentication. +**COMMAND_TIMEOUT** is set to `0` by default, disabling remote executions. To enable it, set it to a value greater than `0`
+⚠️ Enabling remote execution can be extremely risky and can be a major security threat. So use **caution** and set the **API_SECRET** to a strong value. + > `PyNinja` supports [logging.ini] configuration for custom logging. Just place it in the current working directory.
> Refer [samples] directory for examples. diff --git a/doc_gen/index.rst b/doc_gen/index.rst index 89e0e8b..36b231e 100644 --- a/doc_gen/index.rst +++ b/doc_gen/index.rst @@ -35,19 +35,19 @@ Monitors ======== Process -======= +------- .. automodule:: pyninja.process Service -======= +------- .. automodule:: pyninja.service Squire ====== -.. autoclass:: pyninja.squire.StatusPayload(BaseModel) +.. autoclass:: pyninja.squire.Payload(BaseModel) :exclude-members: _abc_impl, model_config, model_fields, model_computed_fields ==== @@ -63,7 +63,7 @@ Squire ==== .. automodule:: pyninja.squire - :exclude-members: StatusPayload, ServiceStatus, EnvConfig + :exclude-members: Payload, ServiceStatus, EnvConfig Indices and tables ================== diff --git a/docs/README.html b/docs/README.html index 9ba168a..1e8c4c7 100644 --- a/docs/README.html +++ b/docs/README.html @@ -93,8 +93,12 @@

Environment Variables

NINJA_HOST - Hostname for the API server.

  • NINJA_PORT - Port number for the API server.

  • WORKERS - Number of workers for the uvicorn server.

  • +
  • COMMAND_TIMEOUT - Number of seconds for a command to timeout.

  • +
  • API_SECRET - Secret access key for running commands on server remotely.

  • APIKEY - API Key for authentication.

  • +

    COMMAND_TIMEOUT is set to 0 by default, disabling remote executions. To enable it, set it to a value greater than 0
    +⚠️ Enabling remote execution can be extremely risky and can be a major security threat. So use caution and set the API_SECRET to a strong value.

    PyNinja supports logging.ini configuration for custom logging. Just place it in the current working directory.
    Refer samples directory for examples.

    diff --git a/docs/README.md b/docs/README.md index 124d18f..6471aa4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -56,8 +56,13 @@ pyninja start - **NINJA_HOST** - Hostname for the API server. - **NINJA_PORT** - Port number for the API server. - **WORKERS** - Number of workers for the uvicorn server. +- **COMMAND_TIMEOUT** - Number of seconds for a command to timeout. +- **API_SECRET** - Secret access key for running commands on server remotely. - **APIKEY** - API Key for authentication. +**COMMAND_TIMEOUT** is set to `0` by default, disabling remote executions. To enable it, set it to a value greater than `0`
    +⚠️ Enabling remote execution can be extremely risky and can be a major security threat. So use **caution** and set the **API_SECRET** to a strong value. + > `PyNinja` supports [logging.ini] configuration for custom logging. Just place it in the current working directory.
    > Refer [samples] directory for examples. diff --git a/docs/_sources/README.md.txt b/docs/_sources/README.md.txt index 124d18f..6471aa4 100644 --- a/docs/_sources/README.md.txt +++ b/docs/_sources/README.md.txt @@ -56,8 +56,13 @@ pyninja start - **NINJA_HOST** - Hostname for the API server. - **NINJA_PORT** - Port number for the API server. - **WORKERS** - Number of workers for the uvicorn server. +- **COMMAND_TIMEOUT** - Number of seconds for a command to timeout. +- **API_SECRET** - Secret access key for running commands on server remotely. - **APIKEY** - API Key for authentication. +**COMMAND_TIMEOUT** is set to `0` by default, disabling remote executions. To enable it, set it to a value greater than `0`
    +⚠️ Enabling remote execution can be extremely risky and can be a major security threat. So use **caution** and set the **API_SECRET** to a strong value. + > `PyNinja` supports [logging.ini] configuration for custom logging. Just place it in the current working directory.
    > Refer [samples] directory for examples. diff --git a/docs/_sources/index.rst.txt b/docs/_sources/index.rst.txt index 89e0e8b..36b231e 100644 --- a/docs/_sources/index.rst.txt +++ b/docs/_sources/index.rst.txt @@ -35,19 +35,19 @@ Monitors ======== Process -======= +------- .. automodule:: pyninja.process Service -======= +------- .. automodule:: pyninja.service Squire ====== -.. autoclass:: pyninja.squire.StatusPayload(BaseModel) +.. autoclass:: pyninja.squire.Payload(BaseModel) :exclude-members: _abc_impl, model_config, model_fields, model_computed_fields ==== @@ -63,7 +63,7 @@ Squire ==== .. automodule:: pyninja.squire - :exclude-members: StatusPayload, ServiceStatus, EnvConfig + :exclude-members: Payload, ServiceStatus, EnvConfig Indices and tables ================== diff --git a/docs/genindex.html b/docs/genindex.html index 49b6318..4e7b333 100644 --- a/docs/genindex.html +++ b/docs/genindex.html @@ -43,6 +43,7 @@

    Index

    A + | C | D | E | F @@ -50,6 +51,7 @@

    Index

    | M | N | P + | R | S | U | W @@ -58,6 +60,8 @@

    Index

    A

    @@ -69,6 +73,18 @@

    A

    +

    C

    + + + +
    +

    D

    diff --git a/docs/objects.inv b/docs/objects.inv index 6d06bf34d25824cac8b9ba5d6d0855ac149e210c..9fb57ad46caf7d3074acf2e10a68e07fca9abd64 100644 GIT binary patch delta 500 zcmV}#J9Xg zU$0M6Fy5?Js;GMSEcUNg|b4@md znT3x(pipv#+D5qXilfwu+|2Pg2k#tA3~?D|M~L2)_fOzVSbstk_&izSNPnuz8>20P zc&rxUJ(DUU)fi44GKpQU5a-}pg*R-381q^UhY<B+%i>&LBCNSbzt|BLlQeO31=ILp__{w|8~+Q84dv5s{O52mD~lCH_Xq^1&Lr43{A*9L}Tt RedirectResponse: + """Redirect to docs page. + + Returns: + RedirectResponse: + Redirects the user to ``/docs`` page. + """ return RedirectResponse("/docs") @@ -61,12 +137,18 @@ async def docs(): APIRoute( path="/service-status", endpoint=service_status, - methods=["POST"], + methods=["GET"], dependencies=[Depends(auth.authenticator)], ), APIRoute( path="/process-status", endpoint=process_status, + methods=["GET"], + dependencies=[Depends(auth.authenticator)], + ), + APIRoute( + path="/run-command", + endpoint=run_command, methods=["POST"], dependencies=[Depends(auth.authenticator)], ), diff --git a/pyninja/squire.py b/pyninja/squire.py index ad39f23..1436c4f 100644 --- a/pyninja/squire.py +++ b/pyninja/squire.py @@ -5,18 +5,18 @@ from typing import Optional import yaml -from pydantic import BaseModel, PositiveInt +from pydantic import BaseModel, Field, PositiveInt from pydantic_settings import BaseSettings -class StatusPayload(BaseModel): - """BaseModel that handles input data for ``StatusPayload``. +class Payload(BaseModel): + """BaseModel that handles input data for ``Payload``. - >>> StatusPayload + >>> Payload """ - service_name: str + command: str class ServiceStatus(BaseModel): @@ -40,6 +40,8 @@ class EnvConfig(BaseSettings): ninja_host: str = socket.gethostbyname("localhost") or "0.0.0.0" ninja_port: PositiveInt = 8000 workers: PositiveInt = 1 + command_timeout: int = Field(0, ge=0, le=60) + api_secret: str | None = None apikey: str @classmethod @@ -68,7 +70,7 @@ def env_loader(filename: str | os.PathLike) -> EnvConfig: filename: Filename from where env vars have to be loaded. Returns: - config.EnvConfig: + EnvConfig: Returns a reference to the ``EnvConfig`` object. """ env_file = pathlib.Path(filename)