diff --git a/.gitignore b/.gitignore index 0ec6dc9..e2bd56f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,6 @@ **/__pycache__/ .DS_Store .coverage -/*.md \ No newline at end of file +/*.md +/.eggs/ +/devel/ \ No newline at end of file diff --git a/README.md b/README.md index 030d58b..8be40cf 100644 --- a/README.md +++ b/README.md @@ -2,28 +2,40 @@ ![](docs/_assets/images/favpng_parrot-royalty-free-cartoon.png) -httpaste is a pastebin application for easily pasting and retrieving data over -HTTP from shell environments and web browsers. It is inspired by [sprunge.us](http://sprunge.us) -and [ix.io](http://ix.io/), but focuses on extendability, advanced security, with little to -no trade-off to simplicity. It can be hosted through WSGI, CGI, Fast CGI, or -as a standalone evaluation server. It offers multiple storage backends, such as -a filesystem backend, SQLite backend, MySQL backend, or MongoDB backend. +**NOTE**: httpaste is publicly hosted at [httpaste.it](http://httpaste.it) and as a hidden Tor service ([https://paste77ubkwxy4fqezffsmthxdh3xerwi72tlsw2mch7ecjhw2xn7iyd.onion](https://paste77ubkwxy4fqezffsmthxdh3xerwi72tlsw2mch7ecjhw2xn7iyd.onion)). +Both services are to be considered evaluatory, as long as the source code +is in pre-release. Regarding voidance of pre-release status, see [Open Issues](https://victorykit.atlassian.net/issues/?jql=project%20%3D%20HTTPASTE%20AND%20fixVersion%20in%20(1.1.0-beta%2C%201.2.0-beta%2C%201.3.0)), for more information. -All pastes are being encrypted on the fly and can only be retrieved by an -authorized user, either through knowing the paste id of a public paste, or -having authentication credentials, as well as the paste id of a private paste. -This makes httpaste ideal as a pastebin for sensitive environments such as the -Tor network. Authentication credentials are created on-the-fly and don’t require a sign-up process. +This program offers an HTTP interface for storing public and private data +(a.k.a. pastes), commonly referred to as a pastebin application. It is inspired by [sprunge.us](http://sprunge.us) and [ix.io](http://ix.io/). It can be hosted through WSGI, CGI, Fast +CGI, or as a standalone evaluation server. It offers multiple storage backends, +such as a filesystem backend, SQLite backend, or MySQL backend. -httpaste supports output formatting for syntax highlighting (powered by +Public data can be accessed through an URL, where as private pastes +additionally require HTTP basic authentication. Creation of authentication +credentials happens on the fly, there is no sign-up process. Public pastes can +only be accessed by knowing their paste ids, they are not listed on any index, +since it isn’t technically possible (by design). + +All pastes are symetrically encrypted server-side with an HMAC derived key and +SHA-256 hashing, a server-side salt and a randomly generated password. Public +paste’s passwords are derived from their ids. Private paste’s passwords are +randomly generated and stored inside a symetrically encrypted personal +database, with the encryption key also being derived through the same HMAC +mechanism, where the HTTP basic authentication credentials act as the master +password. + +Paste ids, usernames, and any other identifiable attributes are only stored +inside storage backends as keyed and salted BLAKE2 hashes. + +The program supports output formatting for syntax highlighting (powered by [pygments](https://pygments.org/)), as well as MIME type output manipulation, and input encoding. -Therefore httpaste can server as an anonymous object storage for small data. +The program can therefore serve as a minimalist, anonymous object storage for +small data. -Minute-based and ‘burn-after-read’ paste expiration are supported. +Minute-based and ‘burn-after-read’ paste expiration are also supported. -httpaste focuses on security through cryptography, making it a computationally intensive application. - -# Get Started +# Getting Started ## Install diff --git a/docs/README.rst b/docs/README.rst index 0bf034c..96f45f3 100644 --- a/docs/README.rst +++ b/docs/README.rst @@ -9,28 +9,41 @@ httpaste - versatile HTTP pastebin .. image:: _assets/images/favpng_parrot-royalty-free-cartoon.png -httpaste is a pastebin application for easily pasting and retrieving data over -HTTP from shell environments and web browsers. It is inspired by `sprunge.us`_ -and `ix.io`_, but focuses on extendability, advanced security, with little to -no trade-off to simplicity. It can be hosted through WSGI, CGI, Fast CGI, or -as a standalone evaluation server. It offers multiple storage backends, such as -a filesystem backend, SQLite backend, MySQL backend, or MongoDB backend. +.. note:: + httpaste is publicly hosted at `httpaste.it`_ and as a hidden Tor service (``_). + Both services are to be considered evaluatory, as long as the source code + is in pre-release. Regarding voidance of pre-release status, see `Open Issues`_, for more information. -All pastes are being encrypted on the fly and can only be retrieved by an -authorized user, either through knowing the paste id of a public paste, or -having authentication credentials, as well as the paste id of a private paste. -This makes httpaste ideal as a pastebin for sensitive environments such as the -Tor network. Authentication credentials are created on-the-fly and don't require a sign-up process. +This program offers an HTTP interface for storing public and private data +(a.k.a. pastes), commonly referred to as a pastebin application. It is inspired by `sprunge.us`_ and `ix.io`_. It can be hosted through WSGI, CGI, Fast +CGI, or as a standalone evaluation server. It offers multiple storage backends, +such as a filesystem backend, SQLite backend, or MySQL backend. -httpaste supports output formatting for syntax highlighting (powered by +Public data can be accessed through an URL, where as private pastes +additionally require HTTP basic authentication. Creation of authentication +credentials happens on the fly, there is no sign-up process. Public pastes can +only be accessed by knowing their paste ids, they are not listed on any index, +since it isn't technically possible (by design). + +All pastes are symetrically encrypted server-side with an HMAC derived key and +SHA-256 hashing, a server-side salt and a randomly generated password. Public +paste's passwords are derived from their ids. Private paste's passwords are +randomly generated and stored inside a symetrically encrypted personal +database, with the encryption key also being derived through the same HMAC +mechanism, where the HTTP basic authentication credentials act as the master +password. + +Paste ids, usernames, and any other identifiable attributes are only stored +inside storage backends as keyed and salted BLAKE2 hashes. + +The program supports output formatting for syntax highlighting (powered by `pygments`_), as well as MIME type output manipulation, and input encoding. -Therefore httpaste can server as an anonymous object storage for small data. +The program can therefore serve as a minimalist, anonymous object storage for +small data. -Minute-based and 'burn-after-read' paste expiration are supported. +Minute-based and 'burn-after-read' paste expiration are also supported. -httpaste focuses on security through cryptography, making it a computationally intensive application. - -.. include:: guide/get-started.rst +.. include:: guide/getting-started.rst Documentation ------------- @@ -69,4 +82,8 @@ This program uses licensed third-party software. .. _ix.io: http://ix.io/ .. _sprunge.us: http://sprunge.us .. _pygments: https://pygments.org/ -.. _icon: https://favpng.com/png_view/parrot-parrot-royalty-free-cartoon-png/gps7HM42 \ No newline at end of file +.. _icon: https://favpng.com/png_view/parrot-parrot-royalty-free-cartoon-png/gps7HM42 + +.. _Open Issues: https://victorykit.atlassian.net/issues/?jql=project%20%3D%20HTTPASTE%20AND%20fixVersion%20in%20(1.1.0-beta%2C%201.2.0-beta%2C%201.3.0) + +.. _httpaste.it: http://httpaste.it \ No newline at end of file diff --git a/docs/guide/get-started.rst b/docs/guide/getting-started.rst similarity index 97% rename from docs/guide/get-started.rst rename to docs/guide/getting-started.rst index 0bbeedc..048f06a 100644 --- a/docs/guide/get-started.rst +++ b/docs/guide/getting-started.rst @@ -1,5 +1,5 @@ -Get Started -=========== +Getting Started +=============== Install """"""" diff --git a/docs/index.rst b/docs/index.rst index bb9e5a0..6b0a60b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -4,7 +4,7 @@ :maxdepth: 1 :caption: Guides - guide/get-started + guide/getting-started guide/advanced-usage guide/backend guide/cli diff --git a/pyproject.toml b/pyproject.toml index 9111d02..cb91714 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,8 @@ [build-system] requires = [ "setuptools", - "wheel" + "wheel", + "setuptools-scm[toml]" ] build-backend = "setuptools.build_meta" @@ -9,4 +10,6 @@ build-backend = "setuptools.build_meta" max_line_length = 80 aggressive = 3 recursive = true -in-place = true \ No newline at end of file +in-place = true + +[tool.setuptools_scm] diff --git a/setup.cfg b/setup.cfg index 62ebeae..465a26b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,5 @@ [metadata] name = httpaste-victorykit -version = 1.0.5-alpha author = Tiara Rodney author_email = t.rodney@victoryk.it description = a versatile HTTP pastebin @@ -39,5 +38,6 @@ console_scripts = where = src [options.package_data] -openapi_schema = src/httpaste/schema/httpaste.openapi.json -sql_schema = *.sql +* = + *.json + *.sql \ No newline at end of file diff --git a/src/httpaste/__init__.py b/src/httpaste/__init__.py index 6eea5ba..14f2385 100755 --- a/src/httpaste/__init__.py +++ b/src/httpaste/__init__.py @@ -143,6 +143,8 @@ from inspect import isclass from configparser import ConfigParser from ast import literal_eval from io import StringIO +from os import environ +from importlib.resources import path as resource_path from connexion import FlaskApp from connexion.resolver import RestyResolver @@ -158,7 +160,7 @@ from httpaste.helper.http import ( UnauthorizedError) -CONFIGPATH_ENVIRON = 'HTTPASTE_CONFIG' +CONFIGPATH_ENVIRON = 'HTTPASTE_CONFIGPATH' def get_sanitized_config_charset(charset: str): @@ -198,17 +200,17 @@ class ServerConfig: bind_address = None -def get_config_path(environ: str = CONFIGPATH_ENVIRON): +def get_config_path(var_name: str = CONFIGPATH_ENVIRON): """ """ try: - return os.environ[environ] + return environ[var_name] except KeyError as e: raise ConfigError( - 'environment variable \'{environ}\' not set.') from e + f'environment variable \'{var_name}\' not set.') from e def load_config(path: str) -> Tuple[Config, ServerConfig]: @@ -300,13 +302,16 @@ def get_flask_app( options = {"swagger_ui": server_config.swagger_ui} - application = FlaskApp(__name__, specification_dir='schema/') + #context manager returns a pathlib.Path object + with resource_path('httpaste.schema', 'httpaste.openapi.json') as path: - application.add_api( - 'httpaste.openapi.json', - options=options, - resolver=RestyResolver('httpaste.controller') - ) + application = FlaskApp(__name__, specification_dir=path.parent) + + application.add_api( + path.name, + options=options, + resolver=RestyResolver('httpaste.controller') + ) for err_cls in [ BadRequestError, @@ -322,6 +327,14 @@ def get_flask_app( with application.app.app_context(): application.app.httpaste = config + #add header for browsers to present a sign-in prompt + @application.app.after_request + def rewrite_forbidden_request(response): + + if response.status_code in [401]: + response.headers['WWW-Authenticate'] = 'Basic realm="private"' + return response + return application diff --git a/src/httpaste/helper/common.py b/src/httpaste/helper/common.py index 92cc6d7..2e6d1c7 100644 --- a/src/httpaste/helper/common.py +++ b/src/httpaste/helper/common.py @@ -1,6 +1,10 @@ from random import choice from base64 import b64decode from urllib.parse import urljoin +from tempfile import mkdtemp +from pathlib import Path +from contextlib import contextmanager + class DecodeError(Exception): """ @@ -29,4 +33,4 @@ def decode(data: str, encoding: str) -> bytes: def join_url(base:str, url: str) -> str: - return urljoin(base, url, True) \ No newline at end of file + return urljoin(base, url, True) diff --git a/src/httpaste/wsgi.py b/src/httpaste/wsgi.py index e45f821..9e43ff0 100755 --- a/src/httpaste/wsgi.py +++ b/src/httpaste/wsgi.py @@ -3,6 +3,6 @@ """ from httpaste import load_config, get_flask_app, get_config_path -config, server_config = load_config(get_config_path) +config, server_config = load_config(get_config_path()) application = get_flask_app(config, server_config)