2025-01-01 18:18:38 +00:00
|
|
|
from typing import Annotated
|
|
|
|
|
2025-01-03 15:06:08 +00:00
|
|
|
from cryptography.fernet import Fernet
|
2025-01-01 18:18:38 +00:00
|
|
|
from fastapi import Depends, FastAPI
|
2024-12-25 10:07:13 +00:00
|
|
|
from fastapi.exceptions import HTTPException
|
2025-01-01 18:18:38 +00:00
|
|
|
from redis.asyncio import Redis
|
2022-12-17 12:44:03 +00:00
|
|
|
|
2025-01-03 15:06:08 +00:00
|
|
|
from pssecret_server.fernet import get_fernet
|
2025-01-01 19:01:10 +00:00
|
|
|
from pssecret_server.models import Secret, SecretSaveResult
|
|
|
|
from pssecret_server.redis_db import get_redis
|
2025-01-08 22:03:12 +00:00
|
|
|
from pssecret_server.utils import decrypt_secret, encrypt_secret, getdel, save_secret
|
2022-06-12 10:47:07 +00:00
|
|
|
|
|
|
|
app = FastAPI()
|
|
|
|
|
2025-01-01 18:18:38 +00:00
|
|
|
RedisDep = Annotated[Redis, Depends(get_redis)]
|
2025-01-03 15:06:08 +00:00
|
|
|
FernetDep = Annotated[Fernet, Depends(get_fernet)]
|
2025-01-01 18:18:38 +00:00
|
|
|
|
2022-06-12 10:47:07 +00:00
|
|
|
|
2024-12-26 22:25:54 +00:00
|
|
|
@app.post(
|
|
|
|
"/secret",
|
|
|
|
summary="Store secret",
|
|
|
|
description=(
|
|
|
|
"Submit secret, it is saved on the server, get retrieval key in response. "
|
|
|
|
"Use that key to retrieve your data. Key could be used only once, "
|
|
|
|
"so use it wisely"
|
|
|
|
),
|
|
|
|
response_model=SecretSaveResult,
|
|
|
|
)
|
2025-01-03 15:06:08 +00:00
|
|
|
async def set_secret(
|
|
|
|
data: Secret, redis: RedisDep, fernet: FernetDep
|
|
|
|
) -> dict[str, str]:
|
|
|
|
data = encrypt_secret(data, fernet)
|
2022-12-17 12:44:03 +00:00
|
|
|
return {
|
2025-01-01 18:18:38 +00:00
|
|
|
"key": await save_secret(data, redis),
|
2022-12-17 12:44:03 +00:00
|
|
|
}
|
2022-12-17 15:02:09 +00:00
|
|
|
|
|
|
|
|
2024-12-25 10:07:13 +00:00
|
|
|
@app.get(
|
|
|
|
"/secret/{secret_key}",
|
2024-12-26 22:25:54 +00:00
|
|
|
summary="Retrieve secret",
|
|
|
|
description=(
|
|
|
|
"Returns previously saved data if it is still on the server. "
|
|
|
|
"Could be the other way around in two cases: "
|
|
|
|
"either it has already been retrieved, either storage timeout has expired"
|
|
|
|
),
|
2024-12-25 10:07:13 +00:00
|
|
|
response_model=Secret,
|
|
|
|
responses={404: {"description": "The item was not found"}},
|
|
|
|
)
|
2025-01-03 15:06:08 +00:00
|
|
|
async def get_secret(
|
|
|
|
secret_key: str, redis: RedisDep, fernet: FernetDep
|
|
|
|
) -> dict[str, bytes]:
|
2025-01-08 22:03:12 +00:00
|
|
|
data: bytes | None = await getdel(redis, secret_key)
|
2024-12-25 10:07:13 +00:00
|
|
|
|
|
|
|
if data is None:
|
|
|
|
raise HTTPException(404)
|
|
|
|
|
2022-12-17 15:02:09 +00:00
|
|
|
return {
|
2025-01-03 15:06:08 +00:00
|
|
|
"data": decrypt_secret(data, fernet),
|
2022-12-17 15:02:09 +00:00
|
|
|
}
|