def create_dir(path: Any, **kwargs: Any) -> bool: """Validate and attempt to create a directory, if it does not exist.""" # If input path is not a path object, try to make it one if not isinstance(path, Path): try: path = Path(path) except TypeError: error("{p} is not a valid path", p=path) # If path does not exist, try to create it if not path.exists(): try: path.mkdir(**kwargs) except PermissionError: error( "{u} does not have permission to create {p}. Try running with sudo?", u=os.getlogin(), p=path, ) # Verify the path was actually created if path.exists(): success("Created {p}", p=path) # If the path already exists, inform the user elif path.exists(): info("{p} already exists", p=path) return True
def write_cert(name: str, org: str, duration: int, starttime: str, size: int, show: bool) -> None: """Generate SSL certificate keypair.""" app_path = find_app_path() cert_path = app_path / "agent_cert.pem" key_path = app_path / "agent_key.pem" start = starttime end = start + timedelta(days=duration * 365) label("Hostname: {cn}", cn=name) status(""" A self-signed certificate with the above hostname as the common name attribute will be generated. This hostname must be resolvable by hyperglass via either DNS or a host file, and must match the device's `address:` field in hyperglass's devices.yaml.""") use_name = confirm("Is this the correct hostname?", default=True) if not use_name: name = prompt("Please enter the correct hostname", type=str) all_ips = [f"{a} [{i}]" for i, a in get_addresses()] status(""" hyperglass-agent adds any IP addresses reachable by hyperglass as subject alternative names to the SSL certificate. Please select any IP addresses over which hyperglass may communicate with hyperglass-agent.""") ips = [Checkbox("ips", message="Select IPs", choices=all_ips)] selected = [i.split("[")[0].strip() for i in inquire(ips)["ips"]] selected_ips = [ip_address(i) for i in selected] cert, key = make_cert(cn=name, sans=selected_ips, o=org, start=start, end=end, size=size) if show: info(f'Public Key:\n{cert.decode("utf8")}') info(f'Private Key:\n{key.decode("utf8")}') with cert_path.open("wb") as cf: cf.write(cert) if not cert_path.exists(): error("Error writing public key to {f}", f=cert_path.absolute()) success("Wrote public key to: {f}", f=cert_path.absolute()) with key_path.open("wb") as kf: kf.write(key) if not key_path.exists(): error("Error writing private key to {f}", f=key_path.absolute()) success("Wrote private key to: {f}", f=key_path.absolute())
def make_systemd(): """Generate a systemd file based on the local system. Arguments: user {str} -- User hyperglass-agent needs to be run as Returns: {str} -- Generated systemd template """ from shutil import which from getpass import getuser template = """ [Unit] Description=hyperglass-agent After=network.target [Service] User={user} Group={group} ExecStart={bin_path} start [Install] WantedBy=multi-user.target """ app_path = find_app_path() service_path = app_path / "hyperglass-agent.service" cmd_path = which("hyperglass-agent") if not cmd_path: bin_path = "python3 -m hyperglass_agent.console" warning("hyperglass executable not found, using {h}", h=bin_path) else: bin_path = cmd_path if app_path == Path.home(): user = getuser() else: user = "******" systemd = template.format(user=user, group=user, bin_path=bin_path) info(f"Generated systemd service:\n{systemd}") if service_path.exists(): service_path.unlink() with service_path.open("w") as f: f.write(systemd) if not service_path.exists(): error("Error writing systemd file to {f}", f=service_path) install_systemd(service_path) return True
def migrate_config(force=False): """Copy example config file and remove .example extensions.""" import os import shutil import secrets app_path = os.environ.get("hyperglass_agent_directory") if app_path is None: app_path = find_app_path() else: app_path = Path(app_path) example = Path(__file__).parent.parent / "example_config.yaml" target_file = app_path / "config.yaml" def copy(): shutil.copyfile(example, target_file) if not target_file.exists(): raise FileNotFoundError(str(target_file) + "does not exist.") with target_file.open("r") as f: data = f.read() gen_secret = secrets.token_urlsafe(32) data = data.replace("secret: null", "secret: '{}'".format(gen_secret)) with target_file.open("w") as f: f.write(data) success("Successfully migrated example config file to {t}", t=target_file) try: if target_file.exists(): if not force: info("{f} already exists", f=str(target_file)) else: copy() else: copy() except Exception as e: error("Failed to migrate '{f}': {e}", f=str(target_file), e=e)
def write_cert(name, org, duration, size, show): """Generate SSL certificate keypair. Arguments: name {str} -- Common Name org {str} -- Organization duration -- Validity in years size {int} -- Key Size show {bool} -- Show private key in CLI """ app_path = find_app_path() cert_path = app_path / "agent_cert.pem" key_path = app_path / "agent_key.pem" start = datetime.now() end = start + timedelta(days=duration * 365) cert, key = make_cert(cn=name, o=org, start=start, end=end, size=size) if show: info(f'Public Key:\n{cert.decode("utf8")}') info(f'Private Key:\n{key.decode("utf8")}') with cert_path.open("wb") as cf: cf.write(cert) if not cert_path.exists(): error("Error writing public key to {f}", f=cert_path.absolute()) success("Wrote public key to: {f}", f=cert_path.absolute()) with key_path.open("wb") as kf: kf.write(key) if not key_path.exists(): error("Error writing private key to {f}", f=key_path.absolute()) success("Wrote private key to: {f}", f=key_path.absolute())