rdev/internal/logging/redact.go
jordan d69da6d627 feat: add structured logging infrastructure and SDLC extensions
Major changes:
- Add internal/logging package with field constants, context propagation,
  sensitive data auto-redaction, and per-component log levels
- Add worker timeout constants (TimeoutQuickOp, TimeoutHealthCheck, etc.)
- Extend SDLC with callback handlers, generate endpoints, and executor
- Add new cookbook trees for aeries and slackpath progression
- Add skeleton templates for queue, realtime, and microservices
- Add worker component template with async job processing
- Refactor services and handlers to use new logging infrastructure
- Split component.go into component_infra.go and component_listing.go

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 22:56:04 -07:00

121 lines
3.1 KiB
Go

package logging
import (
"regexp"
"strings"
)
// RedactedValue is the replacement string for sensitive data.
const RedactedValue = "[REDACTED]"
// sensitiveFieldPatterns are field name patterns that indicate sensitive data.
// These are matched case-insensitively.
var sensitiveFieldPatterns = []string{
"password",
"passwd",
"secret",
"token",
"api_key",
"apikey",
"api-key",
"auth",
"bearer",
"credential",
"private",
"key",
"cert",
"certificate",
}
// sensitiveValuePatterns are regex patterns to detect sensitive values.
var sensitiveValuePatterns = []*regexp.Regexp{
// Bearer tokens
regexp.MustCompile(`(?i)bearer\s+[a-zA-Z0-9\-_.~+/]+=*`),
// API keys (common formats)
regexp.MustCompile(`(?i)(?:api[_-]?key|token|secret)[=:]\s*["']?[a-zA-Z0-9\-_.~+/]{16,}["']?`),
// AWS access keys
regexp.MustCompile(`AKIA[0-9A-Z]{16}`),
// Private keys
regexp.MustCompile(`-----BEGIN [A-Z]+ PRIVATE KEY-----`),
// Connection strings with passwords (supports empty username like redis://:pass@host)
regexp.MustCompile(`(?i)(?:postgres|mysql|mongodb|redis)://[^:]*:[^@]+@`),
// JWT tokens (three base64 parts separated by dots)
regexp.MustCompile(`eyJ[a-zA-Z0-9\-_]+\.eyJ[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+`),
}
// exactSensitiveFields are field names that are always sensitive.
var exactSensitiveFields = map[string]bool{
"password": true,
"passwd": true,
"secret": true,
"token": true,
"api_key": true,
"apikey": true,
"api-key": true,
"bearer": true,
"authorization": true,
"auth_token": true,
"access_token": true,
"refresh_token": true,
"private_key": true,
"secret_key": true,
"encryption_key": true,
"signing_key": true,
"client_secret": true,
"cookie": true,
"session": true,
"session_id": true,
"x-api-key": true,
"x-auth-token": true,
"credentials": true,
"credit_card": true,
"cc_number": true,
"cvv": true,
"ssn": true,
"social_security": true,
"bank_account": true,
"routing_number": true,
"cloudflare_token": true,
"gitea_token": true,
"woodpecker_secret": true,
}
// IsSensitiveField checks if a field name indicates sensitive data.
func IsSensitiveField(fieldName string) bool {
lower := strings.ToLower(fieldName)
// Check exact matches first (fast path)
if exactSensitiveFields[lower] {
return true
}
// Check pattern matches
for _, pattern := range sensitiveFieldPatterns {
if strings.Contains(lower, pattern) {
return true
}
}
return false
}
// RedactValue redacts a value if it matches sensitive patterns.
func RedactValue(value string) string {
for _, pattern := range sensitiveValuePatterns {
if pattern.MatchString(value) {
return RedactedValue
}
}
return value
}
// ContainsSensitiveData checks if a string contains sensitive data patterns.
func ContainsSensitiveData(value string) bool {
for _, pattern := range sensitiveValuePatterns {
if pattern.MatchString(value) {
return true
}
}
return false
}