Add certificate issuance, CSR signing, and cert listing to web UI
- Add SignCSR RPC to v2 CA proto and regenerate; implement handleSignCSR
in CA engine and caServer gRPC layer; add SignCSR client method and
POST /pki/sign-csr web route with result display in pki.html
- Fix issuer detail cert listing: template was using map-style index on
CertSummary structs; switch to struct field access and populate
IssuedBy/IssuedAt fields from proto response
- Add certificate detail view (cert_detail.html) with GET /cert/{serial}
and GET /cert/{serial}/download routes
- Update Makefile proto target to generate both v1 and v2 protos
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -278,6 +278,87 @@ func (c *VaultClient) IssueCert(ctx context.Context, token string, req IssueCert
|
||||
return issued, nil
|
||||
}
|
||||
|
||||
// SignCSRRequest holds parameters for signing an external CSR.
|
||||
type SignCSRRequest struct {
|
||||
Mount string
|
||||
Issuer string
|
||||
CSRPEM string
|
||||
Profile string
|
||||
TTL string
|
||||
}
|
||||
|
||||
// SignedCert holds the result of signing a CSR.
|
||||
type SignedCert struct {
|
||||
Serial string
|
||||
CertPEM string
|
||||
ChainPEM string
|
||||
ExpiresAt string
|
||||
}
|
||||
|
||||
// SignCSR signs an externally generated CSR with the named issuer.
|
||||
func (c *VaultClient) SignCSR(ctx context.Context, token string, req SignCSRRequest) (*SignedCert, error) {
|
||||
resp, err := c.ca.SignCSR(withToken(ctx, token), &pb.SignCSRRequest{
|
||||
Mount: req.Mount,
|
||||
Issuer: req.Issuer,
|
||||
CsrPem: []byte(req.CSRPEM),
|
||||
Profile: req.Profile,
|
||||
Ttl: req.TTL,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sc := &SignedCert{
|
||||
Serial: resp.Serial,
|
||||
CertPEM: string(resp.CertPem),
|
||||
ChainPEM: string(resp.ChainPem),
|
||||
}
|
||||
if resp.ExpiresAt != nil {
|
||||
sc.ExpiresAt = resp.ExpiresAt.AsTime().Format("2006-01-02T15:04:05Z")
|
||||
}
|
||||
return sc, nil
|
||||
}
|
||||
|
||||
// CertDetail holds the full certificate record for the detail view.
|
||||
type CertDetail struct {
|
||||
Serial string
|
||||
Issuer string
|
||||
CommonName string
|
||||
SANs []string
|
||||
Profile string
|
||||
IssuedBy string
|
||||
IssuedAt string
|
||||
ExpiresAt string
|
||||
CertPEM string
|
||||
}
|
||||
|
||||
// GetCert retrieves a full certificate record by serial number.
|
||||
func (c *VaultClient) GetCert(ctx context.Context, token, mount, serial string) (*CertDetail, error) {
|
||||
resp, err := c.ca.GetCert(withToken(ctx, token), &pb.GetCertRequest{Mount: mount, Serial: serial})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rec := resp.GetCert()
|
||||
if rec == nil {
|
||||
return nil, fmt.Errorf("cert not found")
|
||||
}
|
||||
cd := &CertDetail{
|
||||
Serial: rec.Serial,
|
||||
Issuer: rec.Issuer,
|
||||
CommonName: rec.CommonName,
|
||||
SANs: rec.Sans,
|
||||
Profile: rec.Profile,
|
||||
IssuedBy: rec.IssuedBy,
|
||||
CertPEM: string(rec.CertPem),
|
||||
}
|
||||
if rec.IssuedAt != nil {
|
||||
cd.IssuedAt = rec.IssuedAt.AsTime().Format("2006-01-02T15:04:05Z")
|
||||
}
|
||||
if rec.ExpiresAt != nil {
|
||||
cd.ExpiresAt = rec.ExpiresAt.AsTime().Format("2006-01-02T15:04:05Z")
|
||||
}
|
||||
return cd, nil
|
||||
}
|
||||
|
||||
// CertSummary holds lightweight certificate metadata for list views.
|
||||
type CertSummary struct {
|
||||
Serial string
|
||||
|
||||
Reference in New Issue
Block a user