diff --git a/api/kiwi_vpn_api/config.py b/api/kiwi_vpn_api/config.py index d35457f..1bb2e6a 100644 --- a/api/kiwi_vpn_api/config.py +++ b/api/kiwi_vpn_api/config.py @@ -227,6 +227,7 @@ class CryptoConfig(BaseModel): schemes: list[str] = ["bcrypt"] # pki settings + ca_password: str | None cert_algo: CertificateAlgo | None expiry_days: int | None diff --git a/api/kiwi_vpn_api/easyrsa.py b/api/kiwi_vpn_api/easyrsa.py index 3713af7..60f8a23 100644 --- a/api/kiwi_vpn_api/easyrsa.py +++ b/api/kiwi_vpn_api/easyrsa.py @@ -1,3 +1,7 @@ +""" +Python interface to EasyRSA CA. +""" + import subprocess from datetime import datetime from pathlib import Path @@ -5,20 +9,32 @@ from pathlib import Path from OpenSSL import crypto from passlib import pwd +from .config import Config, Settings + class EasyRSA: - __directory: Path | None - __ca_password: str | None + """ + Represents an EasyRSA PKI. + """ - def __init__(self, directory: Path) -> None: - self.__directory = directory + @property + def pki_directory(self) -> Path: + return Settings._.data_dir.joinpath("pki") - def set_ca_password(self, password: str | None = None) -> None: - if password is None: - password = pwd.genword(length=32, charset="ascii_62") + @property + def ca_password(self) -> str: + config = Config._ - self.__ca_password = password - print(self.__ca_password) + if (ca_password := config.crypto.ca_password) is None: + ca_password = pwd.genword( + length=32, + charset="ascii_62", + ) + + config.crypto.ca_password = ca_password + config.save() + + return config.crypto.ca_password def __easyrsa( self, @@ -27,7 +43,7 @@ class EasyRSA: return subprocess.run( [ "easyrsa", "--batch", - f"--pki-dir={self.__directory}", + f"--pki-dir={self.pki_directory}", *easyrsa_args, ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, @@ -42,7 +58,7 @@ class EasyRSA: self.__easyrsa(*easyrsa_args) with open( - self.__directory.joinpath(cert_filename), "r" + self.pki_directory.joinpath(cert_filename), "r" ) as cert_file: return crypto.load_certificate( crypto.FILETYPE_PEM, cert_file.read() @@ -53,14 +69,14 @@ class EasyRSA: def build_ca( self, - days: int = 365 * 50, - cn: str = "kiwi-vpn-ca" ) -> crypto.X509: + config = Config._ + cert = self.__build_cert( Path("ca.crt"), - f"--passout=pass:{self.__ca_password}", - f"--passin=pass:{self.__ca_password}", + f"--passout=pass:{self.ca_password}", + f"--passin=pass:{self.ca_password}", # "--dn-mode=org", # "--req-c=EX", @@ -70,8 +86,8 @@ class EasyRSA: # "--req-ou=EXAMPLE", # "--req-email=EXAMPLE", - f"--req-cn={cn}", - f"--days={days}", + f"--req-cn={config.server_name}", + f"--days={config.crypto.expiry_days}", # "--use-algo=ed", # "--curve=ed25519", @@ -79,20 +95,21 @@ class EasyRSA: "build-ca", ) - self.__easyrsa("gen-dh") + # self.__easyrsa("gen-dh") return cert def issue( self, - days: int = 365 * 50, cn: str = "kiwi-vpn-client", cert_type: str = "client" ) -> crypto.X509: + config = Config._ + return self.__build_cert( Path(f"issued/{cn}.crt"), - f"--passin=pass:{self.__ca_password}", - f"--days={days}", + f"--passin=pass:{self.ca_password}", + f"--days={config.crypto.expiry_days}", f"build-{cert_type}-full", cn, @@ -101,11 +118,10 @@ class EasyRSA: if __name__ == "__main__": - easy_rsa = EasyRSA(Path("tmp/easyrsa")) + easy_rsa = EasyRSA() easy_rsa.init_pki() - easy_rsa.set_ca_password() - ca = easy_rsa.build_ca(cn="kiwi-vpn-ca") + ca = easy_rsa.build_ca() server = easy_rsa.issue(cert_type="server", cn="kiwi-vpn-server") client = easy_rsa.issue(cert_type="client", cn="kiwi-vpn-client")