114 lines
2.9 KiB
Python
114 lines
2.9 KiB
Python
"""Models for the API."""
|
|
|
|
import secrets
|
|
from typing import Annotated, Literal, Self, Union
|
|
from pydantic import (
|
|
AfterValidator,
|
|
BaseModel,
|
|
ConfigDict,
|
|
Field,
|
|
IPvAnyAddress,
|
|
IPvAnyNetwork,
|
|
model_validator,
|
|
)
|
|
from sshecret.crypto import validate_public_key
|
|
|
|
|
|
def public_key_validator(value: str) -> str:
|
|
"""Public key validator."""
|
|
if validate_public_key(value):
|
|
return value
|
|
raise ValueError("Error: Public key must be a valid RSA public key.")
|
|
|
|
|
|
class SecretListView(BaseModel):
|
|
"""Model containing a list of all available secrets."""
|
|
|
|
name: str
|
|
clients: list[str] = Field(default_factory=list) # Clients that have access to it.
|
|
|
|
|
|
class SecretView(BaseModel):
|
|
"""Model containing a secret, including its clear-text value."""
|
|
|
|
name: str
|
|
secret: str
|
|
clients: list[str] = Field(default_factory=list) # Clients that have access to it.
|
|
|
|
|
|
class UpdateKeyModel(BaseModel):
|
|
"""Model for updating client public key."""
|
|
|
|
public_key: Annotated[str, AfterValidator(public_key_validator)]
|
|
|
|
|
|
class UpdateKeyResponse(BaseModel):
|
|
"""Response model after updating the public key."""
|
|
|
|
public_key: str
|
|
updated_secrets: list[str] = Field(default_factory=list)
|
|
detail: str | None = None
|
|
|
|
|
|
class UpdatePoliciesRequest(BaseModel):
|
|
"""Update policy request."""
|
|
|
|
sources: list[IPvAnyAddress | IPvAnyNetwork]
|
|
|
|
|
|
class ClientCreate(BaseModel):
|
|
"""Model to create a client."""
|
|
|
|
name: str
|
|
public_key: Annotated[str, AfterValidator(public_key_validator)]
|
|
sources: list[IPvAnyAddress | IPvAnyNetwork] = Field(default_factory=list)
|
|
|
|
|
|
class AutoGenerateOpts(BaseModel):
|
|
"""Option to auto-generate a password."""
|
|
|
|
auto_generate: Literal[True]
|
|
length: int = 32
|
|
|
|
|
|
class SecretUpdate(BaseModel):
|
|
"""Model to update a secret."""
|
|
|
|
value: str | AutoGenerateOpts = Field(
|
|
description="Secret as string value or auto-generated with optional length",
|
|
examples=["MySecretString", {"auto_generate": True, "length": 32}]
|
|
)
|
|
|
|
def get_secret(self) -> str:
|
|
"""Get secret.
|
|
|
|
This returns the specified one, or generates one according to auto-generation.
|
|
"""
|
|
if isinstance(self.value, str):
|
|
return self.value
|
|
secret = secrets.token_urlsafe(self.value.length)
|
|
return secret
|
|
|
|
|
|
class SecretCreate(SecretUpdate):
|
|
"""Model to create a secret."""
|
|
|
|
name: str
|
|
clients: list[str] | None = Field(default=None, description="Assign the secret to a list of clients.")
|
|
|
|
model_config: ConfigDict = ConfigDict(
|
|
json_schema_extra={
|
|
"examples": [
|
|
{
|
|
"name": "MySecret",
|
|
"clients": ["client-1", "client-2"],
|
|
"value": { "auto_generate": True, "length": 32 }
|
|
},
|
|
{
|
|
"name": "MySecret",
|
|
"value": "mysecretstring",
|
|
}
|
|
]
|
|
}
|
|
)
|