diff --git a/Pareto/AppHandlers.swift b/Pareto/AppHandlers.swift index 54eceda..9a1c8fb 100644 --- a/Pareto/AppHandlers.swift +++ b/Pareto/AppHandlers.swift @@ -284,6 +284,18 @@ class AppHandlers: NSObject, NetworkHandlerObserver { welcomeWindow!.makeKeyAndOrderFront(nil) } + func copyLogs() { + NSPasteboard.general.clearContents() + if let data = try? AppInfo.logEntries().joined(separator: "\n") { + NSPasteboard.general.setString(data, forType: .string) + } + let alert = NSAlert() + alert.messageText = "Logs have been copied to the clipboard." + alert.alertStyle = NSAlert.Style.informational + alert.addButton(withTitle: "OK") + alert.runModal() + } + func copyDebug(_ onlyCheck: String) { var data = "" for claim in Claims.sorted { @@ -457,6 +469,8 @@ class AppHandlers: NSObject, NetworkHandlerObserver { case "debug": let check = url.queryParams()["check"] ?? "" copyDebug(check) + case "logs": + copyLogs() case "runChecks": NSApp.sendAction(#selector(runChecks), to: nil, from: nil) NSApp.activate(ignoringOtherApps: true) diff --git a/Pareto/AppInfo.swift b/Pareto/AppInfo.swift index 17b873a..fabec44 100644 --- a/Pareto/AppInfo.swift +++ b/Pareto/AppInfo.swift @@ -103,7 +103,7 @@ enum AppInfo { static let bugReportURL = { () -> URL in let baseURL = "https://paretosecurity.com/report-bug?" - let logs = logEntries().joined(separator: "\n").addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) + let logs = try? logEntries().joined(separator: "\n").addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) let versions = getVersions().addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) if let url = URL(string: baseURL + "&logs=" + logs! + "&version=" + versions!) { return url @@ -119,7 +119,28 @@ enum AppInfo { logs.append("Build: \(AppInfo.utmSource)") logs.append("\nLogs:") - logs.append("Please copy the logs from the Console app by searching for the ParetoSecurity.") + + if #available(macOS 12.0, *) { + let logStore = try OSLogStore(scope: .currentProcessIdentifier) + // Get all the logs from the last hour. + let oneHourAgo = logStore.position(date: Date().addingTimeInterval(-3600)) + + // Fetch log objects. + let allEntries = try logStore.getEntries(at: oneHourAgo) + + // Filter the log to be relevant for our specific subsystem + // and remove other elements (signposts, etc). + for log in allEntries + .compactMap({ $0 as? OSLogEntryLog }) + .filter({ entry in + entry.subsystem == "niteo.co.Pareto" + }) { + logs.append("\(log.subsystem): \(log.composedMessage)") + } + } else { + logs.append("Please copy the logs from the Console app by searching for the ParetoSecurity.") + } + return logs } diff --git a/Pareto/Checks/Access Security/SSHKeysStrength.swift b/Pareto/Checks/Access Security/SSHKeysStrength.swift index 761dc37..6b832aa 100644 --- a/Pareto/Checks/Access Security/SSHKeysStrength.swift +++ b/Pareto/Checks/Access Security/SSHKeysStrength.swift @@ -92,7 +92,7 @@ class SSHKeysStrengthCheck: ParetoCheck { func isKeyStrong(withKey path: String) -> Bool { let output = runCMD(app: "/usr/bin/ssh-keygen", args: ["-l", "-f", path]) let info = KeyInfo(stringLiteral: output.strip()) - os_log("%s has %d", log: Log.check, path, info.strength) + os_log("%{public}s has %d", log: Log.check, path, info.strength) // https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-57pt3r1.pdf switch info.cipher { case .RSA: diff --git a/Pareto/Info.plist b/Pareto/Info.plist index 7918bdb..8f58e96 100644 --- a/Pareto/Info.plist +++ b/Pareto/Info.plist @@ -26,7 +26,7 @@ CFBundleVersion - 4863 + 4870 LSApplicationCategoryType public.app-category.utilities LSMinimumSystemVersion diff --git a/Pareto/StatusBar/StatusBarController.swift b/Pareto/StatusBar/StatusBarController.swift index 7fba7eb..9c5b449 100644 --- a/Pareto/StatusBar/StatusBarController.swift +++ b/Pareto/StatusBar/StatusBarController.swift @@ -157,9 +157,9 @@ class StatusBarController: NSObject, NSMenuDelegate { Team.update(withReport: report).response { response in switch response.result { case .success: - os_log("Check status was updated", log: Log.app) + os_log("Team status was updated", log: Log.app) case let .failure(err): - os_log("Check status update failed: %s", log: Log.app, err.localizedDescription) + os_log("Team status update failed: %s", log: Log.app, err.localizedDescription) } } } diff --git a/Pareto/Teams.swift b/Pareto/Teams.swift index ab61b0f..311dddf 100644 --- a/Pareto/Teams.swift +++ b/Pareto/Teams.swift @@ -147,8 +147,10 @@ enum Team { let headers: HTTPHeaders = [ "X-Device-Auth": Defaults[.teamAuth] ] + let url = base + "/\(Defaults[.teamID])/device" + os_log("Requesting %{public}s", url) return AF.request( - base + "/\(Defaults[.teamID])/device", + url, method: .put, parameters: device, encoder: JSONParameterEncoder.default, @@ -156,7 +158,7 @@ enum Team { ).validate().cURLDescription { cmd in debugPrint(cmd) }.response(queue: queue) { data in - os_log("%s", log: Log.api, data.debugDescription) + os_log("%{public}s", log: Log.api, data.debugDescription) } } @@ -164,8 +166,10 @@ enum Team { let headers: HTTPHeaders = [ "X-Device-Auth": Defaults[.teamAuth] ] + let url = base + "/\(Defaults[.teamID])/device" + os_log("Requesting %{public}s", url) return AF.request( - base + "/\(Defaults[.teamID])/device", + url, method: .patch, parameters: report, encoder: JSONParameterEncoder.default, @@ -188,7 +192,7 @@ enum Team { os_log("Move detected, ticket parsing failed", log: Log.api) } } else { - os_log("%s", log: Log.api, data.debugDescription) + os_log("%{public}s", log: Log.api, data.debugDescription) } } }