diff --git a/.junie/memory/language.json b/.junie/memory/language.json index 54b056a..3f1e2a9 100644 --- a/.junie/memory/language.json +++ b/.junie/memory/language.json @@ -1 +1 @@ -[{"lang":"en","usageCount":32}] \ No newline at end of file +[{"lang":"en","usageCount":33}] \ No newline at end of file diff --git a/internal/grpcserver/auth.go b/internal/grpcserver/auth.go index 01ff57d..8eaeb7b 100644 --- a/internal/grpcserver/auth.go +++ b/internal/grpcserver/auth.go @@ -27,6 +27,7 @@ func (as *authServer) Login(_ context.Context, req *pb.LoginRequest) (*pb.LoginR if t, err := time.Parse(time.RFC3339, expiresAtStr); err == nil { expiresAt = timestamppb.New(t) } + as.s.logger.Info("audit: login", "username", req.Username) return &pb.LoginResponse{Token: token, ExpiresAt: expiresAt}, nil } @@ -39,6 +40,7 @@ func (as *authServer) Logout(ctx context.Context, _ *pb.LogoutRequest) (*pb.Logo if err == nil { _ = as.s.auth.Logout(client) } + as.s.logger.Info("audit: logout", "username", callerUsername(ctx)) return &pb.LogoutResponse{}, nil } diff --git a/internal/grpcserver/ca.go b/internal/grpcserver/ca.go index f6fa1ba..1aa0b04 100644 --- a/internal/grpcserver/ca.go +++ b/internal/grpcserver/ca.go @@ -48,6 +48,14 @@ func (cs *caServer) caHandleRequest(ctx context.Context, mount, operation string return resp, nil } +func callerUsername(ctx context.Context) string { + ti := tokenInfoFromContext(ctx) + if ti == nil { + return "" + } + return ti.Username +} + func (cs *caServer) callerInfo(ctx context.Context) *engine.CallerInfo { ti := tokenInfoFromContext(ctx) if ti == nil { @@ -82,6 +90,7 @@ func (cs *caServer) ImportRoot(ctx context.Context, req *pb.ImportRootRequest) ( expiresAt = timestamppb.New(t) } } + cs.s.logger.Info("audit: root CA imported", "mount", req.Mount, "cn", cn, "username", callerUsername(ctx)) return &pb.ImportRootResponse{CommonName: cn, ExpiresAt: expiresAt}, nil } @@ -128,6 +137,7 @@ func (cs *caServer) CreateIssuer(ctx context.Context, req *pb.CreateIssuerReques } name, _ := resp.Data["name"].(string) certPEM, _ := resp.Data["cert_pem"].(string) + cs.s.logger.Info("audit: issuer created", "mount", req.Mount, "issuer", name, "username", callerUsername(ctx)) return &pb.CreateIssuerResponse{Name: name, CertPem: []byte(certPEM)}, nil } @@ -143,6 +153,7 @@ func (cs *caServer) DeleteIssuer(ctx context.Context, req *pb.DeleteIssuerReques if err != nil { return nil, err } + cs.s.logger.Info("audit: issuer deleted", "mount", req.Mount, "issuer", req.Name, "username", callerUsername(ctx)) return &pb.DeleteIssuerResponse{}, nil } @@ -270,6 +281,7 @@ func (cs *caServer) IssueCert(ctx context.Context, req *pb.IssueCertRequest) (*p expiresAt = timestamppb.New(t) } } + cs.s.logger.Info("audit: certificate issued", "mount", req.Mount, "issuer", issuedBy, "serial", serial, "cn", cn, "sans", sans, "username", callerUsername(ctx)) return &pb.IssueCertResponse{ Serial: serial, CommonName: cn, @@ -346,6 +358,7 @@ func (cs *caServer) RenewCert(ctx context.Context, req *pb.RenewCertRequest) (*p expiresAt = timestamppb.New(t) } } + cs.s.logger.Info("audit: certificate renewed", "mount", req.Mount, "old_serial", req.Serial, "new_serial", serial, "cn", cn, "issued_by", issuedBy, "username", callerUsername(ctx)) return &pb.RenewCertResponse{ Serial: serial, CommonName: cn, diff --git a/internal/grpcserver/engine.go b/internal/grpcserver/engine.go index 7b2534b..41b237e 100644 --- a/internal/grpcserver/engine.go +++ b/internal/grpcserver/engine.go @@ -40,6 +40,12 @@ func (es *engineServer) Mount(ctx context.Context, req *pb.MountRequest) (*pb.Mo return nil, status.Error(codes.Internal, err.Error()) } } + ti := tokenInfoFromContext(ctx) + username := "" + if ti != nil { + username = ti.Username + } + es.s.logger.Info("audit: engine mounted", "name", req.Name, "type", req.Type, "username", username) return &pb.MountResponse{}, nil } @@ -53,6 +59,12 @@ func (es *engineServer) Unmount(ctx context.Context, req *pb.UnmountRequest) (*p } return nil, status.Error(codes.Internal, err.Error()) } + ti := tokenInfoFromContext(ctx) + username := "" + if ti != nil { + username = ti.Username + } + es.s.logger.Info("audit: engine unmounted", "name", req.Name, "username", username) return &pb.UnmountResponse{}, nil } diff --git a/internal/grpcserver/policy.go b/internal/grpcserver/policy.go index 83e740d..9c35bf2 100644 --- a/internal/grpcserver/policy.go +++ b/internal/grpcserver/policy.go @@ -24,6 +24,7 @@ func (ps *policyServer) CreatePolicy(ctx context.Context, req *pb.CreatePolicyRe ps.s.logger.Error("grpc: create policy", "error", err) return nil, status.Error(codes.Internal, "internal error") } + ps.s.logger.Info("audit: policy created", "id", rule.ID, "username", callerUsername(ctx)) return &pb.CreatePolicyResponse{Rule: ruleToPB(rule)}, nil } @@ -58,6 +59,7 @@ func (ps *policyServer) DeletePolicy(ctx context.Context, req *pb.DeletePolicyRe if err := ps.s.policy.DeleteRule(ctx, req.Id); err != nil { return nil, status.Error(codes.NotFound, "not found") } + ps.s.logger.Info("audit: policy deleted", "id", req.Id, "username", callerUsername(ctx)) return &pb.DeletePolicyResponse{}, nil } diff --git a/internal/grpcserver/system.go b/internal/grpcserver/system.go index a4c4afa..55824d6 100644 --- a/internal/grpcserver/system.go +++ b/internal/grpcserver/system.go @@ -38,6 +38,7 @@ func (ss *systemServer) Init(ctx context.Context, req *pb.InitRequest) (*pb.Init ss.s.logger.Error("grpc: init failed", "error", err) return nil, status.Error(codes.Internal, "initialization failed") } + ss.s.logger.Info("audit: vault initialized") return &pb.InitResponse{State: ss.s.sealMgr.State().String()}, nil } @@ -61,6 +62,7 @@ func (ss *systemServer) Unseal(ctx context.Context, req *pb.UnsealRequest) (*pb. return nil, status.Error(codes.Internal, "engine unseal failed") } + ss.s.logger.Info("audit: vault unsealed") return &pb.UnsealResponse{State: ss.s.sealMgr.State().String()}, nil } @@ -73,5 +75,6 @@ func (ss *systemServer) Seal(_ context.Context, _ *pb.SealRequest) (*pb.SealResp return nil, status.Error(codes.Internal, "seal failed") } ss.s.auth.ClearCache() + ss.s.logger.Info("audit: vault sealed") return &pb.SealResponse{State: ss.s.sealMgr.State().String()}, nil } diff --git a/internal/webserver/client.go b/internal/webserver/client.go index 7e9969a..ae52e9e 100644 --- a/internal/webserver/client.go +++ b/internal/webserver/client.go @@ -284,6 +284,8 @@ type CertSummary struct { Issuer string CommonName string Profile string + IssuedBy string + IssuedAt string ExpiresAt string } @@ -300,6 +302,10 @@ func (c *VaultClient) ListCerts(ctx context.Context, token, mount string) ([]Cer Issuer: s.Issuer, CommonName: s.CommonName, Profile: s.Profile, + IssuedBy: s.IssuedBy, + } + if s.IssuedAt != nil { + cs.IssuedAt = s.IssuedAt.AsTime().Format("2006-01-02T15:04:05Z") } if s.ExpiresAt != nil { cs.ExpiresAt = s.ExpiresAt.AsTime().Format("2006-01-02T15:04:05Z") diff --git a/web/templates/issuer_detail.html b/web/templates/issuer_detail.html index 8dfbb95..c6a30f6 100644 --- a/web/templates/issuer_detail.html +++ b/web/templates/issuer_detail.html @@ -45,12 +45,12 @@ {{range .Certs}} - {{index . "cn"}} - {{index . "profile"}} - {{index . "serial"}} - {{index . "issued_by"}} - {{index . "issued_at"}} - {{index . "expires_at"}} + {{.CommonName}} + {{.Profile}} + {{.Serial}} + {{.IssuedBy}} + {{.IssuedAt}} + {{.ExpiresAt}} {{end}}