Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Azure ORM and deprecate last_dates.json file #12849

Merged
merged 6 commits into from
Apr 7, 2022

Conversation

CarlosRS9
Copy link
Contributor

@CarlosRS9 CarlosRS9 commented Mar 25, 2022

Related issue
Closes #11940

Description

This PR adds an ORM for the Azure module to allow us to use a real database instead of a plain text last_dates.json file. The development includes the following changes:

  • Added orm.py: The core ORM logic.
  • Added Unit tests for orm: test_orm.py.
  • Added the azure/tests/data path with several last_dates.json files used by the unit tests.
  • Updated azure-logs.log to use the new orm functionality and deprecate the last_dates.json file.

ORM details

ORM design highlights:

  • It makes use of SQLAlchemy, similar to how the RBAC ORM works in the Framework.
  • The database consist of 3 tables, one for each service: Graph, LogAnalytics and Storage.
  • The three tables will have the same structure:
    • md5: the md5 value of the query to process, used as a key. The md5 has been kept to avoid breaking compatibility with the old module when migrating the last_dates.json file.
    • query: the text string of the query to execute. It can be used in future versions to replace the md5` field if necessary. Until then, it will serve as additional debug info when debugging the module.
    • min: The smallest date processed. This already existed in last_dates.json.
    • max: The highest date processed. This already existed in last_dates.json.
  • Provides the following capabilities:
    • Manage database session
    • Handle database exceptions
    • Check database integrity
    • Detect the old last_dates.json file
    • Migrate from last_dates.json file
    • Create the database with the valid structure
    • Insert row object into the database
    • Get row object from the database
    • Get all the row objects from a given table
    • Update row object

Considerations

  1. To avoid issues with duplicated events the min and max colums store datetimes as strings instead of Python datetime objects. This is due to Azure's use of datetime to indicate the activity date for the events. As we pointed out in the original Azure issue, in some cases the Azure API returns a value for the activity date whose value for microseconds has 7 decimal places. This is incompatible with the python datetime standard, which requires 6 digits. The database had been created to store Datetime objects, so it was missing this last digit, losing precision which in the end translates into the possibility of duplicate events.
  2. As mentioned, the use of md5 as a key to identify a query in the database has been retained. This is to maintain compatibility or else duplicate logs could be processed during the first run after a migration.

New Azure Unit Tests

New unit tests for the orm.py have been added. Here are the results of the new tests:

======================================================================================= test session starts ========================================================================================
platform linux -- Python 3.10.3, pytest-6.2.5, py-1.11.0, pluggy-0.13.1 -- /home/carlos/venv/unit-tests/bin/python3
cachedir: .pytest_cache
rootdir: /home/carlos/GIT/wazuh/wodles
plugins: cov-3.0.0
collected 76 items

aws/tests/test_aws.py::test_metadata_version_buckets[AWSCloudTrailBucket] PASSED                                                                                                              [  1%]
aws/tests/test_aws.py::test_metadata_version_buckets[AWSConfigBucket] PASSED                                                                                                                  [  2%]
aws/tests/test_aws.py::test_metadata_version_buckets[AWSVPCFlowBucket] PASSED                                                                                                                 [  3%]
aws/tests/test_aws.py::test_metadata_version_buckets[AWSCustomBucket] PASSED                                                                                                                  [  5%]
aws/tests/test_aws.py::test_metadata_version_buckets[AWSGuardDutyBucket] PASSED                                                                                                               [  6%]
aws/tests/test_aws.py::test_metadata_version_services[AWSInspector] PASSED                                                                                                                    [  7%]
aws/tests/test_aws.py::test_db_maintenance[AWSCloudTrailBucket-schema_cloudtrail_test.sql-cloudtrail] PASSED                                                                                  [  9%]
aws/tests/test_aws.py::test_db_maintenance[AWSConfigBucket-schema_config_test.sql-config] PASSED                                                                                              [ 10%]
aws/tests/test_aws.py::test_db_maintenance[AWSVPCFlowBucket-schema_vpcflow_test.sql-vpcflow] PASSED                                                                                           [ 11%]
aws/tests/test_aws.py::test_db_maintenance[AWSCustomBucket-schema_custom_test.sql-custom] PASSED                                                                                              [ 13%]
aws/tests/test_aws.py::test_db_maintenance[AWSGuardDutyBucket-schema_guardduty_test.sql-guardduty] PASSED                                                                                     [ 14%]
aws/tests/test_aws.py::test_decompress_file_gz[aws_bucket0-test.gz-gzip.open] PASSED                                                                                                          [ 15%]
aws/tests/test_aws.py::test_decompress_file_gz[aws_bucket0-test.zip-zipfile.ZipFile] PASSED                                                                                                   [ 17%]
aws/tests/test_aws.py::test_decompress_file_snappy_skip[aws_bucket0-test.snappy] PASSED                                                                                                       [ 18%]
aws/tests/test_aws.py::test_decompress_file_ko[aws_bucket0-test.snappy-False-SystemExit] PASSED                                                                                               [ 19%]
aws/tests/test_aws.py::test_aws_waf_load_information_from_file[aws_waf_bucket0-/home/carlos/GIT/wazuh/wodles/aws/tests/data/log_files/WAF/aws-waf-False] PASSED                               [ 21%]
aws/tests/test_aws.py::test_aws_waf_load_information_from_file[aws_waf_bucket0-/home/carlos/GIT/wazuh/wodles/aws/tests/data/log_files/WAF/aws-waf-True] PASSED                                [ 22%]
aws/tests/test_aws.py::test_aws_waf_load_information_from_file[aws_waf_bucket0-/home/carlos/GIT/wazuh/wodles/aws/tests/data/log_files/WAF/aws-waf-invalid-json-True] PASSED                   [ 23%]
aws/tests/test_aws.py::test_aws_waf_load_information_from_file[aws_waf_bucket0-/home/carlos/GIT/wazuh/wodles/aws/tests/data/log_files/WAF/aws-waf-wrong-structure-True] PASSED                [ 25%]
aws/tests/test_aws.py::test_aws_waf_load_information_from_file_ko[aws_waf_bucket0-/home/carlos/GIT/wazuh/wodles/aws/tests/data/log_files/WAF/aws-waf-invalid-json-False-SystemExit] PASSED    [ 26%]
aws/tests/test_aws.py::test_aws_waf_load_information_from_file_ko[aws_waf_bucket0-/home/carlos/GIT/wazuh/wodles/aws/tests/data/log_files/WAF/aws-waf-wrong-structure-False-SystemExit] PASSED [ 27%]
aws/tests/test_aws.py::test_config_format_created_date[aws_config_bucket0-2021/1/19-20210119] PASSED                                                                                          [ 28%]
aws/tests/test_aws.py::test_config_format_created_date[aws_config_bucket0-2021/1/1-20210101] PASSED                                                                                           [ 30%]
aws/tests/test_aws.py::test_config_format_created_date[aws_config_bucket0-2021/01/01-20210101] PASSED                                                                                         [ 31%]
aws/tests/test_aws.py::test_config_format_created_date[aws_config_bucket0-2000/2/12-20000212] PASSED                                                                                          [ 32%]
aws/tests/test_aws.py::test_config_format_created_date[aws_config_bucket0-2022/02/1-20220201] PASSED                                                                                          [ 34%]
aws/tests/test_aws.py::test_custom_get_creation_date[aws_custom_bucket0-log_file0-20211221] PASSED                                                                                            [ 35%]
aws/tests/test_aws.py::test_custom_get_creation_date[aws_custom_bucket0-log_file1-20200103] PASSED                                                                                            [ 36%]
aws/tests/test_aws.py::test_custom_get_creation_date[aws_custom_bucket0-log_file2-20200920] PASSED                                                                                            [ 38%]
aws/tests/test_aws.py::test_custom_get_creation_date[aws_custom_bucket0-log_file3-20210118] PASSED                                                                                            [ 39%]
aws/tests/test_aws.py::test_custom_get_creation_date[aws_custom_bucket0-log_file4-20200930] PASSED                                                                                            [ 40%]
aws/tests/test_aws.py::test_custom_get_creation_date[aws_custom_bucket0-log_file5-20201015] PASSED                                                                                            [ 42%]
aws/tests/test_aws.py::test_custom_get_creation_date[aws_custom_bucket0-log_file6-20210318] PASSED                                                                                            [ 43%]
aws/tests/test_aws.py::test_custom_get_creation_date[aws_custom_bucket0-log_file7-20210906] PASSED                                                                                            [ 44%]
aws/tests/test_aws.py::test_custom_get_creation_date[aws_custom_bucket0-log_file8-20211112] PASSED                                                                                            [ 46%]
aws/tests/test_aws.py::test_custom_get_creation_date[aws_custom_bucket0-log_file9-20210123] PASSED                                                                                            [ 47%]
azure/tests/test_orm.py::test_create_db[expected_table_names0-expected_columns0] PASSED                                                                                                       [ 48%]
azure/tests/test_orm.py::test_add_get_row PASSED                                                                                                                                              [ 50%]
azure/tests/test_orm.py::test_add_ko PASSED                                                                                                                                                   [ 51%]
azure/tests/test_orm.py::test_get_rows_ko PASSED                                                                                                                                              [ 52%]
azure/tests/test_orm.py::test_update_row_ko PASSED                                                                                                                                            [ 53%]
azure/tests/test_orm.py::test_load_dates_json[/home/carlos/GIT/wazuh/wodles/azure/tests/data/last_date_files/last_dates.json] PASSED                                                          [ 55%]
azure/tests/test_orm.py::test_load_dates_json[/home/carlos/GIT/wazuh/wodles/azure/tests/data/last_date_files/last_dates_graph.json] PASSED                                                    [ 56%]
azure/tests/test_orm.py::test_load_dates_json[/home/carlos/GIT/wazuh/wodles/azure/tests/data/last_date_files/last_dates_log_analytics.json] PASSED                                            [ 57%]
azure/tests/test_orm.py::test_load_dates_json[/home/carlos/GIT/wazuh/wodles/azure/tests/data/last_date_files/last_dates_storage.json] PASSED                                                  [ 59%]
azure/tests/test_orm.py::test_load_dates_json[/home/carlos/GIT/wazuh/wodles/azure/tests/data/last_date_files/last_dates_old.json] PASSED                                                      [ 60%]
azure/tests/test_orm.py::test_load_dates_json[/home/carlos/GIT/wazuh/wodles/azure/tests/data/last_date_files/last_dates_clean.json] PASSED                                                    [ 61%]
azure/tests/test_orm.py::test_load_dates_json_no_file PASSED                                                                                                                                  [ 63%]
azure/tests/test_orm.py::test_load_dates_json_ko[/home/carlos/GIT/wazuh/wodles/azure/tests/data/last_date_files/last_dates_invalid.json] PASSED                                               [ 64%]
azure/tests/test_orm.py::test_check_integrity[True-0] PASSED                                                                                                                                  [ 65%]
azure/tests/test_orm.py::test_check_integrity[True-100] PASSED                                                                                                                                [ 67%]
azure/tests/test_orm.py::test_check_integrity[False-100] PASSED                                                                                                                               [ 68%]
azure/tests/test_orm.py::test_check_integrity_ko PASSED                                                                                                                                       [ 69%]
azure/tests/test_orm.py::test_migrate_from_last_dates_file[/home/carlos/GIT/wazuh/wodles/azure/tests/data/last_date_files/last_dates.json] PASSED                                             [ 71%]
azure/tests/test_orm.py::test_migrate_from_last_dates_file[/home/carlos/GIT/wazuh/wodles/azure/tests/data/last_date_files/last_dates_graph.json] PASSED                                       [ 72%]
azure/tests/test_orm.py::test_migrate_from_last_dates_file[/home/carlos/GIT/wazuh/wodles/azure/tests/data/last_date_files/last_dates_log_analytics.json] PASSED                               [ 73%]
azure/tests/test_orm.py::test_migrate_from_last_dates_file[/home/carlos/GIT/wazuh/wodles/azure/tests/data/last_date_files/last_dates_storage.json] PASSED                                     [ 75%]
azure/tests/test_orm.py::test_migrate_from_last_dates_file[/home/carlos/GIT/wazuh/wodles/azure/tests/data/last_date_files/last_dates_old.json] PASSED                                         [ 76%]
azure/tests/test_orm.py::test_migrate_from_last_dates_file[/home/carlos/GIT/wazuh/wodles/azure/tests/data/last_date_files/last_dates_clean.json] PASSED                                       [ 77%]
gcloud/tests/test_access_logs.py::test_get_access_logs PASSED                                                                                                                                 [ 78%]
gcloud/tests/test_bucket.py::test_get_bucket[gcloud_bucket0] PASSED                                                                                                                           [ 80%]
gcloud/tests/test_bucket.py::test_bucket_ko[unexistent_file-None-test_bucket-GCloudError-1001] PASSED                                                                                         [ 81%]
gcloud/tests/test_bucket.py::test_bucket_ko[invalid_credentials_file.json-None-test_bucket-GCloudError-1000] PASSED                                                                           [ 82%]
gcloud/tests/test_gcloud.py::test_gcloud_ko[parameters0-GCloudError-1002] PASSED                                                                                                              [ 84%]
gcloud/tests/test_gcloud.py::test_gcloud_ko[parameters1-GCloudError-1202] PASSED                                                                                                              [ 85%]
gcloud/tests/test_gcloud.py::test_gcloud_ko[parameters2-GCloudError-1203] PASSED                                                                                                              [ 86%]
gcloud/tests/test_gcloud.py::test_gcloud_ko[parameters3-GCloudError-1103] PASSED                                                                                                              [ 88%]
gcloud/tests/test_gcloud.py::test_gcloud_ko[parameters4-GCloudError-1102] PASSED                                                                                                              [ 89%]
gcloud/tests/test_integration.py::test_send_message_ok PASSED                                                                                                                                 [ 90%]
gcloud/tests/test_integration.py::test_send_message_ko PASSED                                                                                                                                 [ 92%]
gcloud/tests/test_integration.py::test_format_msg PASSED                                                                                                                                      [ 93%]
gcloud/tests/test_integration.py::test_initialize_socket_ko[gcloud_subscriber0-ConnectionRefusedError-WazuhIntegrationInternalError-1] PASSED                                                 [ 94%]
gcloud/tests/test_integration.py::test_initialize_socket_ko[gcloud_subscriber0-OSError-WazuhIntegrationInternalError-2] PASSED                                                                [ 96%]
gcloud/tests/test_subscriber.py::test_get_subscriber[gcloud_subscriber0] PASSED                                                                                                               [ 97%]
gcloud/tests/test_subscriber.py::test_subscription_ko[unexistent_file-None-test_project-test_subscription-GCloudError-GCloudCredentialsNotFoundError] PASSED                                  [ 98%]
gcloud/tests/test_subscriber.py::test_subscription_ko[invalid_credentials_file.json-None-test_project-test_subscription-GCloudError-GCloudCredentialsStructureError] PASSED                   [100%]

================================================================================= 76 passed, 84 warnings in 1.57s ==================================================================================

---------- coverage: platform linux, python 3.10.3-final-0 -----------
Name                               Stmts   Miss  Cover
------------------------------------------------------
__init__.py                            0      0   100%
aws/aws_s3.py                       1609   1219    24%
aws/tests/__init__.py                  0      0   100%
aws/tests/conftest.py                 25      0   100%
aws/tests/test_aws.py                114      0   100%
azure/orm.py                         104      0   100%
azure/tests/test_orm.py              120      0   100%
gcloud/buckets/access_logs.py         16      5    69%
gcloud/buckets/bucket.py             130     82    37%
gcloud/exceptions.py                  23      0   100%
gcloud/gcloud.py                      70     29    59%
gcloud/integration.py                 36      3    92%
gcloud/pubsub/subscriber.py           60     32    47%
gcloud/tests/conftest.py              25      0   100%
gcloud/tests/test_access_logs.py      20      0   100%
gcloud/tests/test_bucket.py           19      0   100%
gcloud/tests/test_gcloud.py           14      0   100%
gcloud/tests/test_integration.py      38      0   100%
gcloud/tests/test_subscriber.py       18      0   100%
gcloud/tools.py                       48     24    50%
utils.py                              57     27    53%
------------------------------------------------------
TOTAL                               2546   1421    44%

Please note that we currently don't have unit test for the azure-logs-py and they are out of the scope of this issue, hence no coverage for this module.

Manual testing

The following tests must be performed in sequential order. No data must be modified or removed unless it was specified for the test.

The tests assume there is a valid authentication file located at {wazuh_path}/wodles/azure/credentials.

A test is considered valid if the following conditions are met:

  • The expected result described in the test itself is met.
  • The expected amount of events were sent to analysisd.
  • The expected output was present in the {wazuh_path}/logs/azure-logs.log file.

Test results

Everything worked as expected

Graph tests

Run the integration using query 'auditLogs/directoryAudits' and time_offset 2d

Remove the database file and run the integration using -graph_query 'auditLogs/directoryAudits' and --offset 2d. Only 4 logs should be processed. The last_dates.json should be updated as expected.

Command used
/var/ossec/wodles/azure/azure-logs --graph --graph_time_offset 2d --graph_query 'auditLogs/directoryAudits' --graph_auth_path /var/ossec/wodles/azure/credentials --graph_tenant_domain wazuh.onmicrosoft.com --graph_tag azure-active_directory -d 2
azure-logs output
/var/ossec/wodles/azure/azure-logs --graph --graph_time_offset 2d --graph_query 'auditLogs/directoryAudits' --graph_auth_path /var/ossec/wodles/azure/credentials --graph_tenant_domain wazuh.onmicrosoft.com --graph_tag azure-active_directory -d 2
2022/04/04 07:36:02 azure: INFO: Checking database integrity
2022/04/04 07:36:02 azure: INFO: Database integrity check finished
2022/04/04 07:36:02 azure: INFO: Azure Graph starting.
2022/04/04 07:36:02 azure: INFO: Graph: Getting authentication token.
2022/04/04 07:36:02 azure: INFO: Graph: Building the url.
2022/04/04 07:36:02 azure: INFO: 5956825a2e7b02dbebce74ec3c2ac5a5 was not found in the database for graph. Adding it.
2022/04/04 07:36:02 azure: DEBUG: Attempting to insert row object into graph with md5='5956825a2e7b02dbebce74ec3c2ac5a5', min_date='2022-04-02T07:36:02.517487Z', max_date='2022-04-02T07:36:02.517487Z'
2022/04/04 07:36:02 azure: INFO: Graph: The search starts for query: 'auditLogs/directoryAudits' using activityDateTime+ge+2022-04-02T07:36:02.527563Z
2022/04/04 07:36:02 azure: INFO: Graph: The URL is 'https://graph.microsoft.com/v1.0/auditLogs/directoryAudits?&$filter=activityDateTime+ge+2022-04-02T07:36:02.527563Z'
2022/04/04 07:36:02 azure: INFO: Graph: Pagination starts
2022/04/04 07:36:02 azure: DEBUG: Attempting to update a graph row object. MD5: '5956825a2e7b02dbebce74ec3c2ac5a5', min_date: '2022-04-02T07:36:02.517487Z', max_date: '2022-04-03T14:50:15.9505931Z'
2022/04/04 07:36:02 azure: INFO: Graph: Sending event by socket.
2022/04/04 07:36:02 azure: INFO: Graph: Sending event by socket.
2022/04/04 07:36:03 azure: INFO: Graph: Sending event by socket.
2022/04/04 07:36:03 azure: INFO: Graph: Sending event by socket.
2022/04/04 07:36:03 azure: INFO: Graph: End
azure.db contents
sqlite3 /var/ossec/wodles/azure/azure.db 'select * from graph;'                               
5956825a2e7b02dbebce74ec3c2ac5a5|auditLogs/directoryAudits|2022-04-02T07:29:07.699702Z|2022-04-03T14:50:15.9505931Z

sqlite3 /var/ossec/wodles/azure/azure.db 'select * from log_analytics;'

sqlite3 /var/ossec/wodles/azure/azure.db 'select * from storage;'

Repeat the test to ensure there are no duplicates. Keep the database file from the previous test and run the integration.

Command used
/var/ossec/wodles/azure/azure-logs --graph --graph_time_offset 2d --graph_query 'auditLogs/directoryAudits' --graph_auth_path /var/ossec/wodles/azure/credentials --graph_tenant_domain wazuh.onmicrosoft.com --graph_tag azure-active_directory -d 2
azure-logs output
/var/ossec/wodles/azure/azure-logs --graph --graph_time_offset 2d --graph_query 'auditLogs/directoryAudits' --graph_auth_path /var/ossec/wodles/azure/credentials --graph_tenant_domain wazuh.onmicrosoft.com --graph_tag azure-active_directory -d 2
2022/04/04 07:36:32 azure: INFO: Checking database integrity
2022/04/04 07:36:32 azure: INFO: Database integrity check finished
2022/04/04 07:36:32 azure: INFO: Azure Graph starting.
2022/04/04 07:36:32 azure: INFO: Graph: Getting authentication token.
2022/04/04 07:36:32 azure: INFO: Graph: Building the url.
2022/04/04 07:36:32 azure: INFO: Graph: The search starts for query: 'auditLogs/directoryAudits' using activityDateTime+gt+2022-04-03T14:50:15.9505931Z
2022/04/04 07:36:32 azure: INFO: Graph: The URL is 'https://graph.microsoft.com/v1.0/auditLogs/directoryAudits?&$filter=activityDateTime+gt+2022-04-03T14:50:15.9505931Z'
2022/04/04 07:36:32 azure: INFO: Graph: Pagination starts
2022/04/04 07:36:32 azure: INFO: Graph: There are no new results
2022/04/04 07:36:32 azure: INFO: Graph: End
azure.db contents
sqlite3 /var/ossec/wodles/azure/azure.db 'select * from graph;'
5956825a2e7b02dbebce74ec3c2ac5a5|auditLogs/directoryAudits|2022-04-02T07:36:02.517487Z|2022-04-03T14:50:15.9505931Z

sqlite3 /var/ossec/wodles/azure/azure.db 'select * from log_analytics;'

sqlite3 /var/ossec/wodles/azure/azure.db 'select * from storage;'
Conclusions

The module worked as expected.

Log Analytic tests

Run the integration with time_offset 30d

Run the command using --la_time_offset 30d. 50 logs should be processed.

Command used
/var/ossec/wodles/azure/azure-logs --log_analytics --la_auth_path /var/ossec/wodles/azure/credentials-analytics --la_tenant_domain wazuh.onmicrosoft.com --la_tag azure-activity --la_query "AzureActivity" --workspace bc8d21bd-b966-4a4f-8eed-9e0328720cbe --la_time_offset 30d -d 2
Command output
/var/ossec/wodles/azure/azure-logs --log_analytics --la_auth_path /var/ossec/wodles/azure/credentials-analytics --la_tenant_domain wazuh.onmicrosoft.com --la_tag azure-activity --la_query "AzureActivity" --workspace bc8d21bd-b966-4a4f-8eed-9e0328720cbe --la_time_offset 30d -d 2
2022/04/04 07:37:21 azure: INFO: Checking database integrity
2022/04/04 07:37:21 azure: INFO: Database integrity check finished
2022/04/04 07:37:21 azure: INFO: Azure Log Analytics starting.
2022/04/04 07:37:21 azure: INFO: Log Analytics: Getting authentication token.
2022/04/04 07:37:22 azure: INFO: f90c15b0327962c9e661142547368572 was not found in the database for log_analytics. Adding it.
2022/04/04 07:37:22 azure: DEBUG: Attempting to insert row object into log_analytics with md5='f90c15b0327962c9e661142547368572', min_date='2022-03-05T07:37:22.330900Z', max_date='2022-03-05T07:37:22.330900Z'
2022/04/04 07:37:22 azure: INFO: Log Analytics: The search starts for query: 'AzureActivity | order by TimeGenerated asc | where TimeGenerated >= datetime(2022-03-05T07:37:22.344495Z) '
2022/04/04 07:37:22 azure: INFO: Log Analytics: Sending a request to the Log Analytics API.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: INFO: Log Analytics: Sending event by socket.
2022/04/04 07:37:23 azure: DEBUG: Attempting to update a log_analytics row object. MD5: 'f90c15b0327962c9e661142547368572', min_date: '2022-03-05T07:37:22.330900Z', max_date: '2022-04-01T12:01:44.372Z'
2022/04/04 07:37:23 azure: INFO: Azure Log Analytics ending.
azure.db contents
sqlite3 /var/ossec/wodles/azure/azure.db 'select * from graph;'
5956825a2e7b02dbebce74ec3c2ac5a5|auditLogs/directoryAudits|2022-04-02T07:36:02.517487Z|2022-04-03T14:50:15.9505931Z

sqlite3 /var/ossec/wodles/azure/azure.db 'select * from log_analytics;'
f90c15b0327962c9e661142547368572|AzureActivity|2022-03-05T07:37:22.330900Z|2022-04-01T12:01:44.372Z

sqlite3 /var/ossec/wodles/azure/azure.db 'select * from storage;'

Repeat the test to ensure there are no duplicates. Keep the database file from the previous test and run the integration.

Command used
/var/ossec/wodles/azure/azure-logs --log_analytics --la_auth_path /var/ossec/wodles/azure/credentials-analytics --la_tenant_domain wazuh.onmicrosoft.com --la_tag azure-activity --la_query "AzureActivity" --workspace bc8d21bd-b966-4a4f-8eed-9e0328720cbe --la_time_offset 30d -d 2
Command output
/var/ossec/wodles/azure/azure-logs --log_analytics --la_auth_path /var/ossec/wodles/azure/credentials-analytics --la_tenant_domain wazuh.onmicrosoft.com --la_tag azure-activity --la_query "AzureActivity" --workspace bc8d21bd-b966-4a4f-8eed-9e0328720cbe --la_time_offset 30d -d 2
2022/04/04 07:40:54 azure: INFO: Checking database integrity
2022/04/04 07:40:54 azure: INFO: Database integrity check finished
2022/04/04 07:40:54 azure: INFO: Azure Log Analytics starting.
2022/04/04 07:40:54 azure: INFO: Log Analytics: Getting authentication token.
2022/04/04 07:40:55 azure: INFO: Log Analytics: The search starts for query: 'AzureActivity | order by TimeGenerated asc | where TimeGenerated > datetime(2022-04-01T12:01:44.372Z) '
2022/04/04 07:40:55 azure: INFO: Log Analytics: Sending a request to the Log Analytics API.
2022/04/04 07:40:55 azure: INFO: Log Analytics: There are no new results
2022/04/04 07:40:55 azure: INFO: Azure Log Analytics ending.
azure.db contents
sqlite3 /var/ossec/wodles/azure/azure.db 'select * from graph;'
5956825a2e7b02dbebce74ec3c2ac5a5|auditLogs/directoryAudits|2022-04-02T07:36:02.517487Z|2022-04-03T14:50:15.9505931Z

sqlite3 /var/ossec/wodles/azure/azure.db 'select * from log_analytics;'
f90c15b0327962c9e661142547368572|AzureActivity|2022-03-05T07:37:22.330900Z|2022-04-01T12:01:44.372Z

sqlite3 /var/ossec/wodles/azure/azure.db 'select * from storage;'
Conclusions

The module worked as expected.

Storage tests

First execution specifying an time_offset value set in the past

Run the integration using --storage_time_offset 120d.

Only the files contained in the test_folder path should be processed as the other ones have an older last_modified datetime.

Command used
/var/ossec/wodles/azure/azure-logs --storage --storage_time_offset 120d --container frameworktestcontainer --storage_auth_path /var/ossec/wodles/azure/credentials-storage -d 2
Command output
/var/ossec/wodles/azure/azure-logs --storage --storage_time_offset 120d --container frameworktestcontainer --storage_auth_path /var/ossec/wodles/azure/credentials-storage -d 2
2022/04/04 07:42:57 azure: INFO: Checking database integrity
2022/04/04 07:42:57 azure: INFO: Database integrity check finished
2022/04/04 07:42:57 azure: INFO: Azure Storage starting.
2022/04/04 07:42:57 azure: INFO: Storage: Authenticating.
2022/04/04 07:42:57 azure: DEBUG: String_to_sign=GET











x-ms-client-request-id:d86f69fe-b3ea-11ec-b9a9-4f6d30fe47b1
x-ms-date:Mon, 04 Apr 2022 07:42:57 GMT
x-ms-version:2019-02-02
/frameworkteststorage/frameworktestcontainer
restype:container
2022/04/04 07:42:57 azure: INFO: Client-Request-ID=d86f69fe-b3ea-11ec-b9a9-4f6d30fe47b1 Outgoing request: Method=GET, Path=/frameworktestcontainer, Query={'snapshot': None, 'timeout': None, 'restype': 'container'}, Headers={'x-ms-version': '2019-02-02', 'User-Agent': 'Azure-Storage/2.1.0-2.1.0 (Python CPython 3.9.9; Linux 5.16.16-200.fc35.x86_64)', 'x-ms-client-request-id': 'd86f69fe-b3ea-11ec-b9a9-4f6d30fe47b1', 'x-ms-date': 'Mon, 04 Apr 2022 07:42:57 GMT', 'Authorization': 'REDACTED'}.
2022/04/04 07:42:58 azure: INFO: Client-Request-ID=d86f69fe-b3ea-11ec-b9a9-4f6d30fe47b1 Receiving Response: Server-Timestamp=Mon, 04 Apr 2022 07:42:57 GMT, Server-Request-ID=1652416c-701e-0082-73f7-47e949000000, HTTP Status Code=200, Message=OK, Headers={'content-length': '0', 'last-modified': 'Wed, 20 Oct 2021 07:47:27 GMT', 'etag': '"0x8D9939DDD0A61EA"', 'server': 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0', 'x-ms-request-id': '1652416c-701e-0082-73f7-47e949000000', 'x-ms-client-request-id': 'd86f69fe-b3ea-11ec-b9a9-4f6d30fe47b1', 'x-ms-version': '2019-02-02', 'x-ms-lease-status': 'unlocked', 'x-ms-lease-state': 'available', 'x-ms-has-immutability-policy': 'false', 'x-ms-has-legal-hold': 'false', 'x-ms-default-encryption-scope': '$account-encryption-key', 'x-ms-deny-encryption-scope-override': 'false', 'date': 'Mon, 04 Apr 2022 07:42:57 GMT'}.
2022/04/04 07:42:58 azure: INFO: Storage: Authenticated.
2022/04/04 07:42:58 azure: INFO: 82e049b81fa6eb88ebf85f1677785f2b was not found in the database for storage. Adding it.
2022/04/04 07:42:58 azure: DEBUG: Attempting to insert row object into storage with md5='82e049b81fa6eb88ebf85f1677785f2b', min_date='2021-12-05T07:42:58.227604Z', max_date='2021-12-05T07:42:58.227604Z'
2022/04/04 07:42:58 azure: INFO: Storage: Getting blobs.
2022/04/04 07:42:58 azure: DEBUG: String_to_sign=GET











x-ms-client-request-id:d8cc175a-b3ea-11ec-9fe4-4f6d30fe47b1
x-ms-date:Mon, 04 Apr 2022 07:42:58 GMT
x-ms-version:2019-02-02
/frameworkteststorage/frameworktestcontainer
comp:list
restype:container
2022/04/04 07:42:58 azure: INFO: Client-Request-ID=d8cc175a-b3ea-11ec-9fe4-4f6d30fe47b1 Outgoing request: Method=GET, Path=/frameworktestcontainer, Query={'restype': 'container', 'comp': 'list', 'prefix': None, 'delimiter': None, 'marker': None, 'maxresults': None, 'include': None, 'timeout': None}, Headers={'x-ms-version': '2019-02-02', 'User-Agent': 'Azure-Storage/2.1.0-2.1.0 (Python CPython 3.9.9; Linux 5.16.16-200.fc35.x86_64)', 'x-ms-client-request-id': 'd8cc175a-b3ea-11ec-9fe4-4f6d30fe47b1', 'x-ms-date': 'Mon, 04 Apr 2022 07:42:58 GMT', 'Authorization': 'REDACTED'}.
2022/04/04 07:42:58 azure: INFO: Client-Request-ID=d8cc175a-b3ea-11ec-9fe4-4f6d30fe47b1 Receiving Response: Server-Timestamp=Mon, 04 Apr 2022 07:42:57 GMT, Server-Request-ID=16524220-701e-0082-1cf7-47e949000000, HTTP Status Code=200, Message=OK, Headers={'transfer-encoding': 'chunked', 'content-type': 'application/xml', 'server': 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0', 'x-ms-request-id': '16524220-701e-0082-1cf7-47e949000000', 'x-ms-client-request-id': 'd8cc175a-b3ea-11ec-9fe4-4f6d30fe47b1', 'x-ms-version': '2019-02-02', 'date': 'Mon, 04 Apr 2022 07:42:57 GMT'}.
2022/04/04 07:42:58 azure: INFO: Storage: The search starts from the date: 2021-12-05 07:42:58.260654+00:00 for blobs in container: 'frameworktestcontainer' 
2022/04/04 07:42:58 azure: INFO: Storage: End
azure.db contents
sqlite3 /var/ossec/wodles/azure/azure.db 'select * from graph;'
5956825a2e7b02dbebce74ec3c2ac5a5|auditLogs/directoryAudits|2022-04-02T07:36:02.517487Z|2022-04-03T14:50:15.9505931Z

sqlite3 /var/ossec/wodles/azure/azure.db 'select * from log_analytics;'
f90c15b0327962c9e661142547368572|AzureActivity|2022-03-05T07:37:22.330900Z|2022-04-01T12:01:44.372Z

sqlite3 /var/ossec/wodles/azure/azure.db 'select * from storage;'
82e049b81fa6eb88ebf85f1677785f2b|frameworkteststorage|2021-12-05T07:42:58.227604Z|2021-12-05T07:42:58.227604Z

Keep the database file and run the same command again to ensure no duplicate logs have been processed.

Command used
/var/ossec/wodles/azure/azure-logs --storage --storage_time_offset 120d --container frameworktestcontainer --storage_auth_path /var/ossec/wodles/azure/credentials-storage -d 2
Command output
/var/ossec/wodles/azure/azure-logs --storage --storage_time_offset 120d --container frameworktestcontainer --storage_auth_path /var/ossec/wodles/azure/credentials-storage -d 2
2022/04/04 07:44:49 azure: INFO: Checking database integrity
2022/04/04 07:44:49 azure: INFO: Database integrity check finished
2022/04/04 07:44:49 azure: INFO: Azure Storage starting.
2022/04/04 07:44:49 azure: INFO: Storage: Authenticating.
2022/04/04 07:44:49 azure: DEBUG: String_to_sign=GET











x-ms-client-request-id:1ada671d-b3eb-11ec-b0d7-a32bbb211570
x-ms-date:Mon, 04 Apr 2022 07:44:49 GMT
x-ms-version:2019-02-02
/frameworkteststorage/frameworktestcontainer
restype:container
2022/04/04 07:44:49 azure: INFO: Client-Request-ID=1ada671d-b3eb-11ec-b0d7-a32bbb211570 Outgoing request: Method=GET, Path=/frameworktestcontainer, Query={'snapshot': None, 'timeout': None, 'restype': 'container'}, Headers={'x-ms-version': '2019-02-02', 'User-Agent': 'Azure-Storage/2.1.0-2.1.0 (Python CPython 3.9.9; Linux 5.16.16-200.fc35.x86_64)', 'x-ms-client-request-id': '1ada671d-b3eb-11ec-b0d7-a32bbb211570', 'x-ms-date': 'Mon, 04 Apr 2022 07:44:49 GMT', 'Authorization': 'REDACTED'}.
2022/04/04 07:44:49 azure: INFO: Client-Request-ID=1ada671d-b3eb-11ec-b0d7-a32bbb211570 Receiving Response: Server-Timestamp=Mon, 04 Apr 2022 07:44:48 GMT, Server-Request-ID=1f3cbd0c-701e-0076-48f7-4722bf000000, HTTP Status Code=200, Message=OK, Headers={'content-length': '0', 'last-modified': 'Wed, 20 Oct 2021 07:47:27 GMT', 'etag': '"0x8D9939DDD0A61EA"', 'server': 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0', 'x-ms-request-id': '1f3cbd0c-701e-0076-48f7-4722bf000000', 'x-ms-client-request-id': '1ada671d-b3eb-11ec-b0d7-a32bbb211570', 'x-ms-version': '2019-02-02', 'x-ms-lease-status': 'unlocked', 'x-ms-lease-state': 'available', 'x-ms-has-immutability-policy': 'false', 'x-ms-has-legal-hold': 'false', 'x-ms-default-encryption-scope': '$account-encryption-key', 'x-ms-deny-encryption-scope-override': 'false', 'date': 'Mon, 04 Apr 2022 07:44:48 GMT'}.
2022/04/04 07:44:49 azure: INFO: Storage: Authenticated.
2022/04/04 07:44:49 azure: INFO: Storage: Getting blobs.
2022/04/04 07:44:49 azure: DEBUG: String_to_sign=GET











x-ms-client-request-id:1b33ceb3-b3eb-11ec-86d0-a32bbb211570
x-ms-date:Mon, 04 Apr 2022 07:44:49 GMT
x-ms-version:2019-02-02
/frameworkteststorage/frameworktestcontainer
comp:list
restype:container
2022/04/04 07:44:49 azure: INFO: Client-Request-ID=1b33ceb3-b3eb-11ec-86d0-a32bbb211570 Outgoing request: Method=GET, Path=/frameworktestcontainer, Query={'restype': 'container', 'comp': 'list', 'prefix': None, 'delimiter': None, 'marker': None, 'maxresults': None, 'include': None, 'timeout': None}, Headers={'x-ms-version': '2019-02-02', 'User-Agent': 'Azure-Storage/2.1.0-2.1.0 (Python CPython 3.9.9; Linux 5.16.16-200.fc35.x86_64)', 'x-ms-client-request-id': '1b33ceb3-b3eb-11ec-86d0-a32bbb211570', 'x-ms-date': 'Mon, 04 Apr 2022 07:44:49 GMT', 'Authorization': 'REDACTED'}.
2022/04/04 07:44:49 azure: INFO: Client-Request-ID=1b33ceb3-b3eb-11ec-86d0-a32bbb211570 Receiving Response: Server-Timestamp=Mon, 04 Apr 2022 07:44:48 GMT, Server-Request-ID=1f3cbd8a-701e-0076-3ff7-4722bf000000, HTTP Status Code=200, Message=OK, Headers={'transfer-encoding': 'chunked', 'content-type': 'application/xml', 'server': 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0', 'x-ms-request-id': '1f3cbd8a-701e-0076-3ff7-4722bf000000', 'x-ms-client-request-id': '1b33ceb3-b3eb-11ec-86d0-a32bbb211570', 'x-ms-version': '2019-02-02', 'date': 'Mon, 04 Apr 2022 07:44:48 GMT'}.
2022/04/04 07:44:49 azure: INFO: Storage: The search starts from the date: 2021-12-05 07:44:49.670426+00:00 for blobs in container: 'frameworktestcontainer' 
2022/04/04 07:44:49 azure: INFO: Storage: End
azure.db contents
sqlite3 /var/ossec/wodles/azure/azure.db 'select * from graph;'
5956825a2e7b02dbebce74ec3c2ac5a5|auditLogs/directoryAudits|2022-04-02T07:36:02.517487Z|2022-04-03T14:50:15.9505931Z

sqlite3 /var/ossec/wodles/azure/azure.db 'select * from log_analytics;'
f90c15b0327962c9e661142547368572|AzureActivity|2022-03-05T07:37:22.330900Z|2022-04-01T12:01:44.372Z

sqlite3 /var/ossec/wodles/azure/azure.db 'select * from storage;'
82e049b81fa6eb88ebf85f1677785f2b|frameworkteststorage|2021-12-05T07:42:58.227604Z|2021-12-05T07:42:58.227604Z
Conclusions

The module worked as expected.

Test last_dates.json migration

Having a last_dates.json file with the following contents:

last_dates.json
{
    "log_analytics": {
        "f90c15b0327962c9e661142547368572": {
            "min": "2021-11-28T10:41:15.080696Z",
            "max": "2021-12-22T14:23:05.008Z"
        },
        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX": {
            "min": "2022-01-28T10:41:15.080696Z",
            "max": "2022-02-22T14:23:05.008Z"
        }
    },
    "graph": {
        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX": {
            "min": "2021-11-27T02:49:59.4427758Z",
            "max": "2021-11-29T09:45:47.358188Z"
        },
        "5956825a2e7b02dbebce74ec3c2ac5a5": {
            "min": "2021-12-24T15:28:00.922662Z",
            "max": "2021-12-27T02:49:56.9180341Z"
        }
    },
    "storage": {
        "82e049b81fa6eb88ebf85f1677785f2b": {
            "min": "2021-11-08T13:04:14.645523Z",
            "max": "2021-11-30T08:50:35.000000Z"
        },
        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX": {
            "min": "2021-10-20T11:29:37.000000Z",
            "max": "2021-12-28T08:56:10.000000Z"
        }
    }
}

Remove the database file and run the module and check the database status after the execution to ensure the data was successfully migrated

Command used
/var/ossec/wodles/azure/azure-logs --graph --graph_time_offset 2d --graph_query 'auditLogs/directoryAudits' --graph_auth_path /var/ossec/wodles/azure/credentials --graph_tenant_domain wazuh.onmicrosoft.com --graph_tag azure-active_directory -d 2
azure-logs output
/var/ossec/wodles/azure/azure-logs --graph --graph_time_offset 2d --graph_query 'auditLogs/directoryAudits' --graph_auth_path /var/ossec/wodles/azure/credentials --graph_tenant_domain wazuh.onmicrosoft.com --graph_tag azure-active_directory -d 2
2022/04/04 07:49:32 azure: INFO: Checking database integrity
2022/04/04 07:49:32 azure: INFO: Migration from an old last_dates file is necessary. 
2022/04/04 07:49:32 azure: INFO: Getting the data from /var/ossec/wodles/azure/last_dates.json.
2022/04/04 07:49:32 azure: INFO: The database migration process finished successfully.
2022/04/04 07:49:32 azure: INFO: Database integrity check finished
2022/04/04 07:49:32 azure: INFO: Azure Graph starting.
2022/04/04 07:49:32 azure: INFO: Graph: Getting authentication token.
2022/04/04 07:49:33 azure: INFO: Graph: Building the url.
2022/04/04 07:49:33 azure: INFO: Graph: The search starts for query: 'auditLogs/directoryAudits' using activityDateTime+ge+2022-04-02T07:49:33.135316Z
2022/04/04 07:49:33 azure: INFO: Graph: The URL is 'https://graph.microsoft.com/v1.0/auditLogs/directoryAudits?&$filter=activityDateTime+ge+2022-04-02T07:49:33.135316Z'
2022/04/04 07:49:33 azure: INFO: Graph: Pagination starts
2022/04/04 07:49:33 azure: DEBUG: Attempting to update a graph row object. MD5: '5956825a2e7b02dbebce74ec3c2ac5a5', min_date: '2021-12-24T15:28:00.922662Z', max_date: '2022-04-03T14:50:15.9505931Z'
2022/04/04 07:49:33 azure: INFO: Graph: Sending event by socket.
2022/04/04 07:49:33 azure: INFO: Graph: Sending event by socket.
2022/04/04 07:49:33 azure: INFO: Graph: Sending event by socket.
2022/04/04 07:49:33 azure: INFO: Graph: Sending event by socket.
2022/04/04 07:49:33 azure: INFO: Graph: End
azure.db contents
sqlite3 /var/ossec/wodles/azure/azure.db 'select * from graph;'
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX||2021-11-27T02:49:59.4427758Z|2021-11-29T09:45:47.358188Z
5956825a2e7b02dbebce74ec3c2ac5a5|auditLogs/directoryAudits|2021-12-24T15:28:00.922662Z|2022-04-03T14:50:15.9505931Z

sqlite3 /var/ossec/wodles/azure/azure.db 'select * from log_analytics;'
f90c15b0327962c9e661142547368572||2021-11-28T10:41:15.080696Z|2021-12-22T14:23:05.008Z
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX||2022-01-28T10:41:15.080696Z|2022-02-22T14:23:05.008Z

sqlite3 /var/ossec/wodles/azure/azure.db 'select * from storage;'
82e049b81fa6eb88ebf85f1677785f2b||2021-11-08T13:04:14.645523Z|2021-11-30T08:50:35.000000Z
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX||2021-10-20T11:29:37.000000Z|2021-12-28T08:56:10.000000Z

@CarlosRS9 CarlosRS9 self-assigned this Mar 25, 2022
@CarlosRS9 CarlosRS9 marked this pull request as draft March 30, 2022 15:09
@CarlosRS9 CarlosRS9 marked this pull request as ready for review March 31, 2022 06:48
Copy link
Contributor

@noise-kngdm noise-kngdm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a couple of improvements that I think it would be great to add to your PR -apart from the ones I suggested directly at the code`:

  • It would be great if you stored the query used for each service along with the md5, even if you don't use it later. It could be useful for debugging purposes.
  • Try to add the subscription ID to each Log Analytics row and use it along with the md5 hash as the primary key of the DB. This way, you will allow different accounts to make the same queries without the hassle of manually configuring them as <query> | where SubscriptionId == '<SubscriptionId-1>'.
  • I think it would have been better to use exceptions to handle ORM errors instead of returning False when something goes wrong. It isn't pythonic at all, which would be fine if it had any clear advantages, but I don't think it does.

