feat: add secure agent enrollment
This commit is contained in:
1 parent
82309db79a
commit
d9f0da694b
26 files changed
+2942
-76
No files matched your search
@@ -0,0 +1,108 @@
|
||||
"""HTTP routes for Agent enrollment and bootstrap."""
|
||||
|
||||
from typing import Annotated
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Response, status
|
||||
|
||||
from app.agent_enrollment.dependencies import get_agent_enrollment_service
|
||||
from app.agent_enrollment.exceptions import (
|
||||
AgentEnrollmentConflict,
|
||||
AgentEnrollmentNotFound,
|
||||
AgentEnrollmentTokenInvalid,
|
||||
)
|
||||
from app.agent_enrollment.models import (
|
||||
AgentEnrollmentCreateRequest,
|
||||
AgentEnrollmentCreateResponse,
|
||||
AgentEnrollmentListResponse,
|
||||
AgentEnrollRequest,
|
||||
AgentEnrollResponse,
|
||||
)
|
||||
from app.agent_enrollment.service import AgentEnrollmentService
|
||||
from app.identity import require_permission
|
||||
|
||||
|
||||
router = APIRouter(tags=["agent-enrollment"])
|
||||
|
||||
EnrollmentService = Annotated[
|
||||
AgentEnrollmentService,
|
||||
Depends(get_agent_enrollment_service),
|
||||
]
|
||||
EnrollmentViewer = Annotated[
|
||||
dict,
|
||||
Depends(require_permission("agents.view")),
|
||||
]
|
||||
EnrollmentManager = Annotated[
|
||||
dict,
|
||||
Depends(require_permission("agents.manage")),
|
||||
]
|
||||
|
||||
|
||||
@router.post(
|
||||
"/api/agent-enrollments",
|
||||
response_model=AgentEnrollmentCreateResponse,
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
)
|
||||
def create_agent_enrollment(
|
||||
request: AgentEnrollmentCreateRequest,
|
||||
response: Response,
|
||||
current_user: EnrollmentManager,
|
||||
service: EnrollmentService,
|
||||
) -> AgentEnrollmentCreateResponse:
|
||||
response.headers["Cache-Control"] = "no-store"
|
||||
|
||||
try:
|
||||
enrollment = service.create_enrollment(
|
||||
request,
|
||||
actor_user_id=UUID(str(current_user["id"])),
|
||||
)
|
||||
return AgentEnrollmentCreateResponse(data=enrollment)
|
||||
except AgentEnrollmentNotFound as exc:
|
||||
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
||||
except AgentEnrollmentConflict as exc:
|
||||
raise HTTPException(status_code=409, detail=str(exc)) from exc
|
||||
|
||||
|
||||
@router.get(
|
||||
"/api/agent-enrollments",
|
||||
response_model=AgentEnrollmentListResponse,
|
||||
)
|
||||
def list_agent_enrollments(
|
||||
current_user: EnrollmentViewer,
|
||||
service: EnrollmentService,
|
||||
site_id: UUID | None = Query(default=None),
|
||||
agent_zone_id: UUID | None = Query(default=None),
|
||||
limit: int = Query(default=100, ge=1, le=500),
|
||||
) -> AgentEnrollmentListResponse:
|
||||
del current_user
|
||||
|
||||
return AgentEnrollmentListResponse(
|
||||
data=service.list_enrollments(
|
||||
site_id=site_id,
|
||||
agent_zone_id=agent_zone_id,
|
||||
limit=limit,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/api/agent/enroll",
|
||||
response_model=AgentEnrollResponse,
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
)
|
||||
def enroll_agent(
|
||||
request: AgentEnrollRequest,
|
||||
response: Response,
|
||||
service: EnrollmentService,
|
||||
) -> AgentEnrollResponse:
|
||||
response.headers["Cache-Control"] = "no-store"
|
||||
|
||||
try:
|
||||
return AgentEnrollResponse(data=service.redeem(request))
|
||||
except AgentEnrollmentTokenInvalid as exc:
|
||||
raise HTTPException(
|
||||
status_code=401,
|
||||
detail="Invalid or expired enrollment token",
|
||||
) from exc
|
||||
except AgentEnrollmentConflict as exc:
|
||||
raise HTTPException(status_code=409, detail=str(exc)) from exc
|
||||
Reference in new issue
Block a user