Add policy CRUD, cert management, and web UI updates

- Add PUT /v1/policy/rule endpoint for updating policy rules; expose
  full policy CRUD through the web UI with a dedicated policy page
- Add certificate revoke, delete, and get-cert to CA engine and wire
  REST + gRPC routes; fix missing interceptor registrations
- Update ARCHITECTURE.md to reflect v2 gRPC as the active implementation,
  document ACME endpoints, correct CA permission levels, and add policy/cert
  management route tables
- Add POLICY.md documenting the priority-based ACL engine design
- Add web/templates/policy.html for policy management UI

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-15 19:41:11 -07:00
parent 02ee538213
commit fbd6d1af04
17 changed files with 1055 additions and 58 deletions

View File

@@ -637,6 +637,9 @@ func (e *CAEngine) handleListIssuers(_ context.Context, req *engine.Request) (*e
if req.CallerInfo == nil {
return nil, ErrUnauthorized
}
if !req.CallerInfo.IsUser() {
return nil, ErrForbidden
}
e.mu.RLock()
defer e.mu.RUnlock()
@@ -661,6 +664,9 @@ func (e *CAEngine) handleIssue(ctx context.Context, req *engine.Request) (*engin
if req.CallerInfo == nil {
return nil, ErrUnauthorized
}
if !req.CallerInfo.IsAdmin {
return nil, ErrForbidden
}
issuerName, _ := req.Data["issuer"].(string)
if issuerName == "" {
@@ -810,6 +816,9 @@ func (e *CAEngine) handleGetCert(ctx context.Context, req *engine.Request) (*eng
if req.CallerInfo == nil {
return nil, ErrUnauthorized
}
if !req.CallerInfo.IsUser() {
return nil, ErrForbidden
}
serial, _ := req.Data["serial"].(string)
if serial == "" {
@@ -858,6 +867,9 @@ func (e *CAEngine) handleListCerts(ctx context.Context, req *engine.Request) (*e
if req.CallerInfo == nil {
return nil, ErrUnauthorized
}
if !req.CallerInfo.IsUser() {
return nil, ErrForbidden
}
e.mu.RLock()
defer e.mu.RUnlock()
@@ -902,6 +914,9 @@ func (e *CAEngine) handleRenew(ctx context.Context, req *engine.Request) (*engin
if req.CallerInfo == nil {
return nil, ErrUnauthorized
}
if !req.CallerInfo.IsAdmin {
return nil, ErrForbidden
}
serial, _ := req.Data["serial"].(string)
if serial == "" {
@@ -1028,6 +1043,9 @@ func (e *CAEngine) handleSignCSR(ctx context.Context, req *engine.Request) (*eng
if req.CallerInfo == nil {
return nil, ErrUnauthorized
}
if !req.CallerInfo.IsAdmin {
return nil, ErrForbidden
}
issuerName, _ := req.Data["issuer"].(string)
if issuerName == "" {