Files
certctl/internal/service/policy_test.go
T
shankar0123 66f04f7afe style: run gofmt -s across all Go files
Fixes Go Report Card gofmt score from 52% to 100%.
Pure formatting changes — no logic modifications.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 19:32:29 -04:00

423 lines
10 KiB
Go

package service
import (
"context"
"encoding/json"
"testing"
"time"
"github.com/shankar0123/certctl/internal/domain"
)
func TestCreateRule(t *testing.T) {
ctx := context.Background()
policyRepo := &mockPolicyRepo{
Rules: make(map[string]*domain.PolicyRule),
Violations: []*domain.PolicyViolation{},
}
auditRepo := &mockAuditRepo{Events: []*domain.AuditEvent{}}
auditService := NewAuditService(auditRepo)
policyService := NewPolicyService(policyRepo, auditService)
config := map[string]interface{}{"issuers": []string{"iss-acme"}}
configJSON, _ := json.Marshal(config)
rule := &domain.PolicyRule{
ID: "rule-001",
Name: "Allowed Issuers",
Type: domain.PolicyTypeAllowedIssuers,
Config: configJSON,
Enabled: true,
}
err := policyService.CreateRule(ctx, rule, "user-1")
if err != nil {
t.Fatalf("CreateRule failed: %v", err)
}
if len(policyRepo.Rules) != 1 {
t.Errorf("expected 1 rule, got %d", len(policyRepo.Rules))
}
if len(auditRepo.Events) != 1 {
t.Errorf("expected 1 audit event, got %d", len(auditRepo.Events))
}
}
func TestGetRule(t *testing.T) {
ctx := context.Background()
now := time.Now()
rule := &domain.PolicyRule{
ID: "rule-001",
Name: "Allowed Issuers",
Type: domain.PolicyTypeAllowedIssuers,
Enabled: true,
CreatedAt: now,
UpdatedAt: now,
}
policyRepo := &mockPolicyRepo{
Rules: map[string]*domain.PolicyRule{"rule-001": rule},
Violations: []*domain.PolicyViolation{},
}
auditRepo := &mockAuditRepo{}
auditService := NewAuditService(auditRepo)
policyService := NewPolicyService(policyRepo, auditService)
retrieved, err := policyService.GetRule(ctx, "rule-001")
if err != nil {
t.Fatalf("GetRule failed: %v", err)
}
if retrieved.Name != "Allowed Issuers" {
t.Errorf("expected name Allowed Issuers, got %s", retrieved.Name)
}
}
func TestGetRule_NotFound(t *testing.T) {
ctx := context.Background()
policyRepo := &mockPolicyRepo{
Rules: make(map[string]*domain.PolicyRule),
Violations: []*domain.PolicyViolation{},
}
auditRepo := &mockAuditRepo{}
auditService := NewAuditService(auditRepo)
policyService := NewPolicyService(policyRepo, auditService)
_, err := policyService.GetRule(ctx, "nonexistent")
if err == nil {
t.Fatal("expected error for nonexistent rule")
}
}
func TestListRules(t *testing.T) {
ctx := context.Background()
now := time.Now()
rule1 := &domain.PolicyRule{
ID: "rule-001",
Name: "Allowed Issuers",
Type: domain.PolicyTypeAllowedIssuers,
Enabled: true,
CreatedAt: now,
UpdatedAt: now,
}
rule2 := &domain.PolicyRule{
ID: "rule-002",
Name: "Required Metadata",
Type: domain.PolicyTypeRequiredMetadata,
Enabled: true,
CreatedAt: now,
UpdatedAt: now,
}
policyRepo := &mockPolicyRepo{
Rules: map[string]*domain.PolicyRule{"rule-001": rule1, "rule-002": rule2},
Violations: []*domain.PolicyViolation{},
}
auditRepo := &mockAuditRepo{}
auditService := NewAuditService(auditRepo)
policyService := NewPolicyService(policyRepo, auditService)
rules, err := policyService.ListRules(ctx)
if err != nil {
t.Fatalf("ListRules failed: %v", err)
}
if len(rules) != 2 {
t.Errorf("expected 2 rules, got %d", len(rules))
}
}
func TestUpdateRule(t *testing.T) {
ctx := context.Background()
now := time.Now()
originalRule := &domain.PolicyRule{
ID: "rule-001",
Name: "Allowed Issuers",
Type: domain.PolicyTypeAllowedIssuers,
Enabled: true,
CreatedAt: now,
UpdatedAt: now,
}
policyRepo := &mockPolicyRepo{
Rules: map[string]*domain.PolicyRule{"rule-001": originalRule},
Violations: []*domain.PolicyViolation{},
}
auditRepo := &mockAuditRepo{Events: []*domain.AuditEvent{}}
auditService := NewAuditService(auditRepo)
policyService := NewPolicyService(policyRepo, auditService)
updatedRule := *originalRule
updatedRule.Enabled = false
err := policyService.UpdateRule(ctx, &updatedRule, "user-1")
if err != nil {
t.Fatalf("UpdateRule failed: %v", err)
}
stored := policyRepo.Rules["rule-001"]
if stored.Enabled {
t.Error("expected rule to be disabled")
}
if len(auditRepo.Events) != 1 {
t.Errorf("expected 1 audit event, got %d", len(auditRepo.Events))
}
}
func TestDeleteRule(t *testing.T) {
ctx := context.Background()
now := time.Now()
rule := &domain.PolicyRule{
ID: "rule-001",
Name: "Allowed Issuers",
Type: domain.PolicyTypeAllowedIssuers,
Enabled: true,
CreatedAt: now,
UpdatedAt: now,
}
policyRepo := &mockPolicyRepo{
Rules: map[string]*domain.PolicyRule{"rule-001": rule},
Violations: []*domain.PolicyViolation{},
}
auditRepo := &mockAuditRepo{Events: []*domain.AuditEvent{}}
auditService := NewAuditService(auditRepo)
policyService := NewPolicyService(policyRepo, auditService)
err := policyService.DeleteRule(ctx, "rule-001", "user-1")
if err != nil {
t.Fatalf("DeleteRule failed: %v", err)
}
if len(policyRepo.Rules) != 0 {
t.Errorf("expected 0 rules, got %d", len(policyRepo.Rules))
}
if len(auditRepo.Events) != 1 {
t.Errorf("expected 1 audit event, got %d", len(auditRepo.Events))
}
}
func TestValidateCertificate(t *testing.T) {
ctx := context.Background()
now := time.Now()
rule := &domain.PolicyRule{
ID: "rule-001",
Name: "Allowed Issuers",
Type: domain.PolicyTypeAllowedIssuers,
Enabled: true,
CreatedAt: now,
UpdatedAt: now,
}
policyRepo := &mockPolicyRepo{
Rules: map[string]*domain.PolicyRule{"rule-001": rule},
Violations: []*domain.PolicyViolation{},
}
auditRepo := &mockAuditRepo{}
auditService := NewAuditService(auditRepo)
policyService := NewPolicyService(policyRepo, auditService)
cert := &domain.ManagedCertificate{
ID: "cert-001",
CommonName: "example.com",
IssuerID: "iss-acme",
Status: domain.CertificateStatusActive,
ExpiresAt: now.AddDate(1, 0, 0),
CreatedAt: now,
UpdatedAt: now,
}
violations, err := policyService.ValidateCertificate(ctx, cert)
if err != nil {
t.Fatalf("ValidateCertificate failed: %v", err)
}
if len(violations) > 0 {
t.Errorf("expected no violations, got %d", len(violations))
}
}
func TestValidateCertificate_WithViolation(t *testing.T) {
ctx := context.Background()
now := time.Now()
rule := &domain.PolicyRule{
ID: "rule-001",
Name: "Allowed Issuers",
Type: domain.PolicyTypeAllowedIssuers,
Enabled: true,
CreatedAt: now,
UpdatedAt: now,
}
policyRepo := &mockPolicyRepo{
Rules: map[string]*domain.PolicyRule{"rule-001": rule},
Violations: []*domain.PolicyViolation{},
}
auditRepo := &mockAuditRepo{}
auditService := NewAuditService(auditRepo)
policyService := NewPolicyService(policyRepo, auditService)
cert := &domain.ManagedCertificate{
ID: "cert-001",
CommonName: "example.com",
IssuerID: "", // Missing issuer
Status: domain.CertificateStatusActive,
ExpiresAt: now.AddDate(1, 0, 0),
CreatedAt: now,
UpdatedAt: now,
}
violations, err := policyService.ValidateCertificate(ctx, cert)
if err != nil {
t.Fatalf("ValidateCertificate failed: %v", err)
}
if len(violations) != 1 {
t.Errorf("expected 1 violation, got %d", len(violations))
}
if violations[0].CertificateID != "cert-001" {
t.Errorf("expected violation for cert-001, got %s", violations[0].CertificateID)
}
}
func TestValidateCertificate_MultipleViolations(t *testing.T) {
ctx := context.Background()
now := time.Now()
rule1 := &domain.PolicyRule{
ID: "rule-001",
Name: "Allowed Issuers",
Type: domain.PolicyTypeAllowedIssuers,
Enabled: true,
CreatedAt: now,
UpdatedAt: now,
}
rule2 := &domain.PolicyRule{
ID: "rule-002",
Name: "Required Metadata",
Type: domain.PolicyTypeRequiredMetadata,
Enabled: true,
CreatedAt: now,
UpdatedAt: now,
}
policyRepo := &mockPolicyRepo{
Rules: map[string]*domain.PolicyRule{"rule-001": rule1, "rule-002": rule2},
Violations: []*domain.PolicyViolation{},
}
auditRepo := &mockAuditRepo{}
auditService := NewAuditService(auditRepo)
policyService := NewPolicyService(policyRepo, auditService)
cert := &domain.ManagedCertificate{
ID: "cert-001",
CommonName: "example.com",
IssuerID: "", // Missing issuer
Tags: nil, // Missing metadata
Status: domain.CertificateStatusActive,
ExpiresAt: now.AddDate(1, 0, 0),
CreatedAt: now,
UpdatedAt: now,
}
violations, err := policyService.ValidateCertificate(ctx, cert)
if err != nil {
t.Fatalf("ValidateCertificate failed: %v", err)
}
if len(violations) != 2 {
t.Errorf("expected 2 violations, got %d", len(violations))
}
}
func TestListPolicies(t *testing.T) {
now := time.Now()
rule1 := &domain.PolicyRule{
ID: "rule-001",
Name: "Rule 1",
Type: domain.PolicyTypeAllowedIssuers,
Enabled: true,
CreatedAt: now,
UpdatedAt: now,
}
rule2 := &domain.PolicyRule{
ID: "rule-002",
Name: "Rule 2",
Type: domain.PolicyTypeRequiredMetadata,
Enabled: true,
CreatedAt: now,
UpdatedAt: now,
}
policyRepo := &mockPolicyRepo{
Rules: map[string]*domain.PolicyRule{"rule-001": rule1, "rule-002": rule2},
Violations: []*domain.PolicyViolation{},
}
auditRepo := &mockAuditRepo{}
auditService := NewAuditService(auditRepo)
policyService := NewPolicyService(policyRepo, auditService)
policies, total, err := policyService.ListPolicies(1, 50)
if err != nil {
t.Fatalf("ListPolicies failed: %v", err)
}
if len(policies) != 2 {
t.Errorf("expected 2 policies, got %d", len(policies))
}
if total != 2 {
t.Errorf("expected total 2, got %d", total)
}
}
func TestCreatePolicy(t *testing.T) {
now := time.Now()
policyRepo := &mockPolicyRepo{
Rules: make(map[string]*domain.PolicyRule),
Violations: []*domain.PolicyViolation{},
}
auditRepo := &mockAuditRepo{}
auditService := NewAuditService(auditRepo)
policyService := NewPolicyService(policyRepo, auditService)
policy := domain.PolicyRule{
Name: "Test Policy",
Type: domain.PolicyTypeAllowedIssuers,
Enabled: true,
CreatedAt: now,
}
created, err := policyService.CreatePolicy(policy)
if err != nil {
t.Fatalf("CreatePolicy failed: %v", err)
}
if created.ID == "" {
t.Fatal("expected non-empty policy ID")
}
if len(policyRepo.Rules) != 1 {
t.Errorf("expected 1 rule in repo, got %d", len(policyRepo.Rules))
}
}