From aca88dff2bb7894cb2c3d2fbd367bab5b0751a9b Mon Sep 17 00:00:00 2001 From: Dan Kortschak Date: Wed, 19 Feb 2025 12:27:04 +1030 Subject: [PATCH 1/2] jamf_pro: normalize jamf_pro.inventory.operating_system.version and os.version to three-part versions Depending on the source of the Jamf data, we may receive two-part (e.g. 15.1) or three-part (e.g. 15.1.0) versions for versions where the last part is zero. This leads to multiplication of the numbers of semantically identical versions in search results and dashboards. So normalise all OS versions to the three-part form, unless there are other syntax components (this should never happen). --- packages/jamf_pro/changelog.yml | 5 ++ .../_dev/test/pipeline/test-inventory.json | 64 ++++++++++++++ .../test-inventory.json-expected.json | 86 +++++++++++++++++++ .../elasticsearch/ingest_pipeline/default.yml | 27 ++++++ packages/jamf_pro/manifest.yml | 2 +- 5 files changed, 183 insertions(+), 1 deletion(-) diff --git a/packages/jamf_pro/changelog.yml b/packages/jamf_pro/changelog.yml index f062981e631..d29bd16b01b 100644 --- a/packages/jamf_pro/changelog.yml +++ b/packages/jamf_pro/changelog.yml @@ -1,4 +1,9 @@ # newer versions go on top +- version: "0.3.0" + changes: + - description: Normalize `jamf_pro.inventory.operating_system.version` and `os.version` to three-part versions. + type: enhancement + link: https://github.com/elastic/integrations/pull/12834 - version: "0.2.6" changes: - description: Updated SSL description in package manifest.yml to be uniform and to include links to documentation. diff --git a/packages/jamf_pro/data_stream/inventory/_dev/test/pipeline/test-inventory.json b/packages/jamf_pro/data_stream/inventory/_dev/test/pipeline/test-inventory.json index 9a9d81f3179..be78a4e431f 100644 --- a/packages/jamf_pro/data_stream/inventory/_dev/test/pipeline/test-inventory.json +++ b/packages/jamf_pro/data_stream/inventory/_dev/test/pipeline/test-inventory.json @@ -388,6 +388,70 @@ "purchasing": null, "udid": "21ED95A7-FF9D-52BD-A55B-36D54585083A" } + }, + { + "message": { + "applications": [ + { + "bundleId": "com.apple.freeform", + "externalVersionId": "0", + "macAppStore": false, + "name": "Freeform.app", + "path": "/System/Applications/Freeform.app", + "sizeMegabytes": 57, + "updateAvailable": false, + "version": "2.4" + } + ], + "operatingSystem": { + "activeDirectoryStatus": "Not Bound", + "build": "23H311", + "extensionAttributes": [], + "fileVault2Status": "NOT_ENCRYPTED", + "name": "macOS", + "rapidSecurityResponse": null, + "softwareUpdateDeviceId": "J314cAP", + "supplementalBuildVersion": "23H311", + "version": "14.7" + }, + "packageReceipts": null, + "plugins": null, + "printers": null, + "purchasing": null, + "udid": "21ED95A7-FF9D-52BD-A55B-36D54585083A" + } + }, + { + "message": { + "applications": [ + { + "bundleId": "com.apple.freeform", + "externalVersionId": "0", + "macAppStore": false, + "name": "Freeform.app", + "path": "/System/Applications/Freeform.app", + "sizeMegabytes": 57, + "updateAvailable": false, + "version": "2.4" + } + ], + "operatingSystem": { + "activeDirectoryStatus": "Not Bound", + "build": "23H311", + "extensionAttributes": [], + "fileVault2Status": "NOT_ENCRYPTED", + "name": "macOS", + "rapidSecurityResponse": null, + "softwareUpdateDeviceId": "J314cAP", + "supplementalBuildVersion": "23H311", + "version": "14" + }, + "packageReceipts": null, + "plugins": null, + "printers": null, + "purchasing": null, + "udid": "21ED95A7-FF9D-52BD-A55B-36D54585083A" + } } ] } \ No newline at end of file diff --git a/packages/jamf_pro/data_stream/inventory/_dev/test/pipeline/test-inventory.json-expected.json b/packages/jamf_pro/data_stream/inventory/_dev/test/pipeline/test-inventory.json-expected.json index 71bc1aa348b..f780aad3584 100644 --- a/packages/jamf_pro/data_stream/inventory/_dev/test/pipeline/test-inventory.json-expected.json +++ b/packages/jamf_pro/data_stream/inventory/_dev/test/pipeline/test-inventory.json-expected.json @@ -429,6 +429,92 @@ "" ] } + }, + { + "ecs": { + "version": "8.11.0" + }, + "event": { + "kind": "asset" + }, + "jamf_pro": { + "inventory": { + "applications": [ + { + "bundle_id": "com.apple.freeform", + "external_version_id": "0", + "mac_app_store": false, + "name": "Freeform.app", + "path": "/System/Applications/Freeform.app", + "size_megabytes": 57, + "update_available": false, + "version": "2.4" + } + ], + "operating_system": { + "active_directory_status": "Not Bound", + "build": "23H311", + "file_vault2status": "NOT_ENCRYPTED", + "name": "macOS", + "software_update_device_id": "J314cAP", + "supplemental_build_version": "23H311", + "version": "14.7.0" + }, + "udid": "21ED95A7-FF9D-52BD-A55B-36D54585083A" + } + }, + "os": { + "name": "macOS", + "version": "14.7.0" + }, + "related": { + "user": [ + "" + ] + } + }, + { + "ecs": { + "version": "8.11.0" + }, + "event": { + "kind": "asset" + }, + "jamf_pro": { + "inventory": { + "applications": [ + { + "bundle_id": "com.apple.freeform", + "external_version_id": "0", + "mac_app_store": false, + "name": "Freeform.app", + "path": "/System/Applications/Freeform.app", + "size_megabytes": 57, + "update_available": false, + "version": "2.4" + } + ], + "operating_system": { + "active_directory_status": "Not Bound", + "build": "23H311", + "file_vault2status": "NOT_ENCRYPTED", + "name": "macOS", + "software_update_device_id": "J314cAP", + "supplemental_build_version": "23H311", + "version": "14.0.0" + }, + "udid": "21ED95A7-FF9D-52BD-A55B-36D54585083A" + } + }, + "os": { + "name": "macOS", + "version": "14.0.0" + }, + "related": { + "user": [ + "" + ] + } } ] } diff --git a/packages/jamf_pro/data_stream/inventory/elasticsearch/ingest_pipeline/default.yml b/packages/jamf_pro/data_stream/inventory/elasticsearch/ingest_pipeline/default.yml index 5b623b54158..dc8faa73e0a 100644 --- a/packages/jamf_pro/data_stream/inventory/elasticsearch/ingest_pipeline/default.yml +++ b/packages/jamf_pro/data_stream/inventory/elasticsearch/ingest_pipeline/default.yml @@ -123,6 +123,33 @@ processors: field: os.name copy_from: jamf_pro.inventory.operating_system.name ignore_empty_value: true +- script: + tag: script_normalize_operating_system_version + lang: painless + if: ctx.jamf_pro?.inventory?.operating_system?.version != null && ctx.jamf_pro.inventory.operating_system.version != '' + source: |- + String normalize(String s) { + int n = 0; + for (int i = 0; i < s.length(); i++){ + char c = s.charAt(i); + if (c == (char)'.') { + n++; + continue; + } + if (c < (char)'0' || (char)'9' < c) { + // If we have non-numeric parts, bail. + return s; + } + } + if (n >= 2) { + return s; + } + if (n == 1) { + return s + ".0"; + } + return s + ".0.0"; + } + ctx.jamf_pro.inventory.operating_system.version = normalize(ctx.jamf_pro.inventory.operating_system.version); - set: field: os.version copy_from: jamf_pro.inventory.operating_system.version diff --git a/packages/jamf_pro/manifest.yml b/packages/jamf_pro/manifest.yml index 982087e7c2a..799cffacfec 100644 --- a/packages/jamf_pro/manifest.yml +++ b/packages/jamf_pro/manifest.yml @@ -1,7 +1,7 @@ format_version: 3.1.5 name: jamf_pro title: "Jamf Pro" -version: 0.2.6 +version: 0.3.0 source: license: "Elastic-2.0" description: "Collect logs and inventory data from Jamf Pro with Elastic Agent" From d27f3cdfa90c766f7d6e931d2b5ebe1ed1f4a1d4 Mon Sep 17 00:00:00 2001 From: Dan Kortschak Date: Thu, 20 Feb 2025 06:56:55 +1030 Subject: [PATCH 2/2] jamf_pro: add os.full for know os versions --- packages/jamf_pro/changelog.yml | 3 ++ .../test-inventory.json-expected.json | 3 ++ .../elasticsearch/ingest_pipeline/default.yml | 46 +++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/packages/jamf_pro/changelog.yml b/packages/jamf_pro/changelog.yml index d29bd16b01b..7e7aa9fb19c 100644 --- a/packages/jamf_pro/changelog.yml +++ b/packages/jamf_pro/changelog.yml @@ -4,6 +4,9 @@ - description: Normalize `jamf_pro.inventory.operating_system.version` and `os.version` to three-part versions. type: enhancement link: https://github.com/elastic/integrations/pull/12834 + - description: Add `os.full` for known OS versions. + type: enhancement + link: https://github.com/elastic/integrations/pull/12834 - version: "0.2.6" changes: - description: Updated SSL description in package manifest.yml to be uniform and to include links to documentation. diff --git a/packages/jamf_pro/data_stream/inventory/_dev/test/pipeline/test-inventory.json-expected.json b/packages/jamf_pro/data_stream/inventory/_dev/test/pipeline/test-inventory.json-expected.json index f780aad3584..dff0bc34139 100644 --- a/packages/jamf_pro/data_stream/inventory/_dev/test/pipeline/test-inventory.json-expected.json +++ b/packages/jamf_pro/data_stream/inventory/_dev/test/pipeline/test-inventory.json-expected.json @@ -421,6 +421,7 @@ } }, "os": { + "full": "sonoma", "name": "macOS", "version": "14.7.2" }, @@ -464,6 +465,7 @@ } }, "os": { + "full": "sonoma", "name": "macOS", "version": "14.7.0" }, @@ -507,6 +509,7 @@ } }, "os": { + "full": "sonoma", "name": "macOS", "version": "14.0.0" }, diff --git a/packages/jamf_pro/data_stream/inventory/elasticsearch/ingest_pipeline/default.yml b/packages/jamf_pro/data_stream/inventory/elasticsearch/ingest_pipeline/default.yml index dc8faa73e0a..8c5da15144f 100644 --- a/packages/jamf_pro/data_stream/inventory/elasticsearch/ingest_pipeline/default.yml +++ b/packages/jamf_pro/data_stream/inventory/elasticsearch/ingest_pipeline/default.yml @@ -149,7 +149,53 @@ processors: } return s + ".0.0"; } + String full_name(String s) { + if (s.startsWith('15.')) { + return 'sequoia'; + } + if (s.startsWith('14.')) { + return 'sonoma'; + } + if (s.startsWith('13.')) { + return 'ventura'; + } + if (s.startsWith('12.')) { + return 'monterey'; + } + if (s.startsWith('11.')) { + return 'big sur'; + } + if (s.startsWith('10.15.')) { + return 'catalina'; + } + if (s.startsWith('10.14.')) { + return 'mojave'; + } + if (s.startsWith('10.13.')) { + return 'high sierra'; + } + if (s.startsWith('10.12.')) { + return 'sierra'; + } + if (s.startsWith('10.11.')) { + return 'el capitan'; + } + if (s.startsWith('10.10.')) { + return 'yosemite'; + } + if (s.startsWith('10.9.')) { + return 'mavericks'; + } + return ''; + } ctx.jamf_pro.inventory.operating_system.version = normalize(ctx.jamf_pro.inventory.operating_system.version); + String name = full_name(ctx.jamf_pro.inventory.operating_system.version); + if (name != '') { + if (ctx.os == null) { + ctx.os = [:]; + } + ctx.os.full = name; + } - set: field: os.version copy_from: jamf_pro.inventory.operating_system.version