From 3ad843d5c7136f3ecdd39dd86625e3ba9b3ced2f Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Wed, 24 Jul 2024 07:21:23 -0500 Subject: [PATCH 01/14] redo under active exploit logic --- CHANGELOG.md | 9 ++++++ Nudge/UI/Main.swift | 69 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 62 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 843d3546..4db7a59a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ 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.5] - 2024-07-24 +Requires macOS 12.0 and higher. + +### Changed +- The `Actively Exploited` logic internally within Nudge and the UI on the left sidebar will show `True` if any previous updates missing on the device had active exploits. + - **WARNNG BREAKING CHANGE** - This changes the SLA computation and will result in a different `requiredInstallationDate` than offered in Nudge v2.0 -> v2.01. + - Ex: Device is on 14.3 and needing to go to 14.5. + - While 14.4.1 -> 14.5 are not under active exploit, 14.4 contains fixes for 14.3 that were under active exploit. + ## [2.0.4] - 2024-07-23 Requires macOS 12.0 and higher. diff --git a/Nudge/UI/Main.swift b/Nudge/UI/Main.swift index 2190476b..1c7e0f07 100644 --- a/Nudge/UI/Main.swift +++ b/Nudge/UI/Main.swift @@ -178,6 +178,9 @@ class AppDelegate: NSObject, NSApplicationDelegate { var foundMatch = false Globals.sofaAssets = NetworkFileManager().getSOFAAssets() if let macOSSOFAAssets = Globals.sofaAssets?.osVersions { + // Get current installed OS version + let currentInstalledVersion = GlobalVariables.currentOSVersion + for osVersion in macOSSOFAAssets { if PrefsWrapper.requiredMinimumOSVersion == "latest" { selectedOS = osVersion.latest @@ -204,24 +207,58 @@ class AppDelegate: NSObject, NSApplicationDelegate { continue } } - let activelyExploitedCVEs = selectedOS!.activelyExploitedCVEs.count > 0 + + var totalActivelyExploitedCVEs = 0 + let selectedOSVersion = selectedOS!.productVersion + var allVersions = [String]() + + // Collect all versions + for osVersion in macOSSOFAAssets { + allVersions.append(osVersion.latest.productVersion) + for securityRelease in osVersion.securityReleases { + allVersions.append(securityRelease.productVersion) + } + } + + // Sort versions + allVersions.sort { VersionManager.versionLessThan(currentVersion: $0, newVersion: $1) } + + // Filter versions between current and selected OS version + let filteredVersions = allVersions.filter { + VersionManager.versionGreaterThan(currentVersion: $0, newVersion: currentInstalledVersion) && + VersionManager.versionLessThanOrEqual(currentVersion: $0, newVersion: selectedOSVersion) + } + + // Count actively exploited CVEs in the filtered versions + for osVersion in macOSSOFAAssets { + if filteredVersions.contains(osVersion.latest.productVersion) { + totalActivelyExploitedCVEs += osVersion.latest.activelyExploitedCVEs.count + } + for securityRelease in osVersion.securityReleases { + if filteredVersions.contains(securityRelease.productVersion) { + totalActivelyExploitedCVEs += securityRelease.activelyExploitedCVEs.count + } + } + } + let activelyExploitedCVEs = totalActivelyExploitedCVEs > 0 + let presentCVEs = selectedOS!.cves.count > 0 let slaExtension: TimeInterval switch (activelyExploitedCVEs, presentCVEs, AppStateManager().requireMajorUpgrade()) { - case (false, true, true): - slaExtension = TimeInterval(OSVersionRequirementVariables.nonActivelyExploitedCVEsMajorUpgradeSLA * 86400) - case (false, true, false): - slaExtension = TimeInterval(OSVersionRequirementVariables.nonActivelyExploitedCVEsMinorUpdateSLA * 86400) - case (true, true, true): - slaExtension = TimeInterval(OSVersionRequirementVariables.activelyExploitedCVEsMajorUpgradeSLA * 86400) - case (true, true, false): - slaExtension = TimeInterval(OSVersionRequirementVariables.activelyExploitedCVEsMinorUpdateSLA * 86400) - case (false, false, true): - slaExtension = TimeInterval(OSVersionRequirementVariables.standardMajorUpgradeSLA * 86400) - case (false, false, false): - slaExtension = TimeInterval(OSVersionRequirementVariables.standardMinorUpdateSLA * 86400) - default: // If we get here, something is wrong, use 90 days as a safety - slaExtension = TimeInterval(90 * 86400) + case (false, true, true): + slaExtension = TimeInterval(OSVersionRequirementVariables.nonActivelyExploitedCVEsMajorUpgradeSLA * 86400) + case (false, true, false): + slaExtension = TimeInterval(OSVersionRequirementVariables.nonActivelyExploitedCVEsMinorUpdateSLA * 86400) + case (true, true, true): + slaExtension = TimeInterval(OSVersionRequirementVariables.activelyExploitedCVEsMajorUpgradeSLA * 86400) + case (true, true, false): + slaExtension = TimeInterval(OSVersionRequirementVariables.activelyExploitedCVEsMinorUpdateSLA * 86400) + case (false, false, true): + slaExtension = TimeInterval(OSVersionRequirementVariables.standardMajorUpgradeSLA * 86400) + case (false, false, false): + slaExtension = TimeInterval(OSVersionRequirementVariables.standardMinorUpdateSLA * 86400) + default: // If we get here, something is wrong, use 90 days as a safety + slaExtension = TimeInterval(90 * 86400) } if OptionalFeatureVariables.disableNudgeForStandardInstalls && !presentCVEs { @@ -252,7 +289,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { supportedDevice in Globals.hardwareModelIDs.contains { $0.uppercased() == supportedDevice.uppercased() } } ) LogManager.notice("Assessed Model ID found in SOFA Entry: \(deviceMatchFound)", logger: sofaLog) - nudgePrimaryState.deviceSupportedByOSVersion = deviceMatchFound // false + nudgePrimaryState.deviceSupportedByOSVersion = deviceMatchFound } } foundMatch = true From c38d799f5a36c2e02b86acc3e2987bd41a4f65c3 Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Wed, 24 Jul 2024 07:22:52 -0500 Subject: [PATCH 02/14] add another note in the changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4db7a59a..36337206 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Requires macOS 12.0 and higher. - **WARNNG BREAKING CHANGE** - This changes the SLA computation and will result in a different `requiredInstallationDate` than offered in Nudge v2.0 -> v2.01. - Ex: Device is on 14.3 and needing to go to 14.5. - While 14.4.1 -> 14.5 are not under active exploit, 14.4 contains fixes for 14.3 that were under active exploit. + - Addresses [610](https://github.com/macadmins/nudge/issues/610) and [613](https://github.com/macadmins/nudge/issues/613) ## [2.0.4] - 2024-07-23 Requires macOS 12.0 and higher. From ccc1d291c4e46743faad47666e204341f366a3f6 Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Wed, 24 Jul 2024 07:31:06 -0500 Subject: [PATCH 03/14] bump to v2.0.5 --- Nudge.xcodeproj/project.pbxproj | 4 ++-- Nudge/Info.plist | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Nudge.xcodeproj/project.pbxproj b/Nudge.xcodeproj/project.pbxproj index 4ea9750c..88ffddff 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.4; + MARKETING_VERSION = 2.0.5; 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.4; + MARKETING_VERSION = 2.0.5; 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 37a39d0b..31ab7d01 100644 --- a/Nudge/Info.plist +++ b/Nudge/Info.plist @@ -15,9 +15,9 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 2.0.4 + 2.0.5 CFBundleVersion - 2.0.4 + 2.0.5 LSApplicationCategoryType public.app-category.utilities LSMinimumSystemVersion From 84fb1653d68649ea1556367bb866c0b732ed71f7 Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Wed, 24 Jul 2024 09:59:58 -0500 Subject: [PATCH 04/14] attempt to show locale when using default values for showRequiredDate --- CHANGELOG.md | 2 ++ Nudge/Utilities/Utils.swift | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36337206..d7d8fc04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ Requires macOS 12.0 and higher. - Ex: Device is on 14.3 and needing to go to 14.5. - While 14.4.1 -> 14.5 are not under active exploit, 14.4 contains fixes for 14.3 that were under active exploit. - Addresses [610](https://github.com/macadmins/nudge/issues/610) and [613](https://github.com/macadmins/nudge/issues/613) +- When `showRequiredDate` is set to `True` and the admin is using the default values for `requiredInstallationDisplayFormat`, Nudge will attempt to understand the current locale and display the menu item appropriately. + - Addresses [615](https://github.com/macadmins/nudge/issues/615) ## [2.0.4] - 2024-07-23 Requires macOS 12.0 and higher. diff --git a/Nudge/Utilities/Utils.swift b/Nudge/Utilities/Utils.swift index 2b971f83..b0a3a950 100644 --- a/Nudge/Utilities/Utils.swift +++ b/Nudge/Utilities/Utils.swift @@ -553,10 +553,20 @@ struct DateManager { return formatter }() - func coerceDateToString(date: Date, formatterString: String) -> String { - let formatter = DateFormatter() - formatter.dateFormat = formatterString - return formatter.string(from: date) + func coerceDateToString(date: Date, formatterString: String, locale: Locale? = nil) -> String { + if formatterString == "MM/dd/yyyy" { + // Use the specified locale or the current locale if none is provided + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .short + dateFormatter.timeStyle = .none + dateFormatter.locale = locale ?? Locale.current + return dateFormatter.string(from: date) + } else { + let formatter = DateFormatter() + formatter.dateFormat = formatterString + formatter.locale = locale ?? Locale.current + return formatter.string(from: date) + } } func coerceStringToDate(dateString: String) -> Date { From 930681f973b4a1291e43e807891e3b514a209f54 Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Wed, 24 Jul 2024 10:38:33 -0500 Subject: [PATCH 05/14] address deprecated github actions --- .github/workflows/build_nudge_pr.yml | 8 ++++---- .github/workflows/build_nudge_prerelease.yml | 8 ++++---- .github/workflows/build_nudge_prerelease_manual.yml | 8 ++++---- .github/workflows/build_nudge_release.yml | 8 ++++---- .github/workflows/build_nudge_release_manual.yml | 8 ++++---- CHANGELOG.md | 4 ++++ 6 files changed, 24 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build_nudge_pr.yml b/.github/workflows/build_nudge_pr.yml index 1efe4b87..17ab5554 100644 --- a/.github/workflows/build_nudge_pr.yml +++ b/.github/workflows/build_nudge_pr.yml @@ -11,20 +11,20 @@ jobs: steps: - name: Checkout nudge repo - uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 - name: Install Apple Xcode certificates - uses: apple-actions/import-codesign-certs@8f3fb608891dd2244cdab3d69cd68c0d37a7fe93 # v2.0.0 + uses: apple-actions/import-codesign-certs@63fff01cd422d4b7b855d40ca1e9d34d2de9427d # v3.0.0 with: keychain-password: ${{ github.run_id }} p12-file-base64: ${{ secrets.APP_CERTIFICATES_P12_MAOS }} p12-password: ${{ secrets.APP_CERTIFICATES_P12_PASSWORD_MAOS }} - name: Install Apple Installer certificates - uses: apple-actions/import-codesign-certs@8f3fb608891dd2244cdab3d69cd68c0d37a7fe93 # v2.0.0 + uses: apple-actions/import-codesign-certs@63fff01cd422d4b7b855d40ca1e9d34d2de9427d # v3.0.0 with: create-keychain: false # do not create a new keychain for this value keychain-password: ${{ github.run_id }} @@ -41,7 +41,7 @@ jobs: echo "NUDGE_MAIN_VERSION=$(/bin/cat ./build_info_main.txt)" >> $GITHUB_ENV - name: Upload zip archive - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 with: name: packages path: outputs/ diff --git a/.github/workflows/build_nudge_prerelease.yml b/.github/workflows/build_nudge_prerelease.yml index 56983b78..6acf5dd6 100644 --- a/.github/workflows/build_nudge_prerelease.yml +++ b/.github/workflows/build_nudge_prerelease.yml @@ -19,19 +19,19 @@ jobs: steps: - name: Checkout nudge repo - uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 - name: Install Apple Xcode certificates - uses: apple-actions/import-codesign-certs@8f3fb608891dd2244cdab3d69cd68c0d37a7fe93 # v2.0.0 + uses: apple-actions/import-codesign-certs@63fff01cd422d4b7b855d40ca1e9d34d2de9427d # v3.0.0 with: keychain-password: ${{ github.run_id }} p12-file-base64: ${{ secrets.APP_CERTIFICATES_P12_MAOS }} p12-password: ${{ secrets.APP_CERTIFICATES_P12_PASSWORD_MAOS }} - name: Install Apple Installer certificates - uses: apple-actions/import-codesign-certs@8f3fb608891dd2244cdab3d69cd68c0d37a7fe93 # v2.0.0 + uses: apple-actions/import-codesign-certs@63fff01cd422d4b7b855d40ca1e9d34d2de9427d # v3.0.0 with: create-keychain: false # do not create a new keychain for this value keychain-password: ${{ github.run_id }} @@ -89,7 +89,7 @@ jobs: files: ${{github.workspace}}/outputs/*.pkg - name: Upload packages - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 with: name: packages path: outputs/ diff --git a/.github/workflows/build_nudge_prerelease_manual.yml b/.github/workflows/build_nudge_prerelease_manual.yml index 141937db..9bbc2092 100644 --- a/.github/workflows/build_nudge_prerelease_manual.yml +++ b/.github/workflows/build_nudge_prerelease_manual.yml @@ -11,19 +11,19 @@ jobs: steps: - name: Checkout nudge repo - uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 - name: Install Apple Xcode certificates - uses: apple-actions/import-codesign-certs@8f3fb608891dd2244cdab3d69cd68c0d37a7fe93 # v2.0.0 + uses: apple-actions/import-codesign-certs@63fff01cd422d4b7b855d40ca1e9d34d2de9427d # v3.0.0 with: keychain-password: ${{ github.run_id }} p12-file-base64: ${{ secrets.APP_CERTIFICATES_P12_MAOS }} p12-password: ${{ secrets.APP_CERTIFICATES_P12_PASSWORD_MAOS }} - name: Install Apple Installer certificates - uses: apple-actions/import-codesign-certs@8f3fb608891dd2244cdab3d69cd68c0d37a7fe93 # v2.0.0 + uses: apple-actions/import-codesign-certs@63fff01cd422d4b7b855d40ca1e9d34d2de9427d # v3.0.0 with: create-keychain: false # do not create a new keychain for this value keychain-password: ${{ github.run_id }} @@ -81,7 +81,7 @@ jobs: files: ${{github.workspace}}/outputs/*.pkg - name: Upload packages - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 with: name: packages path: outputs/ diff --git a/.github/workflows/build_nudge_release.yml b/.github/workflows/build_nudge_release.yml index d5ccbece..f84fe238 100644 --- a/.github/workflows/build_nudge_release.yml +++ b/.github/workflows/build_nudge_release.yml @@ -19,19 +19,19 @@ jobs: steps: - name: Checkout nudge repo - uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 - name: Install Apple Xcode certificates - uses: apple-actions/import-codesign-certs@8f3fb608891dd2244cdab3d69cd68c0d37a7fe93 # v2.0.0 + uses: apple-actions/import-codesign-certs@63fff01cd422d4b7b855d40ca1e9d34d2de9427d # v3.0.0 with: keychain-password: ${{ github.run_id }} p12-file-base64: ${{ secrets.APP_CERTIFICATES_P12_MAOS }} p12-password: ${{ secrets.APP_CERTIFICATES_P12_PASSWORD_MAOS }} - name: Install Apple Installer certificates - uses: apple-actions/import-codesign-certs@8f3fb608891dd2244cdab3d69cd68c0d37a7fe93 # v2.0.0 + uses: apple-actions/import-codesign-certs@63fff01cd422d4b7b855d40ca1e9d34d2de9427d # v3.0.0 with: create-keychain: false # do not create a new keychain for this value keychain-password: ${{ github.run_id }} @@ -89,7 +89,7 @@ jobs: files: ${{github.workspace}}/outputs/*.pkg - name: Upload packages - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 with: name: packages path: outputs/ diff --git a/.github/workflows/build_nudge_release_manual.yml b/.github/workflows/build_nudge_release_manual.yml index 97551cb5..a60f703d 100644 --- a/.github/workflows/build_nudge_release_manual.yml +++ b/.github/workflows/build_nudge_release_manual.yml @@ -11,19 +11,19 @@ jobs: steps: - name: Checkout nudge repo - uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 - name: Install Apple Xcode certificates - uses: apple-actions/import-codesign-certs@8f3fb608891dd2244cdab3d69cd68c0d37a7fe93 # v2.0.0 + uses: apple-actions/import-codesign-certs@63fff01cd422d4b7b855d40ca1e9d34d2de9427d # v3.0.0 with: keychain-password: ${{ github.run_id }} p12-file-base64: ${{ secrets.APP_CERTIFICATES_P12_MAOS }} p12-password: ${{ secrets.APP_CERTIFICATES_P12_PASSWORD_MAOS }} - name: Install Apple Installer certificates - uses: apple-actions/import-codesign-certs@8f3fb608891dd2244cdab3d69cd68c0d37a7fe93 # v2.0.0 + uses: apple-actions/import-codesign-certs@63fff01cd422d4b7b855d40ca1e9d34d2de9427d # v3.0.0 with: create-keychain: false # do not create a new keychain for this value keychain-password: ${{ github.run_id }} @@ -81,7 +81,7 @@ jobs: files: ${{github.workspace}}/outputs/*.pkg - name: Upload packages - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 with: name: packages path: outputs/ diff --git a/CHANGELOG.md b/CHANGELOG.md index d7d8fc04..a50fc4cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ Requires macOS 12.0 and higher. - When `showRequiredDate` is set to `True` and the admin is using the default values for `requiredInstallationDisplayFormat`, Nudge will attempt to understand the current locale and display the menu item appropriately. - Addresses [615](https://github.com/macadmins/nudge/issues/615) +### Fixed +- Several components in the Github Actions were triggering deprecation warnings. These have been addressed by updating to the latest version of these components + - Addresses [616](https://github.com/macadmins/nudge/issues/616) + ## [2.0.4] - 2024-07-23 Requires macOS 12.0 and higher. From 0d538213a3d387ce56e3d61cf8b26d0674613a7c Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Thu, 25 Jul 2024 08:36:24 -0500 Subject: [PATCH 06/14] Add logic for minorVersionRecalculationThreshold --- CHANGELOG.md | 8 +++++ .../Preferences/DefaultPreferencesNudge.swift | 6 ++++ Nudge/Preferences/PreferencesStructure.swift | 4 +++ Nudge/UI/Main.swift | 33 +++++++++++++++++-- Nudge/Utilities/Utils.swift | 10 ++++++ Schema/jamf/com.github.macadmins.Nudge.json | 19 +++++++++++ 6 files changed, 77 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a50fc4cf..ea53292c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2.0.5] - 2024-07-24 Requires macOS 12.0 and higher. +### Added +- To artificially change the `requredInstallationDate` to honor a previous macOS minor version, set `minorVersionRecalculationThreshold` under `osVersionRequirement` in amount of minor versions. + - Ex: `minorVersionRecalculationThreshold` is set to 1 and SOFA feed has macOS 14.5 available + - macOS device is 14.3: Target macOS 14.4.1 requiredInstallationDate of 2024-04-15 00:00:00 +0000 + - macOS device is 14.4: Target macOS 14.4.1 requiredInstallationDate of 2024-04-15 00:00:00 +0000 + - macOS device is 14.4.1: Target macOS 14.5 requiredInstallationDate of 2024-06-03 00:00:00 +0000 + - Addresses [612](https://github.com/macadmins/nudge/issues/612) + ### Changed - The `Actively Exploited` logic internally within Nudge and the UI on the left sidebar will show `True` if any previous updates missing on the device had active exploits. - **WARNNG BREAKING CHANGE** - This changes the SLA computation and will result in a different `requiredInstallationDate` than offered in Nudge v2.0 -> v2.01. diff --git a/Nudge/Preferences/DefaultPreferencesNudge.swift b/Nudge/Preferences/DefaultPreferencesNudge.swift index 05f4808e..ad785943 100644 --- a/Nudge/Preferences/DefaultPreferencesNudge.swift +++ b/Nudge/Preferences/DefaultPreferencesNudge.swift @@ -233,6 +233,12 @@ struct OSVersionRequirementVariables { "" } + static var minorVersionRecalculationThreshold: Int { + osVersionRequirementsProfile?.minorVersionRecalculationThreshold ?? + osVersionRequirementsJSON?.minorVersionRecalculationThreshold ?? + 0 + } + static var nonActivelyExploitedCVEsMajorUpgradeSLA: Int { osVersionRequirementsProfile?.nonActivelyExploitedCVEsMajorUpgradeSLA ?? osVersionRequirementsJSON?.nonActivelyExploitedCVEsMajorUpgradeSLA ?? diff --git a/Nudge/Preferences/PreferencesStructure.swift b/Nudge/Preferences/PreferencesStructure.swift index 085b6e8b..65572c35 100644 --- a/Nudge/Preferences/PreferencesStructure.swift +++ b/Nudge/Preferences/PreferencesStructure.swift @@ -151,6 +151,7 @@ struct OSVersionRequirement: Codable { var activelyExploitedCVEsMajorUpgradeSLA: Int? var activelyExploitedCVEsMinorUpdateSLA: Int? var majorUpgradeAppPath: String? + var minorVersionRecalculationThreshold: Int? var nonActivelyExploitedCVEsMajorUpgradeSLA: Int? var nonActivelyExploitedCVEsMinorUpdateSLA: Int? var requiredInstallationDate: Date? @@ -170,6 +171,7 @@ extension OSVersionRequirement { self.activelyExploitedCVEsMajorUpgradeSLA = fromDictionary["activelyExploitedCVEsMajorUpgradeSLA"] as? Int self.activelyExploitedCVEsMinorUpdateSLA = fromDictionary["activelyExploitedCVEsMinorUpdateSLA"] as? Int self.majorUpgradeAppPath = fromDictionary["majorUpgradeAppPath"] as? String + self.minorVersionRecalculationThreshold = fromDictionary["minorVersionRecalculationThreshold"] as? Int self.nonActivelyExploitedCVEsMajorUpgradeSLA = fromDictionary["nonActivelyExploitedCVEsMajorUpgradeSLA"] as? Int self.nonActivelyExploitedCVEsMinorUpdateSLA = fromDictionary["nonActivelyExploitedCVEsMinorUpdateSLA"] as? Int self.requiredMinimumOSVersion = fromDictionary["requiredMinimumOSVersion"] as? String @@ -248,6 +250,7 @@ extension OSVersionRequirement { activelyExploitedCVEsMajorUpgradeSLA: Int? = nil, activelyExploitedCVEsMinorUpdateSLA: Int? = nil, majorUpgradeAppPath: String? = nil, + minorVersionRecalculationThreshold: Int? = nil, nonActivelyExploitedCVEsMajorUpgradeSLA: Int? = nil, nonActivelyExploitedCVEsMinorUpdateSLA: Int? = nil, requiredInstallationDate: Date? = nil, @@ -265,6 +268,7 @@ extension OSVersionRequirement { activelyExploitedCVEsMajorUpgradeSLA: activelyExploitedCVEsMajorUpgradeSLA ?? self.activelyExploitedCVEsMajorUpgradeSLA, activelyExploitedCVEsMinorUpdateSLA: activelyExploitedCVEsMinorUpdateSLA ?? self.activelyExploitedCVEsMinorUpdateSLA, majorUpgradeAppPath: majorUpgradeAppPath ?? self.majorUpgradeAppPath, + minorVersionRecalculationThreshold: minorVersionRecalculationThreshold ?? self.minorVersionRecalculationThreshold, nonActivelyExploitedCVEsMajorUpgradeSLA: nonActivelyExploitedCVEsMajorUpgradeSLA ?? self.nonActivelyExploitedCVEsMajorUpgradeSLA, nonActivelyExploitedCVEsMinorUpdateSLA: nonActivelyExploitedCVEsMinorUpdateSLA ?? self.nonActivelyExploitedCVEsMinorUpdateSLA, requiredInstallationDate: requiredInstallationDate ?? self.requiredInstallationDate, diff --git a/Nudge/UI/Main.swift b/Nudge/UI/Main.swift index 1c7e0f07..9c4f58cf 100644 --- a/Nudge/UI/Main.swift +++ b/Nudge/UI/Main.swift @@ -180,6 +180,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { if let macOSSOFAAssets = Globals.sofaAssets?.osVersions { // Get current installed OS version let currentInstalledVersion = GlobalVariables.currentOSVersion + let currentMajorVersion = VersionManager.getMajorVersion(from: currentInstalledVersion) for osVersion in macOSSOFAAssets { if PrefsWrapper.requiredMinimumOSVersion == "latest" { @@ -224,10 +225,15 @@ class AppDelegate: NSObject, NSApplicationDelegate { allVersions.sort { VersionManager.versionLessThan(currentVersion: $0, newVersion: $1) } // Filter versions between current and selected OS version - let filteredVersions = allVersions.filter { + let filteredVersions = VersionManager().removeDuplicates(from: allVersions.filter { VersionManager.versionGreaterThan(currentVersion: $0, newVersion: currentInstalledVersion) && VersionManager.versionLessThanOrEqual(currentVersion: $0, newVersion: selectedOSVersion) - } + }) + + // Filter versions with the same major version as the current installed version + let minorVersions = VersionManager().removeDuplicates(from: filteredVersions.filter { version in + VersionManager.getMajorVersion(from: version) == currentMajorVersion + }) // Count actively exploited CVEs in the filtered versions for osVersion in macOSSOFAAssets { @@ -272,7 +278,28 @@ class AppDelegate: NSObject, NSApplicationDelegate { nudgePrimaryState.activelyExploitedCVEs = activelyExploitedCVEs releaseDate = selectedOS!.releaseDate ?? Date() if requiredInstallationDate == Date(timeIntervalSince1970: 0) { - requiredInstallationDate = selectedOS!.releaseDate?.addingTimeInterval(slaExtension) ?? DateManager().getCurrentDate().addingTimeInterval(TimeInterval(90 * 86400)) + if OSVersionRequirementVariables.minorVersionRecalculationThreshold > 0 { + let safeIndex = max(0, minorVersions.count - (OSVersionRequirementVariables.minorVersionRecalculationThreshold + 1)) // Ensure the index is within bounds + let targetVersion = minorVersions[safeIndex] + var foundVersion = false + LogManager.notice("minorVersionRecalculationThreshold is set - Targeting macOS \(targetVersion) requiredInstallationDate via SOFA", logger: sofaLog) + for osVersion in macOSSOFAAssets { + for securityRelease in osVersion.securityReleases { + if securityRelease.productVersion == targetVersion && VersionManager.versionLessThan(currentVersion: currentInstalledVersion, newVersion: targetVersion) { + requiredInstallationDate = securityRelease.releaseDate?.addingTimeInterval(slaExtension) ?? DateManager().getCurrentDate().addingTimeInterval(TimeInterval(90 * 86400)) + foundVersion = true + break + } + } + } + if !foundVersion { + requiredInstallationDate = selectedOS!.releaseDate?.addingTimeInterval(slaExtension) ?? DateManager().getCurrentDate().addingTimeInterval(TimeInterval(90 * 86400)) + LogManager.warning("Could not find requiredInstallationDate from target macOS \(targetVersion)", logger: sofaLog) + LogManager.notice("Setting requiredInstallationDate via SOFA to \(requiredInstallationDate)", logger: sofaLog) + } + } else { + requiredInstallationDate = selectedOS!.releaseDate?.addingTimeInterval(slaExtension) ?? DateManager().getCurrentDate().addingTimeInterval(TimeInterval(90 * 86400)) + } LogManager.notice("Setting requiredInstallationDate via SOFA to \(requiredInstallationDate)", logger: sofaLog) } LogManager.notice("SOFA Matched OS Version: \(selectedOS!.productVersion)", logger: sofaLog) diff --git a/Nudge/Utilities/Utils.swift b/Nudge/Utilities/Utils.swift index b0a3a950..022a28cf 100644 --- a/Nudge/Utilities/Utils.swift +++ b/Nudge/Utilities/Utils.swift @@ -1492,6 +1492,10 @@ struct VersionManager { return majorVersion } + static func getMajorVersion(from version: String) -> Int { + return Int(version.split(separator: ".").first.map(String.init)!)! + } + static func getMinorOSVersion() -> Int { var minorOSVersion = ProcessInfo().operatingSystemVersion.minorVersion // if (CommandLineUtilities().simulateOSVersion() != nil) { @@ -1516,6 +1520,12 @@ struct VersionManager { versionGreaterThan(currentVersion: nudgePrimaryState.requiredMinimumOSVersion, newVersion: nudgePrimaryState.userRequiredMinimumOSVersion) } + // Helper function to remove duplicates while preserving order + func removeDuplicates(from array: [String]) -> [String] { + var seen = Set() + return array.filter { seen.insert($0).inserted } + } + // Adapted from https://stackoverflow.com/a/25453654 static func versionEqual(currentVersion: String, newVersion: String) -> Bool { return currentVersion.compare(newVersion, options: .numeric) == .orderedSame diff --git a/Schema/jamf/com.github.macadmins.Nudge.json b/Schema/jamf/com.github.macadmins.Nudge.json index 00da3811..a5c16b5d 100644 --- a/Schema/jamf/com.github.macadmins.Nudge.json +++ b/Schema/jamf/com.github.macadmins.Nudge.json @@ -508,6 +508,25 @@ } ] }, + "minorVersionRecalculationThreshold": { + "description": "The amount of minor versions a device can be behind before the requiredInstallationDate is recalculated against a previous update. (Note: This key is only used with Nudge v2.0.5 and higher)", + "anyOf": [ + { + "title": "Not Configured", + "type": "null" + }, + { + "title": "Configured", + "default": 0, + "type": "integer", + "options": { + "inputAttributes": { + "placeholder": "0" + } + } + } + ] + }, "nonActivelyExploitedCVEsMajorUpgradeSLA": { "description": "When a major upgrade is not under active exploit but contains CVEs, this is the amount of days a user has to install the update. (Note: This key is only used with Nudge v2.0 and higher)", "anyOf": [ From 07452c3b5ce3cdea4d910612496ebc60e005ede7 Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Thu, 25 Jul 2024 08:43:40 -0500 Subject: [PATCH 07/14] re-order logs --- Nudge/UI/Main.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Nudge/UI/Main.swift b/Nudge/UI/Main.swift index 9c4f58cf..0b15d787 100644 --- a/Nudge/UI/Main.swift +++ b/Nudge/UI/Main.swift @@ -293,9 +293,8 @@ class AppDelegate: NSObject, NSApplicationDelegate { } } if !foundVersion { - requiredInstallationDate = selectedOS!.releaseDate?.addingTimeInterval(slaExtension) ?? DateManager().getCurrentDate().addingTimeInterval(TimeInterval(90 * 86400)) LogManager.warning("Could not find requiredInstallationDate from target macOS \(targetVersion)", logger: sofaLog) - LogManager.notice("Setting requiredInstallationDate via SOFA to \(requiredInstallationDate)", logger: sofaLog) + requiredInstallationDate = selectedOS!.releaseDate?.addingTimeInterval(slaExtension) ?? DateManager().getCurrentDate().addingTimeInterval(TimeInterval(90 * 86400)) } } else { requiredInstallationDate = selectedOS!.releaseDate?.addingTimeInterval(slaExtension) ?? DateManager().getCurrentDate().addingTimeInterval(TimeInterval(90 * 86400)) From 1fd7e94e118719c0dd8ffcebd00b4e11eb9bc29d Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Thu, 25 Jul 2024 09:34:21 -0500 Subject: [PATCH 08/14] fix some logic issues and add safety --- CHANGELOG.md | 18 +++++++++++++++--- Nudge/UI/Main.swift | 32 ++++++++++++++++++-------------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea53292c..a7538398 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,9 +10,21 @@ Requires macOS 12.0 and higher. ### Added - To artificially change the `requredInstallationDate` to honor a previous macOS minor version, set `minorVersionRecalculationThreshold` under `osVersionRequirement` in amount of minor versions. - Ex: `minorVersionRecalculationThreshold` is set to 1 and SOFA feed has macOS 14.5 available - - macOS device is 14.3: Target macOS 14.4.1 requiredInstallationDate of 2024-04-15 00:00:00 +0000 - - macOS device is 14.4: Target macOS 14.4.1 requiredInstallationDate of 2024-04-15 00:00:00 +0000 - - macOS device is 14.4.1: Target macOS 14.5 requiredInstallationDate of 2024-06-03 00:00:00 +0000 + - macOS device is 14.0: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-08 00:00:00 +0000 + - macOS device is 14.1: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-08 00:00:00 +0000 + - macOS device is 14.2: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-08 00:00:00 +0000 + - macOS device is 14.3: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-08 00:00:00 +0000 + - macOS device is 14.4: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-15 00:00:00 +0000 +\ - macOS device is 14.4.1: Required OS: 14.5 - Target macOS 14.5 requiredInstallationDate of 2024-06-03 00:00:00 +0000 + - macOS device is 14.5: Required OS: 14.5 - Fully updated + - Ex: `minorVersionRecalculationThreshold` is set to 2 and SOFA feed has macOS 14.5 available + - macOS device is 14.0: Required OS: 14.5 - Target macOS 14.4 requiredInstallationDate of 2024-03-21 00:00:00 +0000 + - macOS device is 14.1: Required OS: 14.5 - Target macOS 14.4 requiredInstallationDate of 2024-03-21 00:00:00 +0000 + - macOS device is 14.2: Required OS: 14.5 - Target macOS 14.4 requiredInstallationDate of 2024-03-21 00:00:00 +0000 + - macOS device is 14.3: Required OS: 14.5 - Target macOS 14.4 requiredInstallationDate of 2024-03-21 00:00:00 +0000 + - macOS device is 14.4: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-15 00:00:00 +0000 +\ - macOS device is 14.4.1: Required OS: 14.5 - Target macOS 14.5 requiredInstallationDate of 2024-06-03 00:00:00 +0000 + - macOS device is 14.5: Required OS: 14.5 - Fully updated - Addresses [612](https://github.com/macadmins/nudge/issues/612) ### Changed diff --git a/Nudge/UI/Main.swift b/Nudge/UI/Main.swift index 0b15d787..1ff9483e 100644 --- a/Nudge/UI/Main.swift +++ b/Nudge/UI/Main.swift @@ -279,22 +279,26 @@ class AppDelegate: NSObject, NSApplicationDelegate { releaseDate = selectedOS!.releaseDate ?? Date() if requiredInstallationDate == Date(timeIntervalSince1970: 0) { if OSVersionRequirementVariables.minorVersionRecalculationThreshold > 0 { - let safeIndex = max(0, minorVersions.count - (OSVersionRequirementVariables.minorVersionRecalculationThreshold + 1)) // Ensure the index is within bounds - let targetVersion = minorVersions[safeIndex] - var foundVersion = false - LogManager.notice("minorVersionRecalculationThreshold is set - Targeting macOS \(targetVersion) requiredInstallationDate via SOFA", logger: sofaLog) - for osVersion in macOSSOFAAssets { - for securityRelease in osVersion.securityReleases { - if securityRelease.productVersion == targetVersion && VersionManager.versionLessThan(currentVersion: currentInstalledVersion, newVersion: targetVersion) { - requiredInstallationDate = securityRelease.releaseDate?.addingTimeInterval(slaExtension) ?? DateManager().getCurrentDate().addingTimeInterval(TimeInterval(90 * 86400)) - foundVersion = true - break + if minorVersions.isEmpty { + requiredInstallationDate = selectedOS!.releaseDate?.addingTimeInterval(slaExtension) ?? DateManager().getCurrentDate().addingTimeInterval(TimeInterval(90 * 86400)) + } else { + let safeIndex = max(0, minorVersions.count - (OSVersionRequirementVariables.minorVersionRecalculationThreshold + 1)) // Ensure the index is within bounds + let targetVersion = minorVersions[safeIndex] + var foundVersion = false + LogManager.notice("minorVersionRecalculationThreshold is set - Targeting macOS \(targetVersion) requiredInstallationDate via SOFA", logger: sofaLog) + for osVersion in macOSSOFAAssets { + for securityRelease in osVersion.securityReleases.reversed() { + if VersionManager.versionGreaterThanOrEqual(currentVersion: securityRelease.productVersion, newVersion: targetVersion) && VersionManager.versionLessThan(currentVersion: currentInstalledVersion, newVersion: targetVersion) { + requiredInstallationDate = securityRelease.releaseDate?.addingTimeInterval(slaExtension) ?? DateManager().getCurrentDate().addingTimeInterval(TimeInterval(90 * 86400)) + foundVersion = true + break + } } } - } - if !foundVersion { - LogManager.warning("Could not find requiredInstallationDate from target macOS \(targetVersion)", logger: sofaLog) - requiredInstallationDate = selectedOS!.releaseDate?.addingTimeInterval(slaExtension) ?? DateManager().getCurrentDate().addingTimeInterval(TimeInterval(90 * 86400)) + if !foundVersion { + LogManager.warning("Could not find requiredInstallationDate from target macOS \(targetVersion)", logger: sofaLog) + requiredInstallationDate = selectedOS!.releaseDate?.addingTimeInterval(slaExtension) ?? DateManager().getCurrentDate().addingTimeInterval(TimeInterval(90 * 86400)) + } } } else { requiredInstallationDate = selectedOS!.releaseDate?.addingTimeInterval(slaExtension) ?? DateManager().getCurrentDate().addingTimeInterval(TimeInterval(90 * 86400)) From abfccf7c37a9f184b42a5a1da9b0ae6c0df19919 Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Thu, 25 Jul 2024 09:35:49 -0500 Subject: [PATCH 09/14] fix changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7538398..33a69040 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ Requires macOS 12.0 and higher. - macOS device is 14.2: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-08 00:00:00 +0000 - macOS device is 14.3: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-08 00:00:00 +0000 - macOS device is 14.4: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-15 00:00:00 +0000 -\ - macOS device is 14.4.1: Required OS: 14.5 - Target macOS 14.5 requiredInstallationDate of 2024-06-03 00:00:00 +0000 + - macOS device is 14.4.1: Required OS: 14.5 - Target macOS 14.5 requiredInstallationDate of 2024-06-03 00:00:00 +0000 - macOS device is 14.5: Required OS: 14.5 - Fully updated - Ex: `minorVersionRecalculationThreshold` is set to 2 and SOFA feed has macOS 14.5 available - macOS device is 14.0: Required OS: 14.5 - Target macOS 14.4 requiredInstallationDate of 2024-03-21 00:00:00 +0000 @@ -23,7 +23,7 @@ Requires macOS 12.0 and higher. - macOS device is 14.2: Required OS: 14.5 - Target macOS 14.4 requiredInstallationDate of 2024-03-21 00:00:00 +0000 - macOS device is 14.3: Required OS: 14.5 - Target macOS 14.4 requiredInstallationDate of 2024-03-21 00:00:00 +0000 - macOS device is 14.4: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-15 00:00:00 +0000 -\ - macOS device is 14.4.1: Required OS: 14.5 - Target macOS 14.5 requiredInstallationDate of 2024-06-03 00:00:00 +0000 + - macOS device is 14.4.1: Required OS: 14.5 - Target macOS 14.5 requiredInstallationDate of 2024-06-03 00:00:00 +0000 - macOS device is 14.5: Required OS: 14.5 - Fully updated - Addresses [612](https://github.com/macadmins/nudge/issues/612) From 5d5d6a1f82495c35c5f4f70d3ec7b274c811e442 Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Thu, 25 Jul 2024 09:45:20 -0500 Subject: [PATCH 10/14] add an additional note as to why the date is different --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33a69040..59875d7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ Requires macOS 12.0 and higher. - macOS device is 14.1: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-08 00:00:00 +0000 - macOS device is 14.2: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-08 00:00:00 +0000 - macOS device is 14.3: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-08 00:00:00 +0000 - - macOS device is 14.4: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-15 00:00:00 +0000 + - macOS device is 14.4: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-15 00:00:00 +0000 (Note, this time is different than the others as there is no active exploiteds) - macOS device is 14.4.1: Required OS: 14.5 - Target macOS 14.5 requiredInstallationDate of 2024-06-03 00:00:00 +0000 - macOS device is 14.5: Required OS: 14.5 - Fully updated - Ex: `minorVersionRecalculationThreshold` is set to 2 and SOFA feed has macOS 14.5 available From 69421f4cf767e125097522892ce4c7a85445d32e Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Thu, 25 Jul 2024 10:11:57 -0500 Subject: [PATCH 11/14] ensure active exploit logic is properly assessed --- Nudge/UI/Main.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Nudge/UI/Main.swift b/Nudge/UI/Main.swift index 1ff9483e..da32c7e1 100644 --- a/Nudge/UI/Main.swift +++ b/Nudge/UI/Main.swift @@ -226,7 +226,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { // Filter versions between current and selected OS version let filteredVersions = VersionManager().removeDuplicates(from: allVersions.filter { - VersionManager.versionGreaterThan(currentVersion: $0, newVersion: currentInstalledVersion) && + VersionManager.versionGreaterThanOrEqual(currentVersion: $0, newVersion: currentInstalledVersion) && VersionManager.versionLessThanOrEqual(currentVersion: $0, newVersion: selectedOSVersion) }) @@ -236,6 +236,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { }) // Count actively exploited CVEs in the filtered versions + LogManager.notice("Assessing macOS version range for active exploits: \(filteredVersions) ", logger: sofaLog) for osVersion in macOSSOFAAssets { if filteredVersions.contains(osVersion.latest.productVersion) { totalActivelyExploitedCVEs += osVersion.latest.activelyExploitedCVEs.count From 3d618e98249f1e376af8780ee7dc7cd9689083cf Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Thu, 25 Jul 2024 10:12:34 -0500 Subject: [PATCH 12/14] add additional logging for computation --- Nudge/UI/Main.swift | 3 ++- Nudge/Utilities/Utils.swift | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Nudge/UI/Main.swift b/Nudge/UI/Main.swift index da32c7e1..350f7411 100644 --- a/Nudge/UI/Main.swift +++ b/Nudge/UI/Main.swift @@ -286,11 +286,12 @@ class AppDelegate: NSObject, NSApplicationDelegate { let safeIndex = max(0, minorVersions.count - (OSVersionRequirementVariables.minorVersionRecalculationThreshold + 1)) // Ensure the index is within bounds let targetVersion = minorVersions[safeIndex] var foundVersion = false - LogManager.notice("minorVersionRecalculationThreshold is set - Targeting macOS \(targetVersion) requiredInstallationDate via SOFA", logger: sofaLog) + LogManager.notice("minorVersionRecalculationThreshold is set to \(OSVersionRequirementVariables.minorVersionRecalculationThreshold) - Current Version: \(currentInstalledVersion) - Targeting version \(targetVersion) requiredInstallationDate via SOFA", logger: sofaLog) for osVersion in macOSSOFAAssets { for securityRelease in osVersion.securityReleases.reversed() { if VersionManager.versionGreaterThanOrEqual(currentVersion: securityRelease.productVersion, newVersion: targetVersion) && VersionManager.versionLessThan(currentVersion: currentInstalledVersion, newVersion: targetVersion) { requiredInstallationDate = securityRelease.releaseDate?.addingTimeInterval(slaExtension) ?? DateManager().getCurrentDate().addingTimeInterval(TimeInterval(90 * 86400)) + LogManager.notice("Found target macOS version \(targetVersion) - releaseDate is \(securityRelease.releaseDate!), slaExtension is \(LoggerUtilities().printTimeInterval(slaExtension))", logger: sofaLog) foundVersion = true break } diff --git a/Nudge/Utilities/Utils.swift b/Nudge/Utilities/Utils.swift index 022a28cf..69bcf60f 100644 --- a/Nudge/Utilities/Utils.swift +++ b/Nudge/Utilities/Utils.swift @@ -894,6 +894,15 @@ struct LoggerUtilities { return PrefsWrapper.requiredMinimumOSVersion == "0.0" } + func printTimeInterval(_ interval: TimeInterval) -> String { + let days = Int(interval) / (24 * 3600) + let hours = (Int(interval) % (24 * 3600)) / 3600 + let minutes = (Int(interval) % 3600) / 60 + let seconds = Int(interval) % 60 + + return "\(days) days, \(hours) hours, \(minutes) minutes, \(seconds) seconds" + } + private func updateDeferralCount(_ count: inout Int, resetCount: Bool, key: String) { if CommandLineUtilities().demoModeEnabled() { count = 0 From 2f39c0cdf94d8b34299c9237aec92708d07f97fb Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Thu, 25 Jul 2024 10:14:50 -0500 Subject: [PATCH 13/14] fix version comparison --- Nudge/UI/Main.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Nudge/UI/Main.swift b/Nudge/UI/Main.swift index 350f7411..dc7d2e20 100644 --- a/Nudge/UI/Main.swift +++ b/Nudge/UI/Main.swift @@ -289,7 +289,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { LogManager.notice("minorVersionRecalculationThreshold is set to \(OSVersionRequirementVariables.minorVersionRecalculationThreshold) - Current Version: \(currentInstalledVersion) - Targeting version \(targetVersion) requiredInstallationDate via SOFA", logger: sofaLog) for osVersion in macOSSOFAAssets { for securityRelease in osVersion.securityReleases.reversed() { - if VersionManager.versionGreaterThanOrEqual(currentVersion: securityRelease.productVersion, newVersion: targetVersion) && VersionManager.versionLessThan(currentVersion: currentInstalledVersion, newVersion: targetVersion) { + if VersionManager.versionGreaterThanOrEqual(currentVersion: securityRelease.productVersion, newVersion: targetVersion) && VersionManager.versionLessThanOrEqual(currentVersion: currentInstalledVersion, newVersion: targetVersion) { requiredInstallationDate = securityRelease.releaseDate?.addingTimeInterval(slaExtension) ?? DateManager().getCurrentDate().addingTimeInterval(TimeInterval(90 * 86400)) LogManager.notice("Found target macOS version \(targetVersion) - releaseDate is \(securityRelease.releaseDate!), slaExtension is \(LoggerUtilities().printTimeInterval(slaExtension))", logger: sofaLog) foundVersion = true From 500e3176dc2193503d57f466e710c6c27ecff9d8 Mon Sep 17 00:00:00 2001 From: Erik Gomez Date: Thu, 25 Jul 2024 10:26:37 -0500 Subject: [PATCH 14/14] update changelog with new tests --- CHANGELOG.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59875d7f..d4637f76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,16 +14,17 @@ Requires macOS 12.0 and higher. - macOS device is 14.1: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-08 00:00:00 +0000 - macOS device is 14.2: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-08 00:00:00 +0000 - macOS device is 14.3: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-08 00:00:00 +0000 - - macOS device is 14.4: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-15 00:00:00 +0000 (Note, this time is different than the others as there is no active exploiteds) - - macOS device is 14.4.1: Required OS: 14.5 - Target macOS 14.5 requiredInstallationDate of 2024-06-03 00:00:00 +0000 + - macOS device is 14.4: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-08 00:00:00 +0000 + - macOS device is 14.4.1: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-15 00:00:00 +0000 + - This device's requiredInstallationDate is different than the others as there is no active exploit on 14.4.1 - macOS device is 14.5: Required OS: 14.5 - Fully updated - Ex: `minorVersionRecalculationThreshold` is set to 2 and SOFA feed has macOS 14.5 available - macOS device is 14.0: Required OS: 14.5 - Target macOS 14.4 requiredInstallationDate of 2024-03-21 00:00:00 +0000 - macOS device is 14.1: Required OS: 14.5 - Target macOS 14.4 requiredInstallationDate of 2024-03-21 00:00:00 +0000 - macOS device is 14.2: Required OS: 14.5 - Target macOS 14.4 requiredInstallationDate of 2024-03-21 00:00:00 +0000 - macOS device is 14.3: Required OS: 14.5 - Target macOS 14.4 requiredInstallationDate of 2024-03-21 00:00:00 +0000 - - macOS device is 14.4: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-15 00:00:00 +0000 - - macOS device is 14.4.1: Required OS: 14.5 - Target macOS 14.5 requiredInstallationDate of 2024-06-03 00:00:00 +0000 + - macOS device is 14.4: Required OS: 14.5 - Target macOS 14.4 requiredInstallationDate of 2024-03-21 00:00:00 +0000 + - macOS device is 14.4.1: Required OS: 14.5 - Target macOS 14.4.1 requiredInstallationDate of 2024-04-15 00:00:00 +0000 - macOS device is 14.5: Required OS: 14.5 - Fully updated - Addresses [612](https://github.com/macadmins/nudge/issues/612)