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 install_systemd(service_path): """Installs generated systemd file to system's systemd directory. Arguments: app_path {Path} -- hyperglass runtime path Raises: ClickException: Raised if the /etc/systemd/system does not exist ClickException: Raised if the symlinked file does not exit Returns: {bool} -- True if successful """ systemd = Path("/etc/systemd/system") installed = systemd / "hyperglass-service.service" if not systemd.exists(): error("{e} does not exist. Unable to install systemd service.", e=systemd) if installed.is_symlink(): installed.unlink() installed.symlink_to(service_path) if not installed.exists(): error("Unable to symlink {s} to {d}", s=service_path, d=installed) success("Symlinked {s} to {d}", s=service_path, d=installed) return True
def send_cert(): """Send this device's public key to hyperglass.""" import platform from hyperglass_agent.config import params from hyperglass_agent.util import send_public_key from pydantic import AnyHttpUrl, create_model, ValidationError app_path = find_app_path() cert_file = app_path / "agent_cert.pem" if params.ssl is not None and not params.ssl.enable: confirm( "SSL is disabled. Proceed with sending certificate to hyperglass?", default=False, abort=True, ) if not cert_file.exists(): error("File {f} does not exist", f=cert_file) with cert_file.open("r") as f: cert = f.read().strip() _hg_url = prompt("Enter hyperglass URL (e.g. https://lg.example.com)", type=str) url_model = create_model("UrlModel", url=(AnyHttpUrl, ...)) try: hg_url = url_model(url=_hg_url) except ValidationError as ve: msg = ve.errors()[0]["msg"] warning("URL {u} is invalid: {e}", u=_hg_url, e=msg) _hg_url = prompt("Enter hyperglass URL (e.g. https://lg.example.com)", type=str) try: hg_url = url_model(url=_hg_url) except ValidationError as ve: msg = ve.errors()[0]["msg"] error("URL {u} is invalid: {e}", u=_hg_url, e=msg) device_name = platform.node() keep_discovered = confirm( f"This device's hostname appears to be '{device_name}'. " + "Does this match this device's definition in hyperglass?") if not keep_discovered: device_name = prompt( "Enter the device's name as configured in hyperglass") try: status = send_public_key(str(hg_url.url), device_name=device_name, certificate=cert, params=params) success(status) except RuntimeError as re: error(str(re))
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 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)
def install_systemd(service_path: Path) -> bool: """Installs generated systemd file to system's systemd directory.""" systemd = Path("/etc/systemd/system") installed = systemd / "hyperglass-agent.service" if not systemd.exists(): error("{e} does not exist. Unable to install systemd service.", e=systemd) if installed.is_symlink(): installed.unlink() installed.symlink_to(service_path) if not installed.exists(): error("Unable to symlink {s} to {d}", s=service_path, d=installed) success("Symlinked {s} to {d}", s=service_path, d=installed) return True
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())