Brad Bishop | 1932369 | 2019-04-05 15:28:33 -0400 | [diff] [blame] | 1 | #! /usr/bin/env python3 |
| 2 | # |
| 3 | # Copyright (C) 2018 Garmin Ltd. |
| 4 | # |
Brad Bishop | c342db3 | 2019-05-15 21:57:59 -0400 | [diff] [blame] | 5 | # SPDX-License-Identifier: GPL-2.0-only |
Brad Bishop | 1932369 | 2019-04-05 15:28:33 -0400 | [diff] [blame] | 6 | # |
Brad Bishop | c342db3 | 2019-05-15 21:57:59 -0400 | [diff] [blame] | 7 | |
Brad Bishop | 1932369 | 2019-04-05 15:28:33 -0400 | [diff] [blame] | 8 | import os |
| 9 | import sys |
| 10 | import logging |
| 11 | import argparse |
| 12 | import sqlite3 |
Andrew Geissler | 5199d83 | 2021-09-24 16:47:35 -0500 | [diff] [blame] | 13 | import warnings |
Patrick Williams | ac13d5f | 2023-11-24 18:59:46 -0600 | [diff] [blame] | 14 | |
Andrew Geissler | 5199d83 | 2021-09-24 16:47:35 -0500 | [diff] [blame] | 15 | warnings.simplefilter("default") |
Brad Bishop | 1932369 | 2019-04-05 15:28:33 -0400 | [diff] [blame] | 16 | |
Patrick Williams | ac13d5f | 2023-11-24 18:59:46 -0600 | [diff] [blame] | 17 | sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), "lib")) |
Brad Bishop | 1932369 | 2019-04-05 15:28:33 -0400 | [diff] [blame] | 18 | |
| 19 | import hashserv |
Patrick Williams | ac13d5f | 2023-11-24 18:59:46 -0600 | [diff] [blame] | 20 | from hashserv.server import DEFAULT_ANON_PERMS |
Brad Bishop | 1932369 | 2019-04-05 15:28:33 -0400 | [diff] [blame] | 21 | |
| 22 | VERSION = "1.0.0" |
| 23 | |
Patrick Williams | ac13d5f | 2023-11-24 18:59:46 -0600 | [diff] [blame] | 24 | DEFAULT_BIND = "unix://./hashserve.sock" |
Brad Bishop | a34c030 | 2019-09-23 22:34:48 -0400 | [diff] [blame] | 25 | |
Brad Bishop | 1932369 | 2019-04-05 15:28:33 -0400 | [diff] [blame] | 26 | |
| 27 | def main(): |
Patrick Williams | ac13d5f | 2023-11-24 18:59:46 -0600 | [diff] [blame] | 28 | parser = argparse.ArgumentParser( |
| 29 | description="Hash Equivalence Reference Server. Version=%s" % VERSION, |
| 30 | formatter_class=argparse.RawTextHelpFormatter, |
| 31 | epilog=""" |
| 32 | The bind address may take one of the following formats: |
| 33 | unix://PATH - Bind to unix domain socket at PATH |
| 34 | ws://ADDRESS:PORT - Bind to websocket on ADDRESS:PORT |
| 35 | ADDRESS:PORT - Bind to raw TCP socket on ADDRESS:PORT |
Brad Bishop | a34c030 | 2019-09-23 22:34:48 -0400 | [diff] [blame] | 36 | |
Patrick Williams | ac13d5f | 2023-11-24 18:59:46 -0600 | [diff] [blame] | 37 | To bind to all addresses, leave the ADDRESS empty, e.g. "--bind :8686" or |
| 38 | "--bind ws://:8686". To bind to a specific IPv6 address, enclose the address in |
| 39 | "[]", e.g. "--bind [::1]:8686" or "--bind ws://[::1]:8686" |
| 40 | |
| 41 | Note that the default Anonymous permissions are designed to not break existing |
| 42 | server instances when upgrading, but are not particularly secure defaults. If |
| 43 | you want to use authentication, it is recommended that you use "--anon-perms |
| 44 | @read" to only give anonymous users read access, or "--anon-perms @none" to |
| 45 | give un-authenticated users no access at all. |
| 46 | |
| 47 | Setting "--anon-perms @all" or "--anon-perms @user-admin" is not allowed, since |
| 48 | this would allow anonymous users to manage all users accounts, which is a bad |
| 49 | idea. |
| 50 | |
| 51 | If you are using user authentication, you should run your server in websockets |
| 52 | mode with an SSL terminating load balancer in front of it (as this server does |
| 53 | not implement SSL). Otherwise all usernames and passwords will be transmitted |
| 54 | in the clear. When configured this way, clients can connect using a secure |
| 55 | websocket, as in "wss://SERVER:PORT" |
Patrick Williams | 169d7bc | 2024-01-05 11:33:25 -0600 | [diff] [blame] | 56 | |
| 57 | The following permissions are supported by the server: |
| 58 | |
| 59 | @none - No permissions |
| 60 | @read - The ability to read equivalent hashes from the server |
| 61 | @report - The ability to report equivalent hashes to the server |
| 62 | @db-admin - Manage the hash database(s). This includes cleaning the |
| 63 | database, removing hashes, etc. |
| 64 | @user-admin - The ability to manage user accounts. This includes, creating |
| 65 | users, deleting users, resetting login tokens, and assigning |
| 66 | permissions. |
| 67 | @all - All possible permissions, including any that may be added |
| 68 | in the future |
Patrick Williams | ac13d5f | 2023-11-24 18:59:46 -0600 | [diff] [blame] | 69 | """, |
| 70 | ) |
| 71 | |
| 72 | parser.add_argument( |
| 73 | "-b", |
| 74 | "--bind", |
| 75 | default=os.environ.get("HASHSERVER_BIND", DEFAULT_BIND), |
| 76 | help='Bind address (default $HASHSERVER_BIND, "%(default)s")', |
| 77 | ) |
| 78 | parser.add_argument( |
| 79 | "-d", |
| 80 | "--database", |
| 81 | default=os.environ.get("HASHSERVER_DB", "./hashserv.db"), |
| 82 | help='Database file (default $HASHSERVER_DB, "%(default)s")', |
| 83 | ) |
| 84 | parser.add_argument( |
| 85 | "-l", |
| 86 | "--log", |
| 87 | default=os.environ.get("HASHSERVER_LOG_LEVEL", "WARNING"), |
| 88 | help='Set logging level (default $HASHSERVER_LOG_LEVEL, "%(default)s")', |
| 89 | ) |
| 90 | parser.add_argument( |
| 91 | "-u", |
| 92 | "--upstream", |
| 93 | default=os.environ.get("HASHSERVER_UPSTREAM", None), |
| 94 | help="Upstream hashserv to pull hashes from ($HASHSERVER_UPSTREAM)", |
| 95 | ) |
| 96 | parser.add_argument( |
| 97 | "-r", |
| 98 | "--read-only", |
| 99 | action="store_true", |
| 100 | help="Disallow write operations from clients ($HASHSERVER_READ_ONLY)", |
| 101 | ) |
| 102 | parser.add_argument( |
| 103 | "--db-username", |
| 104 | default=os.environ.get("HASHSERVER_DB_USERNAME", None), |
| 105 | help="Database username ($HASHSERVER_DB_USERNAME)", |
| 106 | ) |
| 107 | parser.add_argument( |
| 108 | "--db-password", |
| 109 | default=os.environ.get("HASHSERVER_DB_PASSWORD", None), |
| 110 | help="Database password ($HASHSERVER_DB_PASSWORD)", |
| 111 | ) |
| 112 | parser.add_argument( |
| 113 | "--anon-perms", |
| 114 | metavar="PERM[,PERM[,...]]", |
| 115 | default=os.environ.get("HASHSERVER_ANON_PERMS", ",".join(DEFAULT_ANON_PERMS)), |
| 116 | help='Permissions to give anonymous users (default $HASHSERVER_ANON_PERMS, "%(default)s")', |
| 117 | ) |
| 118 | parser.add_argument( |
| 119 | "--admin-user", |
| 120 | default=os.environ.get("HASHSERVER_ADMIN_USER", None), |
| 121 | help="Create default admin user with name ADMIN_USER ($HASHSERVER_ADMIN_USER)", |
| 122 | ) |
| 123 | parser.add_argument( |
| 124 | "--admin-password", |
| 125 | default=os.environ.get("HASHSERVER_ADMIN_PASSWORD", None), |
| 126 | help="Create default admin user with password ADMIN_PASSWORD ($HASHSERVER_ADMIN_PASSWORD)", |
| 127 | ) |
Brad Bishop | 1932369 | 2019-04-05 15:28:33 -0400 | [diff] [blame] | 128 | |
| 129 | args = parser.parse_args() |
| 130 | |
Patrick Williams | ac13d5f | 2023-11-24 18:59:46 -0600 | [diff] [blame] | 131 | logger = logging.getLogger("hashserv") |
Brad Bishop | 1932369 | 2019-04-05 15:28:33 -0400 | [diff] [blame] | 132 | |
| 133 | level = getattr(logging, args.log.upper(), None) |
| 134 | if not isinstance(level, int): |
Patrick Williams | 73bd93f | 2024-02-20 08:07:48 -0600 | [diff] [blame] | 135 | raise ValueError("Invalid log level: %s (Try ERROR/WARNING/INFO/DEBUG)" % args.log) |
Brad Bishop | 1932369 | 2019-04-05 15:28:33 -0400 | [diff] [blame] | 136 | |
| 137 | logger.setLevel(level) |
| 138 | console = logging.StreamHandler() |
| 139 | console.setLevel(level) |
| 140 | logger.addHandler(console) |
| 141 | |
Patrick Williams | ac13d5f | 2023-11-24 18:59:46 -0600 | [diff] [blame] | 142 | read_only = (os.environ.get("HASHSERVER_READ_ONLY", "0") == "1") or args.read_only |
| 143 | if "," in args.anon_perms: |
| 144 | anon_perms = args.anon_perms.split(",") |
| 145 | else: |
| 146 | anon_perms = args.anon_perms.split() |
| 147 | |
| 148 | server = hashserv.create_server( |
| 149 | args.bind, |
| 150 | args.database, |
| 151 | upstream=args.upstream, |
| 152 | read_only=read_only, |
| 153 | db_username=args.db_username, |
| 154 | db_password=args.db_password, |
| 155 | anon_perms=anon_perms, |
| 156 | admin_username=args.admin_user, |
| 157 | admin_password=args.admin_password, |
| 158 | ) |
Brad Bishop | 1932369 | 2019-04-05 15:28:33 -0400 | [diff] [blame] | 159 | server.serve_forever() |
| 160 | return 0 |
| 161 | |
Brad Bishop | a34c030 | 2019-09-23 22:34:48 -0400 | [diff] [blame] | 162 | |
Patrick Williams | ac13d5f | 2023-11-24 18:59:46 -0600 | [diff] [blame] | 163 | if __name__ == "__main__": |
Brad Bishop | 1932369 | 2019-04-05 15:28:33 -0400 | [diff] [blame] | 164 | try: |
| 165 | ret = main() |
| 166 | except Exception: |
| 167 | ret = 1 |
| 168 | import traceback |
Patrick Williams | ac13d5f | 2023-11-24 18:59:46 -0600 | [diff] [blame] | 169 | |
Brad Bishop | 1932369 | 2019-04-05 15:28:33 -0400 | [diff] [blame] | 170 | traceback.print_exc() |
| 171 | sys.exit(ret) |