diff --git a/.gitignore b/.gitignore index e2bd56f..0ec6dc9 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,4 @@ **/__pycache__/ .DS_Store .coverage -/*.md -/.eggs/ -/devel/ \ No newline at end of file +/*.md \ No newline at end of file diff --git a/README.md b/README.md index 8be40cf..030d58b 100644 --- a/README.md +++ b/README.md @@ -2,40 +2,28 @@ ![](docs/_assets/images/favpng_parrot-royalty-free-cartoon.png) -**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. +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. -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. +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. -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 +httpaste supports output formatting for syntax highlighting (powered by [pygments](https://pygments.org/)), as well as MIME type output manipulation, and input encoding. -The program can therefore serve as a minimalist, anonymous object storage for -small data. +Therefore httpaste can server as an anonymous object storage for small data. -Minute-based and ‘burn-after-read’ paste expiration are also supported. +Minute-based and ‘burn-after-read’ paste expiration are supported. -# Getting Started +httpaste focuses on security through cryptography, making it a computationally intensive application. + +# Get Started ## Install diff --git a/docs/README.rst b/docs/README.rst index 96f45f3..0bf034c 100644 --- a/docs/README.rst +++ b/docs/README.rst @@ -9,41 +9,28 @@ httpaste - versatile HTTP pastebin .. image:: _assets/images/favpng_parrot-royalty-free-cartoon.png -.. 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. +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. -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. +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. -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 +httpaste supports output formatting for syntax highlighting (powered by `pygments`_), as well as MIME type output manipulation, and input encoding. -The program can therefore serve as a minimalist, anonymous object storage for -small data. +Therefore httpaste can server as an anonymous object storage for small data. -Minute-based and 'burn-after-read' paste expiration are also supported. +Minute-based and 'burn-after-read' paste expiration are supported. -.. include:: guide/getting-started.rst +httpaste focuses on security through cryptography, making it a computationally intensive application. + +.. include:: guide/get-started.rst Documentation ------------- @@ -82,8 +69,4 @@ 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 - -.. _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 +.. _icon: https://favpng.com/png_view/parrot-parrot-royalty-free-cartoon-png/gps7HM42 \ No newline at end of file diff --git a/docs/guide/getting-started.rst b/docs/guide/get-started.rst similarity index 97% rename from docs/guide/getting-started.rst rename to docs/guide/get-started.rst index 048f06a..0bbeedc 100644 --- a/docs/guide/getting-started.rst +++ b/docs/guide/get-started.rst @@ -1,5 +1,5 @@ -Getting Started -=============== +Get Started +=========== Install """"""" diff --git a/docs/index.rst b/docs/index.rst index 6b0a60b..bb9e5a0 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -4,7 +4,7 @@ :maxdepth: 1 :caption: Guides - guide/getting-started + guide/get-started guide/advanced-usage guide/backend guide/cli diff --git a/pyproject.toml b/pyproject.toml index cb91714..9111d02 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,7 @@ [build-system] requires = [ "setuptools", - "wheel", - "setuptools-scm[toml]" + "wheel" ] build-backend = "setuptools.build_meta" @@ -10,6 +9,4 @@ build-backend = "setuptools.build_meta" max_line_length = 80 aggressive = 3 recursive = true -in-place = true - -[tool.setuptools_scm] +in-place = true \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 465a26b..d330606 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,6 @@ [metadata] name = httpaste-victorykit +version = 1.0.1-alpha author = Tiara Rodney author_email = t.rodney@victoryk.it description = a versatile HTTP pastebin @@ -36,8 +37,3 @@ console_scripts = [options.packages.find] where = src - -[options.package_data] -* = - *.json - *.sql \ No newline at end of file diff --git a/src/httpaste/__init__.py b/src/httpaste/__init__.py index 14f2385..6eea5ba 100755 --- a/src/httpaste/__init__.py +++ b/src/httpaste/__init__.py @@ -143,8 +143,6 @@ 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 @@ -160,7 +158,7 @@ from httpaste.helper.http import ( UnauthorizedError) -CONFIGPATH_ENVIRON = 'HTTPASTE_CONFIGPATH' +CONFIGPATH_ENVIRON = 'HTTPASTE_CONFIG' def get_sanitized_config_charset(charset: str): @@ -200,17 +198,17 @@ class ServerConfig: bind_address = None -def get_config_path(var_name: str = CONFIGPATH_ENVIRON): +def get_config_path(environ: str = CONFIGPATH_ENVIRON): """ """ try: - return environ[var_name] + return os.environ[environ] except KeyError as e: raise ConfigError( - f'environment variable \'{var_name}\' not set.') from e + 'environment variable \'{environ}\' not set.') from e def load_config(path: str) -> Tuple[Config, ServerConfig]: @@ -302,16 +300,13 @@ def get_flask_app( options = {"swagger_ui": server_config.swagger_ui} - #context manager returns a pathlib.Path object - with resource_path('httpaste.schema', 'httpaste.openapi.json') as path: + application = FlaskApp(__name__, specification_dir='schema/') - application = FlaskApp(__name__, specification_dir=path.parent) - - application.add_api( - path.name, - options=options, - resolver=RestyResolver('httpaste.controller') - ) + application.add_api( + 'httpaste.openapi.json', + options=options, + resolver=RestyResolver('httpaste.controller') + ) for err_cls in [ BadRequestError, @@ -327,14 +322,6 @@ 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/__main__.py b/src/httpaste/__main__.py index ec35404..436a46c 100644 --- a/src/httpaste/__main__.py +++ b/src/httpaste/__main__.py @@ -2,7 +2,6 @@ """ import argparse import os -from importlib.resources import open_text def _this_dir(basename: str) -> str: @@ -21,7 +20,7 @@ def _path_output(path, echo: bool = False) -> str: return path else: - with open_text('httpaste', path) as fh: + with open(path, 'r') as fh: return fh.read() @@ -52,21 +51,21 @@ def command_wsgi(**kwargs): """get WSGI script """ - print(_path_output('wsgi.py', kwargs.get('echo'))) + print(_path_output(_this_dir('wsgi.py'), kwargs.get('echo'))) def command_cgi(**kwargs): """get CGI script """ - print(_path_output('cgi.py', kwargs.get('echo'))) + print(_path_output(_this_dir('cgi.py'), kwargs.get('echo'))) def command_fcgi(**kwargs): """get FastCGI script """ - print(_path_output('fcgi.py', kwargs.get('echo'))) + print(_path_output(_this_dir('fcgi.py'), kwargs.get('echo'))) def command_default_config(**kwargs): diff --git a/src/httpaste/backend/sqlite/paste.py b/src/httpaste/backend/sqlite/paste.py index 51c9fc6..bb0eb17 100644 --- a/src/httpaste/backend/sqlite/paste.py +++ b/src/httpaste/backend/sqlite/paste.py @@ -3,7 +3,6 @@ from os import path from sqlite3 import Connection from time import time -from importlib.resources import open_text def load(proto: object, connection: Connection, model_class: type): @@ -64,7 +63,7 @@ def init(connection: Connection): cur = connection.cursor() - with open_text('httpaste.backend.sqlite', 'paste.sql') as fh: + with open(path.join(path.dirname(__file__), 'paste.sql'), 'r') as fh: cur.execute(fh.read()) diff --git a/src/httpaste/backend/sqlite/user.py b/src/httpaste/backend/sqlite/user.py index e4f712d..11fc53e 100644 --- a/src/httpaste/backend/sqlite/user.py +++ b/src/httpaste/backend/sqlite/user.py @@ -3,7 +3,6 @@ from os import path from sqlite3 import Connection from httpaste.model import User -from importlib.resources import open_text def load(proto: User, connection: Connection): @@ -49,7 +48,7 @@ def init(connection: Connection): cur = connection.cursor() - with open_text('httpaste.backend.sqlite', 'user.sql') as fh: + with open(path.join(path.dirname(__file__), 'user.sql'), 'r') as fh: cur.execute(fh.read()) diff --git a/src/httpaste/helper/common.py b/src/httpaste/helper/common.py index 2e6d1c7..92cc6d7 100644 --- a/src/httpaste/helper/common.py +++ b/src/httpaste/helper/common.py @@ -1,10 +1,6 @@ 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): """ @@ -33,4 +29,4 @@ def decode(data: str, encoding: str) -> bytes: def join_url(base:str, url: str) -> str: - return urljoin(base, url, True) + return urljoin(base, url, True) \ No newline at end of file diff --git a/src/httpaste/schema/__init__.py b/src/httpaste/schema/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/httpaste/schema/httpaste.openapi.json b/src/httpaste/schema/httpaste.openapi.json index 8f55586..163a57e 100644 --- a/src/httpaste/schema/httpaste.openapi.json +++ b/src/httpaste/schema/httpaste.openapi.json @@ -161,15 +161,6 @@ }, { "$ref": "#/components/parameters/syntax" - }, - { - "$ref": "#/components/parameters/format" - }, - { - "$ref": "#/components/parameters/linenos" - }, - { - "$ref": "#/components/parameters/mime" } ], "responses": { diff --git a/src/httpaste/wsgi.py b/src/httpaste/wsgi.py index 9e43ff0..e45f821 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)