Compare commits

...

2 commits

Author SHA1 Message Date
667fcba559 plan: server props 2022-03-30 10:15:24 +00:00
b202f85d3b country max_length 2022-03-30 08:30:20 +00:00
2 changed files with 50 additions and 9 deletions

View file

@ -15,11 +15,12 @@ from datetime import datetime, timedelta
from enum import Enum from enum import Enum
from pathlib import Path from pathlib import Path
from secrets import token_urlsafe from secrets import token_urlsafe
from typing import Any
from jose import JWTError, jwt from jose import JWTError, jwt
from jose.constants import ALGORITHMS from jose.constants import ALGORITHMS
from passlib.context import CryptContext from passlib.context import CryptContext
from pydantic import BaseModel, BaseSettings, Field, validator from pydantic import BaseModel, BaseSettings, constr, validator
class Settings(BaseSettings): class Settings(BaseSettings):
@ -64,7 +65,7 @@ class DBConfig(BaseModel):
user: str | None = None user: str | None = None
password: str | None = None password: str | None = None
host: str | None = None host: str | None = None
database: str | None = Settings._.data_dir.joinpath("vpn.db") database: str | None = Settings._.data_dir.joinpath("kiwi-vpn.db")
mysql_driver: str = "pymysql" mysql_driver: str = "pymysql"
mysql_args: list[str] = ["charset=utf8mb4"] mysql_args: list[str] = ["charset=utf8mb4"]
@ -168,6 +169,35 @@ class JWTConfig(BaseModel):
return username return username
class ToggleString(BaseModel):
value: str
allow: bool
class ToggleCountry(ToggleString):
value: constr(max_length=2)
class DNParts(BaseModel):
"""
This server's "distinguished name"
"""
country: ToggleCountry
state: ToggleString
city: ToggleString
organization: ToggleString
organizational_unit: ToggleString
class CertificateAlgo(Enum):
rsa2048 = "rsa2048"
rsa4096 = "rsa4096"
secp256r1 = "secp256r1"
secp384r1 = "secp384r1"
ed25519 = "ed25519"
class CryptoConfig(BaseModel): class CryptoConfig(BaseModel):
""" """
Configuration for hash algorithms Configuration for hash algorithms
@ -175,8 +205,15 @@ class CryptoConfig(BaseModel):
schemes: list[str] = ["bcrypt"] schemes: list[str] = ["bcrypt"]
force_cipher: ToggleString
force_tls_cipher: ToggleString
force_auth: ToggleString
cert_algo: CertificateAlgo
expiry_days: int
@property @property
def crypt_context(self) -> CryptContext: def context(self) -> CryptContext:
return CryptContext( return CryptContext(
schemes=self.schemes, schemes=self.schemes,
deprecated="auto", deprecated="auto",
@ -188,9 +225,13 @@ class Config(BaseModel):
Configuration for `kiwi-vpn-api` Configuration for `kiwi-vpn-api`
""" """
db: DBConfig = Field(default_factory=DBConfig) server_name: str
jwt: JWTConfig = Field(default_factory=JWTConfig) server_extra_config: dict[str, Any]
crypto: CryptoConfig = Field(default_factory=CryptoConfig)
db: DBConfig
jwt: JWTConfig
crypto: CryptoConfig
dnparts: DNParts
__singleton: Config | None = None __singleton: Config | None = None

View file

@ -24,7 +24,7 @@ class UserBase(SQLModel):
name: str = Field(primary_key=True) name: str = Field(primary_key=True)
email: str | None = Field(default=None) email: str | None = Field(default=None)
country: str | None = Field(default=None) country: str | None = Field(default=None, max_length=2)
state: str | None = Field(default=None) state: str | None = Field(default=None)
city: str | None = Field(default=None) city: str | None = Field(default=None)
organization: str | None = Field(default=None) organization: str | None = Field(default=None)
@ -56,7 +56,7 @@ class UserCreate(UserBase):
if (current_config := Config._) is None: if (current_config := Config._) is None:
raise ValueError("Not configured") raise ValueError("Not configured")
values["password"] = current_config.crypto.crypt_context.hash( values["password"] = current_config.crypto.context.hash(
password_clear) password_clear)
return values return values
@ -132,7 +132,7 @@ class User(UserBase, table=True):
Authenticate with name/password against users in database. Authenticate with name/password against users in database.
""" """
crypt_context = Config._.crypto.crypt_context crypt_context = Config._.crypto.context
if (user := cls.get(name)) is None: if (user := cls.get(name)) is None:
# nonexistent user, fake doing password verification # nonexistent user, fake doing password verification