Files
sshecret/packages/sshecret-admin/src/sshecret_admin/view_models.py

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",
}
]
}
)