From e19f1998e30d5f9afacf3d7ab128aa945dfced58 Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Thu, 8 Aug 2024 11:22:21 -0500 Subject: [PATCH 1/5] add debugging for SMAppService if/when it ever works --- Nudge/UI/Main.swift | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Nudge/UI/Main.swift b/Nudge/UI/Main.swift index 47c0f827..edd9c63d 100644 --- a/Nudge/UI/Main.swift +++ b/Nudge/UI/Main.swift @@ -650,7 +650,22 @@ class AppDelegate: NSObject, NSApplicationDelegate { private func handleSMAppService() { if #available(macOS 13, *) { let appService = SMAppService.agent(plistName: "com.github.macadmins.Nudge.SMAppService.plist") + let mainAppServce = SMAppService.mainApp let appServiceStatus = appService.status + let mainAppServiceStatus = mainAppServce.status +// print("") +// print("com.github.macadmins.Nudge.SMAppService") +// print("notRegistered: \(appServiceStatus == SMAppService.Status.notRegistered)") +// print("enabled: \(appServiceStatus == SMAppService.Status.enabled)") +// print("requiresApproval: \(appServiceStatus == SMAppService.Status.requiresApproval)") +// print("notFound: \(appServiceStatus == SMAppService.Status.notFound)") +// print("") +// print("mainAppService") +// print("notRegistered: \(mainAppServiceStatus == SMAppService.Status.notRegistered)") +// print("enabled: \(mainAppServiceStatus == SMAppService.Status.enabled)") +// print("requiresApproval: \(mainAppServiceStatus == SMAppService.Status.requiresApproval)") +// print("notFound: \(mainAppServiceStatus == SMAppService.Status.notFound)") +// print("") if CommandLine.arguments.contains("--register") || UserExperienceVariables.loadLaunchAgent { SMAppManager().loadSMAppLaunchAgent(appService: appService, appServiceStatus: appServiceStatus) From f13a697dd61400f7f0d73dc38226f7769ed8e4f4 Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Thu, 8 Aug 2024 12:48:43 -0500 Subject: [PATCH 2/5] Quit nudge when MDM profile is updated --- Nudge/UI/Defaults.swift | 2 +- Nudge/UI/Main.swift | 10 ++++++++-- Nudge/Utilities/Utils.swift | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Nudge/UI/Defaults.swift b/Nudge/UI/Defaults.swift index b06e221d..e54a35aa 100644 --- a/Nudge/UI/Defaults.swift +++ b/Nudge/UI/Defaults.swift @@ -23,7 +23,7 @@ struct Globals { static let snc = NSWorkspace.shared.notificationCenter // Preferences static let configJSON = ConfigurationManager().getConfigurationAsJSON() - static var configProfile = ConfigurationManager().getConfigurationAsProfile() + static let configProfile = ConfigurationManager().getConfigurationAsProfile() static let nudgeDefaults = UserDefaults.standard static let nudgeJSONPreferences = NetworkFileManager().getNudgeJSONPreferences() // Device Properties diff --git a/Nudge/UI/Main.swift b/Nudge/UI/Main.swift index edd9c63d..29dc78cd 100644 --- a/Nudge/UI/Main.swift +++ b/Nudge/UI/Main.swift @@ -739,8 +739,14 @@ class AppDelegate: NSObject, NSApplicationDelegate { Globals.nc.addObserver( forName: UserDefaults.didChangeNotification, object: nil, - queue: .main) { [weak self] _ in - Globals.configProfile = ConfigurationManager().getConfigurationAsProfile() + queue: .main) { _ in + if ConfigurationManager().getConfigurationAsProfile() == Globals.configProfile { + LogManager.debug("MDM Profile has been re-installed or updated but configuration is identical, no need to quit Nudge.", logger: sofaLog) + } else { + LogManager.info("MDM Profile has been re-installed or updated. Quitting Nudge to allow LaunchAgent to re-initalize with new settings.", logger: sofaLog) + nudgePrimaryState.shouldExit = true + exit(2) + } } } diff --git a/Nudge/Utilities/Utils.swift b/Nudge/Utilities/Utils.swift index d0892d00..789ff05f 100644 --- a/Nudge/Utilities/Utils.swift +++ b/Nudge/Utilities/Utils.swift @@ -1310,7 +1310,7 @@ struct SMAppManager { print(message) if let code = exitCode { exit(Int32(code)) } } else { - LogManager.info("\(message)", logger: uiLog) + LogManager.notice("\(message)", logger: uiLog) } } From a42f3cb35db9b8d00c6a4b9c7b7b8408d99a44dd Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Thu, 8 Aug 2024 13:06:40 -0500 Subject: [PATCH 3/5] redo SMAppService log method --- Nudge/Utilities/Utils.swift | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Nudge/Utilities/Utils.swift b/Nudge/Utilities/Utils.swift index 789ff05f..6e6dbffb 100644 --- a/Nudge/Utilities/Utils.swift +++ b/Nudge/Utilities/Utils.swift @@ -1283,7 +1283,7 @@ struct SubProcessUtilities { struct SMAppManager { private func handleLegacyLaunchAgent(passedThroughCLI: Bool, action: String) { - logOrPrint("Legacy Nudge LaunchAgent currently loaded. Please disable this agent before attempting to \(action) modern agent.", passedThroughCLI: passedThroughCLI, exitCode: 1) + logOrPrint("Legacy Nudge LaunchAgent currently loaded. Please disable this agent before attempting to \(action) modern agent.", error: false, passedThroughCLI: passedThroughCLI, exitCode: 1) } @available(macOS 13.0, *) @@ -1299,29 +1299,34 @@ struct SMAppManager { switch appServiceStatus { case .enabled: - logOrPrint("Nudge LaunchAgent is currently registered and enabled", passedThroughCLI: passedThroughCLI, exitCode: 0) + logOrPrint("Nudge LaunchAgent is currently registered and enabled", error: false, passedThroughCLI: passedThroughCLI, exitCode: 0) default: registerOrUnregister(appService: appService, passedThroughCLI: passedThroughCLI, action: "register") } } - private func logOrPrint(_ message: String, passedThroughCLI: Bool, exitCode: Int? = nil) { + private func logOrPrint(_ message: String, error: Bool, passedThroughCLI: Bool, exitCode: Int? = nil) { if passedThroughCLI { print(message) if let code = exitCode { exit(Int32(code)) } } else { - LogManager.notice("\(message)", logger: uiLog) + if error { + LogManager.error("\(message)", logger: uiLog) + } else { + LogManager.debug("\(message)", logger: uiLog) + } + } } @available(macOS 13.0, *) private func registerOrUnregister(appService: SMAppService, passedThroughCLI: Bool, action: String) { do { - logOrPrint("\(action.capitalized)ing Nudge LaunchAgent", passedThroughCLI: passedThroughCLI) + logOrPrint("\(action.capitalized)ing Nudge LaunchAgent", error: false, passedThroughCLI: passedThroughCLI) try action == "register" ? appService.register() : appService.unregister() - logOrPrint("Successfully \(action)ed Nudge LaunchAgent", passedThroughCLI: passedThroughCLI, exitCode: 0) + logOrPrint("Successfully \(action)ed Nudge LaunchAgent", error: false, passedThroughCLI: passedThroughCLI, exitCode: 0) } catch { - logOrPrint("Failed to \(action) Nudge LaunchAgent", passedThroughCLI: passedThroughCLI, exitCode: 1) + logOrPrint("Failed to \(action) Nudge LaunchAgent", error: true, passedThroughCLI: passedThroughCLI, exitCode: 1) } } @@ -1331,7 +1336,7 @@ struct SMAppManager { switch appServiceStatus { case .notFound, .notRegistered: - logOrPrint("Nudge LaunchAgent has never been registered or is not currently registered", passedThroughCLI: passedThroughCLI, exitCode: 0) + logOrPrint("Nudge LaunchAgent has never been registered or is not currently registered", error: false, passedThroughCLI: passedThroughCLI, exitCode: 0) default: registerOrUnregister(appService: appService, passedThroughCLI: passedThroughCLI, action: "unregister") } From 2b43ba46e8cb2654b46523bd58517c7828723e24 Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Thu, 8 Aug 2024 13:08:31 -0500 Subject: [PATCH 4/5] v2.0.7 --- CHANGELOG.md | 12 ++++++++++++ Nudge.xcodeproj/project.pbxproj | 4 ++-- Nudge/Info.plist | 4 ++-- Nudge/Utilities/Utils.swift | 2 ++ 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45d57f5b..5da9dc42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.7] - 2024-08-08 +Requires macOS 12.0 and higher. + +### Changed +- The `SMAppService` logic logs have been moved to debug logs +- When an updated Managed Preference is sent for `com.github.macadmins.Nudge`, if the values are different, [Nudge will exit](/~https://github.com/macadmins/nudge/commit/f13a697dd61400f7f0d73dc38226f7769ed8e4f4) + - This is a workaround for issue [602](/~https://github.com/macadmins/nudge/issues/602) + - The LaunchAgent will ensure the application is successfully restarted at a future time. + +### Fixed +- The Jamf JSON schema file had an [item missing](/~https://github.com/macadmins/nudge/pull/632) and a [key incorrectly set](/~https://github.com/macadmins/nudge/pull/634) + ## [2.0.6] - 2024-08-01 Requires macOS 12.0 and higher. diff --git a/Nudge.xcodeproj/project.pbxproj b/Nudge.xcodeproj/project.pbxproj index 278be3c2..de99b846 100644 --- a/Nudge.xcodeproj/project.pbxproj +++ b/Nudge.xcodeproj/project.pbxproj @@ -698,7 +698,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 12.0; - MARKETING_VERSION = 2.0.6; + MARKETING_VERSION = 2.0.7; PRODUCT_BUNDLE_IDENTIFIER = com.github.macadmins.Nudge; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -729,7 +729,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 12.0; - MARKETING_VERSION = 2.0.6; + MARKETING_VERSION = 2.0.7; PRODUCT_BUNDLE_IDENTIFIER = com.github.macadmins.Nudge; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/Nudge/Info.plist b/Nudge/Info.plist index 34cd4143..607a5905 100644 --- a/Nudge/Info.plist +++ b/Nudge/Info.plist @@ -15,9 +15,9 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 2.0.6 + 2.0.7 CFBundleVersion - 2.0.6 + 2.0.7 LSApplicationCategoryType public.app-category.utilities LSMinimumSystemVersion diff --git a/Nudge/Utilities/Utils.swift b/Nudge/Utilities/Utils.swift index 6e6dbffb..ceab386a 100644 --- a/Nudge/Utilities/Utils.swift +++ b/Nudge/Utilities/Utils.swift @@ -1428,6 +1428,8 @@ struct UIUtilities { return } LogManager.notice("User clicked moreInfo button", logger: uiLog) + // TODO: Flesh this out once we understand what to do when there isn't a url in SOFA feed + // if OSVersionRequirementVariables.aboutUpdateURL == "sofa" { NSWorkspace.shared.open(url) } NSWorkspace.shared.open(url) } From 01728354ec5ba416a790d60336910c89ca55527b Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Thu, 8 Aug 2024 13:33:52 -0500 Subject: [PATCH 5/5] allow dynamic sofa aboutUpdateURLs --- CHANGELOG.md | 6 ++++++ .../com.github.macadmins.Nudge.tester.json | 2 +- Nudge/UI/Common/InformationButton.swift | 12 +++++++++++- Nudge/UI/Defaults.swift | 1 + Nudge/UI/Main.swift | 1 + Nudge/Utilities/Utils.swift | 6 ++---- 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5da9dc42..bd5b01b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2.0.7] - 2024-08-08 Requires macOS 12.0 and higher. +### Added +- If using `utilizeSOFAFeed`, you can now set the `aboutUpdateURL` to `sofa` + - If a URL is found in the relevant `SecurityInfo` key for the corresponding update, this value will be used. + - If no URL is found, the aboutUpdateURL button will not be shown to the user + - [Feature Request 629](/~https://github.com/macadmins/nudge/issues/629) + ### Changed - The `SMAppService` logic logs have been moved to debug logs - When an updated Managed Preference is sent for `com.github.macadmins.Nudge`, if the values are different, [Nudge will exit](/~https://github.com/macadmins/nudge/commit/f13a697dd61400f7f0d73dc38226f7769ed8e4f4) diff --git a/Example Assets/com.github.macadmins.Nudge.tester.json b/Example Assets/com.github.macadmins.Nudge.tester.json index 8ea8d003..b6fd09b5 100644 --- a/Example Assets/com.github.macadmins.Nudge.tester.json +++ b/Example Assets/com.github.macadmins.Nudge.tester.json @@ -5,7 +5,7 @@ }, "osVersionRequirements": [ { - "aboutUpdateURL": "https://apple.com", + "aboutUpdateURL": "sofa", "requiredMinimumOSVersion": "latest", "unsupportedURL": "https://google.com" } diff --git a/Nudge/UI/Common/InformationButton.swift b/Nudge/UI/Common/InformationButton.swift index 37384ada..3c9ca48b 100644 --- a/Nudge/UI/Common/InformationButton.swift +++ b/Nudge/UI/Common/InformationButton.swift @@ -20,9 +20,19 @@ struct InformationButton: View { private var informationButton: some View { guard OSVersionRequirementVariables.aboutUpdateURL != "" else { return AnyView(EmptyView()) } + var selectedURL = OSVersionRequirementVariables.aboutUpdateURL + if OSVersionRequirementVariables.aboutUpdateURL == "sofa" && OptionalFeatureVariables.utilizeSOFAFeed { + if nudgePrimaryState.sofaAboutUpdateURL.hasPrefix("https://") { + selectedURL = nudgePrimaryState.sofaAboutUpdateURL + } else { + return AnyView(EmptyView()) + } + } return AnyView( - Button(action: UIUtilities().openMoreInfo) { + Button(action: { + UIUtilities().openMoreInfo(infoURL: selectedURL) + }) { Text(.init(UserInterfaceVariables.informationButtonText.localized(desiredLanguage: getDesiredLanguage(locale: appState.locale)))) .foregroundColor(dynamicTextColor) } diff --git a/Nudge/UI/Defaults.swift b/Nudge/UI/Defaults.swift index e54a35aa..42d912c2 100644 --- a/Nudge/UI/Defaults.swift +++ b/Nudge/UI/Defaults.swift @@ -83,6 +83,7 @@ class AppState: ObservableObject { @Published var requireDualQuitButtons = false @Published var requiredMinimumOSVersion = OSVersionRequirementVariables.requiredMinimumOSVersion @Published var shouldExit = false + @Published var sofaAboutUpdateURL: String = "" @Published var timerCycle = 0 @Published var userDeferrals = Globals.nudgeDefaults.object(forKey: "userDeferrals") as? Int ?? 0 @Published var userQuitDeferrals = Globals.nudgeDefaults.object(forKey: "userQuitDeferrals") as? Int ?? 0 diff --git a/Nudge/UI/Main.swift b/Nudge/UI/Main.swift index 29dc78cd..c941e0c9 100644 --- a/Nudge/UI/Main.swift +++ b/Nudge/UI/Main.swift @@ -282,6 +282,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { // Start setting UI fields nudgePrimaryState.requiredMinimumOSVersion = selectedOS!.productVersion + nudgePrimaryState.sofaAboutUpdateURL = selectedOS!.securityInfo nudgePrimaryState.activelyExploitedCVEs = activelyExploitedCVEs releaseDate = selectedOS!.releaseDate ?? Date() if requiredInstallationDate == Date(timeIntervalSince1970: 0) { diff --git a/Nudge/Utilities/Utils.swift b/Nudge/Utilities/Utils.swift index ceab386a..6b4e2ebc 100644 --- a/Nudge/Utilities/Utils.swift +++ b/Nudge/Utilities/Utils.swift @@ -1423,13 +1423,11 @@ struct UIUtilities { return shellCommands.contains(where: path.hasPrefix) } - func openMoreInfo() { - guard let url = URL(string: OSVersionRequirementVariables.aboutUpdateURL) else { + func openMoreInfo(infoURL: String) { + guard let url = URL(string: infoURL) else { return } LogManager.notice("User clicked moreInfo button", logger: uiLog) - // TODO: Flesh this out once we understand what to do when there isn't a url in SOFA feed - // if OSVersionRequirementVariables.aboutUpdateURL == "sofa" { NSWorkspace.shared.open(url) } NSWorkspace.shared.open(url) }