actually issuing certs
This commit is contained in:
parent
23a806e325
commit
2566702d9e
2 changed files with 52 additions and 26 deletions
|
@ -194,7 +194,7 @@ class LockableCountry(LockableString):
|
||||||
value: constr(max_length=2)
|
value: constr(max_length=2)
|
||||||
|
|
||||||
|
|
||||||
class DNParts(BaseModel):
|
class ServerDN(BaseModel):
|
||||||
"""
|
"""
|
||||||
This server's "distinguished name"
|
This server's "distinguished name"
|
||||||
"""
|
"""
|
||||||
|
@ -204,6 +204,8 @@ class DNParts(BaseModel):
|
||||||
city: LockableString
|
city: LockableString
|
||||||
organization: LockableString
|
organization: LockableString
|
||||||
organizational_unit: LockableString
|
organizational_unit: LockableString
|
||||||
|
email: LockableString
|
||||||
|
common_name: str
|
||||||
|
|
||||||
|
|
||||||
class CertificateAlgo(Enum):
|
class CertificateAlgo(Enum):
|
||||||
|
@ -227,9 +229,10 @@ class CryptoConfig(BaseModel):
|
||||||
schemes: list[str] = ["bcrypt"]
|
schemes: list[str] = ["bcrypt"]
|
||||||
|
|
||||||
# pki settings
|
# pki settings
|
||||||
ca_password: str | None
|
|
||||||
cert_algo: CertificateAlgo | None
|
cert_algo: CertificateAlgo | None
|
||||||
expiry_days: int | None
|
ca_password: str | None
|
||||||
|
ca_expiry_days: int | None
|
||||||
|
cert_expiry_days: int | None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def context(self) -> CryptContext:
|
def context(self) -> CryptContext:
|
||||||
|
@ -244,15 +247,13 @@ class Config(BaseModel):
|
||||||
Configuration for `kiwi-vpn-api`
|
Configuration for `kiwi-vpn-api`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# common name for the server
|
|
||||||
server_name: str
|
|
||||||
# may include client-to-client, cipher etc.
|
# may include client-to-client, cipher etc.
|
||||||
openvpn_extra_options: dict[str, Any] | None
|
openvpn_extra_options: dict[str, Any] | None
|
||||||
|
|
||||||
db: DBConfig
|
db: DBConfig
|
||||||
jwt: JWTConfig
|
jwt: JWTConfig
|
||||||
crypto: CryptoConfig
|
crypto: CryptoConfig
|
||||||
default_dn: DNParts
|
server_dn: ServerDN
|
||||||
|
|
||||||
__singleton: Config | None = None
|
__singleton: Config | None = None
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ from pathlib import Path
|
||||||
from OpenSSL import crypto
|
from OpenSSL import crypto
|
||||||
from passlib import pwd
|
from passlib import pwd
|
||||||
|
|
||||||
from .config import Config, Settings
|
from .config import CertificateAlgo, Config, Settings
|
||||||
|
|
||||||
|
|
||||||
class EasyRSA:
|
class EasyRSA:
|
||||||
|
@ -53,9 +53,39 @@ class EasyRSA:
|
||||||
def __build_cert(
|
def __build_cert(
|
||||||
self,
|
self,
|
||||||
cert_filename: Path,
|
cert_filename: Path,
|
||||||
|
expiry_days: int | None,
|
||||||
*easyrsa_args: str,
|
*easyrsa_args: str,
|
||||||
) -> crypto.X509:
|
) -> crypto.X509:
|
||||||
self.__easyrsa(*easyrsa_args)
|
config = Config._
|
||||||
|
|
||||||
|
extra_args: tuple[str] = tuple()
|
||||||
|
|
||||||
|
if expiry_days is not None:
|
||||||
|
extra_args += tuple([f"--days={expiry_days}"])
|
||||||
|
|
||||||
|
if (algo := config.crypto.cert_algo) is not None:
|
||||||
|
if algo is CertificateAlgo.rsa2048:
|
||||||
|
extra_args += ("--use-algo=rsa", "--keysize=2048")
|
||||||
|
|
||||||
|
elif algo is CertificateAlgo.rsa4096:
|
||||||
|
extra_args += ("--use-algo=rsa", "--keysize=4096")
|
||||||
|
|
||||||
|
elif algo is CertificateAlgo.secp256r1:
|
||||||
|
extra_args += ("--use-algo=ec", "--curve=secp256r1")
|
||||||
|
|
||||||
|
elif algo is CertificateAlgo.secp384r1:
|
||||||
|
extra_args += ("--use-algo=ec", "--curve=secp384r1")
|
||||||
|
|
||||||
|
elif algo is CertificateAlgo.ed25519:
|
||||||
|
extra_args += ("--use-algo=ed", "--curve=ed25519")
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unexpected algorithm: {algo}")
|
||||||
|
|
||||||
|
self.__easyrsa(
|
||||||
|
*extra_args,
|
||||||
|
*easyrsa_args
|
||||||
|
)
|
||||||
|
|
||||||
with open(
|
with open(
|
||||||
self.pki_directory.joinpath(cert_filename), "r"
|
self.pki_directory.joinpath(cert_filename), "r"
|
||||||
|
@ -67,30 +97,25 @@ class EasyRSA:
|
||||||
def init_pki(self) -> bool:
|
def init_pki(self) -> bool:
|
||||||
self.__easyrsa("init-pki")
|
self.__easyrsa("init-pki")
|
||||||
|
|
||||||
def build_ca(
|
def build_ca(self) -> crypto.X509:
|
||||||
self,
|
|
||||||
) -> crypto.X509:
|
|
||||||
config = Config._
|
config = Config._
|
||||||
|
server_dn = config.server_dn
|
||||||
|
|
||||||
cert = self.__build_cert(
|
cert = self.__build_cert(
|
||||||
Path("ca.crt"),
|
Path("ca.crt"),
|
||||||
|
config.crypto.ca_expiry_days,
|
||||||
|
|
||||||
f"--passout=pass:{self.ca_password}",
|
f"--passout=pass:{self.ca_password}",
|
||||||
f"--passin=pass:{self.ca_password}",
|
f"--passin=pass:{self.ca_password}",
|
||||||
|
|
||||||
# "--dn-mode=org",
|
"--dn-mode=org",
|
||||||
# "--req-c=EX",
|
f"--req-c={server_dn.country.value}",
|
||||||
# "--req-st=EXAMPLE",
|
f"--req-st={server_dn.state.value}",
|
||||||
# "--req-city=EXAMPLE",
|
f"--req-city={server_dn.city.value}",
|
||||||
# "--req-org=EXAMPLE",
|
f"--req-org={server_dn.organization.value}",
|
||||||
# "--req-ou=EXAMPLE",
|
f"--req-ou={server_dn.organizational_unit.value}",
|
||||||
# "--req-email=EXAMPLE",
|
f"--req-email={server_dn.email.value}",
|
||||||
|
f"--req-cn={server_dn.common_name}",
|
||||||
f"--req-cn={config.server_name}",
|
|
||||||
f"--days={config.crypto.expiry_days}",
|
|
||||||
|
|
||||||
# "--use-algo=ed",
|
|
||||||
# "--curve=ed25519",
|
|
||||||
|
|
||||||
"build-ca",
|
"build-ca",
|
||||||
)
|
)
|
||||||
|
@ -100,16 +125,16 @@ class EasyRSA:
|
||||||
|
|
||||||
def issue(
|
def issue(
|
||||||
self,
|
self,
|
||||||
|
cert_type: str = "client",
|
||||||
cn: str = "kiwi-vpn-client",
|
cn: str = "kiwi-vpn-client",
|
||||||
cert_type: str = "client"
|
|
||||||
) -> crypto.X509:
|
) -> crypto.X509:
|
||||||
config = Config._
|
config = Config._
|
||||||
|
|
||||||
return self.__build_cert(
|
return self.__build_cert(
|
||||||
Path(f"issued/{cn}.crt"),
|
Path(f"issued/{cn}.crt"),
|
||||||
|
config.crypto.cert_expiry_days,
|
||||||
|
|
||||||
f"--passin=pass:{self.ca_password}",
|
f"--passin=pass:{self.ca_password}",
|
||||||
f"--days={config.crypto.expiry_days}",
|
|
||||||
|
|
||||||
f"build-{cert_type}-full",
|
f"build-{cert_type}-full",
|
||||||
cn,
|
cn,
|
||||||
|
|
Loading…
Reference in a new issue