blob: 33642162aafa9d71d9e92b82f9a0d2da3c93883e [file] [log] [blame]
"""Starts up Apache to provide HTTPS + LDAP for another web server.
This script is used by the apache_wrapper() rule as the main entrypoint for its
"executable". This script sets up a minimal Apache environment in a directory
in /tmp.
Both Apache and the wrapped server binary are started by this script. The
wrapped server should bind to the port specified by the APACHE_WRAPPED_PORT
environment variable.
See the documentation for apache_wrapper() for more information.
"""
import argparse
import json
import os
from pathlib import Path
import signal
import subprocess
import sys
import tempfile
import jinja2
DUMMY_CERT_ANSWERS = """\
US
California
Mountain View
FRC971
Software
frc971.org
dummy@frc971.org
"""
def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument("--binary", type=str, required=True)
parser.add_argument("--https_port", type=int, default=7000)
parser.add_argument("--wrapped_port", type=int, default=7500)
parser.add_argument(
"--ldap_info",
type=str,
help="JSON file containing 'ldap_bind_dn', 'ldap_url', and 'ldap_password' entries.",
default="",
)
args = parser.parse_args(argv[1:])
if not args.ldap_info:
args.ldap_info = os.path.join(os.environ["BUILD_WORKSPACE_DIRECTORY"], "ldap.json")
with open("tools/build_rules/apache_template.conf", "r") as file:
template = jinja2.Template(file.read())
with open(args.ldap_info, "r") as file:
substitutions = json.load(file)
for key in ("ldap_bind_dn", "ldap_url", "ldap_password"):
if key not in substitutions:
raise KeyError(f"The ldap_info JSON file must contain key '{key}'.")
substitutions.update({
"https_port": args.https_port,
"wrapped_port": args.wrapped_port,
})
config_text = template.render(substitutions)
with tempfile.TemporaryDirectory() as temp_dir:
temp_dir = Path(temp_dir)
with open(temp_dir / "apache2.conf", "w") as file:
file.write(config_text)
# Create a directory for error logs and such.
logs_dir = temp_dir / "logs"
os.mkdir(logs_dir)
print("-" * 60)
print(f"Logs are in {logs_dir}/")
print("-" * 60)
# Make modules available.
modules_path = Path("external/apache2/usr/lib/apache2/modules")
os.symlink(modules_path.resolve(), temp_dir / "modules")
# Generate a testing cert.
subprocess.run([
"openssl",
"req",
"-x509",
"-nodes",
"-days=365",
"-newkey=rsa:2048",
"-keyout=" + str(temp_dir / "apache-selfsigned.key"),
"-out=" + str(temp_dir / "apache-selfsigned.crt"),
],
check=True,
input=DUMMY_CERT_ANSWERS,
text=True,
)
# Start the wrapped binary in the background.
# Tell it via the environment what port to listen on.
env = os.environ.copy()
env["APACHE_WRAPPED_PORT"] = str(args.wrapped_port)
wrapped_binary = subprocess.Popen([args.binary], env=env)
# Start the apache server.
env = os.environ.copy()
env["LD_LIBRARY_PATH"] = "external/apache2/usr/lib/x86_64-linux-gnu"
try:
subprocess.run(
["external/apache2/usr/sbin/apache2", "-X", "-d", str(temp_dir)],
check=True,
env=env,
)
finally:
wrapped_binary.send_signal(signal.SIGINT)
wrapped_binary.wait()
if __name__ == "__main__":
sys.exit(main(sys.argv))