From e03a75ed9aded765ca0f55f1a1179d089e39d9f9 Mon Sep 17 00:00:00 2001 From: shankar0123 Date: Fri, 20 Mar 2026 01:20:03 -0400 Subject: [PATCH] fix: replace fmt.Printf with structured slog logging across all services All 10 service files now use slog.Error for failure logging instead of fmt.Printf. Audit event recording errors are checked and logged rather than silently discarded. Adds consistent structured context (resource IDs, operation names) to all error log statements. Co-Authored-By: Claude Opus 4.6 --- internal/service/agent.go | 25 ++++++---- internal/service/certificate.go | 23 ++++++---- internal/service/deployment.go | 59 ++++++++++++++---------- internal/service/issuer.go | 13 ++++-- internal/service/notification.go | 13 ++++-- internal/service/owner.go | 13 ++++-- internal/service/policy.go | 9 ++-- internal/service/renewal.go | 78 +++++++++++++++++++------------- internal/service/target.go | 13 ++++-- internal/service/team.go | 13 ++++-- 10 files changed, 166 insertions(+), 93 deletions(-) diff --git a/internal/service/agent.go b/internal/service/agent.go index ffa4a32..9127c96 100644 --- a/internal/service/agent.go +++ b/internal/service/agent.go @@ -5,6 +5,7 @@ import ( "crypto/sha256" "encoding/hex" "fmt" + "log/slog" "math/rand" "time" @@ -73,7 +74,7 @@ func (s *AgentService) Register(ctx context.Context, name string, hostname strin if err := s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, "agent_registered", "agent", agent.ID, map[string]interface{}{"name": name, "hostname": hostname}); err != nil { - fmt.Printf("failed to record audit event: %v\n", err) + slog.Error("failed to record audit event", "error", err) } // Return the API key only once; the agent must save it securely @@ -96,7 +97,7 @@ func (s *AgentService) HeartbeatWithContext(ctx context.Context, agentID string) if agent.Status != domain.AgentStatusOnline { agent.Status = domain.AgentStatusOnline if err := s.agentRepo.Update(ctx, agent); err != nil { - fmt.Printf("failed to update agent status: %v\n", err) + slog.Error("failed to update agent status", "error", err) } } @@ -140,13 +141,15 @@ func (s *AgentService) SubmitCSR(ctx context.Context, agentID string, certID str } // Record audit event - _ = s.auditService.RecordEvent(ctx, agent.ID, domain.ActorTypeAgent, + if auditErr := s.auditService.RecordEvent(ctx, agent.ID, domain.ActorTypeAgent, "csr_submitted", "certificate", certID, map[string]interface{}{ "agent_hostname": agent.Hostname, "keygen_mode": "agent", "job_id": awaitingJobs[0].ID, - }) + }); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } return nil } @@ -181,15 +184,17 @@ func (s *AgentService) SubmitCSR(ctx context.Context, agentID string, certID str cert.LastRenewalAt = &now cert.UpdatedAt = now if err := s.certRepo.Update(ctx, cert); err != nil { - fmt.Printf("failed to update certificate: %v\n", err) + slog.Error("failed to update certificate", "error", err) } } } // Record audit event - _ = s.auditService.RecordEvent(ctx, agent.ID, domain.ActorTypeAgent, + if auditErr := s.auditService.RecordEvent(ctx, agent.ID, domain.ActorTypeAgent, "csr_submitted", "certificate", certID, - map[string]interface{}{"agent_hostname": agent.Hostname}) + map[string]interface{}{"agent_hostname": agent.Hostname}); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } return nil } @@ -224,7 +229,7 @@ func (s *AgentService) GetCertificateForAgent(ctx context.Context, agentID strin if err := s.auditService.RecordEvent(ctx, agentID, domain.ActorTypeAgent, "certificate_retrieved", "certificate", certID, map[string]interface{}{"version": latestVersion.SerialNumber}); err != nil { - fmt.Printf("failed to record audit event: %v\n", err) + slog.Error("failed to record audit event", "error", err) } return []byte(latestVersion.PEMChain), nil @@ -283,7 +288,7 @@ func (s *AgentService) ReportJobStatus(ctx context.Context, agentID string, jobI if err := s.auditService.RecordEvent(ctx, agentID, domain.ActorTypeAgent, "job_status_reported", "job", jobID, map[string]interface{}{"status": status, "error": errMsg}); err != nil { - fmt.Printf("failed to record audit event: %v\n", err) + slog.Error("failed to record audit event", "error", err) } return nil @@ -302,7 +307,7 @@ func (s *AgentService) MarkStaleAgentsOffline(ctx context.Context, threshold tim if agent.Status == domain.AgentStatusOnline && agent.LastHeartbeatAt != nil && agent.LastHeartbeatAt.Before(cutoff) { agent.Status = domain.AgentStatusOffline if err := s.agentRepo.Update(ctx, agent); err != nil { - fmt.Printf("failed to mark agent %s offline: %v\n", agent.ID, err) + slog.Error("failed to mark agent offline", "agent_id", agent.ID, "error", err) continue } } diff --git a/internal/service/certificate.go b/internal/service/certificate.go index 310de54..b6a1308 100644 --- a/internal/service/certificate.go +++ b/internal/service/certificate.go @@ -3,6 +3,7 @@ package service import ( "context" "fmt" + "log/slog" "time" "github.com/shankar0123/certctl/internal/domain" @@ -62,9 +63,11 @@ func (s *CertificateService) Create(ctx context.Context, cert *domain.ManagedCer if len(violations) > 0 { // Record violations but do not block creation for _, v := range violations { - _ = s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, + if auditErr := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "policy_violation_detected", "certificate", cert.ID, - map[string]interface{}{"rule_id": v.RuleID, "message": v.Message}) + map[string]interface{}{"rule_id": v.RuleID, "message": v.Message}); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } } } @@ -78,7 +81,7 @@ func (s *CertificateService) Create(ctx context.Context, cert *domain.ManagedCer "certificate_created", "certificate", cert.ID, map[string]interface{}{"common_name": cert.CommonName}); err != nil { // Log but don't fail the operation - fmt.Printf("failed to record audit event: %v\n", err) + slog.Error("failed to record audit event", "error", err) } return nil @@ -98,9 +101,11 @@ func (s *CertificateService) Update(ctx context.Context, cert *domain.ManagedCer } if len(violations) > 0 { for _, v := range violations { - _ = s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, + if auditErr := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "policy_violation_detected", "certificate", cert.ID, - map[string]interface{}{"rule_id": v.RuleID, "message": v.Message}) + map[string]interface{}{"rule_id": v.RuleID, "message": v.Message}); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } } } @@ -120,7 +125,7 @@ func (s *CertificateService) Update(ctx context.Context, cert *domain.ManagedCer if err := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "certificate_updated", "certificate", cert.ID, changes); err != nil { - fmt.Printf("failed to record audit event: %v\n", err) + slog.Error("failed to record audit event", "error", err) } return nil @@ -140,7 +145,7 @@ func (s *CertificateService) Archive(ctx context.Context, id string, actor strin if err := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "certificate_archived", "certificate", id, map[string]interface{}{"common_name": cert.CommonName}); err != nil { - fmt.Printf("failed to record audit event: %v\n", err) + slog.Error("failed to record audit event", "error", err) } return nil @@ -185,7 +190,7 @@ func (s *CertificateService) TriggerRenewalWithActor(ctx context.Context, certID if err := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "renewal_triggered", "certificate", certID, map[string]interface{}{"common_name": cert.CommonName}); err != nil { - fmt.Printf("failed to record audit event: %v\n", err) + slog.Error("failed to record audit event", "error", err) } return nil @@ -207,7 +212,7 @@ func (s *CertificateService) TriggerDeploymentWithActor(ctx context.Context, cer if err := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "deployment_triggered", "certificate", certID, map[string]interface{}{"common_name": cert.CommonName}); err != nil { - fmt.Printf("failed to record audit event: %v\n", err) + slog.Error("failed to record audit event", "error", err) } return nil diff --git a/internal/service/deployment.go b/internal/service/deployment.go index aff4959..0b5c1af 100644 --- a/internal/service/deployment.go +++ b/internal/service/deployment.go @@ -3,6 +3,7 @@ package service import ( "context" "fmt" + "log/slog" "time" "github.com/shankar0123/certctl/internal/domain" @@ -68,7 +69,7 @@ func (s *DeploymentService) CreateDeploymentJobs(ctx context.Context, certID str } if err := s.jobRepo.Create(ctx, job); err != nil { - fmt.Printf("failed to create deployment job for target %s: %v\n", target.ID, err) + slog.Error("failed to create deployment job for target", "target_id", target.ID, "error", err) continue } @@ -80,9 +81,11 @@ func (s *DeploymentService) CreateDeploymentJobs(ctx context.Context, certID str } // Record audit event - _ = s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, + if auditErr := s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, "deployment_jobs_created", "certificate", certID, - map[string]interface{}{"target_count": len(targets), "job_count": len(jobIDs)}) + map[string]interface{}{"target_count": len(targets), "job_count": len(jobIDs)}); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } return jobIDs, nil } @@ -99,7 +102,7 @@ func (s *DeploymentService) ProcessDeploymentJob(ctx context.Context, job *domai if err != nil { updateErr := s.jobRepo.UpdateStatus(ctx, job.ID, domain.JobStatusFailed, fmt.Sprintf("certificate fetch failed: %v", err)) if updateErr != nil { - fmt.Printf("failed to update job status: %v\n", updateErr) + slog.Error("failed to update job status", "job_id", job.ID, "error", updateErr) } return fmt.Errorf("failed to fetch certificate: %w", err) } @@ -112,7 +115,7 @@ func (s *DeploymentService) ProcessDeploymentJob(ctx context.Context, job *domai if targetID == "" { updateErr := s.jobRepo.UpdateStatus(ctx, job.ID, domain.JobStatusFailed, "target_id not found in job") if updateErr != nil { - fmt.Printf("failed to update job status: %v\n", updateErr) + slog.Error("failed to update job status", "job_id", job.ID, "error", updateErr) } return fmt.Errorf("target_id not found in job") } @@ -121,7 +124,7 @@ func (s *DeploymentService) ProcessDeploymentJob(ctx context.Context, job *domai if err != nil { updateErr := s.jobRepo.UpdateStatus(ctx, job.ID, domain.JobStatusFailed, fmt.Sprintf("target fetch failed: %v", err)) if updateErr != nil { - fmt.Printf("failed to update job status: %v\n", updateErr) + slog.Error("failed to update job status", "job_id", job.ID, "error", updateErr) } return fmt.Errorf("failed to fetch target: %w", err) } @@ -132,7 +135,7 @@ func (s *DeploymentService) ProcessDeploymentJob(ctx context.Context, job *domai if err != nil { updateErr := s.jobRepo.UpdateStatus(ctx, job.ID, domain.JobStatusFailed, fmt.Sprintf("agent fetch failed: %v", err)) if updateErr != nil { - fmt.Printf("failed to update job status: %v\n", updateErr) + slog.Error("failed to update job status", "job_id", job.ID, "error", updateErr) } return fmt.Errorf("failed to fetch agent: %w", err) } @@ -141,13 +144,17 @@ func (s *DeploymentService) ProcessDeploymentJob(ctx context.Context, job *domai if agent.LastHeartbeatAt != nil && time.Since(*agent.LastHeartbeatAt) > 5*time.Minute { updateErr := s.jobRepo.UpdateStatus(ctx, job.ID, domain.JobStatusFailed, "agent is offline") if updateErr != nil { - fmt.Printf("failed to update job status: %v\n", updateErr) + slog.Error("failed to update job status", "job_id", job.ID, "error", updateErr) } - _ = s.notificationSvc.SendDeploymentNotification(ctx, cert, target, false, fmt.Errorf("agent offline")) - _ = s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, + if notifErr := s.notificationSvc.SendDeploymentNotification(ctx, cert, target, false, fmt.Errorf("agent offline")); notifErr != nil { + slog.Error("failed to send deployment notification", "error", notifErr) + } + if auditErr := s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, "deployment_job_failed", "certificate", job.CertificateID, - map[string]interface{}{"job_id": job.ID, "reason": "agent offline", "target_id": targetID}) + map[string]interface{}{"job_id": job.ID, "reason": "agent offline", "target_id": targetID}); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } return fmt.Errorf("agent %s is offline", agentID) } @@ -157,9 +164,11 @@ func (s *DeploymentService) ProcessDeploymentJob(ctx context.Context, job *domai // For now, we mark it as pending and rely on agent polling. // Record audit event - _ = s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, + if auditErr := s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, "deployment_job_dispatched", "certificate", job.CertificateID, - map[string]interface{}{"job_id": job.ID, "target_id": targetID, "agent_id": agentID}) + map[string]interface{}{"job_id": job.ID, "target_id": targetID, "agent_id": agentID}); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } return nil } @@ -217,7 +226,7 @@ func (s *DeploymentService) MarkDeploymentComplete(ctx context.Context, jobID st // Fetch certificate and target for notification cert, err := s.certRepo.Get(ctx, job.CertificateID) if err != nil { - fmt.Printf("failed to fetch certificate for notification: %v\n", err) + slog.Error("failed to fetch certificate for notification", "error", err) return nil } @@ -229,20 +238,22 @@ func (s *DeploymentService) MarkDeploymentComplete(ctx context.Context, jobID st if targetID != "" { target, err := s.targetRepo.Get(ctx, targetID) if err != nil { - fmt.Printf("failed to fetch target for notification: %v\n", err) + slog.Error("failed to fetch target for notification", "error", err) return nil } // Send deployment success notification if err := s.notificationSvc.SendDeploymentNotification(ctx, cert, target, true, nil); err != nil { - fmt.Printf("failed to send deployment notification: %v\n", err) + slog.Error("failed to send deployment notification", "error", err) } } // Record audit event - _ = s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, + if auditErr := s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, "deployment_job_completed", "certificate", job.CertificateID, - map[string]interface{}{"job_id": jobID, "target_id": targetID}) + map[string]interface{}{"job_id": jobID, "target_id": targetID}); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } return nil } @@ -262,7 +273,7 @@ func (s *DeploymentService) MarkDeploymentFailed(ctx context.Context, jobID stri // Fetch certificate and target for notification cert, err := s.certRepo.Get(ctx, job.CertificateID) if err != nil { - fmt.Printf("failed to fetch certificate for notification: %v\n", err) + slog.Error("failed to fetch certificate for notification", "error", err) return nil } @@ -274,20 +285,22 @@ func (s *DeploymentService) MarkDeploymentFailed(ctx context.Context, jobID stri if targetID != "" { target, err := s.targetRepo.Get(ctx, targetID) if err != nil { - fmt.Printf("failed to fetch target for notification: %v\n", err) + slog.Error("failed to fetch target for notification", "error", err) return nil } // Send deployment failure notification if err := s.notificationSvc.SendDeploymentNotification(ctx, cert, target, false, fmt.Errorf("%s", errMsg)); err != nil { - fmt.Printf("failed to send deployment notification: %v\n", err) + slog.Error("failed to send deployment notification", "error", err) } } // Record audit event - _ = s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, + if auditErr := s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, "deployment_job_failed", "certificate", job.CertificateID, - map[string]interface{}{"job_id": jobID, "target_id": targetID, "error": errMsg}) + map[string]interface{}{"job_id": jobID, "target_id": targetID, "error": errMsg}); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } return nil } diff --git a/internal/service/issuer.go b/internal/service/issuer.go index 677f853..3b5b381 100644 --- a/internal/service/issuer.go +++ b/internal/service/issuer.go @@ -3,6 +3,7 @@ package service import ( "context" "fmt" + "log/slog" "time" "github.com/shankar0123/certctl/internal/domain" @@ -81,7 +82,9 @@ func (s *IssuerService) Create(ctx context.Context, issuer *domain.Issuer, actor } if s.auditService != nil { - _ = s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "create_issuer", "issuer", issuer.ID, nil) + if auditErr := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "create_issuer", "issuer", issuer.ID, nil); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } } return nil @@ -99,7 +102,9 @@ func (s *IssuerService) Update(ctx context.Context, id string, issuer *domain.Is } if s.auditService != nil { - _ = s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "update_issuer", "issuer", id, nil) + if auditErr := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "update_issuer", "issuer", id, nil); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } } return nil @@ -112,7 +117,9 @@ func (s *IssuerService) Delete(ctx context.Context, id string, actor string) err } if s.auditService != nil { - _ = s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "delete_issuer", "issuer", id, nil) + if auditErr := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "delete_issuer", "issuer", id, nil); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } } return nil diff --git a/internal/service/notification.go b/internal/service/notification.go index f0aa592..ea37ac7 100644 --- a/internal/service/notification.go +++ b/internal/service/notification.go @@ -3,6 +3,7 @@ package service import ( "context" "fmt" + "log/slog" "time" "github.com/shankar0123/certctl/internal/domain" @@ -188,7 +189,7 @@ func (s *NotificationService) ProcessPendingNotifications(ctx context.Context) e for _, notif := range pending { if err := s.sendNotification(ctx, notif); err != nil { - fmt.Printf("failed to send notification %s: %v\n", notif.ID, err) + slog.Error("failed to send notification", "notification_id", notif.ID, "error", err) failedCount++ } } @@ -206,20 +207,24 @@ func (s *NotificationService) sendNotification(ctx context.Context, notif *domai notifier, ok := s.notifierRegistry[string(notif.Channel)] if !ok { // No notifier configured for this channel — mark as sent (demo mode) - _ = s.notifRepo.UpdateStatus(ctx, notif.ID, "sent", time.Now()) + if updateErr := s.notifRepo.UpdateStatus(ctx, notif.ID, "sent", time.Now()); updateErr != nil { + slog.Error("failed to update notification status", "notification_id", notif.ID, "error", updateErr) + } return nil } // Send the notification if err := notifier.Send(ctx, notif.Recipient, string(notif.Type), notif.Message); err != nil { // Update status to failed - _ = s.notifRepo.UpdateStatus(ctx, notif.ID, "failed", time.Time{}) + if updateErr := s.notifRepo.UpdateStatus(ctx, notif.ID, "failed", time.Time{}); updateErr != nil { + slog.Error("failed to update notification status", "notification_id", notif.ID, "error", updateErr) + } return fmt.Errorf("failed to send via %s: %w", notif.Channel, err) } // Update status to sent if err := s.notifRepo.UpdateStatus(ctx, notif.ID, "sent", time.Now()); err != nil { - fmt.Printf("failed to update notification status: %v\n", err) + slog.Error("failed to update notification status", "notification_id", notif.ID, "error", err) } return nil diff --git a/internal/service/owner.go b/internal/service/owner.go index 95c4d70..d3eff7e 100644 --- a/internal/service/owner.go +++ b/internal/service/owner.go @@ -3,6 +3,7 @@ package service import ( "context" "fmt" + "log/slog" "time" "github.com/shankar0123/certctl/internal/domain" @@ -81,7 +82,9 @@ func (s *OwnerService) Create(ctx context.Context, owner *domain.Owner, actor st } if s.auditService != nil { - _ = s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "create_owner", "owner", owner.ID, nil) + if auditErr := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "create_owner", "owner", owner.ID, nil); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } } return nil @@ -99,7 +102,9 @@ func (s *OwnerService) Update(ctx context.Context, id string, owner *domain.Owne } if s.auditService != nil { - _ = s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "update_owner", "owner", id, nil) + if auditErr := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "update_owner", "owner", id, nil); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } } return nil @@ -112,7 +117,9 @@ func (s *OwnerService) Delete(ctx context.Context, id string, actor string) erro } if s.auditService != nil { - _ = s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "delete_owner", "owner", id, nil) + if auditErr := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "delete_owner", "owner", id, nil); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } } return nil diff --git a/internal/service/policy.go b/internal/service/policy.go index b1ed8b2..6b94d75 100644 --- a/internal/service/policy.go +++ b/internal/service/policy.go @@ -3,6 +3,7 @@ package service import ( "context" "fmt" + "log/slog" "time" "github.com/shankar0123/certctl/internal/domain" @@ -44,7 +45,7 @@ func (s *PolicyService) ValidateCertificate(ctx context.Context, cert *domain.Ma // Evaluate rule against certificate v, err := s.evaluateRule(rule, cert) if err != nil { - fmt.Printf("failed to evaluate rule %s: %v\n", rule.ID, err) + slog.Error("failed to evaluate rule", "rule_id", rule.ID, "error", err) continue } @@ -149,7 +150,7 @@ func (s *PolicyService) CreateRule(ctx context.Context, rule *domain.PolicyRule, if err := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "policy_rule_created", "policy", rule.ID, map[string]interface{}{"rule_type": rule.Type}); err != nil { - fmt.Printf("failed to record audit event: %v\n", err) + slog.Error("failed to record audit event", "error", err) } return nil @@ -175,7 +176,7 @@ func (s *PolicyService) UpdateRule(ctx context.Context, rule *domain.PolicyRule, if err := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "policy_rule_updated", "policy", rule.ID, changes); err != nil { - fmt.Printf("failed to record audit event: %v\n", err) + slog.Error("failed to record audit event", "error", err) } return nil @@ -213,7 +214,7 @@ func (s *PolicyService) DeleteRule(ctx context.Context, id string, actor string) if err := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "policy_rule_deleted", "policy", id, map[string]interface{}{"rule_type": rule.Type}); err != nil { - fmt.Printf("failed to record audit event: %v\n", err) + slog.Error("failed to record audit event", "error", err) } return nil diff --git a/internal/service/renewal.go b/internal/service/renewal.go index 10c427a..92700eb 100644 --- a/internal/service/renewal.go +++ b/internal/service/renewal.go @@ -10,6 +10,7 @@ import ( "encoding/hex" "encoding/pem" "fmt" + "log/slog" "time" "github.com/shankar0123/certctl/internal/domain" @@ -103,8 +104,7 @@ func (s *RenewalService) CheckExpiringCertificates(ctx context.Context) error { policy, err = s.renewalPolicyRepo.Get(ctx, cert.RenewalPolicyID) if err != nil { // Log but continue with defaults - fmt.Printf("failed to fetch renewal policy %s for cert %s, using defaults: %v\n", - cert.RenewalPolicyID, cert.ID, err) + slog.Error("failed to fetch renewal policy, using defaults", "policy_id", cert.RenewalPolicyID, "cert_id", cert.ID, "error", err) } else { policyCache[cert.RenewalPolicyID] = policy } @@ -153,20 +153,22 @@ func (s *RenewalService) CheckExpiringCertificates(ctx context.Context) error { } if err := s.jobRepo.Create(ctx, job); err != nil { - fmt.Printf("failed to create renewal job for cert %s: %v\n", cert.ID, err) + slog.Error("failed to create renewal job for cert", "cert_id", cert.ID, "error", err) continue } // Update certificate status to RenewalInProgress cert.Status = domain.CertificateStatusRenewalInProgress if err := s.certRepo.Update(ctx, cert); err != nil { - fmt.Printf("failed to update cert status for %s: %v\n", cert.ID, err) + slog.Error("failed to update cert status", "cert_id", cert.ID, "error", err) } // Record audit event - _ = s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, + if auditErr := s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, "renewal_job_created", "certificate", cert.ID, - map[string]interface{}{"days_until_expiry": daysUntil, "job_id": job.ID}) + map[string]interface{}{"days_until_expiry": daysUntil, "job_id": job.ID}); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } } return nil @@ -186,8 +188,7 @@ func (s *RenewalService) sendThresholdAlerts(ctx context.Context, cert *domain.M // Check if we already sent a notification for this threshold (deduplication) alreadySent, err := s.notificationSvc.HasThresholdNotification(ctx, cert.ID, threshold) if err != nil { - fmt.Printf("failed to check notification dedup for cert %s threshold %d: %v\n", - cert.ID, threshold, err) + slog.Error("failed to check notification dedup", "cert_id", cert.ID, "threshold", threshold, "error", err) continue } if alreadySent { @@ -196,17 +197,18 @@ func (s *RenewalService) sendThresholdAlerts(ctx context.Context, cert *domain.M // Send the threshold alert if err := s.notificationSvc.SendThresholdAlert(ctx, cert, daysUntil, threshold); err != nil { - fmt.Printf("failed to send threshold alert for cert %s at %d days: %v\n", - cert.ID, threshold, err) + slog.Error("failed to send threshold alert for cert", "cert_id", cert.ID, "threshold", threshold, "error", err) } // Record audit event for the alert - _ = s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, + if auditErr := s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, "expiration_alert_sent", "certificate", cert.ID, map[string]interface{}{ "threshold_days": threshold, "days_until_expiry": daysUntil, - }) + }); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } } } @@ -234,7 +236,7 @@ func (s *RenewalService) updateCertExpiryStatus(ctx context.Context, cert *domai cert.Status = newStatus cert.UpdatedAt = time.Now() if err := s.certRepo.Update(ctx, cert); err != nil { - fmt.Printf("failed to update cert %s status to %s: %v\n", cert.ID, newStatus, err) + slog.Error("failed to update cert status", "cert_id", cert.ID, "new_status", newStatus, "error", err) } } @@ -290,13 +292,15 @@ func (s *RenewalService) processRenewalAgentKeygen(ctx context.Context, job *dom cert.Status = domain.CertificateStatusRenewalInProgress cert.UpdatedAt = time.Now() if err := s.certRepo.Update(ctx, cert); err != nil { - fmt.Printf("failed to update cert status for %s: %v\n", cert.ID, err) + slog.Error("failed to update cert status", "cert_id", cert.ID, "error", err) } // Record audit event - _ = s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, + if auditErr := s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, "renewal_awaiting_csr", "certificate", job.CertificateID, - map[string]interface{}{"job_id": job.ID, "keygen_mode": "agent"}) + map[string]interface{}{"job_id": job.ID, "keygen_mode": "agent"}); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } return nil } @@ -343,10 +347,14 @@ func (s *RenewalService) processRenewalServerKeygen(ctx context.Context, job *do result, err := connector.RenewCertificate(ctx, cert.CommonName, cert.SANs, csrPEM) if err != nil { s.failJob(ctx, job, fmt.Sprintf("issuer renewal failed: %v", err)) - _ = s.notificationSvc.SendRenewalNotification(ctx, cert, false, err) - _ = s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, + if notifErr := s.notificationSvc.SendRenewalNotification(ctx, cert, false, err); notifErr != nil { + slog.Error("failed to send renewal failure notification", "error", notifErr) + } + if auditErr := s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, "renewal_job_failed", "certificate", job.CertificateID, - map[string]interface{}{"job_id": job.ID, "error": err.Error()}) + map[string]interface{}{"job_id": job.ID, "error": err.Error()}); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } return fmt.Errorf("issuer renewal failed: %w", err) } @@ -392,18 +400,20 @@ func (s *RenewalService) processRenewalServerKeygen(ctx context.Context, job *do // Send success notification if err := s.notificationSvc.SendRenewalNotification(ctx, cert, true, nil); err != nil { - fmt.Printf("failed to send renewal notification: %v\n", err) + slog.Error("failed to send renewal notification", "error", err) } // Record audit event - _ = s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, + if auditErr := s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, "renewal_job_completed", "certificate", job.CertificateID, map[string]interface{}{ "job_id": job.ID, "serial": result.Serial, "not_after": result.NotAfter, "keygen_mode": "server", - }) + }); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } return nil } @@ -427,10 +437,14 @@ func (s *RenewalService) CompleteAgentCSRRenewal(ctx context.Context, job *domai result, err := connector.RenewCertificate(ctx, cert.CommonName, cert.SANs, csrPEM) if err != nil { s.failJob(ctx, job, fmt.Sprintf("issuer signing failed: %v", err)) - _ = s.notificationSvc.SendRenewalNotification(ctx, cert, false, err) - _ = s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, + if notifErr := s.notificationSvc.SendRenewalNotification(ctx, cert, false, err); notifErr != nil { + slog.Error("failed to send renewal failure notification", "error", notifErr) + } + if auditErr := s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, "renewal_job_failed", "certificate", job.CertificateID, - map[string]interface{}{"job_id": job.ID, "error": err.Error()}) + map[string]interface{}{"job_id": job.ID, "error": err.Error()}); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } return fmt.Errorf("issuer signing failed: %w", err) } @@ -475,18 +489,20 @@ func (s *RenewalService) CompleteAgentCSRRenewal(ctx context.Context, job *domai // Send success notification if err := s.notificationSvc.SendRenewalNotification(ctx, cert, true, nil); err != nil { - fmt.Printf("failed to send renewal notification: %v\n", err) + slog.Error("failed to send renewal notification", "error", err) } // Record audit event - _ = s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, + if auditErr := s.auditService.RecordEvent(ctx, "system", domain.ActorTypeSystem, "renewal_job_completed", "certificate", cert.ID, map[string]interface{}{ "job_id": job.ID, "serial": result.Serial, "not_after": result.NotAfter, "keygen_mode": "agent", - }) + }); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } return nil } @@ -509,7 +525,7 @@ func (s *RenewalService) createDeploymentJobs(ctx context.Context, cert *domain. CreatedAt: time.Now(), } if err := s.jobRepo.Create(ctx, deployJob); err != nil { - fmt.Printf("failed to create deployment job for target %s: %v\n", targetID, err) + slog.Error("failed to create deployment job for target", "target_id", targetID, "error", err) } } } @@ -532,7 +548,7 @@ func (s *RenewalService) GetAwaitingCSRJobs(ctx context.Context, certID string) // failJob is a helper to mark a job as failed with an error message. func (s *RenewalService) failJob(ctx context.Context, job *domain.Job, errMsg string) { if updateErr := s.jobRepo.UpdateStatus(ctx, job.ID, domain.JobStatusFailed, errMsg); updateErr != nil { - fmt.Printf("failed to update job status: %v\n", updateErr) + slog.Error("failed to update job status", "job_id", job.ID, "error", updateErr) } } @@ -565,7 +581,7 @@ func (s *RenewalService) RetryFailedJobs(ctx context.Context, maxRetries int) er // Reset status to pending for retry if err := s.jobRepo.UpdateStatus(ctx, job.ID, domain.JobStatusPending, ""); err != nil { - fmt.Printf("failed to reset job status for retry: %v\n", err) + slog.Error("failed to reset job status for retry", "job_id", job.ID, "error", err) continue } } diff --git a/internal/service/target.go b/internal/service/target.go index 79396d4..9785599 100644 --- a/internal/service/target.go +++ b/internal/service/target.go @@ -3,6 +3,7 @@ package service import ( "context" "fmt" + "log/slog" "time" "github.com/shankar0123/certctl/internal/domain" @@ -81,7 +82,9 @@ func (s *TargetService) Create(ctx context.Context, target *domain.DeploymentTar } if s.auditService != nil { - _ = s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "create_target", "target", target.ID, nil) + if auditErr := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "create_target", "target", target.ID, nil); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } } return nil @@ -99,7 +102,9 @@ func (s *TargetService) Update(ctx context.Context, id string, target *domain.De } if s.auditService != nil { - _ = s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "update_target", "target", id, nil) + if auditErr := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "update_target", "target", id, nil); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } } return nil @@ -112,7 +117,9 @@ func (s *TargetService) Delete(ctx context.Context, id string, actor string) err } if s.auditService != nil { - _ = s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "delete_target", "target", id, nil) + if auditErr := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "delete_target", "target", id, nil); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } } return nil diff --git a/internal/service/team.go b/internal/service/team.go index de4fd3b..eed0c77 100644 --- a/internal/service/team.go +++ b/internal/service/team.go @@ -3,6 +3,7 @@ package service import ( "context" "fmt" + "log/slog" "time" "github.com/shankar0123/certctl/internal/domain" @@ -81,7 +82,9 @@ func (s *TeamService) Create(ctx context.Context, team *domain.Team, actor strin } if s.auditService != nil { - _ = s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "create_team", "team", team.ID, nil) + if auditErr := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "create_team", "team", team.ID, nil); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } } return nil @@ -99,7 +102,9 @@ func (s *TeamService) Update(ctx context.Context, id string, team *domain.Team, } if s.auditService != nil { - _ = s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "update_team", "team", id, nil) + if auditErr := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "update_team", "team", id, nil); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } } return nil @@ -112,7 +117,9 @@ func (s *TeamService) Delete(ctx context.Context, id string, actor string) error } if s.auditService != nil { - _ = s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "delete_team", "team", id, nil) + if auditErr := s.auditService.RecordEvent(ctx, actor, domain.ActorTypeUser, "delete_team", "team", id, nil); auditErr != nil { + slog.Error("failed to record audit event", "error", auditErr) + } } return nil