Smail/server/config/sensitive.go

84 lines
2.4 KiB
Go

package config
import "strings"
type PersistencePolicy string
const (
PersistenceEncryptedOnly PersistencePolicy = "encrypted_only"
PersistenceReferenceOnly PersistencePolicy = "reference_only"
PersistenceMemoryOnly PersistencePolicy = "memory_only"
)
type SensitiveField struct {
Path string
Policy PersistencePolicy
}
var sensitiveFields = []SensitiveField{
{Path: "database.password", Policy: PersistenceEncryptedOnly},
{Path: "smtp.relay.password", Policy: PersistenceEncryptedOnly},
{Path: "plugins.*.token", Policy: PersistenceEncryptedOnly},
{Path: "plugins.*.secret", Policy: PersistenceEncryptedOnly},
{Path: "plugins.*.api_key", Policy: PersistenceEncryptedOnly},
{Path: "ssl.private_key", Policy: PersistenceReferenceOnly},
{Path: "security.encryption_master_key", Policy: PersistenceReferenceOnly},
{Path: "security.question_answer", Policy: PersistenceEncryptedOnly},
{Path: "security.offline_recovery_code", Policy: PersistenceEncryptedOnly},
{Path: "security.maintenance_credential", Policy: PersistenceMemoryOnly},
{Path: "verification.code", Policy: PersistenceMemoryOnly},
{Path: "verification.code_hmac", Policy: PersistenceMemoryOnly},
{Path: "verification.process_key", Policy: PersistenceMemoryOnly},
{Path: "recovery.authorization", Policy: PersistenceMemoryOnly},
}
func SensitiveFields() []SensitiveField {
result := make([]SensitiveField, len(sensitiveFields))
copy(result, sensitiveFields)
return result
}
func ClassifySensitive(path string) (SensitiveField, bool) {
path = strings.TrimSpace(path)
for _, field := range sensitiveFields {
if matchSensitivePath(field.Path, path) {
return field, true
}
}
return SensitiveField{}, false
}
func CanGenericSerialize(path string) bool {
_, sensitive := ClassifySensitive(path)
return !sensitive
}
func CanPersist(path string, encrypted bool) bool {
field, sensitive := ClassifySensitive(path)
if !sensitive {
return true
}
switch field.Policy {
case PersistenceEncryptedOnly:
return encrypted
case PersistenceReferenceOnly, PersistenceMemoryOnly:
return false
default:
return false
}
}
func matchSensitivePath(pattern string, value string) bool {
patternParts := strings.Split(pattern, ".")
valueParts := strings.Split(value, ".")
if len(patternParts) != len(valueParts) {
return false
}
for i := range patternParts {
if patternParts[i] != "*" && patternParts[i] != valueParts[i] {
return false
}
}
return true
}