bitbake-hashserv 6.0 KB

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