#11: implement MTA-STS, TLS-RPT & Autoconfig HTTP services
This commit is contained in:
1 parent
c0042ef207
commit
314eb67dda
20 files changed
+1177
-31
No files matched your search
@@ -0,0 +1,79 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
|
||||
"lambdamail/protocols/internal/domain/entity"
|
||||
)
|
||||
|
||||
type ReportRepository struct {
|
||||
pool *pgxpool.Pool
|
||||
}
|
||||
|
||||
func NewReportRepository(pool *pgxpool.Pool) *ReportRepository {
|
||||
return &ReportRepository{pool: pool}
|
||||
}
|
||||
|
||||
func (r *ReportRepository) SaveDmarcReport(ctx context.Context, report *entity.DmarcReport) error {
|
||||
tx, err := r.pool.Begin(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("begin tx: %w", err)
|
||||
}
|
||||
defer tx.Rollback(ctx)
|
||||
|
||||
var reportID uuid.UUID
|
||||
err = tx.QueryRow(ctx, `
|
||||
INSERT INTO dmarc_reports (org_name, report_id, domain, date_range_begin, date_range_end)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id
|
||||
`, report.OrgName, report.ReportID, report.Domain, report.DateRangeBegin, report.DateRangeEnd).Scan(&reportID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("insert dmarc report header: %w", err)
|
||||
}
|
||||
|
||||
for _, rec := range report.Records {
|
||||
_, err := tx.Exec(ctx, `
|
||||
INSERT INTO dmarc_report_records (report_id, source_ip, count, disposition, dkim_result, spf_result, header_from)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
`, reportID, rec.SourceIP, rec.Count, rec.Disposition, rec.DKIMResult, rec.SPFResult, rec.HeaderFrom)
|
||||
if err != nil {
|
||||
return fmt.Errorf("insert dmarc record: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit(ctx)
|
||||
}
|
||||
|
||||
func (r *ReportRepository) SaveTlsRptReport(ctx context.Context, report *entity.TlsRptReport) error {
|
||||
tx, err := r.pool.Begin(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("begin tx: %w", err)
|
||||
}
|
||||
defer tx.Rollback(ctx)
|
||||
|
||||
var reportID uuid.UUID
|
||||
err = tx.QueryRow(ctx, `
|
||||
INSERT INTO tls_rpt_reports (organization_name, report_id, domain, date_range_begin, date_range_end)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id
|
||||
`, report.OrganizationName, report.ReportID, report.Domain, report.DateRangeBegin, report.DateRangeEnd).Scan(&reportID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("insert tls-rpt report header: %w", err)
|
||||
}
|
||||
|
||||
for _, pol := range report.Policies {
|
||||
_, err := tx.Exec(ctx, `
|
||||
INSERT INTO tls_rpt_report_policies (report_id, policy_type, success_count, failure_count)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
`, reportID, pol.PolicyType, pol.SuccessCount, pol.FailureCount)
|
||||
if err != nil {
|
||||
return fmt.Errorf("insert tls-rpt policy: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return tx.Commit(ctx)
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"lambdamail/protocols/internal/domain/entity"
|
||||
)
|
||||
|
||||
func TestReportRepository_SaveDmarcAndTlsRpt(t *testing.T) {
|
||||
dbURL := os.Getenv("TEST_DATABASE_URL")
|
||||
if dbURL == "" {
|
||||
t.Skip("TEST_DATABASE_URL not set - skipping Postgres integration test")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
pool, err := NewPool(ctx, dbURL)
|
||||
if err != nil {
|
||||
t.Fatalf("connect pool: %v", err)
|
||||
}
|
||||
defer pool.Close()
|
||||
|
||||
repo := NewReportRepository(pool)
|
||||
|
||||
// Save DMARC
|
||||
dmarc := &entity.DmarcReport{
|
||||
OrgName: "google.com",
|
||||
ReportID: "r123",
|
||||
Domain: "example.test",
|
||||
DateRangeBegin: time.Now().Add(-24 * time.Hour),
|
||||
DateRangeEnd: time.Now(),
|
||||
Records: []entity.DmarcRecord{
|
||||
{SourceIP: "192.0.2.1", Count: 5, Disposition: "none", DKIMResult: "pass", SPFResult: "pass", HeaderFrom: "example.test"},
|
||||
},
|
||||
}
|
||||
|
||||
if err := repo.SaveDmarcReport(ctx, dmarc); err != nil {
|
||||
t.Fatalf("SaveDmarcReport: %v", err)
|
||||
}
|
||||
|
||||
// Save TLS-RPT
|
||||
tlsRpt := &entity.TlsRptReport{
|
||||
OrganizationName: "Google LLC",
|
||||
ReportID: "tr123",
|
||||
Domain: "example.test",
|
||||
DateRangeBegin: time.Now().Add(-24 * time.Hour),
|
||||
DateRangeEnd: time.Now(),
|
||||
Policies: []entity.TlsRptPolicy{
|
||||
{PolicyType: "sts", SuccessCount: 10, FailureCount: 0},
|
||||
},
|
||||
}
|
||||
|
||||
if err := repo.SaveTlsRptReport(ctx, tlsRpt); err != nil {
|
||||
t.Fatalf("SaveTlsRptReport: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user