Fix web UI download links for CA certs, SSH CA pubkey, and KRL

Templates linked to /v1/ API server routes which don't exist on the
web server (separate binary). Add web server handlers that fetch data
via gRPC and serve the downloads directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-28 19:02:15 -07:00
parent 131d3e778a
commit ae4cc8b420
4 changed files with 63 additions and 3 deletions

View File

@@ -50,6 +50,8 @@ func (ws *WebServer) registerRoutes(r chi.Router) {
r.Route("/sshca", func(r chi.Router) {
r.Get("/", ws.requireAuth(ws.handleSSHCA))
r.Get("/ca", ws.requireAuth(ws.handleSSHCADownload))
r.Get("/krl", ws.requireAuth(ws.handleSSHCAKRLDownload))
r.Post("/sign-user", ws.requireAuth(ws.handleSSHCASignUser))
r.Post("/sign-host", ws.requireAuth(ws.handleSSHCASignHost))
r.Get("/cert/{serial}", ws.requireAuth(ws.handleSSHCACertDetail))
@@ -91,6 +93,7 @@ func (ws *WebServer) registerRoutes(r chi.Router) {
r.Route("/pki", func(r chi.Router) {
r.Get("/", ws.requireAuth(ws.handlePKI))
r.Get("/ca", ws.requireAuth(ws.handlePKIRootCA))
r.Post("/import-root", ws.requireAuth(ws.handleImportRoot))
r.Post("/create-issuer", ws.requireAuth(ws.handleCreateIssuer))
r.Post("/issue", ws.requireAuth(ws.handleIssueCert))
@@ -475,6 +478,25 @@ func (ws *WebServer) handleCreateIssuer(w http.ResponseWriter, r *http.Request)
http.Redirect(w, r, "/pki", http.StatusFound)
}
func (ws *WebServer) handlePKIRootCA(w http.ResponseWriter, r *http.Request) {
token := extractCookie(r)
mountName, err := ws.findCAMount(r, token)
if err != nil {
http.Error(w, "no CA engine mounted", http.StatusNotFound)
return
}
certPEM, err := ws.vault.GetRootCert(r.Context(), mountName)
if err != nil || len(certPEM) == 0 {
http.Error(w, "root CA not found", http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/x-pem-file")
w.Header().Set("Content-Disposition", "attachment; filename=root-ca.pem")
_, _ = w.Write(certPEM) //nolint:gosec
}
func (ws *WebServer) handlePKIIssuer(w http.ResponseWriter, r *http.Request) {
token := extractCookie(r)
mountName, err := ws.findCAMount(r, token)