phi/src/phi/web/app.py

214 lines
5.2 KiB
Python

# -*- encoding: utf-8 -*-
from aiohttp import web
from aiohttp_session import setup
from aiohttp_session.cookie_storage import EncryptedCookieStorage
import click
from pprint import pformat as pp
import yaml
from phi.config import get_config, merge_config, extract_secret
from phi.logging import setup_logging, get_logger
from phi.api.app import api_app
from phi.web.client_store import ClientStore
from phi.web.login import login
log = get_logger(__name__)
LOGIN_ROUTE = "/login"
COOKIE_NAME = "PHI_COOKIE"
def setup_app(config):
app = web.Application()
setup(app, EncryptedCookieStorage(extract_secret(config), cookie_name=COOKIE_NAME))
app["config"] = config
app["store"] = ClientStore(LOGIN_ROUTE)
app["log"] = log
app.add_routes([web.post(LOGIN_ROUTE, login)])
api = api_app(app["store"])
app.add_subapp("/api", api)
return app
def run_app(app):
web.run_app(
app,
host=app["config"]["core"]["listen"].get("host", "127.0.0.1"),
port=app["config"]["core"]["listen"].get("port", "8080"),
)
@click.command(help="phid is the main application daemon.")
@click.option(
"--config",
"config_path",
type=click.Path(exists=True),
help="Path to a valid config file.",
)
@click.option(
"-H",
"--host",
type=click.STRING,
default="localhost",
help='Address to which the application bounds. Defaults to "localhost".',
)
@click.option(
"-p",
"--port",
type=click.INT,
default=8080,
help="Port to which the application bounds. Defaults to 8080.",
)
@click.option(
"--ldap-host",
"ldap_host",
type=click.STRING,
default="localhost",
help='Address of the LDAP server to connect to. Defaults to "localhost".',
)
@click.option(
"--ldap-port",
"ldap_port",
type=click.INT,
default=389,
help="Port where is exposed the LDAP server to connect to. Defaults to 389.",
)
@click.option(
"--ldap-crypt",
"ldap_crypt",
is_flag=True,
default=True,
help="Connect to the LDAP server using TLSv1.2. Defaults to True.",
)
@click.option(
"--ldap-tls-do-not-validate",
"ldap_tls_validate",
is_flag=True,
default=True,
help="Toggle checking of TLS cert against the provided name. Defaults to True.",
)
@click.option(
"--ldap-tls-ca",
"ldap_tls_ca",
type=click.Path(exists=True),
help="Toggle checking of TLS cert against the provided name. Defaults to True.",
)
@click.option(
"--ldap-base-dn", "ldap_base_dn", type=click.STRING, help="The LDAP base_dn to use."
)
@click.option(
"--ldap-username",
"ldap_username",
type=click.STRING,
help="The username to use to connect to the LDAP server.",
)
@click.option(
"--ldap-password",
"ldap_password",
type=click.STRING,
help="The password to use to connect to the LDAP server. "
"THIS CAN BE READ BY OTHER PROCESSES. NEVER USE IN PRODUCTION!",
)
@click.option(
"--log-conf",
"log_conf",
type=click.Path(exists=True),
help="Path to a yaml configuration for the logger.",
)
@click.option(
"--debug",
"debug",
is_flag=True,
default=False,
help="Set the log level to debug.",
)
def cli(
host,
port,
config_path=None,
ldap_host=None,
ldap_port=None,
ldap_crypt=True,
ldap_tls_validate=True,
ldap_tls_ca=None,
ldap_base_dn=None,
ldap_username=None,
ldap_password=None,
log_conf=None,
debug=False,
):
cli_config = prepare_config_from_cli(
host,
port,
ldap_host,
ldap_port,
ldap_crypt,
ldap_tls_validate,
ldap_tls_ca,
ldap_base_dn,
ldap_username,
ldap_password,
log_conf,
debug,
)
config_file, file_config = get_config(config_path)
log.debug(f"FILE: {pp(file_config)}")
config = merge_config(cli_config, file_config)
if debug:
set_to_debug(config)
# Beware that everything happened until now
# could not possibly get logged.
setup_logging(config.get("logging", {}))
if config_file:
log.debug("Config file found at: %s", config_file)
log.debug("{}".format(pp(file_config)))
log.debug("CLI config:\n{}".format(pp(cli_config)))
log.info("Starting app with config:\n{}".format(pp(config)))
app = setup_app(config)
run_app(app)
def prepare_config_from_cli(
host,
port,
ldap_host=None,
ldap_port=None,
ldap_crypt=True,
ldap_tls_validate=True,
ldap_tls_ca=None,
ldap_base_dn=None,
ldap_username=None,
ldap_password=None,
log_conf=None,
debug=False,
):
_core = {"listen": {"host": host, "port": port}}
_ldap = {
"host": ldap_host,
"port": ldap_port,
"encryption": "TLSv1.2" if ldap_crypt else None,
"validate": ldap_tls_validate,
"ca_certs": ldap_tls_ca,
"username": ldap_username,
"password": ldap_password,
"base_dn": ldap_base_dn,
}
_logging = {}
if log_conf:
with open(log_conf) as log_conf_fd:
_logging = yaml.safe_load(log_conf_fd)
return {"core": _core, "ldap": _ldap, "logging": _logging}
def set_to_debug(conf):
for logger, log_conf in conf["logging"]["loggers"].items():
log_conf["level"] = "DEBUG"
conf["logging"]["loggers"][logger] = log_conf