Overloading .debug/.error for ‘.logSecurityEvent’

Search/Replace Strategies:

1.
Search regex: `SecureLogger\.logSecurityEvent\(\s*(.*?),\s*level:\s*\.(\w+)\s*\)`
Replace regex: `SecureLogger.$2($1)`

Sample input:
`SecureLogger.logSecurityEvent(.authenticationFailed(peerID: peerID), level: .warning)`

Sample output:
`SecureLogger.warning(.authenticationFailed(peerID: peerID))`

---

2.
Search regex: `SecureLogger\.logSecurityEvent\(\s*(.*?)\s*\)`
Replace regex: `SecureLogger.info($1)`  (`info` is the default level)

Sample input:
`SecureLogger.logSecurityEvent(.handshakeStarted(peerID: peerID))`

Sample output:
`SecureLogger.info(.handshakeStarted(peerID: peerID))`
This commit is contained in:
islam
2025-09-11 19:03:08 +01:00
parent b5382b129e
commit e5a415d885
4 changed files with 48 additions and 30 deletions
+1 -1
View File
@@ -678,7 +678,7 @@ final class NoiseHandshakeState {
let decrypted = try symmetricState.decryptAndHash(staticData) let decrypted = try symmetricState.decryptAndHash(staticData)
remoteStaticPublic = try NoiseHandshakeState.validatePublicKey(decrypted) remoteStaticPublic = try NoiseHandshakeState.validatePublicKey(decrypted)
} catch { } catch {
SecureLogger.logSecurityEvent(.authenticationFailed(peerID: "Unknown - handshake"), level: .error) SecureLogger.error(.authenticationFailed(peerID: "Unknown - handshake"))
throw NoiseError.authenticationFailure throw NoiseError.authenticationFailure
} }
+6 -6
View File
@@ -131,7 +131,7 @@ class NoiseSession {
handshakeState = nil // Clear handshake state handshakeState = nil // Clear handshake state
SecureLogger.debug("NoiseSession[\(peerID)]: Handshake complete (no response needed), transitioning to established", category: .noise) SecureLogger.debug("NoiseSession[\(peerID)]: Handshake complete (no response needed), transitioning to established", category: .noise)
SecureLogger.logSecurityEvent(.handshakeCompleted(peerID: peerID)) SecureLogger.info(.handshakeCompleted(peerID: peerID))
return nil return nil
} else { } else {
@@ -157,7 +157,7 @@ class NoiseSession {
handshakeState = nil // Clear handshake state handshakeState = nil // Clear handshake state
SecureLogger.debug("NoiseSession[\(peerID)]: Handshake complete after writing response, transitioning to established", category: .noise) SecureLogger.debug("NoiseSession[\(peerID)]: Handshake complete after writing response, transitioning to established", category: .noise)
SecureLogger.logSecurityEvent(.handshakeCompleted(peerID: peerID)) SecureLogger.info(.handshakeCompleted(peerID: peerID))
} }
return response return response
@@ -242,7 +242,7 @@ class NoiseSession {
handshakeHash = nil handshakeHash = nil
if wasEstablished { if wasEstablished {
SecureLogger.logSecurityEvent(.sessionExpired(peerID: peerID)) SecureLogger.info(.sessionExpired(peerID: peerID))
} }
} }
} }
@@ -287,7 +287,7 @@ final class NoiseSessionManager {
managerQueue.sync(flags: .barrier) { managerQueue.sync(flags: .barrier) {
if let session = sessions[peerID] { if let session = sessions[peerID] {
if session.isEstablished() { if session.isEstablished() {
SecureLogger.logSecurityEvent(.sessionExpired(peerID: peerID)) SecureLogger.info(.sessionExpired(peerID: peerID))
} }
// Clear sensitive data before removing // Clear sensitive data before removing
session.reset() session.reset()
@@ -331,7 +331,7 @@ final class NoiseSessionManager {
} catch { } catch {
// Clean up failed session // Clean up failed session
_ = sessions.removeValue(forKey: peerID) _ = sessions.removeValue(forKey: peerID)
SecureLogger.logSecurityEvent(.handshakeFailed(peerID: peerID, error: error.localizedDescription), level: .error) SecureLogger.error(.handshakeFailed(peerID: peerID, error: error.localizedDescription))
throw error throw error
} }
} }
@@ -403,7 +403,7 @@ final class NoiseSessionManager {
self?.onSessionFailed?(peerID, error) self?.onSessionFailed?(peerID, error)
} }
SecureLogger.logSecurityEvent(.handshakeFailed(peerID: peerID, error: error.localizedDescription), level: .error) SecureLogger.error(.handshakeFailed(peerID: peerID, error: error.localizedDescription))
throw error throw error
} }
} }
@@ -392,17 +392,17 @@ final class NoiseEncryptionService {
// Validate peer ID // Validate peer ID
guard NoiseSecurityValidator.validatePeerID(peerID) else { guard NoiseSecurityValidator.validatePeerID(peerID) else {
SecureLogger.logSecurityEvent(.authenticationFailed(peerID: peerID), level: .warning) SecureLogger.warning(.authenticationFailed(peerID: peerID))
throw NoiseSecurityError.invalidPeerID throw NoiseSecurityError.invalidPeerID
} }
// Check rate limit // Check rate limit
guard rateLimiter.allowHandshake(from: peerID) else { guard rateLimiter.allowHandshake(from: peerID) else {
SecureLogger.logSecurityEvent(.authenticationFailed(peerID: "Rate limited: \(peerID)"), level: .warning) SecureLogger.warning(.authenticationFailed(peerID: "Rate limited: \(peerID)"))
throw NoiseSecurityError.rateLimitExceeded throw NoiseSecurityError.rateLimitExceeded
} }
SecureLogger.logSecurityEvent(.handshakeStarted(peerID: peerID)) SecureLogger.info(.handshakeStarted(peerID: peerID))
// Return raw handshake data without wrapper // Return raw handshake data without wrapper
// The Noise protocol handles its own message format // The Noise protocol handles its own message format
@@ -415,19 +415,19 @@ final class NoiseEncryptionService {
// Validate peer ID // Validate peer ID
guard NoiseSecurityValidator.validatePeerID(peerID) else { guard NoiseSecurityValidator.validatePeerID(peerID) else {
SecureLogger.logSecurityEvent(.authenticationFailed(peerID: peerID), level: .warning) SecureLogger.warning(.authenticationFailed(peerID: peerID))
throw NoiseSecurityError.invalidPeerID throw NoiseSecurityError.invalidPeerID
} }
// Validate message size // Validate message size
guard NoiseSecurityValidator.validateHandshakeMessageSize(message) else { guard NoiseSecurityValidator.validateHandshakeMessageSize(message) else {
SecureLogger.logSecurityEvent(.handshakeFailed(peerID: peerID, error: "Message too large"), level: .warning) SecureLogger.warning(.handshakeFailed(peerID: peerID, error: "Message too large"))
throw NoiseSecurityError.messageTooLarge throw NoiseSecurityError.messageTooLarge
} }
// Check rate limit // Check rate limit
guard rateLimiter.allowHandshake(from: peerID) else { guard rateLimiter.allowHandshake(from: peerID) else {
SecureLogger.logSecurityEvent(.authenticationFailed(peerID: "Rate limited: \(peerID)"), level: .warning) SecureLogger.warning(.authenticationFailed(peerID: "Rate limited: \(peerID)"))
throw NoiseSecurityError.rateLimitExceeded throw NoiseSecurityError.rateLimitExceeded
} }
@@ -521,7 +521,7 @@ final class NoiseEncryptionService {
peerFingerprints.removeValue(forKey: peerID) peerFingerprints.removeValue(forKey: peerID)
} }
SecureLogger.logSecurityEvent(.sessionExpired(peerID: peerID)) SecureLogger.info(.sessionExpired(peerID: peerID))
} }
// MARK: - Private Helpers // MARK: - Private Helpers
@@ -537,7 +537,7 @@ final class NoiseEncryptionService {
} }
// Log security event // Log security event
SecureLogger.logSecurityEvent(.handshakeCompleted(peerID: peerID)) SecureLogger.info(.handshakeCompleted(peerID: peerID))
// Notify all handlers about authentication // Notify all handlers about authentication
serviceQueue.async { [weak self] in serviceQueue.async { [weak self] in
+33 -15
View File
@@ -133,6 +133,24 @@ final class SecureLogger {
log(message(), category: category, level: .error, file: file, line: line, function: function) log(message(), category: category, level: .error, file: file, line: line, function: function)
} }
// MARK: Security Event Logging
static func debug(_ event: SecurityEvent, file: String = #file, line: Int = #line, function: String = #function) {
logSecurityEvent(event, level: .debug, file: file, line: line, function: function)
}
static func info(_ event: SecurityEvent, file: String = #file, line: Int = #line, function: String = #function) {
logSecurityEvent(event, level: .info, file: file, line: line, function: function)
}
static func warning(_ event: SecurityEvent, file: String = #file, line: Int = #line, function: String = #function) {
logSecurityEvent(event, level: .warning, file: file, line: line, function: function)
}
static func error(_ event: SecurityEvent, file: String = #file, line: Int = #line, function: String = #function) {
logSecurityEvent(event, level: .error, file: file, line: line, function: function)
}
/// Log errors with context /// Log errors with context
static func error(_ error: Error, context: @autoclosure () -> String, category: OSLog = .noise, static func error(_ error: Error, context: @autoclosure () -> String, category: OSLog = .noise,
file: String = #file, line: Int = #line, function: String = #function) { file: String = #file, line: Int = #line, function: String = #function) {
@@ -147,21 +165,6 @@ final class SecureLogger {
#endif #endif
} }
/// Log a security event
static func logSecurityEvent(_ event: SecurityEvent, level: LogLevel = .info,
file: String = #file, line: Int = #line, function: String = #function) {
guard shouldLog(level) else { return }
let location = formatLocation(file: file, line: line, function: function)
let message = "\(location) \(event.message)"
#if DEBUG
os_log("%{public}@", log: .security, type: level.osLogType, message)
#else
// In release, use private logging to prevent sensitive data exposure
os_log("%{private}@", log: .security, type: level.osLogType, message)
#endif
}
// MARK: - Private Helpers // MARK: - Private Helpers
/// Log general messages with automatic sensitive data filtering /// Log general messages with automatic sensitive data filtering
@@ -181,6 +184,21 @@ final class SecureLogger {
#endif #endif
} }
/// Log a security event
private static func logSecurityEvent(_ event: SecurityEvent, level: LogLevel = .info,
file: String, line: Int, function: String) {
guard shouldLog(level) else { return }
let location = formatLocation(file: file, line: line, function: function)
let message = "\(location) \(event.message)"
#if DEBUG
os_log("%{public}@", log: .security, type: level.osLogType, message)
#else
// In release, use private logging to prevent sensitive data exposure
os_log("%{private}@", log: .security, type: level.osLogType, message)
#endif
}
/// Format location information for logging /// Format location information for logging
private static func formatLocation(file: String, line: Int, function: String) -> String { private static func formatLocation(file: String, line: Int, function: String) -> String {
let fileName = (file as NSString).lastPathComponent let fileName = (file as NSString).lastPathComponent