Skip to main content

Manabi

  ┌───────────┐             ┌───────────┐
  │           │   Token     │           │
  │   Manabi  ├────────────►│    API    │
  │           │   Hook      │           │
  └───────────┘             └─────┬─────┘
        ▲                         │
        │                         │ doc API
WebDAV  │  PUT                    │
        │                   Token │
        │  Token                  ▼
 ┌──────┴──────┐           ┌─────────────┐
 │             │   Token   │             │
 │  Word / LO  │◄──────────┤  Frontend   │
 │             │    Link   │             │
 └─────────────┘           └─────────────┘

Case: Users should have the capability to edit documents in Word and LibreOffice.

Problem: We need to ensure the integrity and authenticity of the WebDAV link passed to Word/LO, confirming that it has not been tampered with or generated by an unauthorized third party.

Solution:

  • The API generates an ephemeral branca token. This token is a temporary and short-lived cryptographic token that contains the file-path as an encrypted payload.
  • Both the API and Manabi share a key. In a symmetric shared-key scenario, encryption can also be employed to verify the data.
  • The frontend displays a link that includes the ephemeral token along with the document, allowing users to easily edit it in Word/LO.
  • When the user clicks the link, the document opens in Word/LO.
  • Manabi retrieves the token from the request URI, checks its validity, and proceeds to open the document if the token is verified.
  • The token is updated and stored as a cookie within Word/LO for future reference.
  • Due to the ephemeral WebDAV lock, Word/LO must regularly contact Manabi to refresh the lock. Consequently, we leverage this mechanism to also refresh the token.

cb_hook_config: We provide an optional write-hooks/callbacks feature that enhances the API's capabilities by adding a versioning system. The pre-write- hook/callback is invoked with the token as an argument prior to the document being saved using WebDAV-PUT. The API has the ability to verify this token and subsequently create a new version of the document. Once the hook operation is successfully completed, Manabi takes over and saves the document. Manabi then continues and invokes the post-write-hook/callback.

Install

Make sure libsodium exists on the system, for example execute:

apk add --no-cache libsodium
apt-get install -y libsodium23

Config

Call manabi-keygen and add the key to config["manabi"]["key"]. The key is shared between the caluma/alexandria backend and the WebDAV server.

mount_path

Prefix that gets passed to wsgidav, if URL rewrites remove any prefixes use "/"

lock_storage

The ManabiLockLockStorage forces the WebDav log-timeout to token-refresh-time / 2

provider_mapping

Extends the FilesystemProvider any will only serve files if the token is valid

pre_write_hook

A hook to enhance the API's capabilities, for example versioning of documents.

middleware_stack

Based on the default middleware_stack but HTTPAuthenticator is replace by ManabiAuthenticator, which validates the tokens.

manabi.key

Shared-key between the server that creates tokens to grant access and wsgi-dav

manabi.refresh

How often tokens are refreshed in seconds, we recommend 10 minutes: 600

manabi.initial

The time from the token being generated till it has to be refreshed the first time, we recommend 1 minues: 60. In case tokens leak, for example via cache on a computer, tokens should be expired by the time an adversary gets them.

from manabi import ManabiDAVApp

# All hooks and callbacks are optional
cb_hook_config = CallbackHookConfig(
    pre_write_hook=_pre_write_hook,
    pre_write_callback=_pre_write_callback,
    post_write_hook=_post_write_hook,
    post_write_callback=_post_write_callback,
)

postgres_dsn = "dbname=manabi user=manabi host=localhost password=manabi"
config = {
    "mount_path": "/dav",
    "lock_storage": ManabiDbLockStorage(refresh, postgres_dsn),
    "provider_mapping": {
        "/": ManabiProvider(settings.MEDIA_ROOT, cb_hook_config=cb_hook_config),
    },
    "middleware_stack": [
        WsgiDavDebugFilter,
        ErrorPrinter,
        ManabiAuthenticator,
        WsgiDavDirBrowser,
        RequestResolver,
    ],
    "manabi": {
        "key": key,
        "refresh": refresh,
        "initial": settings.MANABI_TOKEN_ACTIVATE_TIMEOUT,
    },
}
dav_app = ManabiDAVApp(config)

Dev

Enable dev-env:

pyenv install 3.12.11
poetry env use $HOME/.pyenv/versions/3.12.11/bin/python3.12
poetry install
poetry run python -m manabi.mypy_fix
poetry shell
docker-compose up -d db
(cd manabi_django && ./manage.py migrate manabi_migrations)

Typing rules

My typing rules for this project (there are no company rules):

  • In tests # type: ignore is allowed if fixing the issue does not help production-code
  • In production-code # type: ignore is allowed if a manual check happens or we can guarantee some runtime behavior. For example we guarantee that a weakref is always valid. Similar to unsafe in rust.

Metadata

Release files for manabi 2.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for manabi 2.0.1
File Size Uploaded Provenance
manabi-2.0.1.tar.gz 31.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for manabi 2.0.1
File Interpreter ABI Platform
manabi-2.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 62.2 kB

Release files / manabi-2.0.1.tar.gz

Download URL manabi-2.0.1.tar.gz
Size 31.4 kB
Tags Source
SHA-256 checksum
How to use checksums
9adc2b3ad6de1c4bd54d8bbc915ebeab98719053786f8a9512a9e0af632c4a03
BLAKE2b-256 checksum
How to use checksums
f382a3444f39e87a0a56de4060301a4d61de7b98dd45f8663d191382dcc5b57e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.11

Release files / manabi-2.0.1-py3-none-any.whl

Download URL manabi-2.0.1-py3-none-any.whl
Size 30.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3a98726f8203ff5dccacdd5a176068663f3b6ac039c2d5dd6ca50d4a8e8cce13
BLAKE2b-256 checksum
How to use checksums
8944d5310e1d3d86f4d75a1dfd25f6cec24acf6fdeecb60cb59dccc9315c9d3a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.11

Security for manabi 2.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page