Files
query-orchestration/cmd/auth_related/user.creation.tool/audit.go
T

142 lines
4.0 KiB
Go
Raw Normal View History

// audit.go provides comprehensive audit trail logging functionality for compliance and monitoring.
// This file now uses the `log/slog` structured logging package introduced in Go 1.21.
// A single environment variable LOG_FORMAT controls the output format:
//
// LOG_FORMAT=text -> humanreadable text (default)
// LOG_FORMAT=json -> JSON
//
// The public API (type AuditLogger and all its methods) is unchanged, so no callsites
// (e.g. cognito-permit-sync.go) need to be modified.
package main
import (
"context"
"log/slog"
"os"
)
const envLogFormat = "LOG_FORMAT"
// AuditLogger handles audittrail logging for compliance.
type AuditLogger struct {
logger *slog.Logger
file *os.File
}
// NewAuditLogger initializes the audit logger.
// The signature is unchanged: pass isDryRun=true to write to dry-run-audit.log;
// otherwise logs are appended to audit.log in the working directory.
func NewAuditLogger(isDryRun bool) (*AuditLogger, error) {
filename := "audit.log"
if isDryRun {
filename = "dry-run-audit.log"
}
file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
return nil, err
}
// Choose handler based on LOG_FORMAT
var handler slog.Handler
switch os.Getenv(envLogFormat) {
case "json":
handler = slog.NewJSONHandler(file, &slog.HandlerOptions{AddSource: false})
default: // "text" or unset
handler = slog.NewTextHandler(file, &slog.HandlerOptions{AddSource: false})
}
logger := slog.New(handler)
return &AuditLogger{
logger: logger,
file: file,
}, nil
}
// Close closes the underlying audit file.
func (a *AuditLogger) Close() error {
if a.file != nil {
return a.file.Close()
}
return nil
}
// ----- Public logging helpers ------------------------------------------------
// ActionType represents the type of action being logged.
type ActionType string
const (
ActionCreate ActionType = "CREATE"
ActionDelete ActionType = "DELETE"
ActionDisable ActionType = "DISABLE"
ActionEnable ActionType = "ENABLE"
ActionAssignRole ActionType = "ASSIGN_ROLE"
ActionUnassignRole ActionType = "UNASSIGN_ROLE"
ActionUpdate ActionType = "UPDATE"
ActionSkip ActionType = "SKIP"
)
// SystemType represents the system where the action occurred.
type SystemType string
const (
SystemCognito SystemType = "COGNITO"
SystemPermit SystemType = "PERMIT"
)
// ResultType represents the outcome of the action.
type ResultType string
const (
ResultSuccess ResultType = "SUCCESS"
ResultFailure ResultType = "FAILURE"
ResultSkipped ResultType = "SKIPPED"
)
// LogAction logs a generic action (without subjectID or role).
func (a *AuditLogger) LogAction(action ActionType, system SystemType, userEmail string, result ResultType, details string) {
a.logger.InfoContext(context.TODO(), "audit_event",
"action", action,
"system", system,
"userEmail", userEmail,
"result", result,
"details", details,
)
}
// LogActionWithSubjectID logs an action involving a specific subject identifier.
func (a *AuditLogger) LogActionWithSubjectID(action ActionType, system SystemType, userEmail, subjectID string, result ResultType, details string) {
a.logger.InfoContext(context.TODO(), "audit_event",
"action", action,
"system", system,
"userEmail", userEmail,
"subjectID", subjectID,
"result", result,
"details", details,
)
}
// LogRoleAction logs role assignment/unassignment activities.
func (a *AuditLogger) LogRoleAction(action ActionType, userEmail, role string, result ResultType, details string) {
a.logger.InfoContext(context.TODO(), "audit_event",
"action", action,
"system", SystemPermit,
"userEmail", userEmail,
"role", role,
"result", result,
"details", details,
)
}
// LogDryRunStart marks the beginning of a dryrun execution.
func (a *AuditLogger) LogDryRunStart() {
a.logger.InfoContext(context.TODO(), "dry_run_start")
}
// LogDryRunEnd marks the completion of a dryrun execution.
func (a *AuditLogger) LogDryRunEnd() {
a.logger.InfoContext(context.TODO(), "dry_run_end")
}