wodles/azure/azure-logs.py Outdated Show resolved Hide resolved
wodles/azure/tests/test_orm.py Outdated Show resolved Hide resolved
wodles/azure/tests/test_orm.py Show resolved Hide resolved
wodles/azure/tests/test_orm.py Show resolved Hide resolved
wodles/azure/tests/test_orm.py Show resolved Hide resolved
Copy link
Contributor

@noise-kngdm noise-kngdm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a couple of things that you should review.

wodles/azure/tests/test_orm.py Outdated Show resolved Hide resolved
wodles/azure/azure-logs.py Outdated Show resolved Hide resolved
wodles/azure/azure-logs.py Outdated Show resolved Hide resolved
@CarlosRS9 CarlosRS9 marked this pull request as draft April 4, 2022 07:16
@CarlosRS9 CarlosRS9 marked this pull request as ready for review April 4, 2022 07:23
@CarlosRS9
Copy link
Contributor Author

  • It would be great if you stored the query used for each service along with the md5, even if you don't use it later. It could be useful for debugging purposes.

This was already addressed and included in this PR.

  • Try to add the subscription ID to each Log Analytics row and use it along with the md5 hash as the primary key of the DB. This way, you will allow different accounts to make the same queries without the hassle of manually configuring them as <query> | where SubscriptionId == '<SubscriptionId-1>'.

This will be addressed in #13051

  • I think it would have been better to use exceptions to handle ORM errors instead of returning False when something goes wrong. It isn't pythonic at all, which would be fine if it had any clear advantages, but I don't think it does.

This was replaced with a custom AzureORMError exception to be returned by the different functions in case something goes wrong.

@davidjiglesias davidjiglesias merged commit 745937b into master Apr 7, 2022
@davidjiglesias davidjiglesias deleted the feature/11940-azure-orm branch April 7, 2022 11:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Replace the Azure's last_dates.json file with a database file and an ORM
3 participants