From 5aa8521986d8be3306815245bc1d87d063e11be4 Mon Sep 17 00:00:00 2001 From: Tomas Turina Date: Mon, 22 Jul 2024 22:00:06 +0000 Subject: [PATCH 01/13] feat(ms-graph): add mdm intune auditEvents endpoint logic --- src/modules/ms_graph/include/wm_ms_graph.h | 8 +++++- src/modules/ms_graph/src/wm_ms_graph.c | 33 ++++++++++++++++------ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/modules/ms_graph/include/wm_ms_graph.h b/src/modules/ms_graph/include/wm_ms_graph.h index 31ce2f02d0..13c3bf838a 100644 --- a/src/modules/ms_graph/include/wm_ms_graph.h +++ b/src/modules/ms_graph/include/wm_ms_graph.h @@ -33,10 +33,16 @@ #define WM_MS_GRAPH_DOD_API_QUERY_FQDN "dod-graph.microsoft.us" -#define WM_MS_GRAPH_API_URL "https://%s/%s/%s/%s?$filter=createdDateTime+gt+%s" +#define WM_MS_GRAPH_API_URL "https://%s/%s/%s/%s" +#define WM_MS_GRAPH_API_URL_FILTER_CREATED_DATE WM_MS_GRAPH_API_URL "?$filter=createdDateTime+gt+%s" +#define WM_MS_GRAPH_API_URL_FILTER_ACTIVITY_DATE WM_MS_GRAPH_API_URL "?$filter=activityDateTime+gt+%s" #define WM_MS_GRAPH_ACCESS_TOKEN_URL "https://%s/%s/oauth2/v2.0/token" #define WM_MS_GRAPH_ACCESS_TOKEN_PAYLOAD "scope=https://%s/.default&grant_type=client_credentials&client_id=%s&client_secret=%s" +// MDM Intune +#define WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT "deviceManagement" +#define WM_MS_GRAPH_RELATIONSHIP_AUDIT_EVENTS "auditEvents" + typedef struct wm_ms_graph_state_t { time_t next_time; } wm_ms_graph_state_t; diff --git a/src/modules/ms_graph/src/wm_ms_graph.c b/src/modules/ms_graph/src/wm_ms_graph.c index 19fefb7047..26dfb2359f 100644 --- a/src/modules/ms_graph/src/wm_ms_graph.c +++ b/src/modules/ms_graph/src/wm_ms_graph.c @@ -188,7 +188,7 @@ void wm_ms_graph_get_access_token(wm_ms_graph_auth* auth_config, const ssize_t c void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_scan) { char url[OS_SIZE_8192] = { '\0' }; - char auth_header[OS_SIZE_2048] = { '\0' }; + char auth_header[OS_SIZE_8192] = { '\0' }; char* headers[] = { NULL, NULL }; curl_response* response; char relationship_state_name[OS_SIZE_1024] = { '\0' }; @@ -237,15 +237,32 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_sc gmtime_r(&relationship_state_struc.next_time, &tm_aux); strftime(start_time_str, sizeof(start_time_str), "%Y-%m-%dT%H:%M:%SZ", &tm_aux); - snprintf(auth_header, OS_SIZE_2048 - 1, "Authorization: Bearer %s", it->access_token); + snprintf(auth_header, OS_SIZE_8192 - 1, "Authorization: Bearer %s", it->access_token); os_strdup(auth_header, headers[0]); - snprintf(url, OS_SIZE_8192 - 1, WM_MS_GRAPH_API_URL, - it->query_fqdn, - ms_graph->version, - ms_graph->resources[resource_num].name, - ms_graph->resources[resource_num].relationships[relationship_num], - start_time_str); + if (!strcmp(ms_graph->resources[resource_num].name, WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT)) { + if (!strcmp(ms_graph->resources[resource_num].relationships[relationship_num], WM_MS_GRAPH_RELATIONSHIP_AUDIT_EVENTS)) { + snprintf(url, OS_SIZE_8192 - 1, WM_MS_GRAPH_API_URL_FILTER_ACTIVITY_DATE, + it->query_fqdn, + ms_graph->version, + WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT, + WM_MS_GRAPH_RELATIONSHIP_AUDIT_EVENTS, + start_time_str); + } else { + snprintf(url, OS_SIZE_8192 - 1, WM_MS_GRAPH_API_URL, + it->query_fqdn, + ms_graph->version, + WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT, + ms_graph->resources[resource_num].relationships[relationship_num]); + } + } else { + snprintf(url, OS_SIZE_8192 - 1, WM_MS_GRAPH_API_URL_FILTER_CREATED_DATE, + it->query_fqdn, + ms_graph->version, + ms_graph->resources[resource_num].name, + ms_graph->resources[resource_num].relationships[relationship_num], + start_time_str); + } mtdebug1(WM_MS_GRAPH_LOGTAG, "Microsoft Graph API Log URL: '%s'", url); From 4fbdc04197e506fd8207e33244c7a1ab357948d1 Mon Sep 17 00:00:00 2001 From: Tomas Turina Date: Tue, 23 Jul 2024 19:28:10 +0000 Subject: [PATCH 02/13] fix(ms-graph): improve query date filters --- src/modules/ms_graph/include/wm_ms_graph.h | 4 ++-- src/modules/ms_graph/src/wm_ms_graph.c | 16 +++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/modules/ms_graph/include/wm_ms_graph.h b/src/modules/ms_graph/include/wm_ms_graph.h index 13c3bf838a..c88bcc4cf5 100644 --- a/src/modules/ms_graph/include/wm_ms_graph.h +++ b/src/modules/ms_graph/include/wm_ms_graph.h @@ -34,8 +34,8 @@ #define WM_MS_GRAPH_API_URL "https://%s/%s/%s/%s" -#define WM_MS_GRAPH_API_URL_FILTER_CREATED_DATE WM_MS_GRAPH_API_URL "?$filter=createdDateTime+gt+%s" -#define WM_MS_GRAPH_API_URL_FILTER_ACTIVITY_DATE WM_MS_GRAPH_API_URL "?$filter=activityDateTime+gt+%s" +#define WM_MS_GRAPH_API_URL_FILTER_CREATED_DATE WM_MS_GRAPH_API_URL "?$filter=createdDateTime+ge+%s+and+createdDateTime+lt+%s" +#define WM_MS_GRAPH_API_URL_FILTER_ACTIVITY_DATE WM_MS_GRAPH_API_URL "?$filter=activityDateTime+ge+%s+and+activityDateTime+lt+%s" #define WM_MS_GRAPH_ACCESS_TOKEN_URL "https://%s/%s/oauth2/v2.0/token" #define WM_MS_GRAPH_ACCESS_TOKEN_PAYLOAD "scope=https://%s/.default&grant_type=client_credentials&client_id=%s&client_secret=%s" diff --git a/src/modules/ms_graph/src/wm_ms_graph.c b/src/modules/ms_graph/src/wm_ms_graph.c index 26dfb2359f..5aa6a6e81b 100644 --- a/src/modules/ms_graph/src/wm_ms_graph.c +++ b/src/modules/ms_graph/src/wm_ms_graph.c @@ -193,6 +193,7 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_sc curl_response* response; char relationship_state_name[OS_SIZE_1024] = { '\0' }; char start_time_str[WM_MS_GRAPH_TIMESTAMP_SIZE_80] = { '\0' }; + char end_time_str[WM_MS_GRAPH_TIMESTAMP_SIZE_80] = { '\0' }; struct tm tm_aux = { .tm_sec = 0 }; wm_ms_graph_state_t relationship_state_struc; time_t now; @@ -237,6 +238,9 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_sc gmtime_r(&relationship_state_struc.next_time, &tm_aux); strftime(start_time_str, sizeof(start_time_str), "%Y-%m-%dT%H:%M:%SZ", &tm_aux); + gmtime_r(&now, &tm_aux); + strftime(end_time_str, sizeof(end_time_str), "%Y-%m-%dT%H:%M:%SZ", &tm_aux); + snprintf(auth_header, OS_SIZE_8192 - 1, "Authorization: Bearer %s", it->access_token); os_strdup(auth_header, headers[0]); @@ -247,7 +251,8 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_sc ms_graph->version, WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT, WM_MS_GRAPH_RELATIONSHIP_AUDIT_EVENTS, - start_time_str); + start_time_str, + end_time_str); } else { snprintf(url, OS_SIZE_8192 - 1, WM_MS_GRAPH_API_URL, it->query_fqdn, @@ -261,15 +266,14 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_sc ms_graph->version, ms_graph->resources[resource_num].name, ms_graph->resources[resource_num].relationships[relationship_num], - start_time_str); + start_time_str, + end_time_str); } mtdebug1(WM_MS_GRAPH_LOGTAG, "Microsoft Graph API Log URL: '%s'", url); fail = true; response = wurl_http_request(WURL_GET_METHOD, headers, url, "", ms_graph->curl_max_size, WM_MS_GRAPH_DEFAULT_TIMEOUT); - // It takes the time right after the response to be saved for the next scan. - now = time(0); if (response) { if (response->status_code != 200) { char status_code[4]; @@ -330,13 +334,11 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_sc if (!fail) { relationship_state_struc.next_time = now; - gmtime_r(&relationship_state_struc.next_time, &tm_aux); - strftime(start_time_str, sizeof(start_time_str), "%Y-%m-%dT%H:%M:%SZ", &tm_aux); if (wm_state_io(relationship_state_name, WM_IO_WRITE, &relationship_state_struc, sizeof(relationship_state_struc)) < 0) { mterror(WM_MS_GRAPH_LOGTAG, "Couldn't save running state."); } else { mtdebug1(WM_MS_GRAPH_LOGTAG, "Bookmark updated to '%s' for tenant '%s' resource '%s' and relationship '%s', waiting '%d' seconds to run next scan.", - start_time_str, it->tenant_id, ms_graph->resources[resource_num].name, ms_graph->resources[resource_num].relationships[relationship_num], ms_graph->scan_config.interval); + end_time_str, it->tenant_id, ms_graph->resources[resource_num].name, ms_graph->resources[resource_num].relationships[relationship_num], ms_graph->scan_config.interval); } } os_free(headers[0]); From f506457fbb47229a023a32d73f5a60240b0cee35 Mon Sep 17 00:00:00 2001 From: Tomas Turina Date: Wed, 24 Jul 2024 14:49:31 +0000 Subject: [PATCH 03/13] fix(ms-graph): update url filters query in IT --- .../test_API/data/response_samples/responses.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/ms_graph/tests/integration/test_API/data/response_samples/responses.json b/src/modules/ms_graph/tests/integration/test_API/data/response_samples/responses.json index 061e85bb1e..61dfab3522 100644 --- a/src/modules/ms_graph/tests/integration/test_API/data/response_samples/responses.json +++ b/src/modules/ms_graph/tests/integration/test_API/data/response_samples/responses.json @@ -20,7 +20,7 @@ } }, { - "url": "http://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+gt+*", + "url": "http://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+*+and+createdDateTime+lt+*", "method": "GET", "responseCode": 200, "responseBody": { @@ -30,7 +30,7 @@ } }, { - "url": "http://graph.microsoft.com/v1.0/security/incidents?$filter=createdDateTime+gt+*", + "url": "http://graph.microsoft.com/v1.0/security/incidents?$filter=createdDateTime+ge+*+and+createdDateTime+lt+*", "method": "GET", "responseCode": 200, "responseBody": { @@ -40,7 +40,7 @@ } }, { - "url": "http://graph.microsoft.com/v1.0/resource_name/resource_relationship?$filter=createdDateTime+gt+*", + "url": "http://graph.microsoft.com/v1.0/resource_name/resource_relationship?$filter=createdDateTime+ge+*+and+createdDateTime+lt+*", "method": "GET", "responseCode": 200, "responseBody": { @@ -50,7 +50,7 @@ } }, { - "url": "http://*/*/*/*$filter=createdDateTime+gt+*", + "url": "http://*/*/*/*$filter=createdDateTime+ge+*+and+createdDateTime+lt+*", "method": "GET", "responseCode": 403, "responseBody": { From 40ab80da03f896a76b97dde4e62bf2e25910209a Mon Sep 17 00:00:00 2001 From: Tomas Turina Date: Wed, 24 Jul 2024 20:00:51 +0000 Subject: [PATCH 04/13] test(ms-graph): adapt ms-graph UT to intune changes --- .../tests/unit/tests/test_wm_ms_graph.c | 122 +++++++++++------- 1 file changed, 73 insertions(+), 49 deletions(-) diff --git a/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c b/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c index 4e37cb119e..6e204eb811 100644 --- a/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c +++ b/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c @@ -2205,8 +2205,14 @@ void test_wm_ms_graph_scan_relationships_single_initial_only_no_next_time_no_res will_return(__wrap_strftime,"2023-02-08T12:24:56Z"); will_return(__wrap_strftime, 20); +#ifndef WIN32 + will_return(__wrap_gmtime_r, 1); +#endif + will_return(__wrap_strftime,"2023-02-08T12:25:56Z"); + will_return(__wrap_strftime, 20); + expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+gt+2023-02-08T12:24:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2353,8 +2359,14 @@ void test_wm_ms_graph_scan_relationships_single_unsuccessful_status_code(void ** will_return(__wrap_strftime,"2023-02-08T12:24:56Z"); will_return(__wrap_strftime, 20); +#ifndef WIN32 + will_return(__wrap_gmtime_r, 1); +#endif + will_return(__wrap_strftime,"2023-02-08T12:25:56Z"); + will_return(__wrap_strftime, 20); + expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+gt+2023-02-08T12:24:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2433,8 +2445,14 @@ void test_wm_ms_graph_scan_relationships_single_reached_curl_size(void **state) will_return(__wrap_strftime,"2023-02-08T12:24:56Z"); will_return(__wrap_strftime, 20); +#ifndef WIN32 + will_return(__wrap_gmtime_r, 1); +#endif + will_return(__wrap_strftime,"2023-02-08T12:25:56Z"); + will_return(__wrap_strftime, 20); + expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+gt+2023-02-08T12:24:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2513,8 +2531,14 @@ void test_wm_ms_graph_scan_relationships_single_failed_parse(void **state) { will_return(__wrap_strftime,"2023-02-08T12:24:56Z"); will_return(__wrap_strftime, 20); +#ifndef WIN32 + will_return(__wrap_gmtime_r, 1); +#endif + will_return(__wrap_strftime,"2023-02-08T12:25:56Z"); + will_return(__wrap_strftime, 20); + expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+gt+2023-02-08T12:24:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2593,8 +2617,14 @@ void test_wm_ms_graph_scan_relationships_single_no_logs(void **state) { will_return(__wrap_strftime,"2023-02-08T12:24:56Z"); will_return(__wrap_strftime, 20); +#ifndef WIN32 + will_return(__wrap_gmtime_r, 1); +#endif + will_return(__wrap_strftime,"2023-02-08T12:25:56Z"); + will_return(__wrap_strftime, 20); + expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+gt+2023-02-08T12:24:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2607,12 +2637,6 @@ void test_wm_ms_graph_scan_relationships_single_no_logs(void **state) { expect_string(__wrap__mtdebug2, tag, "wazuh-modulesd:ms-graph"); expect_string(__wrap__mtdebug2, formatted_msg, "No new logs received."); -#ifndef WIN32 - will_return(__wrap_gmtime_r, 1); -#endif - will_return(__wrap_strftime,"2023-02-08T12:24:56Z"); - will_return(__wrap_strftime, 20); - expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-security-alerts_v2"); expect_value(__wrap_wm_state_io, op, WM_IO_WRITE); expect_any(__wrap_wm_state_io, state); @@ -2620,7 +2644,7 @@ void test_wm_ms_graph_scan_relationships_single_no_logs(void **state) { will_return(__wrap_wm_state_io, 1); expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Bookmark updated to '2023-02-08T12:24:56Z' for tenant 'example_tenant' resource 'security' and relationship 'alerts_v2', waiting '60' seconds to run next scan."); + expect_string(__wrap__mtdebug1, formatted_msg, "Bookmark updated to '2023-02-08T12:25:56Z' for tenant 'example_tenant' resource 'security' and relationship 'alerts_v2', waiting '60' seconds to run next scan."); wm_ms_graph_scan_relationships(module_data, initial); } @@ -2689,8 +2713,14 @@ void test_wm_ms_graph_scan_relationships_single_success_one_log(void **state) { will_return(__wrap_strftime,"2023-02-08T12:24:56Z"); will_return(__wrap_strftime, 20); +#ifndef WIN32 + will_return(__wrap_gmtime_r, 1); +#endif + will_return(__wrap_strftime,"2023-02-08T12:25:56Z"); + will_return(__wrap_strftime, 20); + expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+gt+2023-02-08T12:24:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2712,12 +2742,6 @@ void test_wm_ms_graph_scan_relationships_single_success_one_log(void **state) { expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); will_return(__wrap_wm_sendmsg, result); -#ifndef WIN32 - will_return(__wrap_gmtime_r, 1); -#endif - will_return(__wrap_strftime,"2023-02-08T12:24:56Z"); - will_return(__wrap_strftime, 20); - expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-security-alerts_v2"); expect_value(__wrap_wm_state_io, op, WM_IO_WRITE); expect_any(__wrap_wm_state_io, state); @@ -2725,7 +2749,7 @@ void test_wm_ms_graph_scan_relationships_single_success_one_log(void **state) { will_return(__wrap_wm_state_io, 1); expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Bookmark updated to '2023-02-08T12:24:56Z' for tenant 'example_tenant' resource 'security' and relationship 'alerts_v2', waiting '60' seconds to run next scan."); + expect_string(__wrap__mtdebug1, formatted_msg, "Bookmark updated to '2023-02-08T12:25:56Z' for tenant 'example_tenant' resource 'security' and relationship 'alerts_v2', waiting '60' seconds to run next scan."); wm_ms_graph_scan_relationships(module_data, initial); } @@ -2794,8 +2818,14 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { will_return(__wrap_strftime,"2023-02-08T12:24:56Z"); will_return(__wrap_strftime, 20); +#ifndef WIN32 + will_return(__wrap_gmtime_r, 1); +#endif + will_return(__wrap_strftime,"2023-02-08T12:25:56Z"); + will_return(__wrap_strftime, 20); + expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+gt+2023-02-08T12:24:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2831,12 +2861,6 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); will_return(__wrap_wm_sendmsg, 1); -#ifndef WIN32 - will_return(__wrap_gmtime_r, 1); -#endif - will_return(__wrap_strftime,"2023-02-08T12:24:56Z"); - will_return(__wrap_strftime, 20); - expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-security-alerts_v2"); expect_value(__wrap_wm_state_io, op, WM_IO_WRITE); expect_any(__wrap_wm_state_io, state); @@ -2844,7 +2868,7 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { will_return(__wrap_wm_state_io, 1); expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Bookmark updated to '2023-02-08T12:24:56Z' for tenant 'example_tenant' resource 'security' and relationship 'alerts_v2', waiting '60' seconds to run next scan."); + expect_string(__wrap__mtdebug1, formatted_msg, "Bookmark updated to '2023-02-08T12:25:56Z' for tenant 'example_tenant' resource 'security' and relationship 'alerts_v2', waiting '60' seconds to run next scan."); wm_ms_graph_scan_relationships(module_data, initial); } @@ -2891,13 +2915,13 @@ void test_wm_ms_graph_scan_relationships_single_success_two_resources(void **sta os_strdup(WM_MS_GRAPH_GLOBAL_API_QUERY_FQDN, module_data->auth_config[0]->query_fqdn); os_malloc(sizeof(wm_ms_graph_resource) * 2, module_data->resources); os_strdup("security", module_data->resources[0].name); - os_strdup("auditlogs", module_data->resources[1].name); + os_strdup("deviceManagement", module_data->resources[1].name); module_data->num_resources = 2; os_malloc(sizeof(char*) * 2, module_data->resources[0].relationships); os_strdup("alerts_v2", module_data->resources[0].relationships[0]); module_data->resources[0].num_relationships = 1; os_malloc(sizeof(char*) * 2, module_data->resources[1].relationships); - os_strdup("signIns", module_data->resources[1].relationships[0]); + os_strdup("auditEvents", module_data->resources[1].relationships[0]); module_data->resources[1].num_relationships = 1; size_t max_size = OS_SIZE_8192; bool initial = false; @@ -2923,8 +2947,14 @@ void test_wm_ms_graph_scan_relationships_single_success_two_resources(void **sta will_return(__wrap_strftime,"2023-02-08T12:24:56Z"); will_return(__wrap_strftime, 20); +#ifndef WIN32 + will_return(__wrap_gmtime_r, 1); +#endif + will_return(__wrap_strftime,"2023-02-08T12:25:56Z"); + will_return(__wrap_strftime, 20); + expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+gt+2023-02-08T12:24:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2945,12 +2975,6 @@ void test_wm_ms_graph_scan_relationships_single_success_two_resources(void **sta expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); will_return(__wrap_wm_sendmsg, 1); -#ifndef WIN32 - will_return(__wrap_gmtime_r, 1); -#endif - will_return(__wrap_strftime,"2023-02-08T12:24:56Z"); - will_return(__wrap_strftime, 20); - expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-security-alerts_v2"); expect_value(__wrap_wm_state_io, op, WM_IO_WRITE); expect_any(__wrap_wm_state_io, state); @@ -2958,7 +2982,7 @@ void test_wm_ms_graph_scan_relationships_single_success_two_resources(void **sta will_return(__wrap_wm_state_io, 1); expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Bookmark updated to '2023-02-08T12:24:56Z' for tenant 'example_tenant' resource 'security' and relationship 'alerts_v2', waiting '60' seconds to run next scan."); + expect_string(__wrap__mtdebug1, formatted_msg, "Bookmark updated to '2023-02-08T12:25:56Z' for tenant 'example_tenant' resource 'security' and relationship 'alerts_v2', waiting '60' seconds to run next scan."); // resource auditlogs os_calloc(1, sizeof(curl_response), response); @@ -2967,7 +2991,7 @@ void test_wm_ms_graph_scan_relationships_single_success_two_resources(void **sta os_strdup("{\"value\":[{\"full_log\":\"log1_resource_2\"}]}", response->body); os_strdup("test", response->header); - expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-auditlogs-signIns"); + expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-deviceManagement-auditEvents"); expect_value(__wrap_wm_state_io, op, WM_IO_READ); expect_any(__wrap_wm_state_io, state); expect_any(__wrap_wm_state_io, size); @@ -2980,8 +3004,14 @@ void test_wm_ms_graph_scan_relationships_single_success_two_resources(void **sta will_return(__wrap_strftime,"2023-02-08T12:24:56Z"); will_return(__wrap_strftime, 20); +#ifndef WIN32 + will_return(__wrap_gmtime_r, 1); +#endif + will_return(__wrap_strftime,"2023-02-08T12:25:56Z"); + will_return(__wrap_strftime, 20); + expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/auditlogs/signIns?$filter=createdDateTime+gt+2023-02-08T12:24:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/deviceManagement/auditEvents?$filter=activityDateTime+ge+2023-02-08T12:24:56Z+and+activityDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2992,23 +3022,17 @@ void test_wm_ms_graph_scan_relationships_single_success_two_resources(void **sta will_return(__wrap_wurl_http_request, response); expect_string(__wrap__mtdebug2, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1_resource_2\",\"resource\":\"auditlogs\",\"relationship\":\"signIns\"}}'"); + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1_resource_2\",\"resource\":\"deviceManagement\",\"relationship\":\"auditEvents\"}}'"); queue_fd = 0; expect_value(__wrap_wm_sendmsg, usec, 1000000); expect_value(__wrap_wm_sendmsg, queue, queue_fd); - expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1_resource_2\",\"resource\":\"auditlogs\",\"relationship\":\"signIns\"}}"); + expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1_resource_2\",\"resource\":\"deviceManagement\",\"relationship\":\"auditEvents\"}}"); expect_string(__wrap_wm_sendmsg, locmsg, "ms-graph"); expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); will_return(__wrap_wm_sendmsg, 1); -#ifndef WIN32 - will_return(__wrap_gmtime_r, 1); -#endif - will_return(__wrap_strftime,"2023-02-08T12:24:56Z"); - will_return(__wrap_strftime, 20); - - expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-auditlogs-signIns"); + expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-deviceManagement-auditEvents"); expect_value(__wrap_wm_state_io, op, WM_IO_WRITE); expect_any(__wrap_wm_state_io, state); expect_any(__wrap_wm_state_io, size); From f6adc27a4cd98fe587821d483db447ab27aa238e Mon Sep 17 00:00:00 2001 From: Tomas Turina Date: Tue, 6 Aug 2024 18:50:47 +0000 Subject: [PATCH 05/13] fix(ms-graph): add pagination --- src/modules/ms_graph/include/wm_ms_graph.h | 7 +- src/modules/ms_graph/src/wm_ms_graph.c | 124 ++++++++++++--------- 2 files changed, 74 insertions(+), 57 deletions(-) diff --git a/src/modules/ms_graph/include/wm_ms_graph.h b/src/modules/ms_graph/include/wm_ms_graph.h index c88bcc4cf5..1b26904c4d 100644 --- a/src/modules/ms_graph/include/wm_ms_graph.h +++ b/src/modules/ms_graph/include/wm_ms_graph.h @@ -33,11 +33,12 @@ #define WM_MS_GRAPH_DOD_API_QUERY_FQDN "dod-graph.microsoft.us" -#define WM_MS_GRAPH_API_URL "https://%s/%s/%s/%s" -#define WM_MS_GRAPH_API_URL_FILTER_CREATED_DATE WM_MS_GRAPH_API_URL "?$filter=createdDateTime+ge+%s+and+createdDateTime+lt+%s" -#define WM_MS_GRAPH_API_URL_FILTER_ACTIVITY_DATE WM_MS_GRAPH_API_URL "?$filter=activityDateTime+ge+%s+and+activityDateTime+lt+%s" +#define WM_MS_GRAPH_API_URL "https://%s/%s/%s/%s?$top=%d" +#define WM_MS_GRAPH_API_URL_FILTER_CREATED_DATE WM_MS_GRAPH_API_URL "&$filter=createdDateTime+ge+%s+and+createdDateTime+lt+%s" +#define WM_MS_GRAPH_API_URL_FILTER_ACTIVITY_DATE WM_MS_GRAPH_API_URL "&$filter=activityDateTime+ge+%s+and+activityDateTime+lt+%s" #define WM_MS_GRAPH_ACCESS_TOKEN_URL "https://%s/%s/oauth2/v2.0/token" #define WM_MS_GRAPH_ACCESS_TOKEN_PAYLOAD "scope=https://%s/.default&grant_type=client_credentials&client_id=%s&client_secret=%s" +#define WM_MS_GRAPH_ITEM_PER_PAGE 100 // MDM Intune #define WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT "deviceManagement" diff --git a/src/modules/ms_graph/src/wm_ms_graph.c b/src/modules/ms_graph/src/wm_ms_graph.c index 5aa6a6e81b..3a71695c42 100644 --- a/src/modules/ms_graph/src/wm_ms_graph.c +++ b/src/modules/ms_graph/src/wm_ms_graph.c @@ -198,6 +198,7 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_sc wm_ms_graph_state_t relationship_state_struc; time_t now; bool fail; + bool next_page; for (unsigned int resource_num = 0; resource_num < ms_graph->num_resources; resource_num++) { @@ -251,6 +252,7 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_sc ms_graph->version, WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT, WM_MS_GRAPH_RELATIONSHIP_AUDIT_EVENTS, + WM_MS_GRAPH_ITEM_PER_PAGE, start_time_str, end_time_str); } else { @@ -258,7 +260,8 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_sc it->query_fqdn, ms_graph->version, WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT, - ms_graph->resources[resource_num].relationships[relationship_num]); + ms_graph->resources[resource_num].relationships[relationship_num], + WM_MS_GRAPH_ITEM_PER_PAGE); } } else { snprintf(url, OS_SIZE_8192 - 1, WM_MS_GRAPH_API_URL_FILTER_CREATED_DATE, @@ -266,70 +269,83 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_sc ms_graph->version, ms_graph->resources[resource_num].name, ms_graph->resources[resource_num].relationships[relationship_num], + WM_MS_GRAPH_ITEM_PER_PAGE, start_time_str, end_time_str); } - mtdebug1(WM_MS_GRAPH_LOGTAG, "Microsoft Graph API Log URL: '%s'", url); - - fail = true; - response = wurl_http_request(WURL_GET_METHOD, headers, url, "", ms_graph->curl_max_size, WM_MS_GRAPH_DEFAULT_TIMEOUT); - if (response) { - if (response->status_code != 200) { - char status_code[4]; - snprintf(status_code, 4, "%ld", response->status_code); - mtwarn(WM_MS_GRAPH_LOGTAG, "Received unsuccessful status code when attempting to get relationship '%s' logs: Status code was '%s' & response was '%s'", - ms_graph->resources[resource_num].relationships[relationship_num], - status_code, - response->body); - } else if (response->max_size_reached) { - mtwarn(WM_MS_GRAPH_LOGTAG, "Reached maximum CURL size when attempting to get relationship '%s' logs. Consider increasing the value of 'curl_max_size'.", - ms_graph->resources[resource_num].relationships[relationship_num]); - } else { - cJSON* body_parse = NULL; - if (body_parse = cJSON_Parse(response->body), body_parse) { - cJSON* logs = cJSON_GetObjectItem(body_parse, "value"); - int num_logs = cJSON_GetArraySize(logs); - if (num_logs > 0) { - for (int log_index = 0; log_index < num_logs; log_index++) { - cJSON* log = NULL; - if (log = cJSON_GetArrayItem(logs, log_index), log) { - cJSON* full_log = cJSON_CreateObject(); - char* payload; - - cJSON_AddStringToObject(log, "resource", ms_graph->resources[resource_num].name); - cJSON_AddStringToObject(log, "relationship", ms_graph->resources[resource_num].relationships[relationship_num]); - cJSON_AddStringToObject(full_log, "integration", WM_MS_GRAPH_CONTEXT.name); - cJSON_AddItemToObject(full_log, WM_MS_GRAPH_CONTEXT.name, cJSON_Duplicate(log, true)); - - payload = cJSON_PrintUnformatted(full_log); - mtdebug2(WM_MS_GRAPH_LOGTAG, "Sending log: '%s'", payload); - if (wm_sendmsg(1000000 / wm_max_eps, queue_fd, payload, WM_MS_GRAPH_CONTEXT.name, LOCALFILE_MQ) < 0) { - mterror(WM_MS_GRAPH_LOGTAG, QUEUE_ERROR, DEFAULTQUEUE, strerror(errno)); + next_page = true; + while (next_page) { + mtdebug1(WM_MS_GRAPH_LOGTAG, "Microsoft Graph API Log URL: '%s'", url); + + fail = true; + next_page = false; + response = wurl_http_request(WURL_GET_METHOD, headers, url, "", ms_graph->curl_max_size, WM_MS_GRAPH_DEFAULT_TIMEOUT); + if (response) { + if (response->status_code != 200) { + char status_code[4]; + snprintf(status_code, 4, "%ld", response->status_code); + mtwarn(WM_MS_GRAPH_LOGTAG, "Received unsuccessful status code when attempting to get relationship '%s' logs: Status code was '%s' & response was '%s'", + ms_graph->resources[resource_num].relationships[relationship_num], + status_code, + response->body); + } else if (response->max_size_reached) { + mtwarn(WM_MS_GRAPH_LOGTAG, "Reached maximum CURL size when attempting to get relationship '%s' logs. Consider increasing the value of 'curl_max_size'.", + ms_graph->resources[resource_num].relationships[relationship_num]); + } else { + cJSON* body_parse = NULL; + if (body_parse = cJSON_Parse(response->body), body_parse) { + cJSON* logs = cJSON_GetObjectItem(body_parse, "value"); + int num_logs = cJSON_GetArraySize(logs); + if (num_logs > 0) { + for (int log_index = 0; log_index < num_logs; log_index++) { + cJSON* log = NULL; + if (log = cJSON_GetArrayItem(logs, log_index), log) { + cJSON* full_log = cJSON_CreateObject(); + char* payload; + + cJSON_AddStringToObject(log, "resource", ms_graph->resources[resource_num].name); + cJSON_AddStringToObject(log, "relationship", ms_graph->resources[resource_num].relationships[relationship_num]); + cJSON_AddStringToObject(full_log, "integration", WM_MS_GRAPH_CONTEXT.name); + cJSON_AddItemToObject(full_log, WM_MS_GRAPH_CONTEXT.name, cJSON_Duplicate(log, true)); + + payload = cJSON_PrintUnformatted(full_log); + mtdebug2(WM_MS_GRAPH_LOGTAG, "Sending log: '%s'", payload); + if (wm_sendmsg(1000000 / wm_max_eps, queue_fd, payload, WM_MS_GRAPH_CONTEXT.name, LOCALFILE_MQ) < 0) { + mterror(WM_MS_GRAPH_LOGTAG, QUEUE_ERROR, DEFAULTQUEUE, strerror(errno)); + } + + os_free(payload); + cJSON_Delete(full_log); + } else { + mtwarn(WM_MS_GRAPH_LOGTAG, "Failed to parse log array into singular log."); } - - os_free(payload); - cJSON_Delete(full_log); - } else { - mtwarn(WM_MS_GRAPH_LOGTAG, "Failed to parse log array into singular log."); } + fail = false; + } else { + mtdebug2(WM_MS_GRAPH_LOGTAG, "No new logs received."); + fail = false; + } + + cJSON* next_url = cJSON_GetObjectItem(body_parse, "@odata.nextLink"); + if (cJSON_IsString(next_url)) { + memset(url, '\0', OS_SIZE_8192); + snprintf(url, OS_SIZE_8192 -1, "%s", next_url->valuestring); + next_page = true; } - fail = false; + + cJSON_Delete(body_parse); } else { - mtdebug2(WM_MS_GRAPH_LOGTAG, "No new logs received."); - fail = false; + mtwarn(WM_MS_GRAPH_LOGTAG, "Failed to parse relationship '%s' JSON body.", ms_graph->resources[resource_num].relationships[relationship_num]); } - cJSON_Delete(body_parse); - } else { - mtwarn(WM_MS_GRAPH_LOGTAG, "Failed to parse relationship '%s' JSON body.", ms_graph->resources[resource_num].relationships[relationship_num]); } + wurl_free_response(response); + } else { + mtwarn(WM_MS_GRAPH_LOGTAG, "No response received when attempting to get relationship '%s' from resource '%s' on API version '%s'.", + ms_graph->resources[resource_num].relationships[relationship_num], + ms_graph->resources[resource_num].name, + ms_graph->version); } - wurl_free_response(response); - } else { - mtwarn(WM_MS_GRAPH_LOGTAG, "No response received when attempting to get relationship '%s' from resource '%s' on API version '%s'.", - ms_graph->resources[resource_num].relationships[relationship_num], - ms_graph->resources[resource_num].name, - ms_graph->version); } if (!fail) { From 46ea975108adbdb79f1e2ab9bca4e0a11d3795fc Mon Sep 17 00:00:00 2001 From: Tomas Turina Date: Tue, 6 Aug 2024 19:49:58 +0000 Subject: [PATCH 06/13] feat(ms-graph): add inventory queries support --- src/modules/ms_graph/src/wm_ms_graph.c | 58 +++++++++++++++----------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/src/modules/ms_graph/src/wm_ms_graph.c b/src/modules/ms_graph/src/wm_ms_graph.c index 3a71695c42..775de05fc4 100644 --- a/src/modules/ms_graph/src/wm_ms_graph.c +++ b/src/modules/ms_graph/src/wm_ms_graph.c @@ -199,6 +199,7 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_sc time_t now; bool fail; bool next_page; + bool inventory = false; for (unsigned int resource_num = 0; resource_num < ms_graph->num_resources; resource_num++) { @@ -210,37 +211,46 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_sc for (e = 0; ms_graph->auth_config[e]; e++) { it = ms_graph->auth_config[e]; - snprintf(relationship_state_name, OS_SIZE_1024 -1, "%s-%s-%s-%s", WM_MS_GRAPH_CONTEXT.name, - it->tenant_id, ms_graph->resources[resource_num].name, ms_graph->resources[resource_num].relationships[relationship_num]); + if (!strcmp(ms_graph->resources[resource_num].name, WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT)) { + // If not auditEvents, treat as inventory + if (strcmp(ms_graph->resources[resource_num].relationships[relationship_num], WM_MS_GRAPH_RELATIONSHIP_AUDIT_EVENTS)) { + inventory = true; + } + } - memset(&relationship_state_struc, 0, sizeof(relationship_state_struc)); + if (!inventory) { + snprintf(relationship_state_name, OS_SIZE_1024 -1, "%s-%s-%s-%s", WM_MS_GRAPH_CONTEXT.name, + it->tenant_id, ms_graph->resources[resource_num].name, ms_graph->resources[resource_num].relationships[relationship_num]); - // Load state for tenant-resource-relationship - if (wm_state_io(relationship_state_name, WM_IO_READ, &relationship_state_struc, sizeof(relationship_state_struc)) < 0) { memset(&relationship_state_struc, 0, sizeof(relationship_state_struc)); - } - now = time(0); + // Load state for tenant-resource-relationship + if (wm_state_io(relationship_state_name, WM_IO_READ, &relationship_state_struc, sizeof(relationship_state_struc)) < 0) { + memset(&relationship_state_struc, 0, sizeof(relationship_state_struc)); + } - if ((initial_scan && (!relationship_state_struc.next_time || ms_graph->only_future_events)) || - (!initial_scan && !relationship_state_struc.next_time)) { - relationship_state_struc.next_time = now; - if (wm_state_io(relationship_state_name, WM_IO_WRITE, &relationship_state_struc, sizeof(relationship_state_struc)) < 0) { - mterror(WM_MS_GRAPH_LOGTAG, "Couldn't save running state."); - } else if (isDebug()) { - gmtime_r(&now, &tm_aux); - strftime(start_time_str, sizeof(start_time_str), "%Y-%m-%dT%H:%M:%SZ", &tm_aux); - mtdebug1(WM_MS_GRAPH_LOGTAG, "Bookmark updated to '%s' for tenant '%s' resource '%s' and relationship '%s', waiting '%d' seconds to run first scan.", - start_time_str, it->tenant_id, ms_graph->resources[resource_num].name, ms_graph->resources[resource_num].relationships[relationship_num], ms_graph->scan_config.interval); + now = time(0); + + if ((initial_scan && (!relationship_state_struc.next_time || ms_graph->only_future_events)) || + (!initial_scan && !relationship_state_struc.next_time)) { + relationship_state_struc.next_time = now; + if (wm_state_io(relationship_state_name, WM_IO_WRITE, &relationship_state_struc, sizeof(relationship_state_struc)) < 0) { + mterror(WM_MS_GRAPH_LOGTAG, "Couldn't save running state."); + } else if (isDebug()) { + gmtime_r(&now, &tm_aux); + strftime(start_time_str, sizeof(start_time_str), "%Y-%m-%dT%H:%M:%SZ", &tm_aux); + mtdebug1(WM_MS_GRAPH_LOGTAG, "Bookmark updated to '%s' for tenant '%s' resource '%s' and relationship '%s', waiting '%d' seconds to run first scan.", + start_time_str, it->tenant_id, ms_graph->resources[resource_num].name, ms_graph->resources[resource_num].relationships[relationship_num], ms_graph->scan_config.interval); + } + continue; } - continue; - } - gmtime_r(&relationship_state_struc.next_time, &tm_aux); - strftime(start_time_str, sizeof(start_time_str), "%Y-%m-%dT%H:%M:%SZ", &tm_aux); + gmtime_r(&relationship_state_struc.next_time, &tm_aux); + strftime(start_time_str, sizeof(start_time_str), "%Y-%m-%dT%H:%M:%SZ", &tm_aux); - gmtime_r(&now, &tm_aux); - strftime(end_time_str, sizeof(end_time_str), "%Y-%m-%dT%H:%M:%SZ", &tm_aux); + gmtime_r(&now, &tm_aux); + strftime(end_time_str, sizeof(end_time_str), "%Y-%m-%dT%H:%M:%SZ", &tm_aux); + } snprintf(auth_header, OS_SIZE_8192 - 1, "Authorization: Bearer %s", it->access_token); os_strdup(auth_header, headers[0]); @@ -348,7 +358,7 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_sc } } - if (!fail) { + if (!inventory && !fail) { relationship_state_struc.next_time = now; if (wm_state_io(relationship_state_name, WM_IO_WRITE, &relationship_state_struc, sizeof(relationship_state_struc)) < 0) { mterror(WM_MS_GRAPH_LOGTAG, "Couldn't save running state."); From 467f54a202577458473510706bb480889538a594 Mon Sep 17 00:00:00 2001 From: Tomas Turina Date: Wed, 7 Aug 2024 15:07:04 +0000 Subject: [PATCH 07/13] fix(ms-graph): add UT to test managed devices endpoint --- .../tests/unit/tests/test_wm_ms_graph.c | 141 ++++++++++++++++-- 1 file changed, 130 insertions(+), 11 deletions(-) diff --git a/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c b/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c index 6e204eb811..51bb68c6c6 100644 --- a/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c +++ b/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c @@ -2212,7 +2212,7 @@ void test_wm_ms_graph_scan_relationships_single_initial_only_no_next_time_no_res will_return(__wrap_strftime, 20); expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$top=100&$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2366,7 +2366,7 @@ void test_wm_ms_graph_scan_relationships_single_unsuccessful_status_code(void ** will_return(__wrap_strftime, 20); expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$top=100&$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2452,7 +2452,7 @@ void test_wm_ms_graph_scan_relationships_single_reached_curl_size(void **state) will_return(__wrap_strftime, 20); expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$top=100&$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2538,7 +2538,7 @@ void test_wm_ms_graph_scan_relationships_single_failed_parse(void **state) { will_return(__wrap_strftime, 20); expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$top=100&$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2624,7 +2624,7 @@ void test_wm_ms_graph_scan_relationships_single_no_logs(void **state) { will_return(__wrap_strftime, 20); expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$top=100&$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2720,7 +2720,7 @@ void test_wm_ms_graph_scan_relationships_single_success_one_log(void **state) { will_return(__wrap_strftime, 20); expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$top=100&$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2825,7 +2825,7 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { will_return(__wrap_strftime, 20); expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$top=100&$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2873,6 +2873,124 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { wm_ms_graph_scan_relationships(module_data, initial); } +void test_wm_ms_graph_scan_relationships_single_success_two_pages(void **state) { + /* + yes + no + 1M + yes + v1.0 + + example_client + example_tenant + example_secret + global + + + deviceManagement + managedDevices + + */ + wm_ms_graph* module_data = (wm_ms_graph *)*state; + os_calloc(1, sizeof(wm_ms_graph_auth), module_data->auth_config); + os_calloc(1, sizeof(wm_ms_graph_auth), module_data->auth_config[0]); + module_data->enabled = true; + module_data->only_future_events = false; + module_data->curl_max_size = 1024L; + module_data->run_on_start = true; + module_data->scan_config.interval = 60; + os_strdup("v1.0", module_data->version); + os_strdup("example_client", module_data->auth_config[0]->client_id); + os_strdup("example_tenant", module_data->auth_config[0]->tenant_id); + os_strdup("example_secret", module_data->auth_config[0]->secret_value); + os_strdup(WM_MS_GRAPH_GLOBAL_API_LOGIN_FQDN, module_data->auth_config[0]->login_fqdn); + os_strdup(WM_MS_GRAPH_GLOBAL_API_QUERY_FQDN, module_data->auth_config[0]->query_fqdn); + os_malloc(sizeof(wm_ms_graph_resource), module_data->resources); + os_strdup("deviceManagement", module_data->resources[0].name); + module_data->num_resources = 1; + os_malloc(sizeof(char*), module_data->resources[0].relationships); + os_strdup("managedDevices", module_data->resources[0].relationships[0]); + module_data->resources[0].num_relationships = 1; + size_t max_size = OS_SIZE_8192; + bool initial = false; + curl_response* response; + curl_response* response2; + wm_max_eps = 1; + + os_calloc(1, sizeof(curl_response), response); + response->status_code = 200; + response->max_size_reached = false; + os_strdup("{\"@odata.nextLink\":\"next_page_url\",\"value\":[{\"full_log\":\"log1\"},{\"full_log\":\"log2\"}]}", response->body); + os_strdup("test", response->header); + + os_calloc(1, sizeof(curl_response), response2); + response2->status_code = 200; + response2->max_size_reached = false; + os_strdup("{\"value\":[{\"full_log\":\"log3\"}]}", response2->body); + os_strdup("test2", response2->header); + + expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/deviceManagement/managedDevices?$top=100'"); + + expect_any(__wrap_wurl_http_request, method); + expect_any(__wrap_wurl_http_request, header); + expect_any(__wrap_wurl_http_request, url); + expect_any(__wrap_wurl_http_request, payload); + expect_any(__wrap_wurl_http_request, max_size); + expect_value(__wrap_wurl_http_request, timeout, WM_MS_GRAPH_DEFAULT_TIMEOUT); + will_return(__wrap_wurl_http_request, response); + + expect_string(__wrap__mtdebug2, tag, "wazuh-modulesd:ms-graph"); + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}'"); + + queue_fd = 0; + expect_value(__wrap_wm_sendmsg, usec, 1000000); + expect_value(__wrap_wm_sendmsg, queue, queue_fd); + expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}"); + expect_string(__wrap_wm_sendmsg, locmsg, "ms-graph"); + expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); + will_return(__wrap_wm_sendmsg, -1); + + will_return(__wrap_strerror, "Error"); + + expect_string(__wrap__mterror, tag, WM_MS_GRAPH_LOGTAG); + expect_string(__wrap__mterror, formatted_msg, "(1210): Queue 'queue/sockets/queue' not accessible: 'Error'"); + + expect_string(__wrap__mtdebug2, tag, "wazuh-modulesd:ms-graph"); + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}'"); + + expect_value(__wrap_wm_sendmsg, usec, 1000000); + expect_value(__wrap_wm_sendmsg, queue, queue_fd); + expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}"); + expect_string(__wrap_wm_sendmsg, locmsg, "ms-graph"); + expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); + will_return(__wrap_wm_sendmsg, 1); + + expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'next_page_url'"); + + expect_any(__wrap_wurl_http_request, method); + expect_any(__wrap_wurl_http_request, header); + expect_any(__wrap_wurl_http_request, url); + expect_any(__wrap_wurl_http_request, payload); + expect_any(__wrap_wurl_http_request, max_size); + expect_value(__wrap_wurl_http_request, timeout, WM_MS_GRAPH_DEFAULT_TIMEOUT); + will_return(__wrap_wurl_http_request, response2); + + expect_string(__wrap__mtdebug2, tag, "wazuh-modulesd:ms-graph"); + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log3\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}'"); + + queue_fd = 0; + expect_value(__wrap_wm_sendmsg, usec, 1000000); + expect_value(__wrap_wm_sendmsg, queue, queue_fd); + expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log3\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}"); + expect_string(__wrap_wm_sendmsg, locmsg, "ms-graph"); + expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); + will_return(__wrap_wm_sendmsg, 1); + + wm_ms_graph_scan_relationships(module_data, initial); +} + void test_wm_ms_graph_scan_relationships_single_success_two_resources(void **state) { /* yes @@ -2891,8 +3009,8 @@ void test_wm_ms_graph_scan_relationships_single_success_two_resources(void **sta alerts_v2 - auditlogs - signIns + deviceManagement + auditEvents */ wm_ms_graph* module_data = (wm_ms_graph *)*state; @@ -2954,7 +3072,7 @@ void test_wm_ms_graph_scan_relationships_single_success_two_resources(void **sta will_return(__wrap_strftime, 20); expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$top=100&$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -3011,7 +3129,7 @@ void test_wm_ms_graph_scan_relationships_single_success_two_resources(void **sta will_return(__wrap_strftime, 20); expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/deviceManagement/auditEvents?$filter=activityDateTime+ge+2023-02-08T12:24:56Z+and+activityDateTime+lt+2023-02-08T12:25:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/deviceManagement/auditEvents?$top=100&$filter=activityDateTime+ge+2023-02-08T12:24:56Z+and+activityDateTime+lt+2023-02-08T12:25:56Z'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -3109,6 +3227,7 @@ int main(void) { cmocka_unit_test_setup_teardown(test_wm_ms_graph_scan_relationships_single_no_logs, setup_conf, teardown_conf), cmocka_unit_test_setup_teardown(test_wm_ms_graph_scan_relationships_single_success_one_log, setup_conf, teardown_conf), cmocka_unit_test_setup_teardown(test_wm_ms_graph_scan_relationships_single_success_two_logs, setup_conf, teardown_conf), + cmocka_unit_test_setup_teardown(test_wm_ms_graph_scan_relationships_single_success_two_pages, setup_conf, teardown_conf), cmocka_unit_test_setup_teardown(test_wm_ms_graph_scan_relationships_single_success_two_resources, setup_conf, teardown_conf) }; int result = 0; From 895cde705965b2210b50b9e160e90ddbb68beca9 Mon Sep 17 00:00:00 2001 From: Tomas Turina Date: Wed, 7 Aug 2024 15:27:51 +0000 Subject: [PATCH 08/13] fix(ms-graph): fix ms graph IT after including pagination --- .../test_API/data/response_samples/responses.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/ms_graph/tests/integration/test_API/data/response_samples/responses.json b/src/modules/ms_graph/tests/integration/test_API/data/response_samples/responses.json index 61dfab3522..264d600803 100644 --- a/src/modules/ms_graph/tests/integration/test_API/data/response_samples/responses.json +++ b/src/modules/ms_graph/tests/integration/test_API/data/response_samples/responses.json @@ -20,7 +20,7 @@ } }, { - "url": "http://graph.microsoft.com/v1.0/security/alerts_v2?$filter=createdDateTime+ge+*+and+createdDateTime+lt+*", + "url": "http://graph.microsoft.com/v1.0/security/alerts_v2?$top=*&$filter=createdDateTime+ge+*+and+createdDateTime+lt+*", "method": "GET", "responseCode": 200, "responseBody": { @@ -30,7 +30,7 @@ } }, { - "url": "http://graph.microsoft.com/v1.0/security/incidents?$filter=createdDateTime+ge+*+and+createdDateTime+lt+*", + "url": "http://graph.microsoft.com/v1.0/security/incidents?$top=*&$filter=createdDateTime+ge+*+and+createdDateTime+lt+*", "method": "GET", "responseCode": 200, "responseBody": { @@ -40,7 +40,7 @@ } }, { - "url": "http://graph.microsoft.com/v1.0/resource_name/resource_relationship?$filter=createdDateTime+ge+*+and+createdDateTime+lt+*", + "url": "http://graph.microsoft.com/v1.0/resource_name/resource_relationship?$top=*&$filter=createdDateTime+ge+*+and+createdDateTime+lt+*", "method": "GET", "responseCode": 200, "responseBody": { @@ -50,7 +50,7 @@ } }, { - "url": "http://*/*/*/*$filter=createdDateTime+ge+*+and+createdDateTime+lt+*", + "url": "http://*/*/*/*$top=*&$filter=createdDateTime+ge+*+and+createdDateTime+lt+*", "method": "GET", "responseCode": 403, "responseBody": { From eb6ba15f8a86fda266713faa14f5ff9e261a00a5 Mon Sep 17 00:00:00 2001 From: Tomas Turina Date: Thu, 8 Aug 2024 20:07:51 +0000 Subject: [PATCH 09/13] feat(ms-graph): add devices information to detectedApps endpoint --- src/modules/ms_graph/include/wm_ms_graph.h | 3 +++ src/modules/ms_graph/src/wm_ms_graph.c | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/src/modules/ms_graph/include/wm_ms_graph.h b/src/modules/ms_graph/include/wm_ms_graph.h index 1b26904c4d..c8b6d2695e 100644 --- a/src/modules/ms_graph/include/wm_ms_graph.h +++ b/src/modules/ms_graph/include/wm_ms_graph.h @@ -43,6 +43,9 @@ // MDM Intune #define WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT "deviceManagement" #define WM_MS_GRAPH_RELATIONSHIP_AUDIT_EVENTS "auditEvents" +#define WM_MS_GRAPH_RELATIONSHIP_MANAGED_DEVICES "managedDevices" +#define WM_MS_GRAPH_RELATIONSHIP_DETECTED_APPS "detectedApps" +#define WM_MS_GRAPH_API_URL_EXPAND_DEVICES WM_MS_GRAPH_API_URL "&$expand=" WM_MS_GRAPH_RELATIONSHIP_MANAGED_DEVICES "($select=id)" typedef struct wm_ms_graph_state_t { time_t next_time; diff --git a/src/modules/ms_graph/src/wm_ms_graph.c b/src/modules/ms_graph/src/wm_ms_graph.c index 775de05fc4..3d803bfde6 100644 --- a/src/modules/ms_graph/src/wm_ms_graph.c +++ b/src/modules/ms_graph/src/wm_ms_graph.c @@ -265,6 +265,13 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_sc WM_MS_GRAPH_ITEM_PER_PAGE, start_time_str, end_time_str); + } else if (!strcmp(ms_graph->resources[resource_num].relationships[relationship_num], WM_MS_GRAPH_RELATIONSHIP_DETECTED_APPS)) { + snprintf(url, OS_SIZE_8192 - 1, WM_MS_GRAPH_API_URL_EXPAND_DEVICES, + it->query_fqdn, + ms_graph->version, + WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT, + ms_graph->resources[resource_num].relationships[relationship_num], + WM_MS_GRAPH_ITEM_PER_PAGE); } else { snprintf(url, OS_SIZE_8192 - 1, WM_MS_GRAPH_API_URL, it->query_fqdn, From 8d42b89ade612ac3b81a6e00bc3c31c4d6d32371 Mon Sep 17 00:00:00 2001 From: Tomas Turina Date: Thu, 8 Aug 2024 20:31:34 +0000 Subject: [PATCH 10/13] feat(ms-graph): add UT to test detectedApps intune resource --- .../tests/unit/tests/test_wm_ms_graph.c | 48 ++++--------------- 1 file changed, 9 insertions(+), 39 deletions(-) diff --git a/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c b/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c index 51bb68c6c6..660e14f0cc 100644 --- a/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c +++ b/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c @@ -2768,15 +2768,13 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { global - security - alerts_v2 + deviceManagement + detectedApps */ wm_ms_graph* module_data = (wm_ms_graph *)*state; - wm_ms_graph_state_t relationship_state_struc; os_calloc(1, sizeof(wm_ms_graph_auth), module_data->auth_config); os_calloc(1, sizeof(wm_ms_graph_auth), module_data->auth_config[0]); - relationship_state_struc.next_time = 10; module_data->enabled = true; module_data->only_future_events = false; module_data->curl_max_size = 1024L; @@ -2789,10 +2787,10 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { os_strdup(WM_MS_GRAPH_GLOBAL_API_LOGIN_FQDN, module_data->auth_config[0]->login_fqdn); os_strdup(WM_MS_GRAPH_GLOBAL_API_QUERY_FQDN, module_data->auth_config[0]->query_fqdn); os_malloc(sizeof(wm_ms_graph_resource), module_data->resources); - os_strdup("security", module_data->resources[0].name); + os_strdup("deviceManagement", module_data->resources[0].name); module_data->num_resources = 1; os_malloc(sizeof(char*), module_data->resources[0].relationships); - os_strdup("alerts_v2", module_data->resources[0].relationships[0]); + os_strdup("detectedApps", module_data->resources[0].relationships[0]); module_data->resources[0].num_relationships = 1; size_t max_size = OS_SIZE_8192; bool initial = false; @@ -2805,27 +2803,8 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { os_strdup("{\"value\":[{\"full_log\":\"log1\"},{\"full_log\":\"log2\"}]}", response->body); os_strdup("test", response->header); - expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-security-alerts_v2"); - expect_value(__wrap_wm_state_io, op, WM_IO_READ); - expect_any(__wrap_wm_state_io, state); - expect_any(__wrap_wm_state_io, size); - will_return(__wrap_wm_state_io, 0); - will_return(__wrap_wm_state_io, (void *)&relationship_state_struc); - -#ifndef WIN32 - will_return(__wrap_gmtime_r, 1); -#endif - will_return(__wrap_strftime,"2023-02-08T12:24:56Z"); - will_return(__wrap_strftime, 20); - -#ifndef WIN32 - will_return(__wrap_gmtime_r, 1); -#endif - will_return(__wrap_strftime,"2023-02-08T12:25:56Z"); - will_return(__wrap_strftime, 20); - expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/security/alerts_v2?$top=100&$filter=createdDateTime+ge+2023-02-08T12:24:56Z+and+createdDateTime+lt+2023-02-08T12:25:56Z'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/deviceManagement/detectedApps?$top=100&$expand=managedDevices($select=id)'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2836,12 +2815,12 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { will_return(__wrap_wurl_http_request, response); expect_string(__wrap__mtdebug2, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"resource\":\"security\",\"relationship\":\"alerts_v2\"}}'"); + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}'"); queue_fd = 0; expect_value(__wrap_wm_sendmsg, usec, 1000000); expect_value(__wrap_wm_sendmsg, queue, queue_fd); - expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"resource\":\"security\",\"relationship\":\"alerts_v2\"}}"); + expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}"); expect_string(__wrap_wm_sendmsg, locmsg, "ms-graph"); expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); will_return(__wrap_wm_sendmsg, -1); @@ -2852,24 +2831,15 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { expect_string(__wrap__mterror, formatted_msg, "(1210): Queue 'queue/sockets/queue' not accessible: 'Error'"); expect_string(__wrap__mtdebug2, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"resource\":\"security\",\"relationship\":\"alerts_v2\"}}'"); + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}'"); expect_value(__wrap_wm_sendmsg, usec, 1000000); expect_value(__wrap_wm_sendmsg, queue, queue_fd); - expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"resource\":\"security\",\"relationship\":\"alerts_v2\"}}"); + expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}"); expect_string(__wrap_wm_sendmsg, locmsg, "ms-graph"); expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); will_return(__wrap_wm_sendmsg, 1); - expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-security-alerts_v2"); - expect_value(__wrap_wm_state_io, op, WM_IO_WRITE); - expect_any(__wrap_wm_state_io, state); - expect_any(__wrap_wm_state_io, size); - will_return(__wrap_wm_state_io, 1); - - expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Bookmark updated to '2023-02-08T12:25:56Z' for tenant 'example_tenant' resource 'security' and relationship 'alerts_v2', waiting '60' seconds to run next scan."); - wm_ms_graph_scan_relationships(module_data, initial); } From 647fc1a7fe6b2bed0fa4102d17bffa4df7c03727 Mon Sep 17 00:00:00 2001 From: Tomas Turina Date: Mon, 12 Aug 2024 21:28:08 +0000 Subject: [PATCH 11/13] fix(ms-graph): intune - expand devices in apps endpoint with a second api call --- src/modules/ms_graph/include/wm_ms_graph.h | 3 +- src/modules/ms_graph/src/wm_ms_graph.c | 337 ++++++++++-------- .../tests/unit/tests/test_wm_ms_graph.c | 34 +- 3 files changed, 210 insertions(+), 164 deletions(-) diff --git a/src/modules/ms_graph/include/wm_ms_graph.h b/src/modules/ms_graph/include/wm_ms_graph.h index c8b6d2695e..84b73d331c 100644 --- a/src/modules/ms_graph/include/wm_ms_graph.h +++ b/src/modules/ms_graph/include/wm_ms_graph.h @@ -41,11 +41,12 @@ #define WM_MS_GRAPH_ITEM_PER_PAGE 100 // MDM Intune +#define WM_MS_GRAPH_API_URL_DEVICES_EXPANDED "https://%s/%s/%s/%s/%s/%s?$top=%d" +#define WM_MS_GRAPH_API_URL_FILTER_DEVICE_FIELDS WM_MS_GRAPH_API_URL_DEVICES_EXPANDED "&$select=id,deviceName" #define WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT "deviceManagement" #define WM_MS_GRAPH_RELATIONSHIP_AUDIT_EVENTS "auditEvents" #define WM_MS_GRAPH_RELATIONSHIP_MANAGED_DEVICES "managedDevices" #define WM_MS_GRAPH_RELATIONSHIP_DETECTED_APPS "detectedApps" -#define WM_MS_GRAPH_API_URL_EXPAND_DEVICES WM_MS_GRAPH_API_URL "&$expand=" WM_MS_GRAPH_RELATIONSHIP_MANAGED_DEVICES "($select=id)" typedef struct wm_ms_graph_state_t { time_t next_time; diff --git a/src/modules/ms_graph/src/wm_ms_graph.c b/src/modules/ms_graph/src/wm_ms_graph.c index 3d803bfde6..2e14c79854 100644 --- a/src/modules/ms_graph/src/wm_ms_graph.c +++ b/src/modules/ms_graph/src/wm_ms_graph.c @@ -26,7 +26,8 @@ static void* wm_ms_graph_main(wm_ms_graph* ms_graph); static bool wm_ms_graph_setup(wm_ms_graph* ms_graph); static bool wm_ms_graph_check(); static void wm_ms_graph_get_access_token(wm_ms_graph_auth* auth_config, const ssize_t curl_max_size); -static void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_scan); +static void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, wm_ms_graph_auth* auth_config, const bool initial_scan); +static cJSON* wm_ms_graph_scan_apps_devices(const wm_ms_graph* ms_graph, const cJSON* app_id, const char* query_fqdn, char** headers); static void wm_ms_graph_destroy(wm_ms_graph* ms_graph); static void wm_ms_graph_cleanup(); cJSON* wm_ms_graph_dump(const wm_ms_graph* ms_graph); @@ -80,7 +81,7 @@ void* wm_ms_graph_main(wm_ms_graph* ms_graph) { if (it->access_token && time(NULL) < it->token_expiration_time) { mtinfo(WM_MS_GRAPH_LOGTAG, "Scanning tenant '%s'", it->tenant_id); - wm_ms_graph_scan_relationships(ms_graph, initial); + wm_ms_graph_scan_relationships(ms_graph, it, initial); initial = false; } } @@ -186,7 +187,7 @@ void wm_ms_graph_get_access_token(wm_ms_graph_auth* auth_config, const ssize_t c } } -void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_scan) { +void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, wm_ms_graph_auth* auth_config, const bool initial_scan) { char url[OS_SIZE_8192] = { '\0' }; char auth_header[OS_SIZE_8192] = { '\0' }; char* headers[] = { NULL, NULL }; @@ -205,179 +206,223 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, const bool initial_sc for (unsigned int relationship_num = 0; relationship_num < ms_graph->resources[resource_num].num_relationships; relationship_num++) { - int e; - wm_ms_graph_auth *it; - - for (e = 0; ms_graph->auth_config[e]; e++) { - it = ms_graph->auth_config[e]; - - if (!strcmp(ms_graph->resources[resource_num].name, WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT)) { - // If not auditEvents, treat as inventory - if (strcmp(ms_graph->resources[resource_num].relationships[relationship_num], WM_MS_GRAPH_RELATIONSHIP_AUDIT_EVENTS)) { - inventory = true; - } + if (!strcmp(ms_graph->resources[resource_num].name, WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT)) { + // If not auditEvents, treat as inventory + if (strcmp(ms_graph->resources[resource_num].relationships[relationship_num], WM_MS_GRAPH_RELATIONSHIP_AUDIT_EVENTS)) { + inventory = true; } + } + + if (!inventory) { + snprintf(relationship_state_name, OS_SIZE_1024 -1, "%s-%s-%s-%s", WM_MS_GRAPH_CONTEXT.name, + auth_config->tenant_id, ms_graph->resources[resource_num].name, ms_graph->resources[resource_num].relationships[relationship_num]); - if (!inventory) { - snprintf(relationship_state_name, OS_SIZE_1024 -1, "%s-%s-%s-%s", WM_MS_GRAPH_CONTEXT.name, - it->tenant_id, ms_graph->resources[resource_num].name, ms_graph->resources[resource_num].relationships[relationship_num]); + memset(&relationship_state_struc, 0, sizeof(relationship_state_struc)); + // Load state for tenant-resource-relationship + if (wm_state_io(relationship_state_name, WM_IO_READ, &relationship_state_struc, sizeof(relationship_state_struc)) < 0) { memset(&relationship_state_struc, 0, sizeof(relationship_state_struc)); + } - // Load state for tenant-resource-relationship - if (wm_state_io(relationship_state_name, WM_IO_READ, &relationship_state_struc, sizeof(relationship_state_struc)) < 0) { - memset(&relationship_state_struc, 0, sizeof(relationship_state_struc)); - } + now = time(0); - now = time(0); - - if ((initial_scan && (!relationship_state_struc.next_time || ms_graph->only_future_events)) || - (!initial_scan && !relationship_state_struc.next_time)) { - relationship_state_struc.next_time = now; - if (wm_state_io(relationship_state_name, WM_IO_WRITE, &relationship_state_struc, sizeof(relationship_state_struc)) < 0) { - mterror(WM_MS_GRAPH_LOGTAG, "Couldn't save running state."); - } else if (isDebug()) { - gmtime_r(&now, &tm_aux); - strftime(start_time_str, sizeof(start_time_str), "%Y-%m-%dT%H:%M:%SZ", &tm_aux); - mtdebug1(WM_MS_GRAPH_LOGTAG, "Bookmark updated to '%s' for tenant '%s' resource '%s' and relationship '%s', waiting '%d' seconds to run first scan.", - start_time_str, it->tenant_id, ms_graph->resources[resource_num].name, ms_graph->resources[resource_num].relationships[relationship_num], ms_graph->scan_config.interval); - } - continue; + if ((initial_scan && (!relationship_state_struc.next_time || ms_graph->only_future_events)) || + (!initial_scan && !relationship_state_struc.next_time)) { + relationship_state_struc.next_time = now; + if (wm_state_io(relationship_state_name, WM_IO_WRITE, &relationship_state_struc, sizeof(relationship_state_struc)) < 0) { + mterror(WM_MS_GRAPH_LOGTAG, "Couldn't save running state."); + } else if (isDebug()) { + gmtime_r(&now, &tm_aux); + strftime(start_time_str, sizeof(start_time_str), "%Y-%m-%dT%H:%M:%SZ", &tm_aux); + mtdebug1(WM_MS_GRAPH_LOGTAG, "Bookmark updated to '%s' for tenant '%s' resource '%s' and relationship '%s', waiting '%d' seconds to run first scan.", + start_time_str, auth_config->tenant_id, ms_graph->resources[resource_num].name, ms_graph->resources[resource_num].relationships[relationship_num], ms_graph->scan_config.interval); } + continue; + } - gmtime_r(&relationship_state_struc.next_time, &tm_aux); - strftime(start_time_str, sizeof(start_time_str), "%Y-%m-%dT%H:%M:%SZ", &tm_aux); + gmtime_r(&relationship_state_struc.next_time, &tm_aux); + strftime(start_time_str, sizeof(start_time_str), "%Y-%m-%dT%H:%M:%SZ", &tm_aux); - gmtime_r(&now, &tm_aux); - strftime(end_time_str, sizeof(end_time_str), "%Y-%m-%dT%H:%M:%SZ", &tm_aux); - } + gmtime_r(&now, &tm_aux); + strftime(end_time_str, sizeof(end_time_str), "%Y-%m-%dT%H:%M:%SZ", &tm_aux); + } - snprintf(auth_header, OS_SIZE_8192 - 1, "Authorization: Bearer %s", it->access_token); - os_strdup(auth_header, headers[0]); - - if (!strcmp(ms_graph->resources[resource_num].name, WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT)) { - if (!strcmp(ms_graph->resources[resource_num].relationships[relationship_num], WM_MS_GRAPH_RELATIONSHIP_AUDIT_EVENTS)) { - snprintf(url, OS_SIZE_8192 - 1, WM_MS_GRAPH_API_URL_FILTER_ACTIVITY_DATE, - it->query_fqdn, - ms_graph->version, - WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT, - WM_MS_GRAPH_RELATIONSHIP_AUDIT_EVENTS, - WM_MS_GRAPH_ITEM_PER_PAGE, - start_time_str, - end_time_str); - } else if (!strcmp(ms_graph->resources[resource_num].relationships[relationship_num], WM_MS_GRAPH_RELATIONSHIP_DETECTED_APPS)) { - snprintf(url, OS_SIZE_8192 - 1, WM_MS_GRAPH_API_URL_EXPAND_DEVICES, - it->query_fqdn, - ms_graph->version, - WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT, - ms_graph->resources[resource_num].relationships[relationship_num], - WM_MS_GRAPH_ITEM_PER_PAGE); - } else { - snprintf(url, OS_SIZE_8192 - 1, WM_MS_GRAPH_API_URL, - it->query_fqdn, - ms_graph->version, - WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT, - ms_graph->resources[resource_num].relationships[relationship_num], - WM_MS_GRAPH_ITEM_PER_PAGE); - } - } else { - snprintf(url, OS_SIZE_8192 - 1, WM_MS_GRAPH_API_URL_FILTER_CREATED_DATE, - it->query_fqdn, + snprintf(auth_header, OS_SIZE_8192 - 1, "Authorization: Bearer %s", auth_config->access_token); + os_strdup(auth_header, headers[0]); + + if (!strcmp(ms_graph->resources[resource_num].name, WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT)) { + if (!strcmp(ms_graph->resources[resource_num].relationships[relationship_num], WM_MS_GRAPH_RELATIONSHIP_AUDIT_EVENTS)) { + snprintf(url, OS_SIZE_8192 - 1, WM_MS_GRAPH_API_URL_FILTER_ACTIVITY_DATE, + auth_config->query_fqdn, ms_graph->version, - ms_graph->resources[resource_num].name, - ms_graph->resources[resource_num].relationships[relationship_num], + WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT, + WM_MS_GRAPH_RELATIONSHIP_AUDIT_EVENTS, WM_MS_GRAPH_ITEM_PER_PAGE, start_time_str, end_time_str); + } else { + snprintf(url, OS_SIZE_8192 - 1, WM_MS_GRAPH_API_URL, + auth_config->query_fqdn, + ms_graph->version, + WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT, + ms_graph->resources[resource_num].relationships[relationship_num], + WM_MS_GRAPH_ITEM_PER_PAGE); } + } else { + snprintf(url, OS_SIZE_8192 - 1, WM_MS_GRAPH_API_URL_FILTER_CREATED_DATE, + auth_config->query_fqdn, + ms_graph->version, + ms_graph->resources[resource_num].name, + ms_graph->resources[resource_num].relationships[relationship_num], + WM_MS_GRAPH_ITEM_PER_PAGE, + start_time_str, + end_time_str); + } - next_page = true; - while (next_page) { - mtdebug1(WM_MS_GRAPH_LOGTAG, "Microsoft Graph API Log URL: '%s'", url); - - fail = true; - next_page = false; - response = wurl_http_request(WURL_GET_METHOD, headers, url, "", ms_graph->curl_max_size, WM_MS_GRAPH_DEFAULT_TIMEOUT); - if (response) { - if (response->status_code != 200) { - char status_code[4]; - snprintf(status_code, 4, "%ld", response->status_code); - mtwarn(WM_MS_GRAPH_LOGTAG, "Received unsuccessful status code when attempting to get relationship '%s' logs: Status code was '%s' & response was '%s'", - ms_graph->resources[resource_num].relationships[relationship_num], - status_code, - response->body); - } else if (response->max_size_reached) { - mtwarn(WM_MS_GRAPH_LOGTAG, "Reached maximum CURL size when attempting to get relationship '%s' logs. Consider increasing the value of 'curl_max_size'.", - ms_graph->resources[resource_num].relationships[relationship_num]); - } else { - cJSON* body_parse = NULL; - if (body_parse = cJSON_Parse(response->body), body_parse) { - cJSON* logs = cJSON_GetObjectItem(body_parse, "value"); - int num_logs = cJSON_GetArraySize(logs); - if (num_logs > 0) { - for (int log_index = 0; log_index < num_logs; log_index++) { - cJSON* log = NULL; - if (log = cJSON_GetArrayItem(logs, log_index), log) { - cJSON* full_log = cJSON_CreateObject(); - char* payload; - - cJSON_AddStringToObject(log, "resource", ms_graph->resources[resource_num].name); - cJSON_AddStringToObject(log, "relationship", ms_graph->resources[resource_num].relationships[relationship_num]); - cJSON_AddStringToObject(full_log, "integration", WM_MS_GRAPH_CONTEXT.name); - cJSON_AddItemToObject(full_log, WM_MS_GRAPH_CONTEXT.name, cJSON_Duplicate(log, true)); - - payload = cJSON_PrintUnformatted(full_log); - mtdebug2(WM_MS_GRAPH_LOGTAG, "Sending log: '%s'", payload); - if (wm_sendmsg(1000000 / wm_max_eps, queue_fd, payload, WM_MS_GRAPH_CONTEXT.name, LOCALFILE_MQ) < 0) { - mterror(WM_MS_GRAPH_LOGTAG, QUEUE_ERROR, DEFAULTQUEUE, strerror(errno)); - } - - os_free(payload); - cJSON_Delete(full_log); - } else { - mtwarn(WM_MS_GRAPH_LOGTAG, "Failed to parse log array into singular log."); + next_page = true; + while (next_page) { + mtdebug1(WM_MS_GRAPH_LOGTAG, "Microsoft Graph API Log URL: '%s'", url); + + fail = true; + next_page = false; + response = wurl_http_request(WURL_GET_METHOD, headers, url, "", ms_graph->curl_max_size, WM_MS_GRAPH_DEFAULT_TIMEOUT); + if (response) { + if (response->status_code != 200) { + char status_code[4]; + snprintf(status_code, 4, "%ld", response->status_code); + mtwarn(WM_MS_GRAPH_LOGTAG, "Received unsuccessful status code when attempting to get relationship '%s' logs: Status code was '%s' & response was '%s'", + ms_graph->resources[resource_num].relationships[relationship_num], + status_code, + response->body); + if (response->status_code == 401) { + auth_config->token_expiration_time = time(NULL); + } + } else if (response->max_size_reached) { + mtwarn(WM_MS_GRAPH_LOGTAG, "Reached maximum CURL size when attempting to get relationship '%s' logs. Consider increasing the value of 'curl_max_size'.", + ms_graph->resources[resource_num].relationships[relationship_num]); + } else { + cJSON* body_parse = NULL; + if (body_parse = cJSON_Parse(response->body), body_parse) { + cJSON* logs = cJSON_GetObjectItem(body_parse, "value"); + int num_logs = cJSON_GetArraySize(logs); + if (num_logs > 0) { + for (int log_index = 0; log_index < num_logs; log_index++) { + cJSON* log = NULL; + if (log = cJSON_GetArrayItem(logs, log_index), log) { + cJSON* full_log = cJSON_CreateObject(); + char* payload; + + if (inventory && !strcmp(ms_graph->resources[resource_num].relationships[relationship_num], WM_MS_GRAPH_RELATIONSHIP_DETECTED_APPS)) { + cJSON_AddItemToObject(log, WM_MS_GRAPH_RELATIONSHIP_MANAGED_DEVICES, + wm_ms_graph_scan_apps_devices(ms_graph, cJSON_GetObjectItem(log, "id"), auth_config->query_fqdn, headers)); } - } - fail = false; - } else { - mtdebug2(WM_MS_GRAPH_LOGTAG, "No new logs received."); - fail = false; - } - cJSON* next_url = cJSON_GetObjectItem(body_parse, "@odata.nextLink"); - if (cJSON_IsString(next_url)) { - memset(url, '\0', OS_SIZE_8192); - snprintf(url, OS_SIZE_8192 -1, "%s", next_url->valuestring); - next_page = true; - } + cJSON_AddStringToObject(log, "resource", ms_graph->resources[resource_num].name); + cJSON_AddStringToObject(log, "relationship", ms_graph->resources[resource_num].relationships[relationship_num]); + cJSON_AddStringToObject(full_log, "integration", WM_MS_GRAPH_CONTEXT.name); + cJSON_AddItemToObject(full_log, WM_MS_GRAPH_CONTEXT.name, cJSON_Duplicate(log, true)); + + payload = cJSON_PrintUnformatted(full_log); + mtdebug2(WM_MS_GRAPH_LOGTAG, "Sending log: '%s'", payload); + if (wm_sendmsg(1000000 / wm_max_eps, queue_fd, payload, WM_MS_GRAPH_CONTEXT.name, LOCALFILE_MQ) < 0) { + mterror(WM_MS_GRAPH_LOGTAG, QUEUE_ERROR, DEFAULTQUEUE, strerror(errno)); + } - cJSON_Delete(body_parse); + os_free(payload); + cJSON_Delete(full_log); + } else { + mtwarn(WM_MS_GRAPH_LOGTAG, "Failed to parse log array into singular log."); + } + } + fail = false; } else { - mtwarn(WM_MS_GRAPH_LOGTAG, "Failed to parse relationship '%s' JSON body.", ms_graph->resources[resource_num].relationships[relationship_num]); + mtdebug2(WM_MS_GRAPH_LOGTAG, "No new logs received."); + fail = false; + } + + cJSON* next_url = cJSON_GetObjectItem(body_parse, "@odata.nextLink"); + if (cJSON_IsString(next_url)) { + memset(url, '\0', OS_SIZE_8192); + snprintf(url, OS_SIZE_8192 -1, "%s", next_url->valuestring); + next_page = true; } + + cJSON_Delete(body_parse); + } else { + mtwarn(WM_MS_GRAPH_LOGTAG, "Failed to parse relationship '%s' JSON body.", ms_graph->resources[resource_num].relationships[relationship_num]); } - wurl_free_response(response); - } else { - mtwarn(WM_MS_GRAPH_LOGTAG, "No response received when attempting to get relationship '%s' from resource '%s' on API version '%s'.", - ms_graph->resources[resource_num].relationships[relationship_num], - ms_graph->resources[resource_num].name, - ms_graph->version); } + wurl_free_response(response); + } else { + mtwarn(WM_MS_GRAPH_LOGTAG, "No response received when attempting to get relationship '%s' from resource '%s' on API version '%s'.", + ms_graph->resources[resource_num].relationships[relationship_num], + ms_graph->resources[resource_num].name, + ms_graph->version); } + } - if (!inventory && !fail) { - relationship_state_struc.next_time = now; - if (wm_state_io(relationship_state_name, WM_IO_WRITE, &relationship_state_struc, sizeof(relationship_state_struc)) < 0) { - mterror(WM_MS_GRAPH_LOGTAG, "Couldn't save running state."); - } else { - mtdebug1(WM_MS_GRAPH_LOGTAG, "Bookmark updated to '%s' for tenant '%s' resource '%s' and relationship '%s', waiting '%d' seconds to run next scan.", - end_time_str, it->tenant_id, ms_graph->resources[resource_num].name, ms_graph->resources[resource_num].relationships[relationship_num], ms_graph->scan_config.interval); + if (!inventory && !fail) { + relationship_state_struc.next_time = now; + if (wm_state_io(relationship_state_name, WM_IO_WRITE, &relationship_state_struc, sizeof(relationship_state_struc)) < 0) { + mterror(WM_MS_GRAPH_LOGTAG, "Couldn't save running state."); + } else { + mtdebug1(WM_MS_GRAPH_LOGTAG, "Bookmark updated to '%s' for tenant '%s' resource '%s' and relationship '%s', waiting '%d' seconds to run next scan.", + end_time_str, auth_config->tenant_id, ms_graph->resources[resource_num].name, ms_graph->resources[resource_num].relationships[relationship_num], ms_graph->scan_config.interval); + } + } + os_free(headers[0]); + } + } +} + +cJSON* wm_ms_graph_scan_apps_devices(const wm_ms_graph* ms_graph, const cJSON* app_id, const char* query_fqdn, char** headers) { + char url[OS_SIZE_8192] = { '\0' }; + curl_response* response; + bool next_page; + + cJSON *array = cJSON_CreateArray(); + + if (cJSON_IsString(app_id)) { + snprintf(url, OS_SIZE_8192 - 1, WM_MS_GRAPH_API_URL_FILTER_DEVICE_FIELDS, query_fqdn, ms_graph->version, WM_MS_GRAPH_RESOURCE_DEVICE_MANAGEMENT, + WM_MS_GRAPH_RELATIONSHIP_DETECTED_APPS, app_id->valuestring, WM_MS_GRAPH_RELATIONSHIP_MANAGED_DEVICES, WM_MS_GRAPH_ITEM_PER_PAGE); + + next_page = true; + while (next_page) { + mtdebug1(WM_MS_GRAPH_LOGTAG, "Microsoft Graph API Log URL: '%s'", url); + + next_page = false; + response = wurl_http_request(WURL_GET_METHOD, headers, url, "", ms_graph->curl_max_size, WM_MS_GRAPH_DEFAULT_TIMEOUT); + if (response) { + if (response->status_code == 200 && !response->max_size_reached) { + cJSON* body_parse = NULL; + if (body_parse = cJSON_Parse(response->body), body_parse) { + cJSON* logs = cJSON_GetObjectItem(body_parse, "value"); + int num_logs = cJSON_GetArraySize(logs); + if (num_logs > 0) { + for (int log_index = 0; log_index < num_logs; log_index++) { + cJSON* log = NULL; + if (log = cJSON_GetArrayItem(logs, log_index), log) { + cJSON_AddItemToArray(array, cJSON_Duplicate(log, true)); + } + } + } + + cJSON* next_url = cJSON_GetObjectItem(body_parse, "@odata.nextLink"); + if (cJSON_IsString(next_url)) { + memset(url, '\0', OS_SIZE_8192); + snprintf(url, OS_SIZE_8192 -1, "%s", next_url->valuestring); + next_page = true; + } + + cJSON_Delete(body_parse); } } - os_free(headers[0]); + wurl_free_response(response); } } } + + return array; } void wm_ms_graph_destroy(wm_ms_graph* ms_graph) { diff --git a/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c b/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c index 660e14f0cc..a3d05131d0 100644 --- a/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c +++ b/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c @@ -2086,7 +2086,7 @@ void test_wm_ms_graph_scan_relationships_single_initial_only_no(void **state) { expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); expect_string(__wrap__mtdebug1, formatted_msg, "Bookmark updated to '2023-02-08T12:24:56Z' for tenant 'example_tenant' resource 'security' and relationship 'alerts_v2', waiting '60' seconds to run first scan."); - wm_ms_graph_scan_relationships(module_data, initial); + wm_ms_graph_scan_relationships(module_data, module_data->auth_config[0], initial); } void test_wm_ms_graph_scan_relationships_single_initial_only_yes_fail_write(void **state) { @@ -2145,7 +2145,7 @@ void test_wm_ms_graph_scan_relationships_single_initial_only_yes_fail_write(void expect_string(__wrap__mterror, tag, WM_MS_GRAPH_LOGTAG); expect_string(__wrap__mterror, formatted_msg, "Couldn't save running state."); - wm_ms_graph_scan_relationships(module_data, initial); + wm_ms_graph_scan_relationships(module_data, module_data->auth_config[0], initial); } void test_wm_ms_graph_scan_relationships_single_initial_only_no_next_time_no_response(void **state) { @@ -2225,7 +2225,7 @@ void test_wm_ms_graph_scan_relationships_single_initial_only_no_next_time_no_res expect_string(__wrap__mtwarn, tag, "wazuh-modulesd:ms-graph"); expect_string(__wrap__mtwarn, formatted_msg, "No response received when attempting to get relationship 'alerts_v2' from resource 'security' on API version 'v1.0'."); - wm_ms_graph_scan_relationships(module_data, initial); + wm_ms_graph_scan_relationships(module_data, module_data->auth_config[0], initial); } void test_wm_ms_graph_scan_relationships_single_no_initial_no_timestamp(void **state) { @@ -2294,7 +2294,7 @@ void test_wm_ms_graph_scan_relationships_single_no_initial_no_timestamp(void **s expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); expect_string(__wrap__mtdebug1, formatted_msg, "Bookmark updated to '2023-02-08T12:24:56Z' for tenant 'example_tenant' resource 'security' and relationship 'alerts_v2', waiting '60' seconds to run first scan."); - wm_ms_graph_scan_relationships(module_data, initial); + wm_ms_graph_scan_relationships(module_data, module_data->auth_config[0], initial); } void test_wm_ms_graph_scan_relationships_single_unsuccessful_status_code(void **state) { @@ -2379,7 +2379,7 @@ void test_wm_ms_graph_scan_relationships_single_unsuccessful_status_code(void ** expect_string(__wrap__mtwarn, tag, "wazuh-modulesd:ms-graph"); expect_string(__wrap__mtwarn, formatted_msg, "Received unsuccessful status code when attempting to get relationship 'alerts_v2' logs: Status code was '400' & response was '{\"error\":\"bad_request\"}'"); - wm_ms_graph_scan_relationships(module_data, initial); + wm_ms_graph_scan_relationships(module_data, module_data->auth_config[0], initial); } void test_wm_ms_graph_scan_relationships_single_reached_curl_size(void **state) { @@ -2465,7 +2465,7 @@ void test_wm_ms_graph_scan_relationships_single_reached_curl_size(void **state) expect_string(__wrap__mtwarn, tag, "wazuh-modulesd:ms-graph"); expect_string(__wrap__mtwarn, formatted_msg, "Reached maximum CURL size when attempting to get relationship 'alerts_v2' logs. Consider increasing the value of 'curl_max_size'."); - wm_ms_graph_scan_relationships(module_data, initial); + wm_ms_graph_scan_relationships(module_data, module_data->auth_config[0], initial); } void test_wm_ms_graph_scan_relationships_single_failed_parse(void **state) { @@ -2551,7 +2551,7 @@ void test_wm_ms_graph_scan_relationships_single_failed_parse(void **state) { expect_string(__wrap__mtwarn, tag, "wazuh-modulesd:ms-graph"); expect_string(__wrap__mtwarn, formatted_msg, "Failed to parse relationship 'alerts_v2' JSON body."); - wm_ms_graph_scan_relationships(module_data, initial); + wm_ms_graph_scan_relationships(module_data, module_data->auth_config[0], initial); } void test_wm_ms_graph_scan_relationships_single_no_logs(void **state) { @@ -2646,7 +2646,7 @@ void test_wm_ms_graph_scan_relationships_single_no_logs(void **state) { expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); expect_string(__wrap__mtdebug1, formatted_msg, "Bookmark updated to '2023-02-08T12:25:56Z' for tenant 'example_tenant' resource 'security' and relationship 'alerts_v2', waiting '60' seconds to run next scan."); - wm_ms_graph_scan_relationships(module_data, initial); + wm_ms_graph_scan_relationships(module_data, module_data->auth_config[0], initial); } void test_wm_ms_graph_scan_relationships_single_success_one_log(void **state) { @@ -2751,7 +2751,7 @@ void test_wm_ms_graph_scan_relationships_single_success_one_log(void **state) { expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); expect_string(__wrap__mtdebug1, formatted_msg, "Bookmark updated to '2023-02-08T12:25:56Z' for tenant 'example_tenant' resource 'security' and relationship 'alerts_v2', waiting '60' seconds to run next scan."); - wm_ms_graph_scan_relationships(module_data, initial); + wm_ms_graph_scan_relationships(module_data, module_data->auth_config[0], initial); } void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { @@ -2804,7 +2804,7 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { os_strdup("test", response->header); expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/deviceManagement/detectedApps?$top=100&$expand=managedDevices($select=id)'"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/deviceManagement/detectedApps?$top=100'"); expect_any(__wrap_wurl_http_request, method); expect_any(__wrap_wurl_http_request, header); @@ -2815,12 +2815,12 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { will_return(__wrap_wurl_http_request, response); expect_string(__wrap__mtdebug2, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}'"); + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}'"); queue_fd = 0; expect_value(__wrap_wm_sendmsg, usec, 1000000); expect_value(__wrap_wm_sendmsg, queue, queue_fd); - expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}"); + expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}"); expect_string(__wrap_wm_sendmsg, locmsg, "ms-graph"); expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); will_return(__wrap_wm_sendmsg, -1); @@ -2831,16 +2831,16 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { expect_string(__wrap__mterror, formatted_msg, "(1210): Queue 'queue/sockets/queue' not accessible: 'Error'"); expect_string(__wrap__mtdebug2, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}'"); + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}'"); expect_value(__wrap_wm_sendmsg, usec, 1000000); expect_value(__wrap_wm_sendmsg, queue, queue_fd); - expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}"); + expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}"); expect_string(__wrap_wm_sendmsg, locmsg, "ms-graph"); expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); will_return(__wrap_wm_sendmsg, 1); - wm_ms_graph_scan_relationships(module_data, initial); + wm_ms_graph_scan_relationships(module_data, module_data->auth_config[0], initial); } void test_wm_ms_graph_scan_relationships_single_success_two_pages(void **state) { @@ -2958,7 +2958,7 @@ void test_wm_ms_graph_scan_relationships_single_success_two_pages(void **state) expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); will_return(__wrap_wm_sendmsg, 1); - wm_ms_graph_scan_relationships(module_data, initial); + wm_ms_graph_scan_relationships(module_data, module_data->auth_config[0], initial); } void test_wm_ms_graph_scan_relationships_single_success_two_resources(void **state) { @@ -3129,7 +3129,7 @@ void test_wm_ms_graph_scan_relationships_single_success_two_resources(void **sta expect_string(__wrap__mterror, tag, "wazuh-modulesd:ms-graph"); expect_string(__wrap__mterror, formatted_msg, "Couldn't save running state."); - wm_ms_graph_scan_relationships(module_data, initial); + wm_ms_graph_scan_relationships(module_data, module_data->auth_config[0], initial); } int main(void) { From 1ab8cd40ab7f5bc61d0a473004debf413951878b Mon Sep 17 00:00:00 2001 From: Tomas Turina Date: Thu, 15 Aug 2024 19:39:31 +0000 Subject: [PATCH 12/13] feat(ms-graph): add scan id to inventory events --- src/modules/ms_graph/src/wm_ms_graph.c | 19 +++ .../ms_graph/tests/unit/tests/CMakeLists.txt | 4 +- .../tests/unit/tests/test_wm_ms_graph.c | 138 ++++++++++++++++-- 3 files changed, 149 insertions(+), 12 deletions(-) diff --git a/src/modules/ms_graph/src/wm_ms_graph.c b/src/modules/ms_graph/src/wm_ms_graph.c index 2e14c79854..99181e694d 100644 --- a/src/modules/ms_graph/src/wm_ms_graph.c +++ b/src/modules/ms_graph/src/wm_ms_graph.c @@ -202,6 +202,21 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, wm_ms_graph_auth* aut bool next_page; bool inventory = false; +#ifndef WIN32 + int id = os_random(); + if (id < 0) { + id = -id; + } +#else + char random_id[RANDOM_LENGTH]; + snprintf(random_id, RANDOM_LENGTH - 1, "%u%u", os_random(), os_random()); + int id = atoi(random_id); + + if (id < 0) { + id = -id; + } +#endif + for (unsigned int resource_num = 0; resource_num < ms_graph->num_resources; resource_num++) { for (unsigned int relationship_num = 0; relationship_num < ms_graph->resources[resource_num].num_relationships; relationship_num++) { @@ -319,6 +334,10 @@ void wm_ms_graph_scan_relationships(wm_ms_graph* ms_graph, wm_ms_graph_auth* aut cJSON_AddStringToObject(log, "resource", ms_graph->resources[resource_num].name); cJSON_AddStringToObject(log, "relationship", ms_graph->resources[resource_num].relationships[relationship_num]); + + if (inventory) { + cJSON_AddNumberToObject(full_log, "scan_id", id); + } cJSON_AddStringToObject(full_log, "integration", WM_MS_GRAPH_CONTEXT.name); cJSON_AddItemToObject(full_log, WM_MS_GRAPH_CONTEXT.name, cJSON_Duplicate(log, true)); diff --git a/src/modules/ms_graph/tests/unit/tests/CMakeLists.txt b/src/modules/ms_graph/tests/unit/tests/CMakeLists.txt index 9acd16bef5..3560d86449 100644 --- a/src/modules/ms_graph/tests/unit/tests/CMakeLists.txt +++ b/src/modules/ms_graph/tests/unit/tests/CMakeLists.txt @@ -14,8 +14,8 @@ list(APPEND tests_flags "-Wl,--wrap=_merror -Wl,--wrap=_mtinfo -Wl,--wrap=_mtwar -Wl,--wrap,atexit -Wl,--wrap,time -Wl,--wrap,wm_state_io -Wl,--wrap,StartMQ -Wl,--wrap,gmtime_r -Wl,--wrap,isDebug \ -Wl,--wrap,sched_scan_get_time_until_next_scan -Wl,--wrap,is_fim_shutdown -Wl,--wrap,fim_db_teardown -Wl,--wrap,Start_win32_Syscheck \ -Wl,--wrap,strftime -Wl,--wrap,_mtdebug2 -Wl,--wrap,wm_sendmsg -Wl,--wrap,strerror -Wl,--wrap,_imp__rsync_initialize \ - -Wl,--wrap,syscom_dispatch -Wl,--wrap,_imp__dbsync_initialize -Wl,--wrap,w_get_timestamp -Wl,--wrap,FOREVER") - + -Wl,--wrap,syscom_dispatch -Wl,--wrap,_imp__dbsync_initialize -Wl,--wrap,w_get_timestamp -Wl,--wrap,os_random -Wl,--wrap,FOREVER") + list(APPEND use_shared_libs 1) diff --git a/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c b/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c index a3d05131d0..63f4299e40 100644 --- a/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c +++ b/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c @@ -1361,6 +1361,12 @@ void test_main_relationships(void **state) { will_return(__wrap_FOREVER, 1); +#ifdef TEST_WINAGENT + will_return_count(__wrap_os_random, 12345, 2); +#else + will_return(__wrap_os_random, 12345); +#endif + expect_string(__wrap_wm_state_io, tag, "ms-graph"); expect_value(__wrap_wm_state_io, op, WM_IO_READ); expect_value(__wrap_wm_state_io, state, &module_data->state); @@ -2063,6 +2069,12 @@ void test_wm_ms_graph_scan_relationships_single_initial_only_no(void **state) { size_t max_size = OS_SIZE_8192; bool initial = true; +#ifdef TEST_WINAGENT + will_return_count(__wrap_os_random, 12345, 2); +#else + will_return(__wrap_os_random, 12345); +#endif + expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-security-alerts_v2"); expect_value(__wrap_wm_state_io, op, WM_IO_READ); expect_any(__wrap_wm_state_io, state); @@ -2130,6 +2142,12 @@ void test_wm_ms_graph_scan_relationships_single_initial_only_yes_fail_write(void size_t max_size = OS_SIZE_8192; bool initial = true; +#ifdef TEST_WINAGENT + will_return_count(__wrap_os_random, 12345, 2); +#else + will_return(__wrap_os_random, 12345); +#endif + expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-security-alerts_v2"); expect_value(__wrap_wm_state_io, op, WM_IO_READ); expect_any(__wrap_wm_state_io, state); @@ -2192,6 +2210,12 @@ void test_wm_ms_graph_scan_relationships_single_initial_only_no_next_time_no_res size_t max_size = OS_SIZE_8192; bool initial = true; +#ifdef TEST_WINAGENT + will_return_count(__wrap_os_random, 12345, 2); +#else + will_return(__wrap_os_random, 12345); +#endif + expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-security-alerts_v2"); expect_value(__wrap_wm_state_io, op, WM_IO_READ); expect_any(__wrap_wm_state_io, state); @@ -2271,6 +2295,12 @@ void test_wm_ms_graph_scan_relationships_single_no_initial_no_timestamp(void **s size_t max_size = OS_SIZE_8192; bool initial = false; +#ifdef TEST_WINAGENT + will_return_count(__wrap_os_random, 12345, 2); +#else + will_return(__wrap_os_random, 12345); +#endif + expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-security-alerts_v2"); expect_value(__wrap_wm_state_io, op, WM_IO_READ); expect_any(__wrap_wm_state_io, state); @@ -2346,6 +2376,12 @@ void test_wm_ms_graph_scan_relationships_single_unsuccessful_status_code(void ** os_strdup("{\"error\":\"bad_request\"}", response->body); os_strdup("test", response->header); +#ifdef TEST_WINAGENT + will_return_count(__wrap_os_random, 12345, 2); +#else + will_return(__wrap_os_random, 12345); +#endif + expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-security-alerts_v2"); expect_value(__wrap_wm_state_io, op, WM_IO_READ); expect_any(__wrap_wm_state_io, state); @@ -2432,6 +2468,12 @@ void test_wm_ms_graph_scan_relationships_single_reached_curl_size(void **state) os_strdup("{\"error\":\"bad_request\"}", response->body); os_strdup("test", response->header); +#ifdef TEST_WINAGENT + will_return_count(__wrap_os_random, 12345, 2); +#else + will_return(__wrap_os_random, 12345); +#endif + expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-security-alerts_v2"); expect_value(__wrap_wm_state_io, op, WM_IO_READ); expect_any(__wrap_wm_state_io, state); @@ -2518,6 +2560,12 @@ void test_wm_ms_graph_scan_relationships_single_failed_parse(void **state) { os_strdup("no json", response->body); os_strdup("test", response->header); +#ifdef TEST_WINAGENT + will_return_count(__wrap_os_random, 12345, 2); +#else + will_return(__wrap_os_random, 12345); +#endif + expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-security-alerts_v2"); expect_value(__wrap_wm_state_io, op, WM_IO_READ); expect_any(__wrap_wm_state_io, state); @@ -2604,6 +2652,12 @@ void test_wm_ms_graph_scan_relationships_single_no_logs(void **state) { os_strdup("{\"value\":[]}", response->body); os_strdup("test", response->header); +#ifdef TEST_WINAGENT + will_return_count(__wrap_os_random, 12345, 2); +#else + will_return(__wrap_os_random, 12345); +#endif + expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-security-alerts_v2"); expect_value(__wrap_wm_state_io, op, WM_IO_READ); expect_any(__wrap_wm_state_io, state); @@ -2700,6 +2754,12 @@ void test_wm_ms_graph_scan_relationships_single_success_one_log(void **state) { os_strdup("{\"value\":[{\"full_log\":\"log1\"}]}", response->body); os_strdup("test", response->header); +#ifdef TEST_WINAGENT + will_return_count(__wrap_os_random, 12345, 2); +#else + will_return(__wrap_os_random, 12345); +#endif + expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-security-alerts_v2"); expect_value(__wrap_wm_state_io, op, WM_IO_READ); expect_any(__wrap_wm_state_io, state); @@ -2803,6 +2863,12 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { os_strdup("{\"value\":[{\"full_log\":\"log1\"},{\"full_log\":\"log2\"}]}", response->body); os_strdup("test", response->header); +#ifdef TEST_WINAGENT + will_return_count(__wrap_os_random, 12345, 2); +#else + will_return(__wrap_os_random, 12345); +#endif + expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/deviceManagement/detectedApps?$top=100'"); @@ -2815,12 +2881,20 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { will_return(__wrap_wurl_http_request, response); expect_string(__wrap__mtdebug2, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}'"); +#ifdef TEST_WINAGENT + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"scan_id\":1234512345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}'"); +#else + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"scan_id\":12345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}'"); +#endif queue_fd = 0; expect_value(__wrap_wm_sendmsg, usec, 1000000); expect_value(__wrap_wm_sendmsg, queue, queue_fd); - expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}"); +#ifdef TEST_WINAGENT + expect_string(__wrap_wm_sendmsg, message, "{\"scan_id\":1234512345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}"); +#else + expect_string(__wrap_wm_sendmsg, message, "{\"scan_id\":12345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}"); +#endif expect_string(__wrap_wm_sendmsg, locmsg, "ms-graph"); expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); will_return(__wrap_wm_sendmsg, -1); @@ -2831,11 +2905,19 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { expect_string(__wrap__mterror, formatted_msg, "(1210): Queue 'queue/sockets/queue' not accessible: 'Error'"); expect_string(__wrap__mtdebug2, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}'"); +#ifdef TEST_WINAGENT + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"scan_id\":1234512345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}'"); +#else + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"scan_id\":12345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}'"); +#endif expect_value(__wrap_wm_sendmsg, usec, 1000000); expect_value(__wrap_wm_sendmsg, queue, queue_fd); - expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}"); +#ifdef TEST_WINAGENT + expect_string(__wrap_wm_sendmsg, message, "{\"scan_id\":1234512345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}"); +#else + expect_string(__wrap_wm_sendmsg, message, "{\"scan_id\":12345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}"); +#endif expect_string(__wrap_wm_sendmsg, locmsg, "ms-graph"); expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); will_return(__wrap_wm_sendmsg, 1); @@ -2893,6 +2975,12 @@ void test_wm_ms_graph_scan_relationships_single_success_two_pages(void **state) os_strdup("{\"@odata.nextLink\":\"next_page_url\",\"value\":[{\"full_log\":\"log1\"},{\"full_log\":\"log2\"}]}", response->body); os_strdup("test", response->header); +#ifdef TEST_WINAGENT + will_return_count(__wrap_os_random, 12345, 2); +#else + will_return(__wrap_os_random, 12345); +#endif + os_calloc(1, sizeof(curl_response), response2); response2->status_code = 200; response2->max_size_reached = false; @@ -2911,12 +2999,20 @@ void test_wm_ms_graph_scan_relationships_single_success_two_pages(void **state) will_return(__wrap_wurl_http_request, response); expect_string(__wrap__mtdebug2, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}'"); +#ifdef TEST_WINAGENT + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"scan_id\":1234512345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}'"); +#else + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"scan_id\":12345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}'"); +#endif queue_fd = 0; expect_value(__wrap_wm_sendmsg, usec, 1000000); expect_value(__wrap_wm_sendmsg, queue, queue_fd); - expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}"); +#ifdef TEST_WINAGENT + expect_string(__wrap_wm_sendmsg, message, "{\"scan_id\":1234512345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}"); +#else + expect_string(__wrap_wm_sendmsg, message, "{\"scan_id\":12345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log1\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}"); +#endif expect_string(__wrap_wm_sendmsg, locmsg, "ms-graph"); expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); will_return(__wrap_wm_sendmsg, -1); @@ -2927,11 +3023,19 @@ void test_wm_ms_graph_scan_relationships_single_success_two_pages(void **state) expect_string(__wrap__mterror, formatted_msg, "(1210): Queue 'queue/sockets/queue' not accessible: 'Error'"); expect_string(__wrap__mtdebug2, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}'"); +#ifdef TEST_WINAGENT + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"scan_id\":1234512345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}'"); +#else + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"scan_id\":12345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}'"); +#endif expect_value(__wrap_wm_sendmsg, usec, 1000000); expect_value(__wrap_wm_sendmsg, queue, queue_fd); - expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}"); +#ifdef TEST_WINAGENT + expect_string(__wrap_wm_sendmsg, message, "{\"scan_id\":1234512345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}"); +#else + expect_string(__wrap_wm_sendmsg, message, "{\"scan_id\":12345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}"); +#endif expect_string(__wrap_wm_sendmsg, locmsg, "ms-graph"); expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); will_return(__wrap_wm_sendmsg, 1); @@ -2948,12 +3052,20 @@ void test_wm_ms_graph_scan_relationships_single_success_two_pages(void **state) will_return(__wrap_wurl_http_request, response2); expect_string(__wrap__mtdebug2, tag, "wazuh-modulesd:ms-graph"); - expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log3\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}'"); +#ifdef TEST_WINAGENT + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"scan_id\":1234512345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log3\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}'"); +#else + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"scan_id\":12345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log3\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}'"); +#endif queue_fd = 0; expect_value(__wrap_wm_sendmsg, usec, 1000000); expect_value(__wrap_wm_sendmsg, queue, queue_fd); - expect_string(__wrap_wm_sendmsg, message, "{\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log3\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}"); +#ifdef TEST_WINAGENT + expect_string(__wrap_wm_sendmsg, message, "{\"scan_id\":1234512345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log3\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}"); +#else + expect_string(__wrap_wm_sendmsg, message, "{\"scan_id\":12345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log3\",\"resource\":\"deviceManagement\",\"relationship\":\"managedDevices\"}}"); +#endif expect_string(__wrap_wm_sendmsg, locmsg, "ms-graph"); expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ); will_return(__wrap_wm_sendmsg, 1); @@ -3022,6 +3134,12 @@ void test_wm_ms_graph_scan_relationships_single_success_two_resources(void **sta os_strdup("{\"value\":[{\"full_log\":\"log1\"}]}", response->body); os_strdup("test", response->header); +#ifdef TEST_WINAGENT + will_return_count(__wrap_os_random, 12345, 2); +#else + will_return(__wrap_os_random, 12345); +#endif + expect_string(__wrap_wm_state_io, tag, "ms-graph-example_tenant-security-alerts_v2"); expect_value(__wrap_wm_state_io, op, WM_IO_READ); expect_any(__wrap_wm_state_io, state); From 0002046ca206b09dd63f9374cef207d5589df5e3 Mon Sep 17 00:00:00 2001 From: Tomas Turina Date: Thu, 15 Aug 2024 20:27:24 +0000 Subject: [PATCH 13/13] test(ms-graph): complete coverage of intune apps functions --- .../tests/unit/tests/test_wm_ms_graph.c | 46 +++++++++++++++++-- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c b/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c index 63f4299e40..25bef30557 100644 --- a/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c +++ b/src/modules/ms_graph/tests/unit/tests/test_wm_ms_graph.c @@ -2855,14 +2855,28 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { size_t max_size = OS_SIZE_8192; bool initial = false; curl_response* response; + curl_response* response2; + curl_response* response3; wm_max_eps = 1; os_calloc(1, sizeof(curl_response), response); response->status_code = 200; response->max_size_reached = false; - os_strdup("{\"value\":[{\"full_log\":\"log1\"},{\"full_log\":\"log2\"}]}", response->body); + os_strdup("{\"value\":[{\"full_log\":\"log1\"},{\"full_log\":\"log2\",\"id\":\"12345\"}]}", response->body); os_strdup("test", response->header); + os_calloc(1, sizeof(curl_response), response2); + response2->status_code = 200; + response2->max_size_reached = false; + os_strdup("{\"@odata.nextLink\":\"next_page_url\",\"value\":[{\"id\":\"2345\"},{\"name\":\"test\"}]}", response2->body); + os_strdup("test2", response2->header); + + os_calloc(1, sizeof(curl_response), response3); + response3->status_code = 200; + response3->max_size_reached = false; + os_strdup("{\"value\":[{\"id\":\"3456\"}]}", response3->body); + os_strdup("test3", response3->header); + #ifdef TEST_WINAGENT will_return_count(__wrap_os_random, 12345, 2); #else @@ -2904,19 +2918,41 @@ void test_wm_ms_graph_scan_relationships_single_success_two_logs(void **state) { expect_string(__wrap__mterror, tag, WM_MS_GRAPH_LOGTAG); expect_string(__wrap__mterror, formatted_msg, "(1210): Queue 'queue/sockets/queue' not accessible: 'Error'"); + expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'https://graph.microsoft.com/v1.0/deviceManagement/detectedApps/12345/managedDevices?$top=100&$select=id,deviceName'"); + + expect_any(__wrap_wurl_http_request, method); + expect_any(__wrap_wurl_http_request, header); + expect_any(__wrap_wurl_http_request, url); + expect_any(__wrap_wurl_http_request, payload); + expect_any(__wrap_wurl_http_request, max_size); + expect_value(__wrap_wurl_http_request, timeout, WM_MS_GRAPH_DEFAULT_TIMEOUT); + will_return(__wrap_wurl_http_request, response2); + + expect_string(__wrap__mtdebug1, tag, "wazuh-modulesd:ms-graph"); + expect_string(__wrap__mtdebug1, formatted_msg, "Microsoft Graph API Log URL: 'next_page_url'"); + + expect_any(__wrap_wurl_http_request, method); + expect_any(__wrap_wurl_http_request, header); + expect_any(__wrap_wurl_http_request, url); + expect_any(__wrap_wurl_http_request, payload); + expect_any(__wrap_wurl_http_request, max_size); + expect_value(__wrap_wurl_http_request, timeout, WM_MS_GRAPH_DEFAULT_TIMEOUT); + will_return(__wrap_wurl_http_request, response3); + expect_string(__wrap__mtdebug2, tag, "wazuh-modulesd:ms-graph"); #ifdef TEST_WINAGENT - expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"scan_id\":1234512345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}'"); + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"scan_id\":1234512345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"id\":\"12345\",\"managedDevices\":[{\"id\":\"2345\"},{\"name\":\"test\"},{\"id\":\"3456\"}],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}'"); #else - expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"scan_id\":12345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}'"); + expect_string(__wrap__mtdebug2, formatted_msg, "Sending log: '{\"scan_id\":12345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"id\":\"12345\",\"managedDevices\":[{\"id\":\"2345\"},{\"name\":\"test\"},{\"id\":\"3456\"}],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}'"); #endif expect_value(__wrap_wm_sendmsg, usec, 1000000); expect_value(__wrap_wm_sendmsg, queue, queue_fd); #ifdef TEST_WINAGENT - expect_string(__wrap_wm_sendmsg, message, "{\"scan_id\":1234512345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}"); + expect_string(__wrap_wm_sendmsg, message, "{\"scan_id\":1234512345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"id\":\"12345\",\"managedDevices\":[{\"id\":\"2345\"},{\"name\":\"test\"},{\"id\":\"3456\"}],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}"); #else - expect_string(__wrap_wm_sendmsg, message, "{\"scan_id\":12345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"managedDevices\":[],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}"); + expect_string(__wrap_wm_sendmsg, message, "{\"scan_id\":12345,\"integration\":\"ms-graph\",\"ms-graph\":{\"full_log\":\"log2\",\"id\":\"12345\",\"managedDevices\":[{\"id\":\"2345\"},{\"name\":\"test\"},{\"id\":\"3456\"}],\"resource\":\"deviceManagement\",\"relationship\":\"detectedApps\"}}"); #endif expect_string(__wrap_wm_sendmsg, locmsg, "ms-graph"); expect_value(__wrap_wm_sendmsg, loc, LOCALFILE_MQ);