Azure Log Analytics
Log Analytics is a service that helps you collect and analyze data generated by resources in your cloud and on-premises environments.
Analytics & SIEM · Azure Log Analytics
Details
| ID | Azure Log Analytics |
|---|---|
| Provider | Microsoft |
| Category | Analytics & SIEM |
| From Version | 5.0.0 |
| Docker Image | demisto/crypto:1.0.0.10120494 |
| Supported Modules | Agentix XSIAM Cloud Posture Security EDR Cortex Cloud Cloud Runtime Security |
README
Log Analytics is a service that helps you collect and analyze data generated by resources in your cloud and on-premises environments.
This integration was integrated and tested with version 2022-10-01 of Azure Log Analytics.
Authorization
In order to connect to the Azure Log Analytics use either the Cortex XSOAR Azure App or the Self-Deployed Azure App.
Depending on the authentication method that you use, the integration parameters might change.
Note: The Azure account must have permission to manage applications in Entra ID (Azure AD). Any of the following Entra ID roles include the required permissions:
- Application administrator
- Application developer
- Cloud application administrator
In addition, the user that granted the authorization needs to be assigned the Log Analytics Reader role.
For the search job commands the user needs to be assigned the Log Analytics Contributor role.
To add these roles:
1. In the Azure portal, go to `Log Analytics workspace` and select the workspace you are using -> Access control (IAM).
2. From Access control (IAM) select: Add role assignment
3. Select the user that granted the authorization and assign the Roles.
For more information, refer to the following Microsoft article.
Cortex XSOAR Azure Application
You need to grant Cortex XSOAR authorization to access Azure Log Analytics.
For more information, refer to the following article.
Note - The credentials are valid for a single instance only.
Self Deployed Application
To use a self-configured Azure application, you need to add a new Azure App Registration in the Azure Portal. To add the registration, see the Microsoft article.
Required permissions
- Azure Service Management - permission
user_impersonationof typeDelegated - Log Analytics API - permission
Data.Readof typeDelegated
In the self-deployed mode you can authenticate, by using one of the following flows:
- Authorization Code flow
- Client Credentials flow
Authorization Code flow
- In the instance configuration, select the Use a self-deployed Azure application - Authorization Code flow checkbox.
- Enter your client ID in the ID / Client ID parameter (credentials username).
- Enter your client secret in the Key / Client Secret parameter (credentials password).
- Enter your tenant ID in the Token parameter.
- Enter your redirect URI in the Redirect URI parameter.
- Save the integration settings.
- Run the
!azure-log-analytics-generate-login-urlcommand in the War Room and follow the instruction. - Run the azure-log-analytics-test command to test the connection and the authorization process.
Client Credentials Flow
Follow these steps for client-credentials configuration.
- In the instance configuration, select the Use a self-deployed Azure application - Client Credentials Authorization Flow checkbox.
- Enter your Client ID in the ID / Client ID parameter.
- Enter your Client Secret in the Key / Client Secret parameter.
- Enter your Tenant ID in the Tenant ID parameter.
- Click Test to validate the URLs, token, and connection.
Get the additional instance parameters
To get the Subscription ID, Workspace Name, Workspace ID and Resource Group parameters, navigate in the Azure Portal to Azure Sentinel > YOUR-WORKSPACE > Settings and click the Workspace Settings tab.
Configure Azure Log Analytics on Cortex XSOAR
- Navigate to Settings > Integrations > Servers & Services.
- Search for Azure Log Analytics.
-
Click Add instance to create and configure a new integration instance.
Parameter Description Required Token / Tenant ID Received from the authorization process or from the self-deployed configuration process (find the tenant ID in your app overview page in the Azure portal) False Token / Tenant ID False ID / Client ID Received from the authorization process or from the self-deployed configuration process. False Key / Client Secret False Certificate Thumbprint Used for certificate authentication. As appears in the “Certificates & secrets” page of the app. False Certificate Thumbprint Used for certificate authentication. As appears in the “Certificates & secrets” page of the app. False Private Key Used for certificate authentication. The private key of the registered certificate. False Use a self-deployed Azure application - Authorization Code flow Check when authenticating using the Authorization Code flow. False Use a self-deployed Azure application - Client Credentials Flow Check when authenticating using the Client Credentials flow. False Application redirect URI (for self-deployed mode) False Authorization code Get the Authorization code from steps 3-5 in the self deployed authorization process. False Authorization code Get the Authorization code from steps 3-5 in the self deployed authorization process. False Use Azure Managed Identities Relevant only if the integration is running on Azure VM. If selected, authenticates based on the value provided for the Azure Managed Identities Client ID field. If no value is provided for the Azure Managed Identities Client ID field, authenticates based on the System Assigned Managed Identity. For additional information, see the Help tab. False Azure Managed Identities Client ID The Managed Identities client id for authentication - relevant only if the integration is running on Azure VM. False Default Subscription ID The parameter can be saved as 000-000 and added as an argument to each command, but Test button will fail. True Default Resource Group Name The parameter can be saved as 000-000 and added as an argument to each command, but Test button will fail. True Default Workspace Name The parameter can be saved as 000-000 and added as an argument to each command. True Default Workspace ID (the UUID of the workspace, e.g. 123e4567-e89b-12d3-a456-426614174000) The parameter can be saved as 000-000 and added as an argument to each command, but Test button will fail. True Trust any certificate (not secure) False Use system proxy settings False Azure Cloud Azure Cloud the K8S cluster resides in. See table below. False Server URL Use this option when required to customize the URL to the Azure management endpoint. False -
Azure cloud options
Azure Cloud Description Worldwide The publicly accessible Azure Cloud US GCC Azure cloud for the USA Government Cloud Community (GCC) US GCC-High Azure cloud for the USA Government Cloud Community High (GCC-High) DoD Azure cloud for the USA Department of Defense (DoD) Germany Azure cloud for the German Government China Azure cloud for the Chinese Government Custom Custom endpoint configuration to the Azure cloud. See note below. - Note: In most cases, setting Azure cloud is preferred to setting Azure AD endpoint. Only use it in cases where a custom proxy URL is required for accessing a national cloud.
- See further documentation in Using National Cloud.
- Click Test to validate the URLs, token, and connection.
Commands
You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
azure-log-analytics-execute-query
Executes an Analytics query for data.
Base Command
azure-log-analytics-execute-query
Input
| Argument Name | Description | Required |
|---|---|---|
| query | The query to execute. | Required |
| timespan | The timespan over which to query data. This is an ISO8601 time period value. This timespan is applied in addition to any timespans specified in the query expression. | Optional |
| timeout | The amount of time (in seconds) that a request will wait for the query response before a timeout occurs. Default is 10. | Optional |
| workspace_id | The Workspace ID. Note: This argument will override the instance parameter ‘Default Workspace ID’. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| AzureLogAnalytics.Query.Query | String | The executed query. |
| AzureLogAnalytics.Query.TableName | String | The name of the query table. |
Command Example
!azure-log-analytics-execute-query query="Usage | take 10" workspace_id=WORKSPACE_ID
Human Readable Output
Query Results
PrimaryResult
Tenant Id Computer Time Generated Source System Start Time End Time Resource Uri Data Type Solution Batches Within Sla Batches Outside Sla Batches Capped Total Batches Avg Latency In Seconds Quantity Quantity Unit Is Billable Meter Id Linked Meter Id Type TENANT_ID Deprecated field: see http://aka.ms/LA-Usage 2020-07-30T04:00:00Z OMS 2020-07-30T03:00:00Z 2020-07-30T04:00:00Z /subscriptions/SUBSCRIPTION_ID/resourcegroups/RESOURCE_GROUP/providers/microsoft.operationalinsights/workspaces/WORKSPACE_NAME Operation LogManagement 0 0 0 0 0 0.00714 MBytes false METER_ID 00000000-0000-0000-0000-000000000000 Usage TENANT_ID Deprecated field: see http://aka.ms/LA-Usage 2020-07-30T04:00:00Z OMS 2020-07-30T03:00:00Z 2020-07-30T04:00:00Z /subscriptions/SUBSCRIPTION_ID/resourcegroups/RESOURCE_GROUP/providers/microsoft.operationalinsights/workspaces/WORKSPACE_NAME SigninLogs LogManagement 0 0 0 0 0 0.012602 MBytes true METER_ID 00000000-0000-0000-0000-000000000000 Usage TENANT_ID Deprecated field: see http://aka.ms/LA-Usage 2020-07-30T05:00:00Z OMS 2020-07-30T04:00:00Z 2020-07-30T05:00:00Z /subscriptions/SUBSCRIPTION_ID/resourcegroups/RESOURCE_GROUP/providers/microsoft.operationalinsights/workspaces/WORKSPACE_NAME OfficeActivity Office365/SecurityInsights 0 0 0 0 0 0.00201499908978072 MBytes false METER_ID 00000000-0000-0000-0000-000000000000 Usage TENANT_ID Deprecated field: see http://aka.ms/LA-Usage 2020-07-30T05:00:00Z OMS 2020-07-30T04:00:00Z 2020-07-30T05:00:00Z /subscriptions/SUBSCRIPTION_ID/resourcegroups/RESOURCE_GROUP/providers/microsoft.operationalinsights/workspaces/WORKSPACE_NAME SigninLogs LogManagement 0 0 0 0 0 0.009107 MBytes true METER_ID 00000000-0000-0000-0000-000000000000 Usage
azure-log-analytics-test
Tests connectivity to Azure Log Analytics.
Base Command
azure-log-analytics-test
Input
There are no input arguments for this command.
Context Output
There is no context output for this command.
Command Example
#### Human Readable Output
>```✅ Success!```
### azure-log-analytics-list-saved-searches
***
Gets the saved searches of the Log Analytics workspace.
#### Base Command
`azure-log-analytics-list-saved-searches`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| limit | The maximum number of saved searches to return. Default is 50. | Optional |
| page | The page number from which to start a search. Default is 0. | Optional |
| subscription_id | The subscription ID to use. Note: This argument will override the instance parameter 'Default Subscription ID'. | Optional |
| resource_group_name | The name of the resource group within the user's subscription. Note: This argument will override the instance parameter 'Default Resource Group Name'. | Optional |
| workspace_name | The name of the resource group. Note: This argument will override the instance parameter 'Default Workspace Name'. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| AzureLogAnalytics.SavedSearch.id | String | The ID of the saved search. |
| AzureLogAnalytics.SavedSearch.etag | String | The ETag of the saved search. |
| AzureLogAnalytics.SavedSearch.category | String | The category of the saved search. This helps users quickly find a saved search. |
| AzureLogAnalytics.SavedSearch.displayName | String | Display name of the saved search. |
| AzureLogAnalytics.SavedSearch.functionAlias | String | The function alias if the query serves as a function. |
| AzureLogAnalytics.SavedSearch.functionParameters | String | The optional function parameters if the query serves as a function. Value should be in the following format: 'param-name1:type1 = default_value1, param-name2:type2 = default_value2'. For more examples and proper syntax, refer to <https://docs.microsoft.com/en-us/azure/kusto/query/functions/user-defined-functions> |
| AzureLogAnalytics.SavedSearch.query | String | The query expression for the saved search. |
| AzureLogAnalytics.SavedSearch.tags | String | The tags attached to the saved search. |
| AzureLogAnalytics.SavedSearch.version | Number | The version number of the query language. The current version and default is 2. |
| AzureLogAnalytics.SavedSearch.type | String | The resource type, e.g., Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts. |
#### Command Example
```!azure-log-analytics-list-saved-searches limit=3```
#### Human Readable Output
>### Saved searches
>|Etag|Id|Category|Display Name|Function Alias|Function Parameters|Query|Tags|Version|Type|
>|---|---|---|---|---|---|---|---|---|---|
>| W/"datetime'2020-07-05T13%3A38%3A41.053438Z'" | test2 | category1 | test2 | heartbeat_func | a:int=1 | Heartbeat \| summarize Count() by Computer \| take a | {'name': 'Group', 'value': 'Computer'} | 2 | Microsoft.OperationalInsights/savedSearches |
>| W/"datetime'2020-07-28T18%3A43%3A56.8625448Z'" | test123 | Saved Search Test Category | test123 | heartbeat_func | a:int=1 | Heartbeat \| summarize Count() by Computer \| take a | {'name': 'Group', 'value': 'Computer'} | 2 | Microsoft.OperationalInsights/savedSearches |
>| W/"datetime'2020-07-30T11%3A41%3A35.1459664Z'" | test1234 | test | test | | | SecurityAlert<br/>\| summarize arg_max(TimeGenerated, *) by SystemAlertId<br/>\| where SystemAlertId in("TEST_SYSTEM_ALERT_ID") | | 2 | Microsoft.OperationalInsights/savedSearches |
### azure-log-analytics-get-saved-search-by-id
***
Gets a specified saved search from the Log Analytics workspace.
#### Base Command
`azure-log-analytics-get-saved-search-by-id`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| saved_search_id | The ID of the saved search. | Required |
| subscription_id | The subscription ID to use. Note: This argument will override the instance parameter 'Default Subscription ID'. | Optional |
| resource_group_name | The name of the resource group within the user's subscription. Note: This argument will override the instance parameter 'Default Resource Group Name'. | Optional |
| workspace_name | The name of the resource group. Note: This argument will override the instance parameter 'Default Workspace Name'. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| AzureLogAnalytics.SavedSearch.id | String | The ID of the saved search. |
| AzureLogAnalytics.SavedSearch.etag | String | The ETag of the saved search. |
| AzureLogAnalytics.SavedSearch.category | String | The category of the saved search. This helps users quickly find a saved search. |
| AzureLogAnalytics.SavedSearch.displayName | String | The display name of the saved search. |
| AzureLogAnalytics.SavedSearch.functionAlias | String | The function alias if the query serves as a function. |
| AzureLogAnalytics.SavedSearch.functionParameters | String | The optional function parameters if the query serves as a function. Value should be in the following format: 'param-name1:type1 = default_value1, param-name2:type2 = default_value2'. For more examples and proper syntax see the Microsoft documentation, <https://docs.microsoft.com/en-us/azure/kusto/query/functions/user-defined-functions> |
| AzureLogAnalytics.SavedSearch.query | String | The query expression for the saved search. |
| AzureLogAnalytics.SavedSearch.tags | String | The tags attached to the saved search. |
| AzureLogAnalytics.SavedSearch.version | Number | The version number of the query language. The current version and default is 2. |
| AzureLogAnalytics.SavedSearch.type | String | The resource type, e.g., Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts. |
#### Command Example
```!azure-log-analytics-get-saved-search-by-id saved_search_id=test1234```
#### Human Readable Output
>### Saved search `test1234` properties
>|Etag|Id|Category|Display Name|Query|Version|
>|---|---|---|---|---|---|
>| W/"datetime'2020-07-30T12%3A21%3A05.3197505Z'" | test1234 | test | test | SecurityAlert | summarize arg_max(TimeGenerated, *) by SystemAlertId | where SystemAlertId in("TEST_SYSTEM_ALERT_ID") | 2 |
### azure-log-analytics-create-or-update-saved-search
***
Creates or updates a saved search from the Log Analytics workspace.
#### Base Command
`azure-log-analytics-create-or-update-saved-search`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| saved_search_id | The ID of the saved search. | Required |
| etag | The ETag of the saved search. This argument is required for updating an existing saved search. | Optional |
| category | The category of the saved search. This helps users quickly find a saved search. | Required |
| display_name | The display name of the saved search. | Required |
| function_alias | The function alias if the query serves as a function. | Optional |
| function_parameters | The optional function parameters if the query serves as a function. Value should be in the following format: 'param-name1:type1 = default_value1, param-name2:type2 = default_value2'. For more examples and proper syntax, refer to <https://docs.microsoft.com/en-us/azure/kusto/query/functions/user-defined-functions>. | Optional |
| query | The query expression for the saved search. | Required |
| tags | The tags attached to the saved search. Value should be in the following format: 'name=value;name=value'. | Optional |
| subscription_id | The subscription ID to use. Note: This argument will override the instance parameter 'Default Subscription ID'. | Optional |
| resource_group_name | The name of the resource group within the user's subscription. Note: This argument will override the instance parameter 'Default Resource Group Name'. | Optional |
| workspace_name | The name of the resource group. Note: This argument will override the instance parameter 'Default Workspace Name'. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| AzureLogAnalytics.SavedSearch.id | String | The ID of the saved search. |
| AzureLogAnalytics.SavedSearch.etag | String | The ETag of the saved search. |
| AzureLogAnalytics.SavedSearch.category | String | The category of the saved search. This helps users quickly find a saved search. |
| AzureLogAnalytics.SavedSearch.displayName | String | The display name of the saved search. |
| AzureLogAnalytics.SavedSearch.functionAlias | String | The function alias if the query serves as a function. |
| AzureLogAnalytics.SavedSearch.functionParameters | String | The optional function parameters if the query serves as a function. Value should be in the following format: 'param-name1:type1 = default_value1, param-name2:type2 = default_value2'. For more examples and proper syntax, refer to <https://docs.microsoft.com/en-us/azure/kusto/query/functions/user-defined-functions>. |
| AzureLogAnalytics.SavedSearch.query | String | The query expression for the saved search. |
| AzureLogAnalytics.SavedSearch.tags | String | The tags attached to the saved search. |
| AzureLogAnalytics.SavedSearch.version | Number | The version number of the query language. The current version and default is 2. |
| AzureLogAnalytics.SavedSearch.type | String | The resource type, e.g., Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts. |
#### Command Example
!azure-log-analytics-create-or-update-saved-search saved_search_id=”test1234” category=”test” display_name=”new display name test” query=`SecurityAlert
| summarize arg_max(TimeGenerated, *) by SystemAlertId
| where SystemAlertId in(“TEST_SYSTEM_ALERT_ID”)
#### Human Readable Output
>### Saved search `test1234` properties
>|Etag|Id|Category|Display Name|Query|Version|
>|---|---|---|---|---|---|
>| W/"datetime'2020-07-30T12%3A21%3A05.3197505Z'" | test1234 | test | new display name test | SecurityAlert | summarize arg_max(TimeGenerated, *) by SystemAlertId | where SystemAlertId in("TEST_SYSTEM_ALERT_ID") | 2 |
### azure-log-analytics-delete-saved-search
***
Deletes a specified saved search in the Log Analytics workspace.
#### Base Command
`azure-log-analytics-delete-saved-search`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| saved_search_id | The ID of the saved search. | Required |
| subscription_id | The subscription ID to use. Note: This argument will override the instance parameter 'Default Subscription ID'. | Optional |
| resource_group_name | The name of the resource group within the user's subscription. Note: This argument will override the instance parameter 'Default Resource Group Name'. | Optional |
| workspace_name | The name of the resource group. Note: This argument will override the instance parameter 'Default Workspace Name'. | Optional |
#### Context Output
There is no context output for this command.
#### Command Example
```!azure-log-analytics-delete-saved-search saved_search_id=test1234```
#### Human Readable Output
>Successfully deleted the saved search test1234.
### azure-log-analytics-generate-login-url
***
Generate the login url used for Authorization code flow.
#### Base Command
`azure-log-analytics-generate-login-url`
#### Input
There are no input arguments for this command.
#### Context Output
There is no context output for this command.
#### Command Example
```azure-log-analytics-generate-login-url```
#### Human Readable Output
>### Authorization instructions
>
>1. Click on the login URL to sign in and grant Cortex XSOAR permissions for your Azure Service Management.
You will be automatically redirected to a link with the following structure:
```REDIRECT_URI?code=AUTH_CODE&session_state=SESSION_STATE```
>2. Copy the `AUTH_CODE` (without the `“code=”` prefix, and the `session_state` parameter)
and paste it in your instance configuration under the **Authorization code** parameter.
### azure-log-analytics-subscriptions-list
***
List all subscriptions for a tenant.
#### Base Command
`azure-log-analytics-subscriptions-list`
#### Input
There are no input arguments for this command.
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| AzureLogAnalytics.Subscription.authorizationSource | String | The authorization source of the request. |
| AzureLogAnalytics.Subscription.displayName | String | The subscription display name. |
| AzureLogAnalytics.Subscription.id | String | The fully qualified ID for the subscription. For example, /subscriptions/8d65815f-a5b6-402f-9298-045155da7d74. |
| AzureLogAnalytics.Subscription.managedByTenants | Unknown | An array containing the tenants managing the subscription. |
| AzureLogAnalytics.Subscription.state | Unknown | The subscription state. Possible values are Enabled, Warned, PastDue, Disabled, and Deleted. |
| AzureLogAnalytics.Subscription.subscriptionId | String | The subscription ID. |
| AzureLogAnalytics.Subscription.subscriptionPolicies | Unknown | The subscription policies. |
| AzureLogAnalytics.Subscription.tags | Object | The tags attached to the subscription. |
| AzureLogAnalytics.Subscription.tenantId | String | The subscription tenant ID. |
### azure-log-analytics-workspace-list
***
Gets workspaces in a resource group.
#### Base Command
`azure-log-analytics-workspace-list`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| subscription_id | The subscription ID. Note: This argument will override the instance parameter 'Default Subscription ID'. | Optional |
| resource_group_name | The name of the resource group within the user's subscription. Note: This argument will override the instance parameter 'Default Resource Group Name'. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| AzureLogAnalytics.workspace.etag | String | The etag of the workspace. |
| AzureLogAnalytics.workspace.id | String | Fully qualified resource ID for the resource. |
| AzureLogAnalytics.workspace.identity.principalId | String | The principal ID of resource identity. |
| AzureLogAnalytics.workspace.identity.tenantId | String | The tenant ID of resource. |
| AzureLogAnalytics.workspace.identity.type | String | Type of managed service identity. |
| AzureLogAnalytics.workspace.identity.userAssignedIdentities.clientId | String | The client id of user assigned identity. |
| AzureLogAnalytics.workspace.identity.userAssignedIdentities.principalId | String | The principal id of user assigned identity. |
| AzureLogAnalytics.workspace.location | String | The geo-location where the resource lives. |
| AzureLogAnalytics.workspace.name | String | The name of the resource. |
| AzureLogAnalytics.workspace.properties.createdDate | String | Workspace creation date. |
| AzureLogAnalytics.workspace.properties.customerId | String | This is a read-only property. Represents the ID associated with the workspace. |
| AzureLogAnalytics.workspace.properties.defaultDataCollectionRuleResourceId | String | The resource ID of the default Data Collection Rule to use for this workspace. |
| AzureLogAnalytics.workspace.properties.features.clusterResourceId | String | Dedicated LA cluster resourceId that is linked to the workspaces. |
| AzureLogAnalytics.workspace.properties.features.disableLocalAuth | Boolean | Disable Non-AAD based Auth. |
| AzureLogAnalytics.workspace.properties.features.enableDataExport | Boolean | Flag that indicate if data should be exported. |
| AzureLogAnalytics.workspace.properties.features.enableLogAccessUsingOnlyResourcePermissions | Boolean | Flag that indicate which permission to use - resource or workspace or both. |
| AzureLogAnalytics.workspace.properties.features.immediatePurgeDataOn30Days | Boolean | Flag that describes if we want to remove the data after 30 days. |
| AzureLogAnalytics.workspace.properties.forceCmkForQuery | Boolean | Indicates whether customer managed storage is mandatory for query management. |
| AzureLogAnalytics.workspace.properties.modifiedDate | String | Workspace modification date. |
| AzureLogAnalytics.workspace.properties.privateLinkScopedResources.resourceId | String | The full resource Id of the private link scope resource. |
| AzureLogAnalytics.workspace.properties.privateLinkScopedResources.scopeId | String | The private link scope unique Identifier. |
| AzureLogAnalytics.workspace.properties.provisioningState | String | The provisioning state of the workspace. |
| AzureLogAnalytics.workspace.properties.publicNetworkAccessForIngestion | String | The network access type for accessing Log Analytics ingestion. |
| AzureLogAnalytics.workspace.properties.publicNetworkAccessForQuery | String | The network access type for accessing Log Analytics query. |
| AzureLogAnalytics.workspace.properties.retentionInDays | Number | The workspace data retention in days. Allowed values are per pricing plan. See pricing tiers documentation for details. |
| AzureLogAnalytics.workspace.properties.sku.capacityReservationLevel | Number | The capacity reservation level in GB for this workspace, when CapacityReservation sku is selected. |
| AzureLogAnalytics.workspace.properties.sku.lastSkuUpdate | String | lastSkuUpdate |
| AzureLogAnalytics.workspace.properties.sku.name | String | The name of the SKU. |
| AzureLogAnalytics.workspace.properties.workspaceCapping.dailyQuotaGb | Number | The workspace daily quota for ingestion. |
| AzureLogAnalytics.workspace.properties.workspaceCapping.dataIngestionStatus | String | The status of data ingestion for this workspace. |
| AzureLogAnalytics.workspace.properties.workspaceCapping.quotaNextResetTime | String | The time when the quota will be rest. |
| AzureLogAnalytics.workspace.systemData.createdAt | String | The timestamp of resource creation \(UTC\). |
| AzureLogAnalytics.workspace.systemData.createdBy | String | The identity that created the resource. |
| AzureLogAnalytics.workspace.systemData.createdByType | String | The type of identity that created the resource. |
| AzureLogAnalytics.workspace.systemData.lastModifiedAt | String | The timestamp of resource last modification \(UTC\). |
| AzureLogAnalytics.workspace.systemData.lastModifiedBy | String | The identity that last modified the resource. |
| AzureLogAnalytics.workspace.systemData.lastModifiedByType | String | lastModifiedByType |
| AzureLogAnalytics.workspace.tags | Object | Resource tags. |
| AzureLogAnalytics.workspace.type | String | The type of the resource. |
### azure-log-analytics-resource-group-list
***
List all resource groups for a subscription.
#### Base Command
`azure-log-analytics-resource-group-list`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| subscription_id | The subscription ID. Note: This argument will override the instance parameter 'Default Subscription ID'. | Optional |
| limit | Limit on the number of resource groups to return. Default is 50. | Optional |
| tag | A single tag in the form of '{"Tag Name":"Tag Value"}' to filter the list by. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| AzureLogAnalytics.ResourceGroup.id | String | The ID of the resource group. |
| AzureLogAnalytics.ResourceGroup.location | String | The location of the resource group. |
| AzureLogAnalytics.ResourceGroup.managedBy | String | The ID of the resource that manages this resource group. |
| AzureLogAnalytics.ResourceGroup.name | String | The name of the resource group. |
| AzureLogAnalytics.ResourceGroup.properties.provisioningState | String | The provisioning state. |
| AzureLogAnalytics.ResourceGroup.tags | Object | The tags attached to the resource group. |
| AzureLogAnalytics.ResourceGroup.type | String | The type of the resource group. |
### azure-log-analytics-auth-reset
***
Run this command if for some reason you need to rerun the authentication process.
#### Base Command
`azure-log-analytics-auth-reset`
#### Input
There are no input arguments for this command.
#### Context Output
There is no context output for this command.
### azure-log-analytics-run-search-job
***
Run a search job to fetch records from large datasets into a new search results table in your workspace.
#### Base Command
`azure-log-analytics-run-search-job`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| table_name | The name of the table to add. Must contain '_SRCH' suffix. Example value: AuditLogs_SRCH. | Required |
| limit | Maximum number of records in the result set, up to one million records. Default is 50. | Optional |
| query | Log query written in KQL format to retrieve data. Search job queries must always start with a table name. For the proper syntax, see <https://learn.microsoft.com/en-us/azure/data-explorer/kusto/query/whereoperator> | Required |
| start_search_time | Start of the time range to search. The value can either be in minutes, days, weeks, or a simple ISO 8601 format such as "2023-10-31T00:00:00Z". Default is 1 day. | Optional |
| end_search_time | End of the time range to search. The value can either be in minutes, days, weeks, or a simple ISO 8601 format such as "2023-10-31T00:00:00Z". Default is now. | Optional |
| timeout | The timeout in seconds until polling ends. Default is 600. | Optional |
| interval | The interval in seconds between each poll. Default is 60. | Optional |
| subscription_id | The subscription ID to use. Note: This argument will override the instance parameter 'Default Subscription ID'. | Optional |
| resource_group_name | The name of the resource group within the user's subscription. Note: This argument will override the instance parameter 'Default Resource Group Name'. | Optional |
| workspace_name | The name of the resource group. Note: This argument will override the instance parameter 'Default Workspace Name'. | Optional |
| first_run | This argument is used to determine whether the current execution of the command is the initial run. After the command is executed, the argument is updated to 'false.' During polling, the code checks the status only for the first execution. This argument is for a developer, not for a user. Default is True. | Optional |
| hide_polling_output | Hide the polling message and only print the final status at the end. This argument is for a developer, not for a user. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| AzureLogAnalytics.RunSearchJob.TableName | String | Table name. |
| AzureLogAnalytics.RunSearchJob.Query | String | The query that was used to create the table. |
#### Command example
```!azure-log-analytics-run-search-job table_name=test_SRCH query=AuditLogs limit=10```
#### Human Readable Output
>The command was sent successfully. You can check the status of the command by running `!azure-log-analytics-get-search-job` command or wait.
After polling is ending
> The test_SRCH table created successfully. In order to get the table, run `!azure-log-analytics-execute-query query=test_SRCH`
### azure-log-analytics-get-search-job
***
Gets a Log Analytics workspace table.
#### Base Command
`azure-log-analytics-get-search-job`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| table_name | The name of the table. Example value: AuditLogs_SRCH. | Optional |
| subscription_id | The subscription ID to use. Note: This argument will override the instance parameter 'Default Subscription ID'. | Optional |
| resource_group_name | The name of the resource group within the user's subscription. Note: This argument will override the instance parameter 'Default Resource Group Name'. | Optional |
| workspace_name | The name of the resource group. Note: This argument will override the instance parameter 'Default Workspace Name'. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| AzureLogAnalytics.SearchJob.systemData.createdBy | String | The identity that created the resource. |
| AzureLogAnalytics.SearchJob.systemData.createdAt | Date | The timestamp of resource creation (UTC). |
| AzureLogAnalytics.SearchJob.properties.resultStatistics.progress | Number | Search job completion percentage. |
| AzureLogAnalytics.SearchJob.properties.resultStatistics.ingestedRecords | Number | The number of rows that were returned by the search job. |
| AzureLogAnalytics.SearchJob.properties.resultStatistics.scannedGb | Number | Amount of scanned data in the search job. |
| AzureLogAnalytics.SearchJob.properties.searchResults.query | String | Search job query. |
| AzureLogAnalytics.SearchJob.properties.searchResults.description | String | Search job description. |
| AzureLogAnalytics.SearchJob.properties.searchResults.limit | Number | Limit the search job to return up to the specified number of rows. |
| AzureLogAnalytics.SearchJob.properties.searchResults.startSearchTime | Date | The timestamp to start the search from (UTC). |
| AzureLogAnalytics.SearchJob.properties.searchResults.endSearchTime | Date | The timestamp to end the search by (UTC). |
| AzureLogAnalytics.SearchJob.properties.searchResults.sourceTable | String | The table used in the search job. |
| AzureLogAnalytics.SearchJob.properties.schema.name | String | Table name. |
| AzureLogAnalytics.SearchJob.properties.schema.tableSubType | String | The subtype describes what APIs can be used to interact with the table, and what features are available against it (Any, Classic, DataCollectionRuleBased). |
| AzureLogAnalytics.SearchJob.properties.schema.tableType | String | Table's creator. |
| AzureLogAnalytics.SearchJob.properties.schema.displayName | String | Table display name. |
| AzureLogAnalytics.SearchJob.properties.schema.description | String | Table description. |
| AzureLogAnalytics.SearchJob.properties.schema.columns | List | A list of table custom columns. |
| AzureLogAnalytics.SearchJob.properties.schema.standardColumns.isHidden | Boolean | Is column hidden. |
| AzureLogAnalytics.SearchJob.properties.schema.standardColumns.name | String | Column name. |
| AzureLogAnalytics.SearchJob.properties.schema.standardColumns.type | String | Column data type (bool, datetime, dynamic, guid, int, long, real, string). |
| AzureLogAnalytics.SearchJob.properties.schema.standardColumns.dataTypeHint | String | Column data type logical hint (armPath, guid, ip, uri). |
| AzureLogAnalytics.SearchJob.properties.schema.standardColumns.displayName | String | Column display name. |
| AzureLogAnalytics.SearchJob.properties.schema.standardColumns.description | String | Column description. |
| AzureLogAnalytics.SearchJob.properties.schema.standardColumns.isDefaultDisplay | Boolean | Is displayed by default. |
| AzureLogAnalytics.SearchJob.properties.schema.categories | String | Table category. |
| AzureLogAnalytics.SearchJob.properties.schema.labels | String | Table labels. |
| AzureLogAnalytics.SearchJob.properties.schema.source | String | Table's creator (customer, microsoft). |
| AzureLogAnalytics.SearchJob.properties.schema.solutions | String | List of solutions the table is affiliated with. |
| AzureLogAnalytics.SearchJob.properties.provisioningState | String | Table's current provisioning state (Deleting, InProgress, Succeeded, Updating). If set to 'updating', indicates a resource lock due to an ongoing operation, forbidding any update to the table until the ongoing operation is concluded. |
| AzureLogAnalytics.SearchJob.properties.retentionInDays | Number | The table retention in days, between 4 and 730. Setting this property to -1 will default to the workspace retention. |
| AzureLogAnalytics.SearchJob.properties.totalRetentionInDays | Number | The table total retention in days, between 4 and 2556. Setting this property to -1 will default to table retention. |
| AzureLogAnalytics.SearchJob.properties.archiveRetentionInDays | Number | The table data archive retention in days. Calculated as (totalRetentionInDays-retentionInDays). |
| AzureLogAnalytics.SearchJob.properties.retentionInDaysAsDefault | Boolean | True - Value originates from workspace retention in days, False - Customer specific. |
| AzureLogAnalytics.SearchJob.properties.totalRetentionInDaysAsDefault | Boolean | True - Value originates from retention in days, False - Customer specific. |
| AzureLogAnalytics.SearchJob.properties.plan | String | Instruct the system how to handle and charge the logs ingested to this table. |
| AzureLogAnalytics.SearchJob.id | String | Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}. |
| AzureLogAnalytics.SearchJob.name | String | The name of the resource. |
#### Command example
```!azure-log-analytics-get-search-job table_name=test_SRCH```
#### Context Example
```json
{
"AzureLogAnalytics": {
"SearchJob": {
"id": "/tables/test_SRCH",
"name": "test_SRCH",
"properties": {
"archiveRetentionInDays": 0,
"createDate": "2023-11-01T21:27:50.3032268Z",
"createdBy": "TEST",
"lastPlanModifiedDate": "2023-11-01T21:27:50.3031023Z",
"plan": "Analytics",
"provisioningState": "InProgress",
"resultStatistics": {
"ingestedRecords": 0,
"progress": 0,
"scannedGb": 0
},
"retentionInDays": 30,
"retentionInDaysAsDefault": true,
"schema": {
"columns": [
{
"isDefaultDisplay": false,
"isHidden": false,
"name": "_OriginalTenantId",
"type": "string"
},
{
"isDefaultDisplay": false,
"isHidden": false,
"name": "SourceSystem",
"type": "string"
}
],
"isTroubleshootingAllowed": false,
"name": "test_SRCH",
"solutions": [
"LogManagement"
],
"standardColumns": [
{
"isDefaultDisplay": false,
"isHidden": false,
"name": "TenantId",
"type": "guid"
}
],
"tableSubType": "DataCollectionRuleBased",
"tableType": "SearchResults"
},
"searchResults": {
"azureAsyncOperationId": "TEST",
"description": "This table was created using a Search Job with the following query: 'AuditLogs'.",
"endSearchTime": "2023-11-01T21:27:43.744Z",
"limit": 10,
"query": "AuditLogs",
"sourceTable": "AuditLogs",
"startSearchTime": "2023-10-31T21:27:43.735Z"
},
"totalRetentionInDays": 30,
"totalRetentionInDaysAsDefault": true
},
"systemData": {
"createdAt": "2023-11-01T21:27:50.3032268Z",
"createdBy": "TEST",
"createdByType": null,
"lastModifiedAt": null,
"lastModifiedBy": null,
"lastModifiedByType": null
}
}
}
}
Human Readable Output
Search Job
Create Date Description Name Plan Query endSearchTime provisioningState startSearchTime 2023-11-02T17:28:22.9374877Z This table was created using a Search Job with the following query: ‘AuditLogs’. test_SRCH Analytics AuditLogs 2023-11-02T17:28:18.602Z InProgress 2023-11-01T17:28:18.592Z
azure-log-analytics-delete-search-job
Delete a Log Analytics workspace table. We recommend you delete the search job when you’re done querying the table. This reduces workspace clutter and extra charges for data retention.
Base Command
azure-log-analytics-delete-search-job
Input
| Argument Name | Description | Required |
|---|---|---|
| table_name | The name of the table. Must contain ‘_SRCH’ suffix. Example value: AuditLogs_SRCH. | Optional |
| subscription_id | The subscription ID to use. Note: This argument will override the instance parameter ‘Default Subscription ID’. | Optional |
| resource_group_name | The name of the resource group within the user’s subscription. Note: This argument will override the instance parameter ‘Default Resource Group Name’. | Optional |
| workspace_name | The name of the resource group. Note: This argument will override the instance parameter ‘Default Workspace Name’. | Optional |
Context Output
There is no context output for this command.
Command example
!azure-log-analytics-delete-search-job table_name=test_SRCH
Human Readable Output
Search job test_SRCH deleted successfully.
Troubleshooting
In case of a hash verification error:
- Use the Oproxy flow to generate a new pair of credentials. This is crucial as it ensures that any issues related to authentication can be mitigated with fresh credentials.
- Execute the command !azure-log-analytics-auth-reset. This command resets the authentication mechanism, allowing for the new credentials to be accepted.
- Insert the newly created credentials into the original instance where the error occurred. Make sure the credentials are entered correctly to avoid further errors.
- After updating the credentials, test the integration.
Configuration parameters
azure_cloud— Azure Cloudserver_url— Server URLrefresh_token— Token / Tenant IDcredentials_refresh_token—creds_client_id—credentials—certificate_thumbprint— Certificate Thumbprintcredentials_certificate_thumbprint—private_key— Private Keyself_deployed— Use a self-deployed Azure application - Authorization Code flowclient_credentials— Use a self-deployed Azure application - Client Credentials Flowredirect_uri— Application redirect URI (for self-deployed mode)auth_code— Authorization codecredentials_auth_code—use_managed_identities— Use Azure Managed Identitiesmanaged_identities_client_id—subscriptionID— Default Subscription ID (required)resourceGroupName— Default Resource Group Name (required)workspaceName— Default Workspace Name (required)workspaceID— Default Workspace ID (the UUID of the workspace, e.g. 123e4567-e89b-12d3-a456-426614174000) (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (14)
-
azure-log-analytics-auth-resetRun this command if for some reason you need to rerun the authentication process.
-
azure-log-analytics-create-or-update-saved-searchCreates or updates a saved search from the Log Analytics workspace.
-
azure-log-analytics-delete-saved-searchDeletes a specified saved search in the Log Analytics workspace.
-
azure-log-analytics-delete-search-jobDelete a Log Analytics workspace table. We recommend you delete the search job when you're done querying the table. This reduces workspace clutter and extra charges for data retention.
-
azure-log-analytics-execute-queryExecutes an Analytics query for data.
-
azure-log-analytics-generate-login-urlGenerate the login url used for Authorization code flow.
-
azure-log-analytics-get-saved-search-by-idGets a specified saved search from the Log Analytics workspace.
-
azure-log-analytics-get-search-jobGets a Log Analytics workspace table.
-
azure-log-analytics-list-saved-searchesGets the saved searches of the Log Analytics workspace.
-
azure-log-analytics-resource-group-listList all resource groups for a subscription.
-
azure-log-analytics-run-search-jobRun a search job to fetch records from large datasets into a new search results table in your workspace. Tables use the retention value set for the workspace, but this value can be modified after the table is created.
-
azure-log-analytics-subscriptions-listList all subscriptions for a tenant.
-
azure-log-analytics-testTests connectivity to Azure Log Analytics.
-
azure-log-analytics-workspace-listGets workspaces in a resource group.
import json from collections.abc import Callable from pathlib import Path import pytest from AzureLogAnalytics import ( Client, create_or_update_saved_search_command, delete_saved_search_command, delete_search_job_command, execute_query_command, get_saved_search_by_id_command, get_search_job_command, list_saved_searches_command, run_search_job_command, tags_arg_to_request_format, ) from CommonServerPython import CommandResults, DemistoException, ScheduledCommand from MicrosoftApiModule import * # noqa: E402 from pytest_mock import MockerFixture from requests_mock import MockerCore def util_load_json(path: str) -> dict: return json.loads(Path(path).read_text()) MOCKED_SAVED_SEARCHES_OUTPUT = { "value": [ { "id": "mocked_id/mocked_saved_search", "etag": "mocked_etag", "properties": { "displayName": "mocked saved search", "query": "mocked_query", }, }, {"id": "MORE_DUMMY_DATA"}, ] } MOCKED_SAVED_SEARCH_OUTPUT = { "id": "test", "etag": "Mock", "properties": { "category": "test", "displayName": "new display name test", "query": "mock", "version": 2, "id": "test1234", "etag": "*", "type": None, }, } MOCKED_EXECUTE_QUERY_OUTPUT = { "tables": [ { "name": "Table 1", "columns": [ {"name": "column1", "type": "string"}, {"name": "column2", "type": "long"}, ], "rows": [["test", 1], ["test", 2]], }, { "name": "Table 2", "columns": [ {"name": "column3", "type": "string"}, {"name": "column4", "type": "int"}, ], "rows": [["test", 3], ["test", 4]], }, ] } BASE_URL = "https://management.azure.com/subscriptions" SUBSCRIPTION_ID = "subscriptionID" RESOURCE_GROUP_NAME = "resourceGroupName" WORKSPACE_NAME = "workspaceName" TABLE_NAME = "test_SRCH" BASE_URL_SEARCH_JOB = ( f"{BASE_URL}/{SUBSCRIPTION_ID}/resourcegroups/{RESOURCE_GROUP_NAME}" f"/providers/microsoft.operationalinsights/workspaces/{WORKSPACE_NAME}/tables/{TABLE_NAME}" ) def get_azure_access_token_mock() -> dict: """ Mock Azure access token object. Returns: dict: Azure access token mock. """ return { "access_token": "my-access-token", "expires_in": 3595, "refresh_token": "my-refresh-token", } def authorization_mock(requests_mock: MockerCore) -> None: """ Azure authorization API request mock. """ authorization_url = "https://login.microsoftonline.com/refresh_token/oauth2/token" requests_mock.post(authorization_url, json=get_azure_access_token_mock()) CLIENT = Client( self_deployed=True, refresh_token="refresh_token", auth_and_token_url="auth_id", redirect_uri="redirect_uri", enc_key="enc_key", auth_code="auth_code", subscription_id=SUBSCRIPTION_ID, resource_group_name=RESOURCE_GROUP_NAME, workspace_name=WORKSPACE_NAME, verify=False, proxy=False, certificate_thumbprint=None, private_key=None, azure_cloud=AZURE_WORLDWIDE_CLOUD, client_credentials=False, ) def load_mock_response(file_path: str) -> dict: """ Load mock file that simulates an API response. Args: file_path (str): Path of the mock response JSON file to return. Returns: str: Mock file content. """ with open(file_path, encoding="utf-8") as mock_file: return json.loads(mock_file.read()) def test_execute_query_command(mocker: MockerFixture) -> None: """ Given: - A LogAnalytics client object When: - Calling function execute_query_command Then: - Ensure the readable output's title is correct - Ensure the output's structure is as expected """ args: dict = {"query": "dummy"} mocker.patch.object(CLIENT, "http_request", return_value=MOCKED_EXECUTE_QUERY_OUTPUT) command_result = execute_query_command(CLIENT, args=args) assert "Query Results" in command_result.readable_output assert len(command_result.outputs) == 2 assert command_result.outputs[0]["TableName"] == "Table 1" assert command_result.outputs[1]["Data"][1]["column4"] == 4 def test_list_saved_searches_command(mocker: MockerFixture) -> None: """ Given: - A LogAnalytics client object - Arguments of azure-log-analytics-list-saved-searches command, representing we want a single saved search from the first page of the list to be retrieved When: - Calling function list_saved_searches_command Then: - Ensure the readable output's title is correct - Ensure a single saved search is returned - Ensure the output's structure is as expected """ args = {"limit": "1", "page": "0"} mocker.patch.object(CLIENT, "http_request", return_value=MOCKED_SAVED_SEARCHES_OUTPUT) command_result = list_saved_searches_command(CLIENT, args=args) assert "Saved searches" in command_result.readable_output assert len(command_result.outputs) == 1 assert command_result.outputs[0]["id"] == "mocked_saved_search" assert command_result.outputs[0]["query"] == "mocked_query" assert command_result.outputs[0]["displayName"] == "mocked saved search" def test_get_saved_search_by_id_command(mocker: MockerFixture) -> None: """ Test function for get_saved_search_by_id_command. """ mocker.patch.object(CLIENT, "http_request", return_value=MOCKED_SAVED_SEARCH_OUTPUT) command_result = get_saved_search_by_id_command(CLIENT, {"saved_search_id": "test"}) assert command_result.outputs["id"] == "test" assert command_result.readable_output == ( "### Saved search `test` properties\n" "|Etag|Id|Category|Display Name|Query|Version|\n" "|---|---|---|---|---|---|\n" "| Mock | test | test | new display name test | mock | 2 |\n" ) def test_create_or_update_saved_search_command(mocker: MockerFixture) -> None: args = { "saved_search_id": "test_saved_search_id", "display_name": "test_display_name", "category": "test_category", "query": "test_query", } mocker.patch.object(CLIENT, "http_request", return_value=MOCKED_SAVED_SEARCH_OUTPUT) result = create_or_update_saved_search_command(CLIENT, args) assert result.readable_output == ( "### Saved search `test_saved_search_id` properties\n" "|Etag|Id|Category|Display Name|Query|Version|\n" "|---|---|---|---|---|---|\n" "| Mock | test | test | new display name test | mock | 2 |\n" ) assert result.outputs["id"] == "test" def test_delete_saved_search_command(mocker: MockerFixture) -> None: mocker.patch.object(CLIENT, "http_request", return_value=None) result = delete_saved_search_command(CLIENT, {"saved_search_id": "SAVED_SEARCH_ID"}) assert result == "Successfully deleted the saved search SAVED_SEARCH_ID." def test_tags_arg_to_request_format() -> None: """ Given: - `tags` argument from azure-log-analytics-execute-query command - The argument has two tags (a name and a value for each tag) When: - Calling function tags_arg_to_request_format Then: - Ensure the argument is parsed correctly to a dict with two tags. """ tags_arg = "name1=value1;name2=value2" parsed_tags = tags_arg_to_request_format(tags_arg) assert len(parsed_tags) == 2 assert parsed_tags[0]["name"] == "name1" assert parsed_tags[1]["value"] == "value2" @pytest.mark.parametrize("client_id", [("test_client_id"), (None)]) def test_test_module_command_with_managed_identities( mocker: MockerFixture, requests_mock: MockerCore, client_id: str | None ) -> None: """ Scenario: run test module when managed identities client id provided. Given: - User has provided managed identities client oid. When: - test-module called. Then: - Ensure the output are as expected """ import AzureLogAnalytics import demistomock as demisto from AzureLogAnalytics import MANAGED_IDENTITIES_TOKEN_URL, main mock_token = {"access_token": "test_token", "expires_in": "86400"} requests_mock.get(MANAGED_IDENTITIES_TOKEN_URL, json=mock_token) params = { "managed_identities_client_id": {"password": client_id}, "use_managed_identities": "True", "auth_type": "Azure Managed Identities", "subscription_id": {"password": "test"}, "resource_group": "test_resource_group", "credentials_refresh_token": {"password": "test"}, "subscriptionID": "subscriptionID", "resourceGroupName": "resourceGroupName", "workspaceName": "workspaceName", "client_credentials": True, } mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "command", return_value="test-module") mocker.patch.object(AzureLogAnalytics, "return_results") mocker.patch.object(AzureLogAnalytics, "execute_query_command") main() assert "ok" in AzureLogAnalytics.return_results.call_args[0][0] def test_generate_login_url(mocker: MockerFixture) -> None: """ Given: - Self-deployed are true and auth code are the auth flow When: - Calling function azure-log-analytics-generate-login-url Then: - Ensure the generated url are as expected. """ # prepare import AzureLogAnalytics import demistomock as demisto from AzureLogAnalytics import main redirect_uri = "redirect_uri" tenant_id = "tenant_id" client_id = "client_id" mocked_params = { "redirect_uri": redirect_uri, "self_deployed": "True", "refresh_token": tenant_id, "credentials": {"identifier": client_id, "password": "client_secret"}, "subscriptionID": "subscriptionID", "resourceGroupName": "resourceGroupName", "workspaceName": "workspaceName", "server_url": None, } mocker.patch.object(demisto, "params", return_value=mocked_params) mocker.patch.object(demisto, "command", return_value="azure-log-analytics-generate-login-url") mocker.patch.object(AzureLogAnalytics, "return_results") # call main() # assert expected_url = ( f"[login URL](https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/authorize?" "response_type=code&scope=offline_access%20https://api.loganalytics.io/Data.Read" "%20https://management.azure.com/user_impersonation" f"&client_id={client_id}&redirect_uri={redirect_uri})" ) res = AzureLogAnalytics.return_results.call_args[0][0].readable_output assert expected_url in res def test_run_search_job_command(mocker: MockerFixture, requests_mock: MockerCore) -> None: """ Given: ----- a mocked CLIENT and input arguments for a search job, When: ---- the run_search_job_command function is called for the first run and the second run, Then: ---- it should perform the required actions for each run and return the expected readable output. This test covers the run_search_job_command function, which is responsible for running search jobs. It tests two scenarios: the first run and the second run. The first run sends a 'PUT' request to create the search job, and the second run checks the job status with a 'GET' request and prepares arguments for the next run. It ensures that the function behaves as expected in both cases. """ authorization_mock(requests_mock) args = {"table_name": TABLE_NAME, "query": "test", "limit": 50, "first_run": True} mocker.patch.object(ScheduledCommand, "raise_error_if_not_supported", return_value=None) """ First run""" requests_mock.put(BASE_URL_SEARCH_JOB, status_code=202) # first_run, 'PUT' response: CommandResults = run_search_job_command(args, CLIENT) assert response.readable_output == ( "The command was sent successfully. " "You can check the status of the command by running !azure-log-analytics-get-search-job command or wait." ) """Secund run""" # 'GET' get status requests_mock.get(BASE_URL_SEARCH_JOB, json={"properties": {"provisioningState": "Succeeded"}}) args_to_next_run = response.scheduled_command._args assert args_to_next_run == { "table_name": TABLE_NAME, "query": "test", "limit": 50, "first_run": False, "hide_polling_output": True, } response: CommandResults = run_search_job_command(args_to_next_run, CLIENT) assert response.readable_output == ( f"The {TABLE_NAME} table created successfully. " f"The table can be queried by running the following command: " f"!azure-log-analytics-execute-query query={TABLE_NAME}" ) @pytest.mark.parametrize( "index", [ pytest.param("case schema", id="searchResults key under schema key"), pytest.param("case properties", id="searchResults key under properties key"), ], ) def test_get_search_job_command(requests_mock: MockerCore, index: str) -> None: """The searchResults key could be under schema or properties key, this test checks both cases Given: ---- a mocked CLIENT, a specific test data index, and an existing search job with the table name "test", When: ---- the get_search_job_command function is called with the CLIENT and the search job parameters, Then: ---- it should retrieve the search job information and return a readable output with the expected table. """ authorization_mock(requests_mock) mock_data = util_load_json("test_data/get_search_job.json")[index] requests_mock.get(BASE_URL_SEARCH_JOB, json=mock_data) response = get_search_job_command(CLIENT, {"table_name": TABLE_NAME}) assert response.readable_output == ( "### Search Job\n" "|Create Date|Description|Name|Plan|Query|endSearchTime|provisioningState|startSearchTime|\n" "|---|---|---|---|---|---|---|---|\n" "| 2023-10-26T21:49:25.6588002Z | This table was created using a Search Job with the following query: 'testLogs'. |" " test | Analytics | testLogs | 2023-10-25T00:00:00Z | Succeeded | 2023-10-23T00:00:00Z |\n" ) def test_delete_search_job_command(requests_mock: MockerCore) -> None: """ Given: ----- a mocked CLIENT and a search job with the table name "test_SRCH" exists, When: ---- the delete_search_job_command function is called with the CLIENT and the search job parameters, Then: ---- it should delete the search job and return a readable output confirming the deletion. """ authorization_mock(requests_mock) requests_mock.delete(BASE_URL_SEARCH_JOB, status_code=204) response = delete_search_job_command(CLIENT, {"table_name": TABLE_NAME}) assert response.readable_output == "Search job test_SRCH deleted successfully." def test_subscriptions_list_command(requests_mock: MockerCore) -> None: """ Given: - Mock response from API client When: - Calling subscriptions_list_command Then: - Validate expected outputs returned """ from AzureLogAnalytics import subscriptions_list_command authorization_mock(requests_mock) mock_response = load_mock_response("test_data/subscriptions_list.json") requests_mock.get(BASE_URL, json=mock_response) command_result = subscriptions_list_command(CLIENT) assert len(command_result.outputs) == 2 assert command_result.outputs_prefix == "AzureLogAnalytics.Subscription" assert command_result.outputs[0].get("id") == "/subscriptions/1234" def test_workspace_list_command(requests_mock: MockerCore) -> None: """ Given: - Mock response from API client When: - Calling workspace_list_command Then: - Validate expected outputs returned """ from AzureLogAnalytics import workspace_list_command authorization_mock(requests_mock) mock_response = load_mock_response("test_data/workspace_list.json") url = f"{BASE_URL}/{SUBSCRIPTION_ID}/resourcegroups/{RESOURCE_GROUP_NAME}/providers/Microsoft.OperationalInsights/workspaces" requests_mock.get(url, json=mock_response) command_result = workspace_list_command(CLIENT) assert len(command_result.outputs) == 1 assert command_result.outputs_prefix == "AzureLogAnalytics.workspace" assert command_result.outputs[0].get("name") == "Test2170" def test_resource_group_list_command(requests_mock: MockerCore) -> None: """ Given: - limit argument - Mock response from API client When: - Calling resource_group_list_command Then: - Validate expected outputs returned """ from AzureLogAnalytics import resource_group_list_command authorization_mock(requests_mock) url = f"{BASE_URL}/{SUBSCRIPTION_ID}/resourcegroups" mock_response = load_mock_response("test_data/resource_group_list.json") requests_mock.get(url, json=mock_response) command_result = resource_group_list_command(CLIENT, {"limit": 50}) assert len(command_result.outputs) == 1 assert command_result.outputs_prefix == "AzureLogAnalytics.ResourceGroup" assert command_result.outputs[0].get("id") == "id" @pytest.mark.parametrize( "function, message", [ (delete_search_job_command, "Deleting tables without '_SRCH' suffix is not allowed."), (run_search_job_command, "The table_name should end with '_SRCH' suffix."), ], ) def test_table_with_invalid_name(function: Callable, message: str) -> None: with pytest.raises(DemistoException, match=message): # in the run_search_job_command the args is the first argument instead of the second because it use the polling decorator function({"table_name": "invalid"}, {"table_name": "invalid"}) @pytest.mark.parametrize("azure_cloud", [(AZURE_WORLDWIDE_CLOUD), (AZURE_US_GCC_CLOUD), (AZURE_US_GCC_HIGH_CLOUD)]) def test_client_endpoints(azure_cloud) -> None: """ Given: - The instance is configured with the Azure Cloud parameter. When: - The client object is set. Then: - Validate the ms_client object (created in the scope of the client object) is set with the correct set of endpoints. """ client = Client( self_deployed=True, refresh_token="refresh_token", auth_and_token_url="auth_id", redirect_uri="redirect_uri", enc_key="enc_key", auth_code="auth_code", subscription_id=SUBSCRIPTION_ID, resource_group_name=RESOURCE_GROUP_NAME, workspace_name=WORKSPACE_NAME, verify=False, proxy=False, certificate_thumbprint=None, private_key=None, azure_cloud=azure_cloud, client_credentials=False, ) assert client.ms_client.managed_identities_resource_uri == azure_cloud.endpoints.resource_manager assert client.ms_client.azure_ad_endpoint == azure_cloud.endpoints.active_directory assert client.azure_cloud.name == azure_cloud.name def test_main_uses_new_separate_client_id(mocker): """ Given - The new 'creds_client_id' param is provided with a Client ID value. - The legacy 'credentials' param does NOT contain an identifier. When - main() is called. Then - The Client object is instantiated with auth_and_token_url taken from 'creds_client_id'. """ import AzureLogAnalytics from AzureLogAnalytics import main params = { "creds_client_id": {"password": "new-client-id"}, "credentials": {"password": "client-secret"}, "credentials_refresh_token": {"password": "tenant-id"}, "subscriptionID": "sub-id", "resourceGroupName": "rg-name", "workspaceName": "ws-name", "azure_cloud": "Worldwide", "self_deployed": True, "client_credentials": True, } mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value={}) mocker.patch.object(demisto, "command", return_value="test-module") mock_client_cls = mocker.patch("AzureLogAnalytics.Client", autospec=True) mocker.patch.object(AzureLogAnalytics, "return_results") mocker.patch("AzureLogAnalytics.test_connection") main() call_kwargs = mock_client_cls.call_args[1] assert call_kwargs["auth_and_token_url"] == "new-client-id" def test_main_falls_back_to_legacy_client_id_when_new_param_absent(mocker): """ Given - The new 'creds_client_id' param is NOT provided. - The legacy 'credentials' param IS provided with both identifier (client_id) and password (client_secret). When - main() is called. Then - The Client object is instantiated with auth_and_token_url taken from 'credentials.identifier' (legacy fallback). """ import AzureLogAnalytics from AzureLogAnalytics import main params = { "credentials": {"identifier": "legacy-client-id", "password": "legacy-client-secret"}, "credentials_refresh_token": {"password": "tenant-id"}, "subscriptionID": "sub-id", "resourceGroupName": "rg-name", "workspaceName": "ws-name", "azure_cloud": "Worldwide", "self_deployed": True, "client_credentials": True, } mocker.patch.object(demisto, "params", return_value=params) mocker.patch.object(demisto, "args", return_value={}) mocker.patch.object(demisto, "command", return_value="test-module") mock_client_cls = mocker.patch("AzureLogAnalytics.Client", autospec=True) mocker.patch.object(AzureLogAnalytics, "return_results") mocker.patch("AzureLogAnalytics.test_connection") main() call_kwargs = mock_client_cls.call_args[1] assert call_kwargs["auth_and_token_url"] == "legacy-client-id"