Azure

Cloud integrations are installed from the **Data Sources** page. To configure a cloud integration, go to Settings > Data Sources and click "Add Data Source", select Azure, then in Advanced Settings > Security Capabilities, enable "Automation".

Cloud Services · Azure

Details

IDAzure
ProviderMicrosoft
CategoryCloud Services
From Version8.11.0
Docker Imagedemisto/crypto:1.0.0.10120494
Supported ModulesCloud Posture Security Cortex Cloud Cloud Runtime Security Agentix XSIAM

README

Cloud integrations are installed from the Data Sources page.
To configure a cloud integration, go to Settings > Data Sources, click Add Data Source, and select Microsoft Azure.
Click Connect, then click Show advanced settings, and under Additional Security Capabilities, enable Automation.

Configure Azure in Cortex

Parameter Description Required
Application ID    
Default Subscription ID You can set the value either in the configuration or directly within the commands. If you set it in both places, the value in the command will override the configuration setting. True
Default Resource Group Name You can set the value either in the configuration or directly within the commands. If you set it in both places, the value in the command will override the configuration setting.  
Azure AD endpoint Azure AD endpoint associated with a national cloud. False
Authentication Type The type of authentication. Can be Client Credentials (default authentication type), Device Code, Authorization Code, or Azure Managed Identities. False
Trust any certificate (not secure)   False
Use system proxy settings   False
Tenant ID The tenant ID of the Azure app registration. False
Client Secret The client secret of the Azure app registration. Required when using the Client Credentials flow. False
Application redirect URI The application redirect URI for the Authorization Code flow. False
Authorization code The authorization code for the Authorization Code flow, received from the authorization step. See the Detailed Instructions (?) section. False
Azure Managed Identities Client ID The managed identities client ID for authentication. Relevant only when the integration is running on an Azure VM. False

Commands

You can execute these commands from the 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-nsg-security-rule-update


Update a security rule. If one does not exist, it will be created. The command is deprecated, please use azure-vn-security-rule-update. Required Permissions: Microsoft.Network/networkSecurityGroups/securityRules/read, Microsoft.Network/networkSecurityGroups/securityRules/write.

Base Command

azure-nsg-security-rule-update

Input

Argument Name Description Required
subscription_id The subscription ID. Required
resource_group_name The name of the resource group. Required
security_group_name The name of the security group. Required
security_rule_name The name of the rule to be updated. Required
direction The direction of the rule. Possible values are: “Inbound” and “Outbound”. Possible values are: Inbound, Outbound. Optional
action Whether to allow the traffic. Possible values are “Allow” and “Deny”. Possible values are: Allow, Deny. Optional
protocol The protocol on which to apply the rule. Possible values are: “Any”, “TCP”, “UDP”, and “ICMP”. Possible values are: Any, TCP, UDP, ICMP. Optional
source The source IP address range from which incoming traffic will be allowed or denied by this rule. Possible values are “Any”, an IP address range, an application security group, or a default tag. Default is “Any”. Optional
priority The priority by which the rules will be processed. The lower the number, the higher the priority. We recommend leaving gaps between rules - 100, 200, 300, etc. - so that it is easier to add new rules without having to edit existing rules. Default is “4096”. Optional
source_ports The source ports from which traffic is allowed or denied by this rule. Provide a single port, such as 80; a port range, such as 1024-65535; or a comma-separated list of single ports and/or port ranges, such as 80,1024-65535. Use an asterisk () to allow traffic on any port. Default is “”. Optional
destination The destination IP address range for outgoing traffic that is allowed or denied by this rule. The destination filter can be “Any”, an IP address range, an application security group, or a default tag. Optional
destination_ports The destination ports from which traffic is allowed or denied by this rule. Provide a single port, such as 80; a port range, such as 1024-65535; or a comma-separated list of single ports and/or port ranges, such as 80,1024-65535. Use an asterisk (*) to allow traffic on any port. Optional
description A description to add to the rule. Optional
access The network traffic is allowed or denied. Possible values are: Allow, Deny. Optional

Context Output

Path Type Description
Azure.NSGRule.name String The rule’s name.
Azure.NSGRule.id String The rule’s ID.
Azure.NSGRule.etag String The rule’s ETag.
Azure.NSGRule.type String The rule’s type.
Azure.NSGRule.provisioningState String The rule’s provisioning state.
Azure.NSGRule.protocol String The protocol, which can be “TCP”, “UDP”, “ICMP”, or “*”.
Azure.NSGRule.sourcePortRange String For a single port, the source port or a range of ports.
Azure.NSGRule.sourcePortRanges String For multiple ports, a list of these ports.
Azure.NSGRule.destinationPortRange String For a single port, the destination port or range of ports.
Azure.NSGRule.destinationPortRanges String For multiple ports, a list of destination ports.
Azure.NSGRule.sourceAddressPrefix String The source address.
Azure.NSGRule.destinationAddressPrefix String The destination address.
Azure.NSGRule.access String The rule’s access. Can be “Allow” or “Deny”.
Azure.NSGRule.priority Number The rule’s priority. Can be from 100 to 4096.
Azure.NSGRule.direction String The rule’s direction. Can be “Inbound” or “Outbound”.

azure-storage-account-update


Updates a specific account storage. Required permissions: Microsoft.Storage/storageAccounts/read, Microsoft.Storage/storageAccounts/write.

Base Command

azure-storage-account-update

Input

Argument Name Description Required
resource_group_name The resource group name. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
account_name The name of the storage account. Required
sku Gets or sets the SKU name, Required for account creation; optional for update. Possible values are: Premium_LRS, Premium_ZRS, Standard_GRS, Standard_GZRS, Standard_LRS, Standard_RAGRS, Standard_RAGZRS, Standard_ZRS. Optional
kind Indicates the type of storage account, Required for account creation; optional for update. Possible values are: Storage, StorageV2, BlobStorage, FileStorage, BlockBlobStorage. Optional
location Gets or sets the location of the resource. The geo region of a resource cannot be changed once it is created, but if an identical geo region is specified on update, the request will succeed. Required for account creation; optional for update. Possible values are: eastus, eastus2, westus, westeurope, eastasia, southeastasia, japaneast, japanwest, northcentralus, southcentralus, centralus, northeurope, brazilsouth, australiaeast, australiasoutheast, southindia, centralindia, westindia, canadaeast, canadacentral, westus2, westcentralus, uksouth, ukwest, koreacentral, koreasouth, francecentral, australiacentral, southafricanorth, uaenorth, switzerlandnorth, germanywestcentral, norwayeast. Optional
tags Gets or sets a list of tags that describe the resource. Optional
custom_domain_name Gets or sets the custom domain name assigned to the storage account. Optional
use_sub_domain_name Indicates whether indirect CName validation is enabled. Possible values are: true, false. Optional
enc_key_source The encryption keySource. Possible values are: Microsoft.Storage, Microsoft.Keyvault. Optional
enc_requireInfrastructureEncryption Indicates whether the service applies a secondary layer of encryption with platform managed keys for data at rest. Possible values are: true, false. Optional
enc_keyvault_key_name The name of KeyVault key. Optional
enc_keyvault_key_version The version of KeyVault key. Optional
enc_keyvault_uri The Uri of KeyVault. Optional
access_tier The access tier for the account. Required where kind = BlobStorage. Possible values are: Hot, Cool. Optional
supports_https_traffic_only Allows https traffic only to storage service if sets to true. Possible values are: true, false. Optional
is_hns_enabled Account HierarchicalNamespace enabled if sets to true. Possible values are: true, false. Optional
large_file_shares_state If set to Enabled, allows large file shares. Possible values are: Disabled, Enabled. Optional
allow_blob_public_access If set to true, allows public access to all blobs or containers in the storage account. Possible values are: true, false. Optional
minimum_tls_version Sets the minimum TLS version to be permitted on requests to storage. Possible values are: TLS1_0, TLS1_1, TLS1_2. Optional
network_ruleset_bypass Specifies whether traffic is bypassed for Logging/Metrics/AzureServices. Possible values are: AzureServices, Logging, Metrics, None. Optional
network_ruleset_default_action Specifies the default action of allow or deny when no other rules match. Possible values are: Allow, Deny. Optional
network_ruleset_ipRules Sets the IP ACL rules. Optional
virtual_network_rules Sets the virtual network rules. Optional
allow_cross_tenant_replication Allow or disallow cross AAD tenant object replication. Possible values are: true, false. Optional

Context Output

Path Type Description
Azure.Storage.StorageAccounts.id String Fully qualified resource ID for the resource.
Azure.Storage.StorageAccounts.kind String The kind of storage account.
Azure.Storage.StorageAccounts.location String The geo-location where the resource lives.
Azure.Storage.StorageAccounts.name String The name of the resource.
Azure.Storage.StorageAccounts.properties.isHnsEnabled Boolean Account HierarchicalNamespace enabled if sets to true.
Azure.Storage.StorageAccounts.properties.allowBlobPublicAccess Boolean If set to true (default), allows public access to all blobs or containers in the storage account.
Azure.Storage.StorageAccounts.properties.minimumTlsVersion String The minimum TLS version to be permitted on requests to storage. Default is TLS 1.0.
Azure.Storage.StorageAccounts.properties.allowSharedKeyAccess Boolean Whether the storage account permits requests to be authorized with the account access key via Shared Key. If false, then all requests (including shared access signatures) must be authorized with Azure Active Directory (Azure AD).
Azure.Storage.StorageAccounts.properties.creationTime Date The creation date and time of the storage account in UTC.
Azure.Storage.StorageAccounts.properties.primaryEndpoints String The URLs that are used to retrieve a public blob, queue, or table object.
Azure.Storage.StorageAccounts.properties.primaryLocation String The storage account primary data center location.
Azure.Storage.StorageAccounts.properties.provisioningState String The status of the storage account at the time the operation was called.
Azure.Storage.StorageAccounts.properties.routingPreference.routingChoice String The kind of network routing the user chose.
Azure.Storage.StorageAccounts.properties.routingPreference.publishMicrosoftEndpoints Boolean Whether Microsoft routing storage endpoints are to be published.
Azure.Storage.StorageAccounts.properties.routingPreference.publishInternetEndpoints Boolean Whether internet routing storage endpoints are to be published.
Azure.Storage.StorageAccounts.properties.encryption String Encryption settings to be used for server-side encryption for the storage account.
Azure.Storage.StorageAccounts.properties.secondaryLocation String The geo-replicated secondary location for the storage account. Only available if the accountType is Standard_GRS or Standard_RAGRS.
Azure.Storage.StorageAccounts.properties.statusOfPrimary String Whether the storage account primary location is available or unavailable.
Azure.Storage.StorageAccounts.properties.statusOfSecondary String Whether the storage account secondary location is available or unavailable. Only available if the SKU name is Standard_GRS or Standard_RAGRS.
Azure.Storage.StorageAccounts.properties.supportsHttpsTrafficOnly Boolean If set to true, allows https traffic only to storage service.
Azure.Storage.StorageAccounts.sku.name String The SKU name. Required for account creation; optional for update.
Azure.Storage.StorageAccounts.sku.tier String The SKU tier. This is based on the SKU name.
Azure.Storage.StorageAccounts.tags unknown Resource tags.
Azure.Storage.StorageAccounts.type String The storage account type.

azure-storage-blob-service-properties-set


Sets properties for the blob service in a specific account storage. The command is deprecated, please use azure-storage-blob-service-property-set. Required Permissions: Microsoft.Storage/storageAccounts/blobServices/read, Microsoft.Storage/storageAccounts/blobServices/write.

Base Command

azure-storage-blob-service-properties-set

Input

Argument Name Description Required
resource_group_name The resource group name. Required
subscription_id The subscription ID. Required
account_name The name of the storage account. Required
delete_rentention_policy_enabled Whether DeleteRetentionPolicy is enabled. Possible values are: true, false. Optional
delete_rentention_policy_days The number of days the deleted item should be retained. Optional

Context Output

Path Type Description
Azure.StorageAccountBlobServiceProperties.id String The resource ID.
Azure.StorageAccountBlobServiceProperties.name String The name of the resource.
Azure.StorageAccountBlobServiceProperties.type String The type of the resource.
Azure.StorageAccountBlobServiceProperties.properties.cors String Specifies CORS rules for the Blob service.
Azure.StorageAccountBlobServiceProperties.properties.defaultServiceVersion Date The default version for requests to the Blob service if an incoming request’s version is not specified. Possible values include version 2008-10-27 and all more recent versions.
Azure.StorageAccountBlobServiceProperties.properties.deleteRetentionPolicy unknown The service properties for soft delete.
Azure.StorageAccountBlobServiceProperties.properties.isVersioningEnabled Boolean If set to true, enables versioning.
Azure.StorageAccountBlobServiceProperties.properties.changeFeed unknown The blob service properties for change feed events.
Azure.StorageAccountBlobServiceProperties.sku.name String The SKU name.
Azure.StorageAccountBlobServiceProperties.sku.tier String The SKU tier.

azure-policy-assignment-create


Creates a policy assignment. Required permissions: Microsoft.Authorization/policyAssignments/read, Microsoft.Authorization/policyAssignments/write.

Base Command

azure-policy-assignment-create

Input

Argument Name Description Required
name Name of the policy assignment. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
scope The scope of the policy assignment. Required
policy_definition_id The ID of the policy definition or policy set definition being assigned. Optional
display_name The assignment display name. Optional
parameters The JSON object for policy properties parameters and their values. Optional
description This message will be part of the response in case of policy violation. Optional

Context Output

Path Type Description
Azure.Policy.PolicyAssignments.ID string The resource ID of the policy assignment.
Azure.Policy.PolicyAssignments.Name string The name of the policy assignment.
Azure.Policy.PolicyAssignments.Type string The type of the resource (e.g., ‘Microsoft.Authorization/policyAssignments’).
Azure.Policy.PolicyAssignments.Location string The location of the policy assignment.
Azure.Policy.PolicyAssignments.Identity unknown The managed identity associated with the policy assignment.
Azure.Policy.PolicyAssignments.Properties.DisplayName string The display name of the policy assignment.
Azure.Policy.PolicyAssignments.Properties.Description string The description of the policy assignment.
Azure.Policy.PolicyAssignments.Properties.PolicyDefinitionId string The ID of the policy definition or policy set definition being assigned.
Azure.Policy.PolicyAssignments.Properties.Scope string The scope of the policy assignment.
Azure.Policy.PolicyAssignments.Properties.NotScopes unknown The list of scopes that are excluded from the policy assignment.
Azure.Policy.PolicyAssignments.Properties.Parameters unknown The parameter values for the assigned policy rule.
Azure.Policy.PolicyAssignments.Properties.Metadata unknown The metadata associated with the policy assignment.
Azure.Policy.PolicyAssignments.Properties.EnforcementMode string The policy assignment enforcement mode (e.g., ‘Default’ or ‘DoNotEnforce’).
Azure.Policy.PolicyAssignments.Properties.latestDefinitionVersion string The latest version of the policy definition available. This is only present if requested via the $expand query parameter.
Azure.Policy.PolicyAssignments.Properties.NonComplianceMessages unknown The messages that describe why a resource is non-compliant with the policy.
Azure.Policy.PolicyAssignments.Properties.DefinitionVersion string The version of the policy definition to use.
Azure.Policy.PolicyAssignments.Properties.Overrides unknown The policy property value overrides.
Azure.Policy.PolicyAssignments.Properties.ResourceSelectors unknown The resource selectors to filter policies by resource properties.
Azure.Policy.PolicyAssignments.SystemData unknown The system metadata relating to this resource.

azure-postgres-config-set


Updates a configuration of a server. The command is deprecated due to the retirement of Azure PostgreSQL Single Server.

Base Command

azure-postgres-config-set

Input

Argument Name Description Required
resource_group_name The resource group name. Optional
server_name Name of the PostgreSQL server. Required
configuration_name The configuration setting name. Required
subscription_id Subscription ID. Optional
source Source of the configuration. Optional
value Value of the configuration. Optional

Context Output

There is no context output for this command.

azure-webapp-config-set


Updates the configuration settings of an existing Azure Web App. The command is deprecated, please use azure-appservice-webapp-config-update. Required Permissions: Microsoft.Web/sites/config/read, Microsoft.Web/sites/config/write.

Base Command

azure-webapp-config-set

Input

Argument Name Description Required
resource_group_name The resource group name. Optional
subscription_id Subscription ID. Optional
name Name of the Web App. Required
http20_enabled Configures a web site to allow clients to connect over http2.0. Possible values are: true, false. Optional
remote_debugging_enabled True if remote debugging is enabled; otherwise, false. Possible values are: true, false. Optional
min_tls_version Configures the minimum version of TLS required for SSL requests. Possible values are: 1.0, 1.1, 1.2, 1.3. Optional

Context Output

Path Type Description
Azure.WebAppConfig.id String Resource ID.
Azure.WebAppConfig.name String Resource name.
Azure.WebAppConfig.type String Resource type.
Azure.WebAppConfig.location String Resource location.
Azure.WebAppConfig.properties.numberOfWorkers Number Number of workers.
Azure.WebAppConfig.properties.defaultDocuments Unknown List of default documents.
Azure.WebAppConfig.properties.netFrameworkVersion String .NET Framework version.
Azure.WebAppConfig.properties.phpVersion String PHP version.
Azure.WebAppConfig.properties.pythonVersion String Python version.
Azure.WebAppConfig.properties.nodeVersion String Node.js version.
Azure.WebAppConfig.properties.powerShellVersion String PowerShell version.
Azure.WebAppConfig.properties.linuxFxVersion String Linux app framework and version.
Azure.WebAppConfig.properties.windowsFxVersion String Windows container image name.
Azure.WebAppConfig.properties.requestTracingEnabled Boolean Indicates whether request tracing is enabled.
Azure.WebAppConfig.properties.remoteDebuggingEnabled Boolean Indicates whether remote debugging is enabled.
Azure.WebAppConfig.properties.remoteDebuggingVersion String Remote debugging version.
Azure.WebAppConfig.properties.http20Enabled Boolean Indicates whether HTTP/2 is enabled.
Azure.WebAppConfig.properties.minTlsVersion String Minimum TLS version required.
Azure.WebAppConfig.properties.ftpsState String State of FTP / FTPS service.
Azure.WebAppConfig.properties.webSocketsEnabled Boolean Indicates whether WebSockets are enabled.
Azure.WebAppConfig.properties.alwaysOn Boolean Indicates whether Always On is enabled.
Azure.WebAppConfig.properties.managedPipelineMode String Managed pipeline mode.
Azure.WebAppConfig.properties.loadBalancing String Site load balancing mode.
Azure.WebAppConfig.properties.autoHealEnabled Boolean Indicates whether Auto Heal is enabled.
Azure.WebAppConfig.properties.autoHealRules Unknown Auto Heal rules configuration.
Azure.WebAppConfig.properties.cors.allowedOrigins Unknown CORS allowed origins.
Azure.WebAppConfig.properties.cors.supportCredentials Boolean Indicates whether CORS supports credentials.
Azure.WebAppConfig.properties.apiDefinition.url String URL of the API definition.
Azure.WebAppConfig.properties.apiManagementConfig.id String Azure API management integration ID.

azure-webapp-auth-update


Updates the authentication and authorization settings of an existing Azure Web App. The command is deprecated, please use azure-appservice-webapp-auth-settings-update. Required Permissions: Microsoft.Web/sites/config/read, Microsoft.Web/sites/config/write.

Base Command

azure-webapp-auth-update

Input

Argument Name Description Required
resource_group_name The resource group name. Optional
subscription_id Subscription ID. Optional
name Name of the Web App. Required
enabled True if the Authentication / Authorization feature is enabled for the current app; otherwise, false. Possible values are: true, false. Optional

Context Output

Path Type Description
Azure.WebAppAuth.id String Resource ID.
Azure.WebAppAuth.name String Resource Name.
Azure.WebAppAuth.type String Resource type.
Azure.WebAppAuth.properties.enabled Boolean Indicates whether Authentication/Authorization is enabled for the app.
Azure.WebAppAuth.properties.runtimeVersion String The RuntimeVersion of the Authentication/Authorization feature.
Azure.WebAppAuth.properties.unauthenticatedClientAction String The action to take when an unauthenticated client attempts to access the app.
Azure.WebAppAuth.properties.tokenStoreEnabled Boolean Indicates whether the Azure App Service Authentication platform’s token store is enabled.
Azure.WebAppAuth.properties.allowedExternalRedirectUrls Unknown External URLs that are allowed to be redirected to as part of logging in or logging out of the app.
Azure.WebAppAuth.properties.defaultProvider String The default authentication provider to use when multiple providers are configured.
Azure.WebAppAuth.properties.clientId String The Client ID of the app used for AAD login.
Azure.WebAppAuth.properties.clientSecret String The client secret associated with the AAD app.
Azure.WebAppAuth.properties.clientSecretSettingName String The app setting that contains the client secret.
Azure.WebAppAuth.properties.issuer String The OpenID Connect Issuer URI that represents the entity that issues access tokens.
Azure.WebAppAuth.properties.allowedAudiences Unknown The list of audiences that can receive the authentication tokens.
Azure.WebAppAuth.properties.additionalLoginParams Unknown Additional parameters to send to the authentication provider.
Azure.WebAppAuth.properties.isAadAutoProvisioned Boolean True if AAD is auto-provisioned; otherwise false.
Azure.WebAppAuth.properties.googleClientId String The Client ID of the app used for Google login.
Azure.WebAppAuth.properties.googleClientSecret String The client secret associated with the Google app.
Azure.WebAppAuth.properties.googleClientSecretSettingName String The app setting that contains the client secret.
Azure.WebAppAuth.properties.facebookAppId String The App ID of the Facebook app used for login.
Azure.WebAppAuth.properties.facebookAppSecret String The app secret associated with the Facebook app.
Azure.WebAppAuth.properties.facebookAppSecretSettingName String The app setting that contains the Facebook app secret.
Azure.WebAppAuth.properties.twitterConsumerKey String The OAuth 1.0a consumer key of the Twitter application used for login.
Azure.WebAppAuth.properties.twitterConsumerSecret String The consumer secret associated with the Twitter application.
Azure.WebAppAuth.properties.twitterConsumerSecretSettingName String The app setting that contains the Twitter consumer secret.
Azure.WebAppAuth.properties.microsoftAccountClientId String The OAuth 2.0 client ID for the Microsoft account provider.
Azure.WebAppAuth.properties.microsoftAccountClientSecret String The client secret for the Microsoft account provider.
Azure.WebAppAuth.properties.microsoftAccountClientSecretSettingName String The app setting that contains the Microsoft account client secret.
Azure.WebAppAuth.properties.appleClientId String The client ID for the Apple provider.
Azure.WebAppAuth.properties.appleClientSecret String The client secret for the Apple provider.
Azure.WebAppAuth.properties.appleClientSecretSettingName String The app setting that contains the Apple provider client secret.
Azure.WebAppAuth.properties.authFilePath String The path to the authentication configuration file.

azure-mysql-flexible-server-param-set


Updates a server configuration. Required permissions: Microsoft.DBforMySQL/flexibleServers/configurations/read, Microsoft.DBforMySQL/flexibleServers/configurations/write.

Base Command

azure-mysql-flexible-server-param-set

Input

Argument Name Description Required
resource_group_name The resource group name. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
server_name Name of the MySQL flexible server. Required
configuration_name The name of the server configuration. Required
source Source of the configuration. Optional
value Value of the configuration. Optional

Context Output

There is no context output for this command.

azure-monitor-log-profile-update


Updates a log profile in Azure Monitoring REST API. Required permissions: Microsoft.Insights/logprofiles/read, Microsoft.Insights/logprofiles/write.

Base Command

azure-monitor-log-profile-update

Input

Argument Name Description Required
log_profile_name The name of the log profile to update. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
location Resource location. Optional
retention_policy_days Number of days to retain logs. Optional
retention_policy_enabled Whether to enable the retention policy. Possible values are: true, false. Optional

Context Output

Path Type Description
Azure.Monitor.LogProfiles.id String The fully qualified Azure resource ID for the log profile.
Azure.Monitor.LogProfiles.name String The name of the log profile.
Azure.Monitor.LogProfiles.type String The type of the resource (Microsoft.Insights/logProfiles).
Azure.Monitor.LogProfiles.location String The location of the log profile.
Azure.Monitor.LogProfiles.tags Object Resource tags.
Azure.Monitor.LogProfiles.properties.storageAccountId String The resource ID of the storage account to which diagnostic logs are delivered.
Azure.Monitor.LogProfiles.properties.serviceBusRuleId String The service bus rule ID to which diagnostic logs are sent.
Azure.Monitor.LogProfiles.properties.locations Array A list of regions for which events are collected.
Azure.Monitor.LogProfiles.properties.categories Array A list of categories of logs that are collected.
Azure.Monitor.LogProfiles.properties.retentionPolicy.enabled Boolean Specifies whether the retention policy is enabled.
Azure.Monitor.LogProfiles.properties.retentionPolicy.days Number The number of days for the retention policy.

azure-disk-update


Updates a disk. The command is deprecated, please use azure-compute-disk-update. Required Permissions: Microsoft.Compute/disks/read, Microsoft.Compute/disks/write.

Base Command

azure-disk-update

Input

Argument Name Description Required
resource_group_name The resource group name. Optional
subscription_id Subscription ID. Optional
disk_name The name of the managed disk that is being created. Supported characters for the name are a-z, A-Z, 0-9, _ and -. The maximum name length is 80 characters. Required
public_network_access Policy for controlling export on the disk. Possible values are: Disabled, Enabled. Optional
network_access_policy Policy for accessing the disk via network. Possible values are: AllowAll, AllowPrivate, DenyAll. Optional
data_access_auth_mode Additional authentication requirements when exporting or uploading to a disk or snapshot. Possible values are: AzureActiveDirectory. Optional

Context Output

Path Type Description
Azure.Disk.id String Resource ID of the disk.
Azure.Disk.name String Name of the disk.
Azure.Disk.type String Type of the resource.
Azure.Disk.location String Location of the disk.
Azure.Disk.tags unknown Resource tags.
Azure.Disk.managedBy String ARM ID of the resource that manages the disk.
Azure.Disk.sku unknown The disk SKU name.
Azure.Disk.zones unknown A list of availability zones.
Azure.Disk.properties.timeCreated String The time when the disk was created.
Azure.Disk.properties.diskSizeGB Number Size of the disk in GB.
Azure.Disk.properties.diskIopsReadWrite Number The number of IOPS allowed for this disk.
Azure.Disk.properties.diskMBpsReadWrite Number The bandwidth allowed for this disk in MBps.
Azure.Disk.properties.diskIOPSReadOnly Number The number of read-only IOPS for this disk.
Azure.Disk.properties.diskMBpsReadOnly Number The read-only bandwidth for this disk in MBps.
Azure.Disk.properties.diskSizeBytes Number The size of the disk in bytes.
Azure.Disk.properties.networkAccessPolicy String Policy for accessing the disk via network.
Azure.Disk.properties.publicNetworkAccess String Policy for export on the disk.
Azure.Disk.properties.burstingEnabled Boolean Whether bursting is enabled on the disk.
Azure.Disk.properties.optimization String The disk optimization setting.
Azure.Disk.properties.diskState String The current state of the disk.
Azure.Disk.properties.supportedCapabilities unknown Supported capabilities of the disk.
Azure.Disk.properties.supportedPerformanceTiers unknown Supported performance tiers of the disk.
Azure.Disk.properties.supportedDiskTypes unknown Supported disk types for the disk.
Azure.Disk.properties.provisioningState unknown The provisioning state of the disk.
Azure.Disk.properties.timeModified unknown The time when the disk was last modified.
Azure.Disk.properties.diskAccessId String The ARM ID of the DiskAccess resource.
Azure.Disk.properties.networkProfile unknown The network profile of the disk.
Azure.Disk.properties.creationData unknown Disk creation data.
Azure.Disk.properties.encryption unknown Encryption settings for the disk.
Azure.Disk.properties.encryptionSettingsCollection unknown A collection of encryption settings.
Azure.Disk.properties.encryptionType String The type of key used to encrypt the data on the disk.
Azure.Disk.properties.securityProfile unknown Security profile for the disk.
Azure.Disk.properties.tieringProfile unknown Tiering profile for the disk.
Azure.Disk.properties.supportedTierList unknown List of supported tiers for the disk.
Azure.Disk.properties.availabilityZone String Availability zone of the disk.
Azure.Disk.properties.dataAccessAuthMode String Additional authentication requirements when exporting or uploading to a disk.
Azure.Disk.properties.osType String The operating system type.
Azure.Disk.properties.hyperVGeneration String The HyperVGenerationType of the virtual machine.
Azure.Disk.properties.lastOwnershipUpdateTime String The last time ownership of the disk was updated.

azure-webapp-update


Updates an Azure Web App. The command is deprecated, please use azure-appservice-webapp-update. Required Permissions: Microsoft.Web/sites/read, Microsoft.Web/sites/write.

Base Command

azure-webapp-update

Input

Argument Name Description Required
resource_group_name The resource group name. Optional
subscription_id Subscription ID. Optional
name Name of the Web App. Required
identity_type Managed service identity type. Possible values are: None, SystemAssigned. Optional
https_only Configures the web site to accept only https requests. Possible values are: true, false. Optional
client_cert_enabled Configures the web site to accept only https requests. Possible values are: true, false. Optional

Context Output

Path Type Description
Azure.WebApp.id String Fully qualified resource ID for the web app.
Azure.WebApp.name String The name of the web app.
Azure.WebApp.type String The resource type, e.g., Microsoft.Web/sites.
Azure.WebApp.location String Geographic location of the web app.
Azure.WebApp.kind String The kind of the app, e.g., app, functionapp, etc.
Azure.WebApp.tags unknown Resource tags as key-value pairs.
Azure.WebApp.identity.type String The type of managed identity (SystemAssigned, UserAssigned, etc.).
Azure.WebApp.identity.principalId String The principal ID of the system-assigned identity.
Azure.WebApp.identity.tenantId String The tenant ID of the system-assigned identity.
Azure.WebApp.identity.userAssignedIdentities unknown The list of user-assigned identities associated with the web app.
Azure.WebApp.properties.state String Current state of the web app (Running, Stopped, etc.).
Azure.WebApp.properties.enabled Boolean Whether the web app is enabled.
Azure.WebApp.properties.defaultHostName String Default host name of the web app.
Azure.WebApp.properties.hostNames unknown List of host names associated with the web app.
Azure.WebApp.properties.repositorySiteName String Name of the repository site.
Azure.WebApp.properties.clientAffinityEnabled Boolean Whether client affinity is enabled.
Azure.WebApp.properties.clientCertEnabled Boolean Whether client certificates are enabled.
Azure.WebApp.properties.clientCertExclusionPaths String Paths to exclude from client certificate authentication.
Azure.WebApp.properties.hostingEnvironment String App Service Environment to use for the web app.
Azure.WebApp.properties.serverFarmId String Resource ID of the associated App Service plan.
Azure.WebApp.properties.reserved Boolean Whether the web app is on a Linux plan.
Azure.WebApp.properties.isXenon Boolean Whether the web app is hosted in Xenon.
Azure.WebApp.properties.hyperV Boolean Whether Hyper-V is enabled for the web app.
Azure.WebApp.properties.siteConfig.appSettings unknown List of app settings.
Azure.WebApp.properties.siteConfig.metadata unknown List of metadata settings.
Azure.WebApp.properties.siteConfig.connectionStrings unknown List of connection strings.
Azure.WebApp.properties.siteConfig.localMySqlEnabled Boolean Whether local MySQL is enabled.
Azure.WebApp.properties.siteConfig.alwaysOn Boolean Whether Always On is enabled.
Azure.WebApp.properties.siteConfig.http20Enabled Boolean Whether HTTP/2 is enabled.
Azure.WebApp.properties.siteConfig.minTlsVersion String Minimum TLS version required.
Azure.WebApp.properties.siteConfig.ftpsState String FTPS state (Disabled, AllAllowed, etc.).
Azure.WebApp.properties.siteConfig.linuxFxVersion String Runtime stack for Linux apps.
Azure.WebApp.properties.siteConfig.windowsFxVersion String Runtime stack for Windows apps.
Azure.WebApp.properties.siteConfig.numberOfWorkers Number Number of workers allocated.
Azure.WebApp.properties.siteConfig.webSocketsEnabled Boolean Whether WebSockets are enabled.
Azure.WebApp.properties.siteConfig.preWarmedInstanceCount Number Number of pre-warmed instances.
Azure.WebApp.properties.siteConfig.acrUseManagedIdentityCreds Boolean Whether ACR uses managed identity credentials.
Azure.WebApp.properties.siteConfig.acrUserManagedIdentityID String User-assigned identity ID for ACR.
Azure.WebApp.properties.siteConfig.scmType String Source control management type.
Azure.WebApp.properties.siteConfig.use32BitWorkerProcess Boolean Whether to use 32-bit worker process.
Azure.WebApp.properties.siteConfig.autoHealEnabled Boolean Whether auto-heal is enabled.
Azure.WebApp.properties.siteConfig.autoHealRules unknown Auto-heal rules configuration.
Azure.WebApp.properties.siteConfig.tracingOptions String Tracing options.
Azure.WebApp.properties.siteConfig.remoteDebuggingEnabled Boolean Whether remote debugging is enabled.
Azure.WebApp.properties.siteConfig.remoteDebuggingVersion String Remote debugging version.
Azure.WebApp.properties.siteConfig.detailedErrorLoggingEnabled Boolean Whether detailed error logging is enabled.
Azure.WebApp.properties.siteConfig.httpLoggingEnabled Boolean Whether HTTP logging is enabled.
Azure.WebApp.properties.siteConfig.requestTracingEnabled Boolean Whether request tracing is enabled.
Azure.WebApp.properties.siteConfig.requestTracingExpirationTime DateTime Request tracing expiration time.
Azure.WebApp.properties.siteConfig.remoteDebuggingEnabled Boolean Whether remote debugging is enabled.
Azure.WebApp.properties.siteConfig.remoteDebuggingVersion String Remote debugging version.
Azure.WebApp.properties.siteConfig.defaultDocuments unknown List of default documents.
Azure.WebApp.properties.siteConfig.virtualApplications unknown List of virtual applications.
Azure.WebApp.properties.siteConfig.loadBalancing String Load balancing settings.
Azure.WebApp.properties.siteConfig.experiments unknown Experiments configuration.
Azure.WebApp.properties.siteConfig.limits unknown Site limits configuration.
Azure.WebApp.properties.siteConfig.autoSwapSlotName String Auto-swap slot name.
Azure.WebApp.properties.siteConfig.localMySqlEnabled Boolean Whether local MySQL is enabled.
Azure.WebApp.properties.siteConfig.ipSecurityRestrictions unknown IP security restrictions.
Azure.WebApp.properties.siteConfig.scmIpSecurityRestrictions unknown SCM IP security restrictions.
Azure.WebApp.properties.siteConfig.scmIpSecurityRestrictionsUseMain Boolean Whether SCM IP restrictions use main settings.
Azure.WebApp.properties.siteConfig.cors unknown CORS settings.
Azure.WebApp.properties.siteConfig.push unknown Push settings.
Azure.WebApp.properties.siteConfig.apiDefinition unknown API definition settings.
Azure.WebApp.properties.siteConfig.apiManagementConfig unknown API management configuration.
Azure.WebApp.properties.siteConfig.autoHealEnabled Boolean Whether auto-heal is enabled.
Azure.WebApp.properties.siteConfig.autoHealRules unknown Auto-heal rules configuration.
Azure.WebApp.properties.siteConfig.tracingOptions String Tracing options.
Azure.WebApp.properties.siteConfig.remoteDebuggingEnabled Boolean Whether remote debugging is enabled.
Azure.WebApp.properties.siteConfig.remoteDebuggingVersion String Remote debugging version.
Azure.WebApp.properties.siteConfig.detailedErrorLoggingEnabled Boolean Whether detailed error logging is enabled.
Azure.WebApp.properties.siteConfig.httpLoggingEnabled Boolean Whether HTTP logging is enabled.
Azure.WebApp.properties.siteConfig.requestTracingEnabled Boolean Whether request tracing is enabled.

azure-acr-update


Updates a container registry. The command is deprecated, please use azure-cr-registry-update. Required Permissions: Microsoft.ContainerRegistry/registries/read, Microsoft.ContainerRegistry/registries/write.

Base Command

azure-acr-update

Input

Argument Name Description Required
resource_group_name The resource group name. Optional
subscription_id Subscription ID. Optional
registry_name The name of the container registry. Required
allow_exports Whether artifacts can be exported. Possible values are: disabled, enabled. Optional
public_network_access Whether public network access is allowed for the container registry. Possible values are: disabled, enabled. Optional
anonymous_pull_enabled Whether to enable registry-wide pulls from unauthenticated clients. Possible values are: true, false. Optional
authentication_as_arm_policy Whether the policy is enabled or not. Possible values are: disabled, enabled. Optional

Context Output

Path Type Description
Azure.ACR.id String The resource ID.
Azure.ACR.identity Unknown The identity of the container registry.
Azure.ACR.location String The location of the resource.
Azure.ACR.name String The name of the resource.
Azure.ACR.properties.adminUserEnabled Boolean The value that indicates whether the admin user is enabled.
Azure.ACR.properties.anonymousPullEnabled Boolean Enables registry-wide pull from unauthenticated clients.
Azure.ACR.properties.creationDate String The creation date of the container registry in ISO8601 format.
Azure.ACR.properties.dataEndpointEnabled Boolean Enable a single data endpoint per region for serving data.
Azure.ACR.properties.dataEndpointHostNames Unknown List of host names that will serve data when dataEndpointEnabled is true.
Azure.ACR.properties.encryption Unknown The encryption settings of container registry.
Azure.ACR.properties.loginServer String The URL that can be used to log into the container registry.
Azure.ACR.properties.networkRuleBypassOptions String Whether to allow trusted Azure services to access a network restricted registry.
Azure.ACR.properties.networkRuleSet Unknown The network rule set for a container registry.
Azure.ACR.properties.policies Unknown The policies for a container registry.
Azure.ACR.properties.privateEndpointConnections Unknown List of private endpoint connections for a container registry.
Azure.ACR.properties.provisioningState String The provisioning state of the container registry at the time the operation was called.
Azure.ACR.properties.publicNetworkAccess String Whether or not public network access is allowed for the container registry.
Azure.ACR.properties.status Unknown The status of the container registry at the time the operation was called.
Azure.ACR.properties.zoneRedundancy String Whether or not zone redundancy is enabled for this container registry.
Azure.ACR.sku Unknown The SKU of the container registry.
Azure.ACR.systemData Unknown Metadata pertaining to creation and last modification of the resource.
Azure.ACR.tags Unknown The tags of the resource.
Azure.ACR.type String The type of the resource.

azure-postgres-server-update


Updates an existing server. The command is deprecated due to the retirement of Azure PostgreSQL Single Server.

Base Command

azure-postgres-server-update

Input

Argument Name Description Required
resource_group_name The resource group name. Optional
subscription_id Subscription ID. Optional
server_name Name of the PostgreSQL server. Required
ssl_enforcement Whether to enable SSL authentication when connecting to the server. Possible values are: Disabled, Enabled. Optional

Context Output

There is no context output for this command.

azure-key-vault-update


Updates a key vault in the specified subscription. The command is deprecated, please use azure-keyvault-vault-update. Required Permissions: Microsoft.KeyVault/vaults/read, Microsoft.KeyVault/vaults/write.

Base Command

azure-key-vault-update

Input

Argument Name Description Required
vault_name Key Vault name. Required
subscription_id The subscription ID. Optional
resource_group_name The name of the resource group. Optional
enable_purge_protection Whether protection against purge is enabled for this vault. This functionality is always enabled, it cannot be disabled. Possible values are: true. Optional
enable_soft_delete Whether soft delete is enabled for this key vault. This functionality is always enabled, it cannot be disabled. Possible values are: true. Optional

Context Output

Path Type Description
Azure.KeyVault.id String Resource ID.
Azure.KeyVault.name String Key Vault name.
Azure.KeyVault.type String Resource type in Azure.
Azure.KeyVault.location String Key Vault location.
Azure.KeyVault.tags unknown Resource tags.
Azure.KeyVault.properties.sku.family String SKU family name.
Azure.KeyVault.properties.sku.name String SKU name to specify whether the key vault is a standard vault or a premium vault.
Azure.KeyVault.properties.tenantId String The Entra ID tenant ID that should be used for authenticating requests to the key vault.
Azure.KeyVault.properties.accessPolicies unknown An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault’s tenant ID.
Azure.KeyVault.properties.accessPolicies.tenantId String The Entra ID tenant ID that should be used for authenticating requests to the key vault.
Azure.KeyVault.properties.accessPolicies.objectId String The object ID of a user, service principal or security group in the Entra ID tenant for the vault. The object ID must be unique for the list of access policies.
Azure.KeyVault.properties.accessPolicies.permissions unknown Permissions the identity has for keys, secrets and certificates.
Azure.KeyVault.properties.enabledForDeployment Boolean Whether Azure Virtual Machines are allowed to retrieve certificates stored as secrets from the key vault.
Azure.KeyVault.properties.enabledForDiskEncryption Boolean Whether Azure Disk Encryption is allowed to retrieve secrets from the vault and unwrap keys.
Azure.KeyVault.properties.enabledForTemplateDeployment Boolean Whether Azure Resource Manager is allowed to retrieve secrets from the key vault.
Azure.KeyVault.properties.enableSoftDelete Boolean Whether soft delete is enabled for this key vault.
Azure.KeyVault.properties.enablePurgeProtection Boolean Whether purge protection is enabled for this key vault.
Azure.KeyVault.properties.enableRbacAuthorization Boolean Whether Azure Key Vault uses Role Based Access Control (RBAC) for authorization of data actions.
Azure.KeyVault.properties.vaultUri String The URI of the vault for performing operations on keys and secrets.
Azure.KeyVault.properties.provisioningState String The current provisioning state.
Azure.KeyVault.properties.privateEndpointConnections unknown List of private endpoint connections associated with the key vault.
Azure.KeyVault.properties.networkAcls unknown Rules governing the accessibility of the key vault from specific network locations.
Azure.KeyVault.properties.networkAcls.bypass String What traffic can bypass network rules.
Azure.KeyVault.properties.networkAcls.defaultAction String The default action when no rules match from ipRules and virtualNetworkRules.
Azure.KeyVault.properties.networkAcls.ipRules unknown The list of IP address rules.
Azure.KeyVault.properties.networkAcls.virtualNetworkRules unknown The list of virtual network rules.

azure-sql-db-threat-policy-update


Updates the database’s threat detection policy. The command is deprecated, please use azure-sqldb-security-alert-policy-update. Required Permissions: Microsoft.Sql/servers/databases/securityAlertPolicies/read, Microsoft.Sql/servers/databases/securityAlertPolicies/write.

Base Command

azure-sql-db-threat-policy-update

Input

Argument Name Description Required
server_name Server name. Required
db_name Database name. Required
email_account_admins_enabled Whether the alert is sent to the account administrators. Possible values: “true” and “false”. Possible values are: true, false. Optional
subscription_id Subscription ID. Optional
resource_group_name The name of the resource group. Optional

Context Output

Path Type Description
Azure.SqlDBThreatPolicy.kind String Kind of threat policy.
Azure.SqlDBThreatPolicy.location String Threat policy location.
Azure.SqlDBThreatPolicy.id String Threat policy ID.
Azure.SqlDBThreatPolicy.name String Threat policy name.
Azure.SqlDBThreatPolicy.type String Threat policy type.
Azure.SqlDBThreatPolicy.state String Threat policy state.
Azure.SqlDBThreatPolicy.creationTime String Threat policy creation time.
Azure.SqlDBThreatPolicy.retentionDays Number Number of days to keep in the Threat Detection audit logs.
Azure.SqlDBThreatPolicy.storageAccountAccessKey String The identifier key of the Threat Detection audit storage account.
Azure.SqlDBThreatPolicy.storageEndpoint String Threat Detection audit storage account.
Azure.SqlDBThreatPolicy.emailAccountAdmins Boolean Email accounts administrators who the alert is sent to.
Azure.SqlDBThreatPolicy.emailAddresses String List of email addresses to which the alert is sent.
Azure.SqlDBThreatPolicy.disabledAlerts String List of alerts that are disabled, or an empty string if no alerts are disabled.
Azure.SqlDBThreatPolicy.useServerDefault unknown Whether to use the default server policy.
Azure.SqlDBThreatPolicy.databaseName String The name of the database that the threat policy is related to.
Azure.SqlDBThreatPolicy.serverName String The name of server that the threat policy is related to.

azure-sql-db-transparent-data-encryption-set


Updates a logical database’s transparent data encryption configuration. Required permissions: Microsoft.Sql/servers/databases/transparentDataEncryption/read, Microsoft.Sql/servers/databases/transparentDataEncryption/write.

Base Command

azure-sql-db-transparent-data-encryption-set

Input

Argument Name Description Required
server_name Server name. Required
db_name Database name. Required
state The state of the transparent data encryption. Possible values are: Disabled, Enabled. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The name of the resource group. Required

Context Output

There is no context output for this command.

azure-vm-instance-details-get


Gets the properties of a given virtual machine. The command is deprecated, please use azure-compute-vm-get. Required Permissions: Microsoft.Compute/virtualMachines/read.

Base Command

azure-vm-instance-details-get

Input

Argument Name Description Required
subscription_id The subscription ID. Required
resource_group_name The resource group to which the virtual machine belongs.
To see all the resource groups associated with your subscription, run the azure-list-resource-groups command
.
Required
virtual_machine_name The name of the virtual machine you want to view the details of. Required
expand The expand expression to apply on the operation. ‘instanceView’ retrieves a snapshot of the runtime properties of the virtual machine that is managed by the platform and can change outside of control plane operations. ‘userData’ retrieves the UserData property as part of the VM model view that was provided by the user during the VM Create/Update operation. Default value is False. Possible values are: instanceView, userData. Default is instanceView. Optional

Context Output

Path Type Description
Azure.Compute.name string The name of the virtual machine you want to get details of.
Azure.Compute.id string The ID of the virtual machine.
Azure.Compute.location string The region in which the virtual machine is hosted.
Azure.Compute.Size number The size of the deployed virtual machine (in gigabytes).
Azure.Compute.OS string The OS running on the given virtual machine.
Azure.Compute.properties.provisioningState string The provisioning state of the deployed virtual machine.
Azure.Compute.networkProfile.networkInterfaces string The list of network interfaces attached to this virtual machine.
Azure.Compute.properties.hardwareProfile.vmSize string The size or SKU of the virtual machine, defining CPU, memory, and storage capacity.
Azure.Compute.properties.provisioningState string The current provisioning state of the virtual machine (e.g., Succeeded, Updating, Failed).
Azure.Compute.properties.osProfile string The operating system configuration of the virtual machine, including admin credentials and hostname.
Azure.Compute.properties.storageProfile string The storage settings for the virtual machine, including OS and data disks.
Azure.Compute.properties.vmId string The unique identifier assigned to the virtual machine instance.
Azure.Compute.properties.instanceView string Detailed runtime status information about the virtual machine, such as power state and extensions.
Azure.Compute.properties.timeCreated string The timestamp when the virtual machine was created.
Azure.Compute.properties.networkProfile string The network configuration of the virtual machine, including associated network interfaces and settings.
Azure.Compute.properties.diagnosticsProfile string The configuration for boot diagnostics and monitoring of the virtual machine.

azure-nsg-security-groups-list


List all network security groups. The command is deprecated, please use azure-vn-security-groups-list. Required Permissions: Microsoft.Network/networkSecurityGroups/read.

Base Command

azure-nsg-security-groups-list

Input

Argument Name Description Required
subscription_id The subscription ID. Required
resource_group_name The resource group name. Required

Context Output

Path Type Description
Azure.NSGSecurityGroup.name String The security group’s name.
Azure.NSGSecurityGroup.id String The security group’s ID.
Azure.NSGSecurityGroup.type String The security group’s type.
Azure.NSGSecurityGroup.location String The security group’s location.
Azure.NSGSecurityGroup.etag String The security group’s ETag.
Azure.NSGSecurityGroup.tags String The security group’s tags.
Azure.NSGSecurityGroup.properties.defaultSecurityRules List The default security rules.
Azure.NSGSecurityGroup.properties.networkInterfaces List The network interfaces.
Azure.NSGSecurityGroup.properties.provisioningState String The provisioning state.
Azure.NSGSecurityGroup.properties.resourceGuid String The resource GUID.
Azure.NSGSecurityGroup.properties.SecurityRules List The security rules.

azure-nsg-security-rule-delete


Delete a security rule. The command is deprecated, please use azure-vn-security-rule-delete. Required Permissions: Microsoft.Network/networkSecurityGroups/securityRules/delete.

Base Command

azure-nsg-security-rule-delete

Input

Argument Name Description Required
subscription_id The subscription ID. Required
resource_group_name Resource group name. Required
security_group_name The name of the security group. Required
security_rule_name The name of the rule to delete. Required

Context Output

There is no context output for this command.

azure-storage-blob-containers-update


Run this command to update a specific blob container. Required Permissions: Microsoft.Storage/storageAccounts/blobServices/containers/write. The command is deprecated, please use azure-storage-blob-container-update.

Base Command

azure-storage-blob-containers-update

Input

Argument Name Description Required
subscription_id The subscription ID. Required
resource_group_name The resource group name. Required
account_name The storage account name. Required
container_name The container name. Required
default_encryption_scope Uses the specified encryption scope by default for all writes to the container. Optional
deny_encryption_scope_override Blocks overriding the container’s default encryption scope. Possible values: true, false. Possible values are: true, false. Optional
public_access Specifies the access level. Possible values: Blob, Container, None. Possible values are: Blob, Container, None. Optional

Context Output

Path Type Description
Azure.StorageBlobContainer.id String Fully qualified resource ID for the resource.
Azure.StorageBlobContainer.name String The name of the resource.
Azure.StorageBlobContainer.type String The resource type.
Azure.StorageBlobContainer.properties.metadata.metadata String A metadata entry for the container, in name–value format.
Azure.StorageBlobContainer.properties.publicAccess String Specifies whether data in the container may be accessed publicly and the access level.
Azure.StorageBlobContainer.properties.hasImmutabilityPolicy Boolean The hasImmutabilityPolicy property is set to true by SRP if an ImmutabilityPolicy exists for this container, and false if it does not.
Azure.StorageBlobContainer.properties.hasLegalHold Boolean The hasLegalHold property is set to true by SRP if at least one legal hold tag exists, and false if all tags are cleared.

azure-vm-instance-start


Powers on a given virtual machine. The command is deprecated, please use azure-compute-vm-start. Required Permissions: Microsoft.Compute/virtualMachines/read, Microsoft.Compute/virtualMachines/start/action.

Base Command

azure-vm-instance-start

Input

Argument Name Description Required
subscription_id The subscription ID. Required
resource_group_name Resource Group to which the virtual machine belongs.
To see all the resource groups associated with your subscription, run the azure-list-resource-groups command
.
Required
virtual_machine_name Name of the virtual machine to power on. Required

Context Output

Path Type Description
Azure.Compute.name string Name of the VM that was started.
Azure.Compute.resourceGroup string Resource group the VM resides in.
Azure.Compute.powerState string Whether the VM instance is powered on or off.

azure-nsg-network-interfaces-list


Gets network interfaces in a resource group. The command is deprecated, please use azure-vn-network-interfaces-list. Required Permissions: Microsoft.Network/networkInterfaces/read.

Base Command

azure-nsg-network-interfaces-list

Input

Argument Name Description Required
resource_group_name The resource group name. Required
subscription_id The subscription ID. Required
limit The maximum number of records to return. Default is 50. Optional
all_results Whether to retrieve all results by overriding the default limit. Possible values are: false, true. Optional

Context Output

Path Type Description
Azure.NSGNetworkInterfaces.name String The network interface’s name.
Azure.NSGNetworkInterfaces.id String The network interface’s ID.
Azure.NSGNetworkInterfaces.kind String The kind of the network interface.
Azure.NSGNetworkInterfaces.etag String The ETag of the network interface.
Azure.NSGNetworkInterfaces.location String The location of the network interface.
Azure.NSGNetworkInterfaces.managedBy String The entity that manages the network interface.
Azure.NSGNetworkInterfaces.tags String The tags associated with the network interface.
Azure.NSGNetworkInterfaces.properties.provisioningState String The network interface’s provisioning state.
Azure.NSGNetworkInterfaces.properties.ipConfigurations.name List The name of the IP configuration resource that is unique within a resource group.
Azure.NSGNetworkInterfaces.properties.ipConfigurations.id List The IP configuration resource ID.
Azure.NSGNetworkInterfaces.properties.ipConfigurations.etag List The ETag of the IP configuration.
Azure.NSGNetworkInterfaces.properties.ipConfigurations.type List The type of the IP configuration resource.
Azure.NSGNetworkInterfaces.properties.tapConfigurations List List of tap configurations.
Azure.NSGNetworkInterfaces.properties.allowPort25Out Boolean Whether port 25 outbound traffic is allowed.
Azure.NSGNetworkInterfaces.properties.nicType String The network interface card type (Standard/Basic).

azure-vm-network-interface-details-get


Gets the properties of a given network interface. The command is deprecated, please use azure-vn-network-interface-get. Required Permissions: Microsoft.Network/networkInterfaces/read.

Base Command

azure-vm-network-interface-details-get

Input

Argument Name Description Required
subscription_id The subscription ID. Required
resource_group_name The resource group to which the network interface belongs.
To see all the resource groups associated with your subscription, run the azure-list-resource-groups command
.
Required
network_interface_name The name of the network interface you want to view the details of. Required

Context Output

Path Type Description
Azure.Network.Interfaces.properties.ipConfigurations Unknown The interface public IP address ID.
Azure.Network.Interfaces.properties.macAddress String The interface MAC address.
Azure.Network.Interfaces.name String The interface name.
Azure.Network.Interfaces.location String The interface location.
Azure.Network.Interfaces.id String The interface ID.
Azure.Network.Interfaces.location String The Azure region where the network interface is deployed.
Azure.Network.Interfaces.etag String A unique read-only string that changes whenever the network interface resource is updated.
Azure.Network.Interfaces.kind String The type of the network interface resource, used for Azure internal classification.
Azure.Network.Interfaces.properties.tapConfigurations String The list of tap configurations attached to the network interface for traffic mirroring.
Azure.Network.Interfaces.properties.allowPort25Out String Indicates whether outbound traffic on port 25 (SMTP) is allowed from this network interface.
Azure.Network.Interfaces.properties.nicType String Specifies the type of network interface, such as Standard or Elastic.
Azure.Network.Interfaces.properties.provisioningState String The current provisioning state of the network interface (e.g., Succeeded, Updating, Failed).
Azure.Network.Interfaces.properties.dnsSettings String The DNS configuration of the network interface, including DNS servers and domain name.
Azure.Network.Interfaces.properties.enableIPForwarding String Indicates whether IP forwarding is enabled for the network interface.

azure-nsg-security-rule-get


Get a specific rule. The command is deprecated, please use azure-vn-security-rule-get. Required Permissions: Microsoft.Network/networkSecurityGroups/securityRules/read.

Base Command

azure-nsg-security-rule-get

Input

Argument Name Description Required
subscription_id The subscription ID. Required
resource_group_name Resource group name. Required
security_group_name The name of the security group. Required
security_rule_name The name of the rule to get. Required

Context Output

Path Type Description
Azure.NSGRule.name String The rule’s name.
Azure.NSGRule.id String The rule’s ID.
Azure.NSGRule.location String The rule’s location.
Azure.NSGRule.etag String The rule’s ETag.
Azure.NSGRule.type String The rule’s type.
Azure.NSGRule.properties.provisioningState String The rule’s provisioning state.
Azure.NSGRule.properties.protocol String The protocol, which can be “TCP”, “UDP”, “ICMP”, or “*”.
Azure.NSGRule.properties.sourcePortRange String For a single port, the source port or a range of ports. For multiple ports, `sourcePortRanges` is used instead.
Azure.NSGRule.properties.sourcePortRanges String For multiple ports, a list of ports. For a single port, `sourcePortRange` is used instead.
Azure.NSGRule.properties.destinationPortRange String For a single port, the destination port or range of ports. For multiple ports, `destinationPortRanges` is used instead.
Azure.NSGRule.properties.destinationPortRanges String For multiple ports, a list of destination ports. For a single port, `destinationPortRange` is used instead.
Azure.NSGRule.properties.sourceAddressPrefix String The source address.
Azure.NSGRule.properties.destinationAddressPrefix String The destination address.
Azure.NSGRule.properties.access String The rule’s access. Can be “Allow” or “Deny”.
Azure.NSGRule.properties.priority Number The rule’s priority, ranging from 100 to 4096.
Azure.NSGRule.properties.direction String The rule’s direction, which can be “Inbound” or “Outbound”.

azure-nsg-public-ip-addresses-list


Gets public IP addresses in a resource group. The command is deprecated, please use azure-vn-public-ip-addresses-list. Required Permissions: Microsoft.Network/publicIPAddresses/read.

Base Command

azure-nsg-public-ip-addresses-list

Input

Argument Name Description Required
resource_group_name The resource group name. Required
subscription_id The subscription ID. Required
limit The maximum number of records to return. Default is 50. Optional
all_results Whether to retrieve all results by overriding the default limit. Possible values are: false, true. Optional

Context Output

Path Type Description
Azure.NSGPublicIPAddress.name String The public IP address’s name.
Azure.NSGPublicIPAddress.id String The public IP address’s ID.
Azure.NSGPublicIPAddress.location String The location of the public IP address.
Azure.NSGPublicIPAddress.sku String The public IP address’s SKU.
Azure.NSGPublicIPAddress.type String The type of the public IP address.
Azure.NSGPublicIPAddress.etag String The public IP address’s ETag.
Azure.NSGPublicIPAddress.properties.provisioningState String The public IP address’s provisioning state.
Azure.NSGPublicIPAddress.properties.publicIPAddressVersion String The public IP address’s version.
Azure.NSGPublicIPAddress.properties.ipAddress String The public IP address’s IP address.
Azure.NSGPublicIPAddress.properties.domainNameLabel String The public IP address’s domain name label.
Azure.NSGPublicIPAddress.properties.publicIPAllocationMethod String The public IP address’s allocation method.
Azure.NSGPublicIPAddress.properties.fqdn String The public IP address’s fully qualified domain name (FQDN).
Azure.NSGPublicIPAddress.properties.resourceGuid String The public IP address’s resource GUID.
Azure.NSGPublicIPAddress.sku.name String The public IP address’s SKU name.
Azure.NSGPublicIPAddress.sku.tier String The public IP address’s SKU tier.

azure-storage-blob-service-properties-get


Run this command to get the blob service properties of a specific account storage. The command is deprecated, please use azure-storage-blob-service-property-get. Required Permissions: Microsoft.Storage/storageAccounts/blobServices/read, Microsoft.Storage/storageAccounts/blobServices/write.

Base Command

azure-storage-blob-service-properties-get

Input

Argument Name Description Required
subscription_id The subscription ID. Required
resource_group_name The resource group name. Required
account_name The storage account name. Required

Context Output

Path Type Description
Azure.StorageBlobServiceProperties.id String Fully qualified resource ID for the resource.
Azure.StorageBlobServiceProperties.name String The name of the resource.
Azure.StorageBlobServiceProperties.type String The resource type.
Azure.StorageBlobServiceProperties.properties.lastAccessTimeTrackingPolicy.enable Boolean When set to true, last access time–based tracking is enabled.
Azure.StorageBlobServiceProperties.properties.lastAccessTimeTrackingPolicy.name String Name of the policy. The valid value is AccessTimeTracking.
Azure.StorageBlobServiceProperties.properties.lastAccessTimeTrackingPolicy.trackingGranularityInDays Number Specifies the blob object tracking granularity in days, indicating how often the blob should be tracked.
Azure.StorageBlobServiceProperties.properties.lastAccessTimeTrackingPolicy.blobType String An array of predefined, supported blob types. The only supported value is BlockBlob.

azure-vm-public-ip-details-get


Gets the properties of a given public IP address. The command is deprecated, please use azure-vn-public-ip-address-get. Required Permissions: Microsoft.Network/publicIPAddresses/read.

Base Command

azure-vm-public-ip-details-get

Input

Argument Name Description Required
subscription_id The subscription ID. Required
resource_group_name The resource group to which the IP address belongs.
To see all the resource groups associated with your subscription, run the azure-list-resource-groups command
.
Required
address_name The IP address name. Required

Context Output

Path Type Description
Azure.Network.IPConfigurations.location String The Azure region where the IP configuration resource is located.
Azure.Network.IPConfigurations.id String The unique resource ID of the IP configuration.
Azure.Network.IPConfigurations.name String The name of the IP configuration.
Azure.Network.IPConfigurations.etag String A unique read-only string that changes whenever the IP configuration resource is updated.
Azure.Network.IPConfigurations.properties.idleTimeoutInMinutes String The idle timeout value in minutes for the associated public IP address.
Azure.Network.IPConfigurations.properties.ipAddress String The private IP address assigned to the network interface or resource.
Azure.Network.IPConfigurations.properties.provisioningState String The current provisioning state of the IP configuration (e.g., Succeeded, Updating, Failed).
Azure.Network.IPConfigurations.properties.ipConfiguration String The reference to another IP configuration associated with this resource.
Azure.Network.IPConfigurations.properties.publicIPAddressVersion String The version of the public IP address (IPv4 or IPv6).
Azure.Network.IPConfigurations.properties.publicIPAllocationMethod String Defines how the public IP address is allocated — Static or Dynamic.
Azure.Network.IPConfigurations.properties.resourceGuid String The unique Azure resource GUID for the IP configuration.
Azure.Network.IPConfigurations.properties.sku String The SKU of the public IP address associated with the configuration, defining its performance tier.

azure-nsg-security-rule-create


Create a security rule. The command is deprecated, please use azure-vn-security-rule-create. Required Permissions: Microsoft.Network/networkSecurityGroups/securityRules/read, Microsoft.Network/networkSecurityGroups/securityRules/write.

Base Command

azure-nsg-security-rule-create

Input

Argument Name Description Required
subscription_id The subscription ID. Required
resource_group_name Resource group name. Required
security_group_name The name of the security group. Required
security_rule_name The name of the rule to create. Required
direction The direction of the rule. Possible values are: “Inbound” and “Outbound”. Possible values are: Inbound, Outbound. Required
action Whether to allow the traffic. Possible values are: “Allow” and “Deny”. Possible values are: Allow, Deny. Default is Allow. Optional
protocol The protocol on which to apply the rule. Possible values are: “Any”, “TCP”, “UDP” and “ICMP”. Possible values are: Any, TCP, UDP, ICMP. Default is Any. Optional
source The source IP address range from which incoming traffic is allowed or denied by this rule. Possible values are “Any”, an IP address range, an application security group, or a default tag. Default is “Any”. Default is Any. Optional
priority The priority of the rule, with a value between 100 and 4096. Each rule in the collection must have a unique priority number. Lower numbers indicate higher priority. Required
source_ports The source ports from which traffic is allowed or denied by this rule. Provide a single port, such as 80; a port range, such as 1024-65535; or a comma-separated list of single ports and/or port ranges, such as 80,1024-65535. Use an asterisk () to allow traffic on any port. Default is “”. Default is *. Optional
destination The destination IP address range for outgoing traffic that is allowed or denied by this rule. The destination filter can be “Any”, an IP address range, an application security group, or a default tag. Default is Any. Optional
destination_ports The destination ports from which traffic is allowed or denied by this rule. Provide a single port, such as 80; a port range, such as 1024-65535; or a comma-separated list of single ports and/or port ranges, such as 80,1024-65535. Use an asterisk () to allow traffic on any port. Default is. Optional
description A description to add to the rule. Optional

Context Output

Path Type Description
Azure.NSGRule.name String The rule’s name.
Azure.NSGRule.id String The rule’s ID.
Azure.NSGRule.etag String The rule’s ETag.
Azure.NSGRule.type String The rule’s type.
Azure.NSGRule.properties.provisioningState String The rule’s provisioning state.
Azure.NSGRule.properties.protocol String The protocol, which can be “TCP”, “UDP”, “ICMP”, or “*”.
Azure.NSGRule.properties.sourcePortRange String For a single port, the source port or a range of ports. For multiple ports, `sourcePortRanges` is used instead.
Azure.NSGRule.properties.sourcePortRanges String For multiple ports, a list of ports. For a single port, `sourcePortRange` is used instead.
Azure.NSGRule.properties.destinationPortRange String For a single port, the destination port or range of ports. For multiple ports, `destinationPortRanges` is used instead.
Azure.NSGRule.properties.destinationPortRanges String For multiple ports, a list of destination ports. For a single port, `destinationPortRange` is used instead.
Azure.NSGRule.properties.sourceAddressPrefix String The source address.
Azure.NSGRule.properties.destinationAddressPrefix String The destination address.
Azure.NSGRule.properties.access String The rule’s access. Can be “Allow” or “Deny”.
Azure.NSGRule.properties.priority Number The rule’s priority, ranging from 100 to 4096.
Azure.NSGRule.properties.direction String The rule’s direction, which can be “Inbound” or “Outbound”.

azure-nsg-resource-group-list


Gets all resource groups for a subscription. The command is deprecated, please use azure-rm-resource-groups-list. Required Permissions: Microsoft.Resources/subscriptions/resourceGroups/read.

Base Command

azure-nsg-resource-group-list

Input

Argument Name Description Required
subscription_id The subscription ID. Required
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
Azure.NSGResourceGroup.id String The unique identifier of the Azure Network Security Groups resource group.
Azure.NSGResourceGroup.name String The name of the Azure Network Security Groups resource group.
Azure.NSGResourceGroup.type String The type of the Azure Network Security Groups resource group.
Azure.NSGResourceGroup.location String The location of the Azure Network Security Groups resource group.
Azure.NSGResourceGroup.properties.provisioningState String The provisioning state of the Azure Network Security Groups resource group.
Azure.NSGResourceGroup.tags.Owner String The owner tag of the Azure Network Security Groups resource group.
Azure.NSGResourceGroup.tags Unknown The tags associated with the Azure Network Security Groups resource group.
Azure.NSGResourceGroup.tags.Name String The name tag of the Azure Network Security Groups resource group.
Azure.NSGResourceGroup.managedBy String The entity that manages the Azure Network Security Groups resource group.
Azure.NSGResourceGroup.tags.aNSG-managed-cluster-name String The ANSG managed cluster name tag associated with the Azure Network Security Groups resource group.
Azure.NSGResourceGroup.tags.aNSG-managed-cluster-rg String The ANSG managed cluster resource group tag associated with the Azure Network Security Groups resource group.
Azure.NSGResourceGroup.tags.type String The type tag associated with the Azure Network Security Groups resource group.

azure-vm-instance-power-off


Powers off a given virtual machine. The command is deprecated, please use azure-compute-vm-power-off. Required Permissions: Microsoft.Compute/virtualMachines/read, Microsoft.Compute/virtualMachines/poweroff/action.

Base Command

azure-vm-instance-power-off

Input

Argument Name Description Required
subscription_id The subscription ID. Required
resource_group_name The resource group to which the virtual machine belongs. Required
virtual_machine_name The name of the virtual machine to power off. To see all virtual machines with their associated names for a specific resource group, run the azure-compute-vm-list command. Required
skip_shutdown Set to True to request non-graceful VM shutdown. Possible values are: true, false. Default is false. Optional

Context Output

Path Type Description
Azure.Compute.name string The name of the virtual machine that was powered off.
Azure.Compute.resourceGroup string The resource group in which the virtual machine resides.
Azure.Compute.powerState string Whether the virtual machine instance is powered on or off.

azure-billing-usage-list


Returns actual usage and cost details for a given time period, optionally filtered by service name. Required permission: Microsoft.Consumption/usageDetails/read.

Base Command

azure-billing-usage-list

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
expand_result Whether to expand the result. Default - false. Possible values are: false, true. Optional
filter Optional filter for the API. API argument - $filter. Optional
metric The metric to retrieve. API values [actualcost, amortizedcost, usage]. Possible values are: Actual Cost, Amortized Cost, Usage. Optional
max_results Maximum results to return. Default - 50, Max - 1000. Default is 50. Optional
next_page_token Next page token for pagination. Use value from Azure.Billing.UsageNextToken. Optional

Context Output

Path Type Description
Azure.Billing.Usage unknown List of usage details from Azure Consumption API.
Azure.Billing.Usage.id String Fully qualified resource ID for the usage detail.
Azure.Billing.Usage.name String Name of the usage detail resource.
Azure.Billing.Usage.type String Resource type (Microsoft.Consumption/usageDetails).
Azure.Billing.Usage.kind String Kind of usage detail (legacy, modern).
Azure.Billing.Usage.properties.billingAccountId String Billing account identifier.
Azure.Billing.Usage.properties.billingAccountName String Billing account name.
Azure.Billing.Usage.properties.billingPeriodStartDate Date Billing period start date.
Azure.Billing.Usage.properties.billingPeriodEndDate Date Billing period end date.
Azure.Billing.Usage.properties.billingProfileId String Billing profile identifier.
Azure.Billing.Usage.properties.billingProfileName String Billing profile name.
Azure.Billing.Usage.properties.accountOwnerId String Account owner identifier.
Azure.Billing.Usage.properties.accountName String Account name.
Azure.Billing.Usage.properties.subscriptionId String Subscription identifier.
Azure.Billing.Usage.properties.subscriptionName String Subscription name.
Azure.Billing.Usage.properties.date Date Usage date.
Azure.Billing.Usage.properties.product String Product name.
Azure.Billing.Usage.properties.partNumber String Part number for the product.
Azure.Billing.Usage.properties.meterId String Meter identifier.
Azure.Billing.Usage.properties.meterDetails unknown Meter details object.
Azure.Billing.Usage.properties.meterDetails.meterName String Meter name.
Azure.Billing.Usage.properties.meterDetails.meterCategory String Meter category.
Azure.Billing.Usage.properties.meterDetails.meterSubCategory String Meter subcategory.
Azure.Billing.Usage.properties.meterDetails.unit String Unit of measure.
Azure.Billing.Usage.properties.meterDetails.meterLocation String Meter location.
Azure.Billing.Usage.properties.meterDetails.totalIncludedQuantity Number Total included quantity.
Azure.Billing.Usage.properties.meterDetails.pretaxStandardRate Number Pretax standard rate.
Azure.Billing.Usage.properties.quantity Number Usage quantity.
Azure.Billing.Usage.properties.effectivePrice Number Effective price for the usage.
Azure.Billing.Usage.properties.cost Number Cost amount.
Azure.Billing.Usage.properties.unitPrice Number Unit price.
Azure.Billing.Usage.properties.billingCurrency String Billing currency.
Azure.Billing.Usage.properties.resourceLocation String Resource location.
Azure.Billing.Usage.properties.consumedService String Consumed service name.
Azure.Billing.Usage.properties.resourceId String Resource identifier.
Azure.Billing.Usage.properties.resourceName String Resource name.
Azure.Billing.Usage.properties.serviceInfo1 String Service info 1.
Azure.Billing.Usage.properties.serviceInfo2 String Service info 2.
Azure.Billing.Usage.properties.additionalInfo String Additional information.
Azure.Billing.Usage.properties.invoiceSection String Invoice section.
Azure.Billing.Usage.properties.costCenter String Cost center.
Azure.Billing.Usage.properties.resourceGroup String Resource group name.
Azure.Billing.Usage.properties.reservationId String Reservation identifier.
Azure.Billing.Usage.properties.reservationName String Reservation name.
Azure.Billing.Usage.properties.productOrderId String Product order identifier.
Azure.Billing.Usage.properties.productOrderName String Product order name.
Azure.Billing.Usage.properties.offerId String Offer identifier.
Azure.Billing.Usage.properties.isAzureCreditEligible Boolean Whether usage is Azure credit eligible.
Azure.Billing.Usage.properties.term String Term.
Azure.Billing.Usage.properties.publisherName String Publisher name.
Azure.Billing.Usage.properties.publisherType String Publisher type.
Azure.Billing.Usage.properties.planName String Plan name.
Azure.Billing.Usage.properties.chargeType String Charge type.
Azure.Billing.Usage.properties.frequency String Frequency.
Azure.Billing.Usage.properties.payGPrice Number Pay-as-you-go price.
Azure.Billing.Usage.properties.pricingModel String Pricing model.
Azure.Billing.UsageNextToken String Next page token for pagination.

azure-billing-forecast-list


Returns cost forecast for a subscription over a given time range. Required permission: Microsoft.CostManagement/forecast/read.

Base Command

azure-billing-forecast-list

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
type Forecast type (required). Possible values are: Usage, ActualCost, AmortizedCost. Required
aggregation_function_name The name of the column to aggregate (required). Possible values are: PreTaxCostUSD, Cost, CostUSD, PreTaxCost. Required
aggregation_function_type The name of the aggregation function to use. Default is Sum. Optional
granularity The granularity of the forecast. Default is Daily. Optional
start_date Start date for the forecast. Default value current time (UTC). e.g. 2022-01-01T00:00:00Z. Optional
end_date End date for the forecast. Default value 7 days from current time (UTC). e.g. 2022-01-01T00:00:00Z. Optional
filter A URL parameter to filter forecasts by properties/usageDate (Utc time), properties/chargeType or properties/grain. The filter supports ‘eq’, ‘lt’, ‘gt’, ‘le’, ‘ge’, and ‘and’. It does not currently support ‘ne’, ‘or’, or ‘not’. Optional
include_actual_cost Include actual cost data. Possible values are: true, false. Default is false. Optional
include_fresh_partial_cost Include fresh partial cost data. Possible values are: true, false. Default is false. Optional

Context Output

Path Type Description
Azure.Billing.Forecast.Cost Number Cost amount.
Azure.Billing.Forecast.CostUSD Number Cost in USD.
Azure.Billing.Forecast.PreTaxCost Number Pre-tax cost amount.
Azure.Billing.Forecast.UsageDate String Usage date for the forecast (YYYY-MM-DD format).
Azure.Billing.Forecast.CostStatus String Cost status (Forecast, Actual).
Azure.Billing.Forecast.Currency String Currency code for the forecast.

azure-billing-budgets-list


Lists configured budgets at the subscription or resource group level. Required permission: Microsoft.Consumption/budgets/read.

Base Command

azure-billing-budgets-list

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
budget_name Name of the budget. Optional; if provided, returns a specific budget. Optional

Context Output

Path Type Description
Azure.Billing.Budget unknown List of budget details from Azure Consumption API.
Azure.Billing.Budget.id String Fully qualified resource ID for the budget.
Azure.Billing.Budget.name String Name of the budget resource.
Azure.Billing.Budget.type String Resource type (Microsoft.Consumption/budgets).
Azure.Billing.Budget.eTag String ETag for the budget resource.
Azure.Billing.Budget.properties.category String Budget category (Cost, Usage).
Azure.Billing.Budget.properties.amount Number Budget amount limit.
Azure.Billing.Budget.properties.timeGrain String Time grain for the budget (Monthly, Quarterly, Annually).
Azure.Billing.Budget.properties.timePeriod unknown Time period object for the budget.
Azure.Billing.Budget.properties.timePeriod.startDate Date Start date of the budget period.
Azure.Billing.Budget.properties.timePeriod.endDate Date End date of the budget period.
Azure.Billing.Budget.properties.currentSpend unknown Current spend object.
Azure.Billing.Budget.properties.currentSpend.amount Number Current spend amount.
Azure.Billing.Budget.properties.currentSpend.unit String Currency unit for current spend.
Azure.Billing.Budget.properties.notifications unknown Budget notifications configuration.
Azure.Billing.Budget.properties.filter unknown Budget filter configuration.
Azure.Billing.Budget.properties.filter.and unknown AND filter conditions.
Azure.Billing.Budget.properties.filter.dimensions unknown Dimension filters.
Azure.Billing.Budget.properties.filter.dimensions.name String Dimension name (ResourceGroup, ResourceType, etc.).
Azure.Billing.Budget.properties.filter.dimensions.operator String Filter operator (In, Equal).
Azure.Billing.Budget.properties.filter.dimensions.values unknown Filter values array.
Azure.Billing.Budget.properties.filter.tags unknown Tag filters.
Azure.Billing.Budget.properties.filter.tags.name String Tag name.
Azure.Billing.Budget.properties.filter.tags.operator String Tag filter operator.
Azure.Billing.Budget.properties.filter.tags.values unknown Tag filter values.
Azure.Billing.Budget.properties.forecastSpend unknown Forecasted spend object.
Azure.Billing.Budget.properties.forecastSpend.amount Number Forecasted spend amount.
Azure.Billing.Budget.properties.forecastSpend.unit String Currency unit for forecasted spend.

azure-storage-container-property-get


Retrieves properties for a specific Container. Required permission: Microsoft.Storage/storageAccounts/blobServices/containers/read.

Base Command

azure-storage-container-property-get

Input

Argument Name Description Required
container_name The name of the Container. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group name. Required
account_name The storage account name. Required

Context Output

Path Type Description
Azure.Storage.Container.Property.Last-Modified Date Last modified time of the container.
Azure.Storage.Container.Property.Etag String The entity tag for the container.
Azure.Storage.Container.Property.X-Ms-Lease-Status String The lease status of the container.
Azure.Storage.Container.Property.X-Ms-Lease-State String The lease state of the container.
Azure.Storage.Container.Property.X-Ms-Has-Immutability-Policy String Indicates whether the container has an immutability policy set on it.
Azure.Storage.Container.Property.X-Ms-Has-Legal-Hold String Indicates whether the container has a legal hold.
Azure.Storage.Container.ContainerName String Container name.

azure-storage-container-create


Creates a new Container under the specified account. Required permission: Microsoft.Storage/storageAccounts/blobServices/containers/write.

Base Command

azure-storage-container-create

Input

Argument Name Description Required
container_name The name of the Container to create. Rules for naming containers can be found here:
https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-containers–blobs–and-metadata
.
Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group name. Required
account_name The storage account name. Required

Context Output

There is no context output for this command.

azure-storage-container-delete


Marks a specific Container for deletion. The Container and any Blobs contained within it will be deleted during garbage collection. Required permission: Microsoft.Storage/storageAccounts/blobServices/containers/delete.

Base Command

azure-storage-container-delete

Input

Argument Name Description Required
container_name The name of the Container to delete. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group name. Required
account_name The storage account name. Required

Context Output

There is no context output for this command.

azure-storage-container-blob-create


Create a new Blob under the specified Container. The command is deprecated, please use azure-storage-blob-create. Required Permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write.

Base Command

azure-storage-container-blob-create

Input

Argument Name Description Required
container_name The name of the Blob Container. Required
file_entry_id The entry ID of the file to upload as a new blob. Available from the war room while the context data contains file output. Required
blob_name The name of the Blob to create. Default is the file name Optional
subscription_id The subscription ID. Required
resource_group_name The resource group name. Required
account_name The storage account name. Required

Context Output

There is no context output for this command.

azure-storage-container-blob-get


Retrieve Blob from Container. The command is deprecated, please use azure-storage-blob-get. Required Permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read.

Base Command

azure-storage-container-blob-get

Input

Argument Name Description Required
container_name The name of the Blob Container. Required
blob_name The name of the Blob to retrieve. Required
subscription_id The subscription ID. Required
resource_group_name The resource group name. Required
account_name The storage account name. Required

Context Output

Path Type Description
File.Size String The size of the file.
File.SHA1 String The SHA1 hash of the file.
File.SHA256 String The SHA256 hash of the file.
File.Name String The name of the file.
File.SSDeep String The SSDeep hash of the file.
File.EntryID String The entry ID of the file.
File.Info String File information.
File.Type String The file type.
File.MD5 Unknown The MD5 hash of the file.
File.Extension String The file extension.

azure-storage-container-blob-tag-get


Retrieve the tags of the specified Blob. The command is deprecated, please use azure-storage-blob-tag-get. Required Permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/read.

Base Command

azure-storage-container-blob-tag-get

Input

Argument Name Description Required
container_name The name of the Blob Container. Required
blob_name The name of the blob. Required
subscription_id The subscription ID. Required
resource_group_name The resource group name. Required
account_name The storage account name. Required

Context Output

Path Type Description
Azure.StorageContainer.Container.Blob.Tag.Key String Tag key.
Azure.StorageContainer.Container.Blob.Tag.Value String Tag value.
Azure.StorageContainer.Container.Blob.name String Blob name.
Azure.StorageContainer.Container.name String Container name.

azure-storage-container-blob-tag-set


Sets the tags for the specified Blob. The command replace the entire tags of the Blob and can be used to remove tags. The command is deprecated, please use azure-storage-blob-tag-set. Required Permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/read, Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/write.

Base Command

azure-storage-container-blob-tag-set

Input

Argument Name Description Required
container_name The name of the Blob Container. Required
blob_name The name of the blob. Required
tags Tags fields in JSON format: {“tag-name-1”: “tag-value-1”, “tag-name-2”: “tag-value-2”}. The tags fields may contain at most 10 tags. Required
subscription_id The subscription ID. Required
resource_group_name The resource group name. Required
account_name The storage account name. Required

Context Output

There is no context output for this command.

azure-storage-container-blob-property-get


Retrieve Blob properties. The command is deprecated, please use azure-storage-blob-property-get. Required Permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read.

Base Command

azure-storage-container-blob-property-get

Input

Argument Name Description Required
container_name The name of the Blob Container. Required
blob_name The name of the blob. Required
subscription_id The subscription ID. Required
resource_group_name The resource group name. Required
account_name The storage account name. Required

Context Output

Path Type Description
Azure.StorageContainer.Container.Blob.Property.last_modified Date Last modified time of the blob.
Azure.StorageContainer.Container.Blob.Property.etag String The entity tag for the blob.
Azure.StorageContainer.Container.Blob.Property.lease_status String The lease status of the blob.
Azure.StorageContainer.Container.Blob.Property.lease_state String The lease state of the blob.
Azure.StorageContainer.Container.Blob.Property.blob_type String The blob type.
Azure.StorageContainer.Container.Blob.Property.content_length Number The size of the blob in bytes.
Azure.StorageContainer.Container.Blob.Property.content_type String The content type specified for the blob. If no content type was specified, the default content type is application/octet-stream.
Azure.StorageContainer.Container.Blob.Property.content-md5 String The MD5 hash of the blob content.
Azure.StorageContainer.Container.Blob.Property.creation_time Date The date at which the blob was created.
Azure.StorageContainer.Container.Blob.name String Blob name.

azure-storage-container-blob-property-set


Set Blob properties. Required Permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write.

Base Command

azure-storage-container-blob-property-set

Input

Argument Name Description Required
container_name The name of the Blob Container. Required
blob_name The name of the blob. Required
subscription_id The subscription ID. Required
resource_group_name The resource group name. Required
account_name The storage account name. Required
content_type Blob content type. Indicates the media type of the blob. Optional
content_md5 Blob MD5 hash value. Can be used by the client to check for content integrity. Optional
content_encoding Blob content encoding. Used to specify the compression algorithm of the blob content. Optional
content_language Blob content language. Describes the human languages of the blob content. Optional
content_disposition Blob content disposition. Conveys additional information about how to process the response payload, and also can be used to attach additional metadata. Optional
cache_control Modifies the cache control string for the blob. Indicates directives for caching in both requests and responses. Optional
request_id Request ID generated by the client and recorded in the analytics logs when storage analytics logging is enabled. Optional
lease_id Required if the blob has an active lease. Optional

Context Output

There is no context output for this command.

azure-storage-container-public-access-block


Blocks public access to a container. Required permission: Microsoft.Storage/storageAccounts/blobServices/containers/setAcl/action.

Base Command

azure-storage-container-public-access-block

Input

Argument Name Description Required
container_name Name of a container. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group name. Required
account_name The storage account name. Required

Context Output

There is no context output for this command.

azure-storage-blob-property-get


Retrieve Blob properties. Required Permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read.

Base Command

azure-storage-blob-property-get

Input

Argument Name Description Required
container_name The name of the Blob Container. Required
blob_name The name of the blob. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group name. Required
account_name The storage account name. Required

Context Output

Path Type Description
Azure.Storage.Blob.Property.Last-Modified Date Last modified time of the blob.
Azure.Storage.Blob.Property.Etag String The entity tag for the blob.
Azure.Storage.Blob.Property.X-Ms-Lease-Status String The lease status of the blob.
Azure.Storage.Blob.Property.X-Ms-Lease-State String The lease state of the blob.
Azure.Storage.Blob.Property.X-Ms-Blob-Type String The blob type.
Azure.Storage.Blob.Property.Content-Type String The content type specified for the blob. If no content type was specified, the default content type is application/octet-stream.
Azure.Storage.Blob.Property.Content-Md5 String The MD5 hash of the blob content.
Azure.Storage.Blob.Property.X-Ms-Creation-Time String The date at which the blob was created.
Azure.Storage.Blob.Property.Server String The server used to process the request.
Azure.Storage.Blob.Property.Accept-Ranges String Indicates that the service supports requests for partial blob content.
Azure.Storage.Blob.Property.Connection String The connection status of the response.
Azure.Storage.Blob.Property.Date String A UTC date/time value generated by the service that indicates the time when the response was initiated.
Azure.Storage.Blob.Property.Transfer-Encoding String The form of encoding used to safely transfer the payload to the user.
Azure.Storage.Blob.Property.X-Ms-Access-Tier String The tier of page blob on a Premium Storage account or tier of a block blob in a Blob Storage or general purpose v2 account.
Azure.Storage.Blob.Property.X-Ms-Access-Tier-Inferred String For page blobs on a Premium Storage account only. If the access tier isn’t explicitly set on the blob, the tier is inferred based on its content length, and this header is returned with a value of true.
Azure.Storage.Blob.Property.X-Ms-Request-Id String This header uniquely identifies the request that was made.
Azure.Storage.Blob.Property.X-Ms-Server-Encrypted String The value of this header is set to true if the blob data and application metadata are completely encrypted using the specified algorithm.
Azure.Storage.Blob.Property.X-Ms-Version String Specifies the version of the operation to use for this request.
Azure.Storage.Blob.name String Blob name.
Azure.Storage.Blob.ContainerName String Container name.

azure-storage-blob-tag-get


Retrieve the tags of the specified Blob. Required Permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/read.

Base Command

azure-storage-blob-tag-get

Input

Argument Name Description Required
container_name The name of the Blob Container. Required
blob_name The name of the blob. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group name. Required
account_name The storage account name. Required

Context Output

Path Type Description
Azure.Storage.Blob.Tag.Key String Tag key.
Azure.Storage.Blob.Tag.Value String Tag value.
Azure.Storage.Blob.name String Blob name.
Azure.Storage.Blob.ContainerName String Container name.

azure-compute-vm-list


Lists all the virtual machines in the specified subscription. Use the next_token argument to view the next page of results. Required Permissions: Microsoft.Compute/virtualMachines/read.

Base Command

azure-compute-vm-list

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The name of the resource group. Required
next_token The URI to fetch the next page of results. Optional

Context Output

Path Type Description
Azure.Compute.VirtualMachines.type String The type of the resource.
Azure.Compute.VirtualMachines.location String The location of the resource.
Azure.Compute.VirtualMachines.tags Unknown The tags of the resource.
Azure.Compute.VirtualMachines.id String The ID of the resource.
Azure.Compute.VirtualMachines.name String The name of the resource.
Azure.Compute.VirtualMachines.etag String The ETag of the virtual machine, used to prevent overwriting concurrent updates.
Azure.Compute.VirtualMachines.extendedLocation Unknown The extended location of the Virtual Machine.
Azure.Compute.VirtualMachines.identity Unknown The identity of the virtual machine, if configured.
Azure.Compute.VirtualMachines.managedBy Unknown MThe ARM resource ID of the Virtual Machine Scale Set (VMSS) that manages the virtual machine, if applicable. Used for internal resource group delete optimization.
Azure.Compute.VirtualMachines.placement Unknown The user-defined constraints for virtual machine hardware placement. This property cannot be changed once the VM is provisioned. Minimum api-version: 2024-11-01.
Azure.Compute.VirtualMachines.plan Unknown Information about the marketplace image used to create the virtual machine.
Azure.Compute.VirtualMachines.systemData Unknown Azure Resource Manager metadata containing createdBy and modifiedBy information.
Azure.Compute.VirtualMachines.zones Unknown. The availability zones.
Azure.Compute.VirtualMachines.properties.vmId String The unique ID of the virtual machine.
Azure.Compute.VirtualMachines.properties.availabilitySet String The availability set that the virtual machine is in.
Azure.Compute.VirtualMachines.properties.hardwareProfile Unknown The hardware settings for the virtual machine.
Azure.Compute.VirtualMachines.properties.storageProfile Unknown The storage settings for the virtual machine disks.
Azure.Compute.VirtualMachines.properties.osProfile Unknown The operating system settings for the virtual machine.
Azure.Compute.VirtualMachines.properties.networkProfile Unknown The network interfaces of the virtual machine.
Azure.Compute.VirtualMachines.properties.provisioningState String The provisioning state, which only appears in the response.
Azure.Compute.VirtualMachines.properties.additionalCapabilities Unknown Additional capabilities enabled or disabled on the virtual machine.
Azure.Compute.VirtualMachines.properties.securityProfile Unknown The security settings for the virtual machine.
Azure.Compute.VirtualMachines.properties.diagnosticsProfile Unknown The boot diagnostic settings state.
Azure.Compute.VirtualMachines.properties.virtualMachineScaleSet Unknown The virtual machine scale set that the virtual machine is in.
Azure.Compute.VirtualMachines.properties.proximityPlacementGroup Unknown The proximity placement group that the virtual machine is in.
Azure.Compute.VirtualMachines.properties.scheduledEventsPolicy Unknown The Redeploy, Reboot, and ScheduledEventsAdditionalPublishingTargets Scheduled Event related configurations for the virtual machine.
Azure.Compute.VirtualMachines.properties.priority String The priority for the virtual machine.
Azure.Compute.VirtualMachines.properties.evictionPolicy String The eviction policy for the virtual machine.
Azure.Compute.VirtualMachines.properties.billingProfile Unknown The billing related details of a Azure Spot virtual machine.
Azure.Compute.VirtualMachines.properties.host Unknown The host that the virtual machine is in.
Azure.Compute.VirtualMachines.properties.hostGroup Unknown The host group that the virtual machine is in.
Azure.Compute.VirtualMachines.properties.licenseType String The license type for bringing your own license scenario.
Azure.Compute.VirtualMachines.properties.extensionsTimeBudget String The time alloted for all extensions to start.
Azure.Compute.VirtualMachines.properties.platformFaultDomain Number The fault domain that the virtual machine is in.
Azure.Compute.VirtualMachines.properties.scheduledEventsProfile Unknown The scheduled event related configurations.
Azure.Compute.VirtualMachines.properties.userData String The user data for the VM, which must be base-64 encoded.
Azure.Compute.VirtualMachines.properties.capacityReservation Unknown The capacity reservation related details of a virtual machine.
Azure.Compute.VirtualMachines.properties.applicationProfile Unknown The gallery applications that should be made available to the VM/VMSS.
Azure.Compute.VirtualMachines.properties.timeCreated Date The time when the virtual machine was created.
Azure.Compute.VirtualMachines.plan.name String The plan name.
Azure.Compute.VirtualMachines.plan.publisher String The publisher of the plan.
Azure.Compute.VirtualMachines.plan.product String The product of the plan.
Azure.Compute.VirtualMachines.plan.promotionCode String The promotion code of the plan.
Azure.Compute.VirtualMachines.resources.properties Unknown The properties of the resource.
Azure.Compute.VirtualMachines.resources.id String The ID of the resource.
Azure.Compute.VirtualMachines.resources.name String The name of the resource.
Azure.Compute.VirtualMachines.resources.type String The type of the resource.
Azure.Compute.VirtualMachines.resources.location String The location of the resource.
Azure.Compute.VirtualMachines.resources.tags Unknown The tags of the resource.
Azure.Compute.VirtualMachines.identity.principalId String The principal ID of the identity.
Azure.Compute.VirtualMachines.identity.tenantId String The tenant ID of the identity.
Azure.Compute.VirtualMachines.identity.type String The type of the identity.
Azure.Compute.VirtualMachines.identity.userAssignedIdentities String The list of user assigned identities associated with the virtual machine.
Azure.Compute.VirtualMachines.zones String The zones of the virtual machine.
Azure.Compute.VirtualMachines.extendedLocation.name String The name of the extended location.
Azure.Compute.VirtualMachines.extendedLocation.type String The type of the extended location.
Azure.Compute.VirtualMachines.properties.instanceView Unknown The virtual machine instance view.
Azure.Compute.VirtualMachinesNextToken String The URI to fetch the next page of VMs. Run the same command with the next_token argument to get the next page of VMs.

azure-compute-vm-get


Gets the properties of a given virtual machine. Required Permissions: Microsoft.Compute/virtualMachines/read.

Base Command

azure-compute-vm-get

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group to which the virtual machine belongs. Required
virtual_machine_name The name of the virtual machine you want to view the details of. To see all the virtual machines with their associated names for a specific resource group, run the azure-compute-vm-list command. Required
expand The expand expression to apply on the operation. ‘InstanceView’ retrieves a snapshot of the runtime properties of the virtual machine that is managed by the platform and can change outside of control plane operations. ‘UserData’ retrieves the UserData property as part of the VM model view that was provided by the user during the VM Create/Update operation. Possible values are: instanceView, userData, resiliencyView. Default is instanceView. Optional

Context Output

Path Type Description
Azure.Compute.VirtualMachines.name string The name of the virtual machine you want to get details of.
Azure.Compute.VirtualMachines.id string The ID of the virtual machine.
Azure.Compute.VirtualMachines.location string The region in which the virtual machine is hosted.
Azure.Compute.VirtualMachines.properties.provisioningState string The provisioning state of the deployed virtual machine.
Azure.Compute.VirtualMachines.networkProfile.networkInterfaces string The list of network interfaces attached to this virtual machine.
Azure.Compute.VirtualMachines.properties.hardwareProfile Unknown Specifies the hardware settings for the virtual machine.
Azure.Compute.VirtualMachines.properties.osProfile string The operating system configuration of the virtual machine, including admin credentials and hostname.
Azure.Compute.VirtualMachines.properties.storageProfile string The storage settings for the virtual machine, including OS and data disks.
Azure.Compute.VirtualMachines.properties.vmId string The unique identifier assigned to the virtual machine instance.
Azure.Compute.VirtualMachines.properties.instanceView string Detailed runtime status information about the virtual machine, such as power state and extensions.
Azure.Compute.VirtualMachines.properties.timeCreated string The timestamp when the virtual machine was created.
Azure.Compute.VirtualMachines.properties.networkProfile string The network configuration of the virtual machine, including associated network interfaces and settings.
Azure.Compute.VirtualMachines.properties.diagnosticsProfile string The configuration for boot diagnostics and monitoring of the virtual machine.

azure-vn-security-group-create


Creates a network security group. Required Permissions: Microsoft.Network/networkSecurityGroups/write.

Base Command

azure-vn-security-group-create

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group name. Required
security_group_name The name of the network security group. Required
location The location of the network security group. Possible values are: australiacentral, australiacentral2, australiaeast, australiasoutheast, brazilsouth, brazilsoutheast, brazilus, canadacentral, canadaeast, centralindia, centralus, centraluseuap, eastasia, eastus, eastus2, eastus2euap, francecentral, francesouth, germanynorth, germanywestcentral, israelcentral, italynorth, japaneast, japanwest, jioindiacentral, jioindiawest, koreacentral, koreasouth, malaysiasouth, mexicocentral, newzealandnorth, northcentralus, northeurope, norwayeast, norwaywest, polandcentral, qatarcentral, southafricanorth, southafricawest, southcentralus, southeastasia, southindia, spaincentral, swedencentral, swedensouth, switzerlandnorth, switzerlandwest, uaecentral, uaenorth, uksouth, ukwest, westcentralus, westeurope, westindia, westus, westus2, westus3, australiaeastfoundational, austriaeast, chilecentral, eastusslv, indonesiacentral, israelnorthwest, malaysiawest, southcentralus2, southeastus, southeastus3, southwestus, usgovarizona, usgovtexas, usgovvirginia. Required

Context Output

Path Type Description
Azure.VirtualNetworks.SecurityGroups.name String The security group’s name.
Azure.VirtualNetworks.SecurityGroups.id String The security group’s ID.
Azure.VirtualNetworks.SecurityGroups.etag String The security group’s ETag.
Azure.VirtualNetworks.SecurityGroups.type String The resource type.
Azure.VirtualNetworks.SecurityGroups.location String The resource location.
Azure.VirtualNetworks.SecurityGroups.properties.provisioningState String The provisioning state of the network security group resource.
Azure.VirtualNetworks.SecurityGroups.properties.resourceGuid String The resource GUID property of the network security group resource.
Azure.VirtualNetworks.SecurityGroups.properties.flushConnection Boolean When enabled, flows created from Network Security Group connections will be re-evaluated when rules are updates. Initial enablement will trigger re-evaluation.
Azure.VirtualNetworks.SecurityGroups.properties.securityRules Unknown A collection of security rules of the network security group.
Azure.VirtualNetworks.SecurityGroups.properties.defaultSecurityRules Unknown A collection of the default security rules of the network security group.
Azure.VirtualNetworks.SecurityGroups.properties.flowLogs Unknown A collection of references to flow log resources.
Azure.VirtualNetworks.SecurityGroups.properties.networkInterfaces Unknown A collection of references to network interfaces.
Azure.VirtualNetworks.SecurityGroups.properties.subnets Unknown A collection of references to subnets.

azure-compute-vm-power-off


Powers off a given virtual machine. Required Permissions: Microsoft.Compute/virtualMachines/poweroff/action.

Base Command

azure-compute-vm-power-off

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group to which the virtual machine belongs. To see all the resource groups associated with your subscription, run the azure-rm-resource-groups-list command. Required
virtual_machine_name The name of the virtual machine to power off. To see all virtual machines with their associated names for a specific resource group, run the azure-compute-vm-list command. Required
skip_shutdown Set to True to request non-graceful VM shutdown. Possible values are: true, false. Default is false. Optional

Context Output

Path Type Description
Azure.Compute.VirtualMachines.name string The name of the virtual machine that was powered off.
Azure.Compute.VirtualMachines.resourceGroup string The resource group in which the virtual machine resides.
Azure.Compute.VirtualMachines.powerState string Whether the virtual machine instance is powered on or off.

azure-compute-vm-start


Powers on a given virtual machine. Required Permissions: Microsoft.Compute/virtualMachines/start/action.

Base Command

azure-compute-vm-start

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name Resource Group to which the virtual machine belongs. Required
virtual_machine_name Name of the virtual machine to power on. To see all virtual machines and their associated names for a specific resource group, run the azure-compute-vm-list command. Required

Context Output

Path Type Description
Azure.Compute.VirtualMachines.name String Name of the VM that was started.
Azure.Compute.VirtualMachines.resourceGroup String Resource group the VM resides in.
Azure.Compute.VirtualMachines.powerState String Whether the VM instance is powered on or off.

azure-cosmosdb-db-account-update


Updates the properties of an existing Azure Cosmos DB database account. The required permissions are: Microsoft.DocumentDB/databaseAccounts/read, Microsoft.DocumentDB/databaseAccounts/write.

Base Command

azure-cosmosdb-db-account-update

Input

Argument Name Description Required
account_name Cosmos DB database account name. Required
disable_key_based_metadata_write_access Whether to disable write operations on metadata resources via account keys. Possible values are: true, false. Optional
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The name of the resource group. Required

Context Output

Path Type Description
Azure.CosmosDB.DBAccounts.id String The unique resource identifier of the ARM resource.
Azure.CosmosDB.DBAccounts.name String The name of the ARM resource.
Azure.CosmosDB.DBAccounts.location String The location of the resource group to which the resource belongs.
Azure.CosmosDB.DBAccounts.kind String The database account type.
Azure.CosmosDB.DBAccounts.identity.type String The type of identity used for the resource.
Azure.CosmosDB.DBAccounts.identity.userAssignedIdentities Unknown The list of user identities associated with the resource.
Azure.CosmosDB.DBAccounts.properties.analyticalStorageConfiguration Unknown Analytical storage specific properties.
Azure.CosmosDB.DBAccounts.properties.apiProperties Unknown API specific properties.
Azure.CosmosDB.DBAccounts.properties.backupPolicy Unknown The policy for taking backups on an account.
Azure.CosmosDB.DBAccounts.properties.capabilities Unknown List of Cosmos DB capabilities for the account.
Azure.CosmosDB.DBAccounts.properties.capacity Number Properties related to capacity enforcement on an account.
Azure.CosmosDB.DBAccounts.properties.connectorOffer String The Cassandra connector offer type for the Cosmos DB database account.
Azure.CosmosDB.DBAccounts.properties.consistencyPolicy String The consistency policy for the Cosmos DB database account.
Azure.CosmosDB.DBAccounts.properties.cors Unknown The CORS policy for the Cosmos DB database account.
Azure.CosmosDB.DBAccounts.properties.createMode String The mode of account creation.
Azure.CosmosDB.DBAccounts.properties.customerManagedKeyStatus String Status of the Customer Managed Key feature on the account.
Azure.CosmosDB.DBAccounts.properties.databaseAccountOfferType String The offer type for the Cosmos DB database account.
Azure.CosmosDB.DBAccounts.properties.defaultIdentity String The default identity for accessing key vault used in features like customer managed keys.
Azure.CosmosDB.DBAccounts.properties.disableKeyBasedMetadataWriteAccess Boolean Whether write operations on metadata resources via account keys is disabled.
Azure.CosmosDB.DBAccounts.properties.disableLocalAuth Boolean Whether local authentication is disabled.
Azure.CosmosDB.DBAccounts.properties.documentEndpoint String The connection endpoint for the Cosmos DB database account.
Azure.CosmosDB.DBAccounts.properties.enableAnalyticalStorage Boolean Whether storage analytics are enabled.
Azure.CosmosDB.DBAccounts.properties.enableAutomaticFailover Boolean Enables automatic failover of the write region.
Azure.CosmosDB.DBAccounts.properties.enableBurstCapacity Boolean Whether Burst Capacity is enabled.
Azure.CosmosDB.DBAccounts.properties.enableCassandraConnector Boolean Enables the Cassandra connector on the Cosmos DB account.
Azure.CosmosDB.DBAccounts.properties.enableFreeTier Boolean Whether Free Tier is enabled.
Azure.CosmosDB.DBAccounts.properties.enableMultipleWriteLocations Boolean Enables the account to write in multiple locations.
Azure.CosmosDB.DBAccounts.properties.enablePartitionMerge Boolean Whether Partition Merge is enabled.
Azure.CosmosDB.DBAccounts.properties.enablePerRegionPerPartitionAutoscale Boolean Whether PerRegionPerPartitionAutoscale is enabled.
Azure.CosmosDB.DBAccounts.properties.failoverPolicies Unknown An array that contains the regions ordered by their failover priorities.
Azure.CosmosDB.DBAccounts.properties.instanceId String A unique identifier assigned to the database account.
Azure.CosmosDB.DBAccounts.properties.ipRules Unknown List of IP rules.
Azure.CosmosDB.DBAccounts.properties.isVirtualNetworkFilterEnabled Boolean Whether the Virtual Network ACL rules are enabled.
Azure.CosmosDB.DBAccounts.properties.keyVaultKeyUri String The URI of the key vault.
Azure.CosmosDB.DBAccounts.properties.keysMetadata Unknown Metadata related to each access key for the given Cosmos DB database account.
Azure.CosmosDB.DBAccounts.properties.locations Unknown An array that contains all of the locations enabled for the Cosmos DB account.
Azure.CosmosDB.DBAccounts.properties.minimalTlsVersion String The minimum allowed TLS version.
Azure.CosmosDB.DBAccounts.properties.networkAclBypass String Which services are allowed to bypass firewall checks.
Azure.CosmosDB.DBAccounts.properties.networkAclBypassResourceIds Unknown List of resource IDs that are allowed to bypass firewall checks.
Azure.CosmosDB.DBAccounts.properties.privateEndpointConnections Unknown List of private endpoint connections.
Azure.CosmosDB.DBAccounts.properties.provisioningState String The status of the Cosmos DB account at the time the operation was called.
Azure.CosmosDB.DBAccounts.properties.readLocations Unknown An array that contains the read locations enabled for the Cosmos DB account.
Azure.CosmosDB.DBAccounts.properties.virtualNetworkRules Unknown List of Virtual Network ACL rules.
Azure.CosmosDB.DBAccounts.properties.writeLocations Unknown An array that contains the write locations enabled for the Cosmos DB account.

azure-keyvault-vault-update


Updates a key vault in the specified subscription. The required permissions are: Microsoft.KeyVault/vaults/read, Microsoft.KeyVault/vaults/write.

Base Command

azure-keyvault-vault-update

Input

Argument Name Description Required
vault_name Key Vault name. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The name of the resource group. Required
enable_purge_protection Whether protection against purge is enabled for this vault. This functionality is always enabled, it cannot be disabled. Possible values are: true, false. Optional
enable_soft_delete Whether soft delete is enabled for this key vault. This functionality is always enabled, it cannot be disabled. Possible values are: true, false. Optional

Context Output

Path Type Description
Azure.KeyVault.Vault.id String Resource ID.
Azure.KeyVault.Vault.name String Key Vault name.
Azure.KeyVault.Vault.type String Resource type in Azure.
Azure.KeyVault.Vault.location String Key Vault location.
Azure.KeyVault.Vault.tags Unknown Resource tags.
Azure.KeyVault.Vault.properties.sku String SKU details.
Azure.KeyVault.Vault.properties.tenantId String The Entra ID tenant ID that should be used for authenticating requests to the key vault.
Azure.KeyVault.Vault.properties.accessPolicies Unknown An array of 0 to 1024 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault’s tenant ID.
Azure.KeyVault.Vault.properties.enabledForDeployment Boolean Whether Azure Virtual Machines are allowed to retrieve certificates stored as secrets from the key vault.
Azure.KeyVault.Vault.properties.enabledForDiskEncryption Boolean Whether Azure Disk Encryption is allowed to retrieve secrets from the vault and unwrap keys.
Azure.KeyVault.Vault.properties.enabledForTemplateDeployment Boolean Whether Azure Resource Manager is allowed to retrieve secrets from the key vault.
Azure.KeyVault.Vault.properties.enableSoftDelete Boolean Whether soft delete is enabled for this key vault.
Azure.KeyVault.Vault.properties.enablePurgeProtection Boolean Whether purge protection is enabled for this key vault.
Azure.KeyVault.Vault.properties.enableRbacAuthorization Boolean Whether Azure Key Vault uses Role Based Access Control, RBAC, for authorization of data actions.
Azure.KeyVault.Vault.properties.vaultUri String The URI of the vault for performing operations on keys and secrets.
Azure.KeyVault.Vault.properties.provisioningState String The current provisioning state.
Azure.KeyVault.Vault.properties.privateEndpointConnections Unknown List of private endpoint connections associated with the key vault.
Azure.KeyVault.Vault.properties.networkAcls Unknown Rules governing the accessibility of the key vault from specific network locations.

azure-rm-resource-groups-list


Gets all resource groups for a subscription. Required Permissions: Microsoft.Resources/subscriptions/resourceGroups/read.

Base Command

azure-rm-resource-groups-list

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. 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
Azure.ResourceManagement.ResourceGroups.id String The unique identifier of the Azure Network Security Groups resource group.
Azure.ResourceManagement.ResourceGroups.name String The name of the Azure Network Security Groups resource group.
Azure.ResourceManagement.ResourceGroups.type String The type of the Azure Network Security Groups resource group.
Azure.ResourceManagement.ResourceGroups.location String The location of the Azure Network Security Groups resource group.
Azure.ResourceManagement.ResourceGroups.properties.provisioningState String The provisioning state of the Azure Network Security Groups resource group.
Azure.ResourceManagement.ResourceGroups.tags.Owner String The owner tag of the Azure Network Security Groups resource group.
Azure.ResourceManagement.ResourceGroups.tags Unknown The tags associated with the Azure Network Security Groups resource group.
Azure.ResourceManagement.ResourceGroups.tags.Name String The name tag of the Azure Network Security Groups resource group.
Azure.ResourceManagement.ResourceGroups.managedBy String The entity that manages the Azure Network Security Groups resource group.
Azure.ResourceManagement.ResourceGroups.tags.aNSG-managed-cluster-name String The ANSG managed cluster name tag associated with the Azure Network Security Groups resource group.
Azure.ResourceManagement.ResourceGroups.tags.aNSG-managed-cluster-rg String The ANSG managed cluster resource group tag associated with the Azure Network Security Groups resource group.
Azure.ResourceManagement.ResourceGroups.tags.type String The type tag associated with the Azure Network Security Groups resource group.

azure-sqldb-security-alert-policy-update


Updates a database’s security alert policy. The required permissions are: Microsoft.Sql/servers/databases/securityAlertPolicies/read, Microsoft.Sql/servers/databases/securityAlertPolicies/write.

Base Command

azure-sqldb-security-alert-policy-update

Input

Argument Name Description Required
server_name Server name. Required
db_name Database name. Required
email_account_admins_enabled Whether the alert is sent to the account administrators. Possible values are: true, false. Optional
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The name of the resource group. Required

Context Output

Path Type Description
Azure.SqlDB.SecurityAlertPolicies.id String Threat policy ID.
Azure.SqlDB.SecurityAlertPolicies.name String Threat policy name.
Azure.SqlDB.SecurityAlertPolicies.properties.state String Specifies the state of the policy, whether it is enabled or disabled or a policy has not been applied yet on the specific database.
Azure.SqlDB.SecurityAlertPolicies.properties.creationTime String Specifies the UTC creation time of the policy.
Azure.SqlDB.SecurityAlertPolicies.properties.retentionDays Number Specifies the number of days to keep in the Threat Detection audit logs.
Azure.SqlDB.SecurityAlertPolicies.properties.storageAccountAccessKey String Specifies the identifier key of the Threat Detection audit storage account.
Azure.SqlDB.SecurityAlertPolicies.properties.storageEndpoint String Specifies the blob storage endpoint.
Azure.SqlDB.SecurityAlertPolicies.properties.emailAccountAdmins Boolean Specifies that the alert is sent to the account administrators.
Azure.SqlDB.SecurityAlertPolicies.properties.emailAddresses String Specifies an array of e-mail addresses to which the alert is sent.
Azure.SqlDB.SecurityAlertPolicies.properties.disabledAlerts Unknown Specifies an array of alerts that are disabled.
Azure.SqlDB.SecurityAlertPolicies.systemData.createdAt Unknown The timestamp of resource creation (UTC).
Azure.SqlDB.SecurityAlertPolicies.systemData.createdBy Unknown The identity that created the resource.
Azure.SqlDB.SecurityAlertPolicies.systemData.createdByType Unknown The type of identity that created the resource.
Azure.SqlDB.SecurityAlertPolicies.systemData.lastModifiedAt Unknown The timestamp of resource last modification (UTC).
Azure.SqlDB.SecurityAlertPolicies.systemData.lastModifiedBy Unknown The identity that last modified the resource.
Azure.SqlDB.SecurityAlertPolicies.systemData.lastModifiedByType Unknown The type of identity that last modified the resource.

azure-vn-network-interfaces-list


Gets network interfaces in a resource group. Required permissions: Microsoft.Network/networkInterfaces/read.

Base Command

azure-vn-network-interfaces-list

Input

Argument Name Description Required
resource_group_name The resource group name. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
limit The maximum number of records to return. Default is 50. Optional
all_results Whether to retrieve all results by overriding the default limit. Possible values are: false, true. Default is false. Optional

Context Output

Path Type Description
Azure.VirtualNetworks.NetworkInterfaces.name String The network interface’s name.
Azure.VirtualNetworks.NetworkInterfaces.id String The network interface’s ID.
Azure.VirtualNetworks.NetworkInterfaces.kind String The kind of the network interface.
Azure.VirtualNetworks.NetworkInterfaces.etag String The ETag of the network interface.
Azure.VirtualNetworks.NetworkInterfaces.location String The location of the network interface.
Azure.VirtualNetworks.NetworkInterfaces.managedBy String The entity that manages the network interface.
Azure.VirtualNetworks.NetworkInterfaces.tags String The tags associated with the network interface.
Azure.VirtualNetworks.NetworkInterfaces.properties.provisioningState String The network interface’s provisioning state.
Azure.VirtualNetworks.NetworkInterfaces.properties.ipConfigurations Unknown A list of IPConfigurations of the network interface.
Azure.VirtualNetworks.NetworkInterfaces.properties.tapConfigurations List List of tap configurations.
Azure.VirtualNetworks.NetworkInterfaces.properties.allowPort25Out Boolean Whether port 25 outbound traffic is allowed.
Azure.VirtualNetworks.NetworkInterfaces.properties.nicType String The network interface card type (Standard/Basic).

azure-vn-public-ip-addresses-list


Gets public IP addresses in a resource group. Required permissions: Microsoft.Network/publicIPAddresses/read.

Base Command

azure-vn-public-ip-addresses-list

Input

Argument Name Description Required
resource_group_name The resource group name. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
limit The maximum number of records to return. Default is 50. Optional
all_results Whether to retrieve all results by overriding the default limit. Possible values are: false, true. Default is false. Optional

Context Output

Path Type Description
Azure.VirtualNetworks.PublicIPAddresses.name String The public IP address’s name.
Azure.VirtualNetworks.PublicIPAddresses.id String The public IP address’s ID.
Azure.VirtualNetworks.PublicIPAddresses.location String The location of the public IP address.
Azure.VirtualNetworks.PublicIPAddresses.sku String The public IP address’s SKU.
Azure.VirtualNetworks.PublicIPAddresses.type String The type of the public IP address.
Azure.VirtualNetworks.PublicIPAddresses.etag String The public IP address’s ETag.
Azure.VirtualNetworks.PublicIPAddresses.properties.provisioningState String The public IP address’s provisioning state.
Azure.VirtualNetworks.PublicIPAddresses.properties.publicIPAddressVersion String The public IP address’s version.
Azure.VirtualNetworks.PublicIPAddresses.properties.ipAddress String The public IP address’s IP address.
Azure.VirtualNetworks.PublicIPAddresses.properties.publicIPAllocationMethod String The public IP address’s allocation method.
Azure.VirtualNetworks.PublicIPAddresses.properties.resourceGuid String The public IP address’s resource GUID.
Azure.VirtualNetworks.PublicIPAddresses.sku.name String The public IP address’s SKU name.
Azure.VirtualNetworks.PublicIPAddresses.sku.tier String The public IP address’s SKU tier.
Azure.VirtualNetworks.PublicIPAddresses.properties.ipConfiguration String The reference to another IP configuration associated with this resource.

azure-vn-security-groups-list


List all network security groups. Required permissions: Microsoft.Network/networkSecurityGroups/read.

Base Command

azure-vn-security-groups-list

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group name. Required

Context Output

Path Type Description
Azure.VirtualNetworks.SecurityGroups.name String The security group’s name.
Azure.VirtualNetworks.SecurityGroups.id String The security group’s ID.
Azure.VirtualNetworks.SecurityGroups.type String The security group’s type.
Azure.VirtualNetworks.SecurityGroups.location String The security group’s location.
Azure.VirtualNetworks.SecurityGroups.etag String The security group’s ETag.
Azure.VirtualNetworks.SecurityGroups.tags String The security group’s tags.
Azure.VirtualNetworks.SecurityGroups.properties.defaultSecurityRules List The default security rules.
Azure.VirtualNetworks.SecurityGroups.properties.networkInterfaces List The network interfaces.
Azure.VirtualNetworks.SecurityGroups.properties.provisioningState String The provisioning state.
Azure.VirtualNetworks.SecurityGroups.properties.resourceGuid String The resource GUID.
Azure.VirtualNetworks.SecurityGroups.properties.SecurityRules List The security rules.

azure-vn-security-rule-create


Create a security rule. Required permissions: Microsoft.Network/networkSecurityGroups/securityRules/read, Microsoft.Network/networkSecurityGroups/securityRules/write.

Base Command

azure-vn-security-rule-create

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name Resource group name. Required
security_group_name The name of the security group. Required
security_rule_name The name of the rule to create. Required
direction The direction of the rule. Possible values are: Inbound, Outbound. Required
access Whether to allow the traffic. Possible values are: Allow, Deny. Default is Allow. Optional
protocol The protocol on which to apply the rule. Possible values are: Any, TCP, UDP, ICMP. Default is Any. Optional
source The source IP address range from which incoming traffic is allowed or denied by this rule. Possible values are “Any”, an IP address range, an application security group, or a default tag. Default is Any. Optional
priority The priority of the rule, with a value between 100 and 4096. Each rule in the collection must have a unique priority number. Lower numbers indicate higher priority. Required
source_ports The source ports from which traffic is allowed or denied by this rule. Provide a single port, such as 80; a port range, such as 1024-65535; or a comma-separated list of single ports and/or port ranges, such as 80,1024-65535. Use an asterisk (*) to allow traffic on any port. Default is *. Optional
destination The destination IP address range for outgoing traffic that is allowed or denied by this rule. The destination filter can be “Any”, an IP address range, an application security group, or a default tag. Default is Any. Optional
destination_ports The destination ports from which traffic is allowed or denied by this rule. Provide a single port, such as 80; a port range, such as 1024-65535; or a comma-separated list of single ports and/or port ranges, such as 80,1024-65535. Use an asterisk () to allow traffic on any port. Default is. Optional
description A description to add to the rule. Optional

Context Output

Path Type Description
Azure.VirtualNetworks.SecurityRules.name String The rule’s name.
Azure.VirtualNetworks.SecurityRules.id String The rule’s ID.
Azure.VirtualNetworks.SecurityRules.etag String The rule’s ETag.
Azure.VirtualNetworks.SecurityRules.type String The rule’s type.
Azure.VirtualNetworks.SecurityRules.properties.provisioningState String The rule’s provisioning state.
Azure.VirtualNetworks.SecurityRules.properties.protocol String The protocol, which can be “TCP”, “UDP”, “ICMP”, or “*”.
Azure.VirtualNetworks.SecurityRules.properties.sourcePortRange String For a single port, the source port or a range of ports. For multiple ports, sourcePortRanges is used instead.
Azure.VirtualNetworks.SecurityRules.properties.sourcePortRanges String For multiple ports, a list of ports. For a single port, sourcePortRange is used instead.
Azure.VirtualNetworks.SecurityRules.properties.destinationPortRange String For a single port, the destination port or range of ports. For multiple ports, destinationPortRanges is used instead.
Azure.VirtualNetworks.SecurityRules.properties.destinationPortRanges String For multiple ports, a list of destination ports. For a single port, destinationPortRange is used instead.
Azure.VirtualNetworks.SecurityRules.properties.sourceAddressPrefix String The source address.
Azure.VirtualNetworks.SecurityRules.properties.destinationAddressPrefix String The destination address.
Azure.VirtualNetworks.SecurityRules.properties.access String The rule’s access. Can be “Allow” or “Deny”.
Azure.VirtualNetworks.SecurityRules.properties.priority Number The rule’s priority, ranging from 100 to 4096.
Azure.VirtualNetworks.SecurityRules.properties.direction String The rule’s direction, which can be “Inbound” or “Outbound”.

azure-vn-network-interface-update


Updates a network interface. Required Permissions: Microsoft.Network/networkInterfaces/read, Microsoft.Network/networkInterfaces/write, Microsoft.Network/virtualNetworks/subnets/join/action, Microsoft.Network/publicIPAddresses/join/action, Microsoft.Network/networkSecurityGroups/join/action, Microsoft.Network/loadBalancers/backendAddressPools/join/action.

Base Command

azure-vn-network-interface-update

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group to which the network interface belongs. Required
network_interface_name The name of the network interface to update. Required
location The location of the network security group. Possible values are: australiacentral, australiacentral2, australiaeast, australiasoutheast, brazilsouth, brazilsoutheast, brazilus, canadacentral, canadaeast, centralindia, centralus, centraluseuap, eastasia, eastus, eastus2, eastus2euap, francecentral, francesouth, germanynorth, germanywestcentral, israelcentral, italynorth, japaneast, japanwest, jioindiacentral, jioindiawest, koreacentral, koreasouth, malaysiasouth, mexicocentral, newzealandnorth, northcentralus, northeurope, norwayeast, norwaywest, polandcentral, qatarcentral, southafricanorth, southafricawest, southcentralus, southeastasia, southindia, spaincentral, swedencentral, swedensouth, switzerlandnorth, switzerlandwest, uaecentral, uaenorth, uksouth, ukwest, westcentralus, westeurope, westindia, westus, westus2, westus3, australiaeastfoundational, austriaeast, chilecentral, eastusslv, indonesiacentral, israelnorthwest, malaysiawest, southcentralus2, southeastus, southeastus3, southwestus, usgovarizona, usgovtexas, usgovvirginia. Optional
enable_ip_forwarding Whether to enable IP forwarding for the network interface. Possible values are: true, false. Optional
enable_accelerate_networking Whether the network interface is configured for accelerated networking. Possible values are: true, false. Optional
auxiliary_mode The auxiliary mode of the Network Interface resource. Possible values are: MaxConnections, Floating, AcceleratedConnections. Optional
auxiliary_sku The auxiliary SKU of the Network Interface resource. Possible values are: A1, A2, A4, A8. Optional
dns_servers A comma-separated list of DNS server IP addresses for the network interface. Optional
internal_dns_name_label The internal DNS name label for the network interface. Optional
network_security_group_name The name of the network security group. Optional
remove_network_security_group Whether to remove the property networkSecurityGroup from the network interface. Possible values are: yes, no. Default is no. Optional
nic_type The type of Network Interface resource. Possible values are: Standard, Elastic. Optional

Context Output

Path Type Description
Azure.VirtualNetworks.NetworkInterfaces.id String The network interface ID.
Azure.VirtualNetworks.NetworkInterfaces.name String The network interface name.
Azure.VirtualNetworks.NetworkInterfaces.location String The Azure region where the network interface is deployed.
Azure.VirtualNetworks.NetworkInterfaces.etag String A unique read-only string that changes whenever the network interface resource is updated.
Azure.VirtualNetworks.NetworkInterfaces.type String The resource type.
Azure.VirtualNetworks.NetworkInterfaces.tags Unknown The resource tags.
Azure.VirtualNetworks.NetworkInterfaces.extendedLocation Unknown The extended location of the network interface.
Azure.VirtualNetworks.NetworkInterfaces.properties.provisioningState String The current provisioning state of the network interface (e.g., Succeeded, Updating, Failed).
Azure.VirtualNetworks.NetworkInterfaces.properties.ipConfigurations Unknown The list of IP configurations for the network interface.
Azure.VirtualNetworks.NetworkInterfaces.properties.dnsSettings Unknown The DNS configuration of the network interface, including DNS servers and domain name.
Azure.VirtualNetworks.NetworkInterfaces.properties.macAddress String The MAC address of the network interface.
Azure.VirtualNetworks.NetworkInterfaces.properties.enableIPForwarding Boolean Whether IP forwarding is enabled for the network interface.
Azure.VirtualNetworks.NetworkInterfaces.properties.enableAcceleratedNetworking Boolean Whether accelerated networking is enabled for the network interface.
Azure.VirtualNetworks.NetworkInterfaces.properties.networkSecurityGroup Unknown The network security group associated with the network interface.
Azure.VirtualNetworks.NetworkInterfaces.properties.primary Boolean Whether this is a primary network interface on a virtual machine.
Azure.VirtualNetworks.NetworkInterfaces.properties.virtualMachine Unknown The reference to a virtual machine.
Azure.VirtualNetworks.NetworkInterfaces.properties.nicType String The type of network interface (Standard or Elastic).
Azure.VirtualNetworks.NetworkInterfaces.properties.auxiliaryMode Unknown The auxiliary mode of the Network Interface resource.
Azure.VirtualNetworks.NetworkInterfaces.properties.auxiliarySku Unknown The auxiliary SKU of the Network Interface resource.
Azure.VirtualNetworks.NetworkInterfaces.properties.defaultOutboundConnectivityEnabled Boolean Whether default outbound connectivity for nic was configured.
Azure.VirtualNetworks.NetworkInterfaces.properties.disableTcpStateTracking Boolean Whether to disable TCP state tracking.
Azure.VirtualNetworks.NetworkInterfaces.properties.dscpConfiguration Unknown A reference to the DSCP configuration to which the network interface is linked.
Azure.VirtualNetworks.NetworkInterfaces.properties.hostedWorkloads Unknown A list of references to linked BareMetal resources.
Azure.VirtualNetworks.NetworkInterfaces.properties.migrationPhase Unknown The migration phase of the Network Interface resource.
Azure.VirtualNetworks.NetworkInterfaces.properties.privateEndpoint Unknown A reference to the private endpoint to which the network interface is linked.
Azure.VirtualNetworks.NetworkInterfaces.properties.privateLinkService Unknown The privatelinkservice of the network interface resource.
Azure.VirtualNetworks.NetworkInterfaces.properties.resourceGuid String The resource GUID property of the network interface resource.
Azure.VirtualNetworks.NetworkInterfaces.properties.tapConfigurations Unknown A list of TapConfigurations of the network interface.
Azure.VirtualNetworks.NetworkInterfaces.properties.vnetEncryptionSupported Boolean Whether the virtual machine this nic is attached to supports encryption.
Azure.VirtualNetworks.NetworkInterfaces.properties.workloadType String The workload type of the NetworkInterface for BareMetal resources.

azure-vn-security-rule-delete


Delete a security rule. Required permissions: Microsoft.Network/networkSecurityGroups/securityRules/delete.

Base Command

azure-vn-security-rule-delete

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name Resource group name. Required
security_group_name The name of the security group. Required
security_rule_name The name of the rule to delete. Required

Context Output

There is no context output for this command.

azure-vn-security-rule-get


Get a specific rule. Required permissions: Microsoft.Network/networkSecurityGroups/securityRules/read.

Base Command

azure-vn-security-rule-get

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name Resource group name. Required
security_group_name The name of the security group. Required
security_rule_name The name of the rule to get. Required

Context Output

Path Type Description
Azure.VirtualNetworks.SecurityRules.name String The rule’s name.
Azure.VirtualNetworks.SecurityRules.id String The rule’s ID.
Azure.VirtualNetworks.SecurityRules.location String The rule’s location.
Azure.VirtualNetworks.SecurityRules.etag String The rule’s ETag.
Azure.VirtualNetworks.SecurityRules.type String The rule’s type.
Azure.VirtualNetworks.SecurityRules.properties.provisioningState String The rule’s provisioning state.
Azure.VirtualNetworks.SecurityRules.properties.protocol String The protocol, which can be “TCP”, “UDP”, “ICMP”, or “*”.
Azure.VirtualNetworks.SecurityRules.properties.sourcePortRange String For a single port, the source port or a range of ports. For multiple ports, sourcePortRanges is used instead.
Azure.VirtualNetworks.SecurityRules.properties.sourcePortRanges String For multiple ports, a list of ports. For a single port, sourcePortRange is used instead.
Azure.VirtualNetworks.SecurityRules.properties.destinationPortRange String For a single port, the destination port or range of ports. For multiple ports, destinationPortRanges is used instead.
Azure.VirtualNetworks.SecurityRules.properties.destinationPortRanges String For multiple ports, a list of destination ports. For a single port, destinationPortRange is used instead.
Azure.VirtualNetworks.SecurityRules.properties.sourceAddressPrefix String The source address.
Azure.VirtualNetworks.SecurityRules.properties.destinationAddressPrefix String The destination address.
Azure.VirtualNetworks.SecurityRules.properties.access String The rule’s access. Can be “Allow” or “Deny”.
Azure.VirtualNetworks.SecurityRules.properties.priority Number The rule’s priority, ranging from 100 to 4096.
Azure.VirtualNetworks.SecurityRules.properties.direction String The rule’s direction, which can be “Inbound” or “Outbound”.

azure-vn-security-rule-update


Update a security rule. If one does not exist, it will be created. Required permissions: Microsoft.Network/networkSecurityGroups/securityRules/read, Microsoft.Network/networkSecurityGroups/securityRules/write.

Base Command

azure-vn-security-rule-update

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The name of the resource group. Required
security_group_name The name of the security group. Required
security_rule_name The name of the rule to be updated. Required
direction The direction of the rule. Possible values are: Inbound, Outbound. Optional
protocol The protocol on which to apply the rule. Possible values are: Any, TCP, UDP, ICMP. Optional
source The source IP address range from which incoming traffic will be allowed or denied by this rule. Possible values are “Any”, an IP address range, an application security group, or a default tag. Optional
priority The priority by which the rules will be processed. The lower the number, the higher the priority. We recommend leaving gaps between rules - 100, 200, 300, etc. - so that it is easier to add new rules without having to edit existing rules. Optional
source_ports The source ports from which traffic is allowed or denied by this rule. Provide a single port, such as 80; a port range, such as 1024-65535; or a comma-separated list of single ports and/or port ranges, such as 80,1024-65535. Use an asterisk (*) to allow traffic on any port. Optional
destination The destination IP address range for outgoing traffic that is allowed or denied by this rule. The destination filter can be “Any”, an IP address range, an application security group, or a default tag. Optional
destination_ports The destination ports from which traffic is allowed or denied by this rule. Provide a single port, such as 80; a port range, such as 1024-65535; or a comma-separated list of single ports and/or port ranges, such as 80,1024-65535. Use an asterisk (*) to allow traffic on any port. Optional
description A description to add to the rule. Optional
access The network traffic is allowed or denied. Possible values are: Allow, Deny. Optional

Context Output

Path Type Description
Azure.VirtualNetworks.SecurityRules.name String The rule’s name.
Azure.VirtualNetworks.SecurityRules.id String The rule’s ID.
Azure.VirtualNetworks.SecurityRules.etag String The rule’s ETag.
Azure.VirtualNetworks.SecurityRules.type String The rule’s type.
Azure.VirtualNetworks.SecurityRules.properties.provisioningState String The rule’s provisioning state.
Azure.VirtualNetworks.SecurityRules.properties.protocol String The protocol, which can be “TCP”, “UDP”, “ICMP”, or “*”.
Azure.VirtualNetworks.SecurityRules.properties.sourcePortRange String For a single port, the source port or a range of ports. For multiple ports, sourcePortRanges is used instead.
Azure.VirtualNetworks.SecurityRules.properties.sourcePortRanges String For multiple ports, a list of ports. For a single port, sourcePortRange is used instead.
Azure.VirtualNetworks.SecurityRules.properties.destinationPortRange String For a single port, the destination port or range of ports. For multiple ports, destinationPortRanges is used instead.
Azure.VirtualNetworks.SecurityRules.properties.destinationPortRanges String For multiple ports, a list of destination ports. For a single port, destinationPortRange is used instead.
Azure.VirtualNetworks.SecurityRules.properties.sourceAddressPrefix String The source address.
Azure.VirtualNetworks.SecurityRules.properties.destinationAddressPrefix String The destination address.
Azure.VirtualNetworks.SecurityRules.properties.access String The rule’s access. Can be “Allow” or “Deny”.
Azure.VirtualNetworks.SecurityRules.properties.priority Number The rule’s priority, ranging from 100 to 4096.
Azure.VirtualNetworks.SecurityRules.properties.direction String The rule’s direction, which can be “Inbound” or “Outbound”.

azure-vn-security-rules-list


Gets all security rules in a network security group. Required permissions: Microsoft.Network/networkSecurityGroups/securityRules/read.

Base Command

azure-vn-security-rules-list

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name Resource group name. Required
network_security_group_name The name of the network security group. Required

Context Output

Path Type Description
Azure.VirtualNetworks.SecurityRules.name String The rule’s name.
Azure.VirtualNetworks.SecurityRules.id String The rule’s ID.
Azure.VirtualNetworks.SecurityRules.properties.provisioningState String The rule’s provisioning state.
Azure.VirtualNetworks.SecurityRules.properties.protocol String The protocol, which can be “TCP”, “UDP”, “ICMP”, or “*”.
Azure.VirtualNetworks.SecurityRules.properties.sourcePortRange String For a single port, the source port or a range of ports.
Azure.VirtualNetworks.SecurityRules.properties.destinationPortRange String For a single port, the destination port or range of ports.
Azure.VirtualNetworks.SecurityRules.properties.sourceAddressPrefix String The source address.
Azure.VirtualNetworks.SecurityRules.properties.destinationAddressPrefix String The destination address.
Azure.VirtualNetworks.SecurityRules.properties.access String The rule’s access. Can be “Allow” or “Deny”.
Azure.VirtualNetworks.SecurityRules.properties.priority Number The rule’s priority, ranging from 100 to 4096.
Azure.VirtualNetworks.SecurityRules.properties.direction String The rule’s direction, which can be “Inbound” or “Outbound”.

Base Command

azure-vn-network-interface-get


Gets the properties of a given network interface. Required permissions: Microsoft.Network/networkInterfaces/read.

Base Command

azure-vn-network-interface-get

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group to which the network interface belongs. Required
network_interface_name The name of the network interface you want to view the details of. Required

Context Output

Path Type Description
Azure.VirtualNetworks.NetworkInterfaces.properties.ipConfigurations Unknown The interface public IP address ID.
Azure.VirtualNetworks.NetworkInterfaces.properties.macAddress String The interface MAC address.
Azure.VirtualNetworks.NetworkInterfaces.name String The interface name.
Azure.VirtualNetworks.NetworkInterfaces.location String The interface location.
Azure.VirtualNetworks.NetworkInterfaces.id String The interface ID.
Azure.VirtualNetworks.NetworkInterfaces.etag String A unique read-only string that changes whenever the network interface resource is updated.
Azure.VirtualNetworks.NetworkInterfaces.kind String The type of the network interface resource, used for Azure internal classification.
Azure.VirtualNetworks.NetworkInterfaces.properties.tapConfigurations String The list of tap configurations attached to the network interface for traffic mirroring.
Azure.VirtualNetworks.NetworkInterfaces.properties.allowPort25Out String Indicates whether outbound traffic on port 25 (SMTP) is allowed from this network interface.
Azure.VirtualNetworks.NetworkInterfaces.properties.nicType String Specifies the type of network interface, such as Standard or Elastic.
Azure.VirtualNetworks.NetworkInterfaces.properties.provisioningState String The current provisioning state of the network interface (e.g., Succeeded, Updating, Failed).
Azure.VirtualNetworks.NetworkInterfaces.properties.dnsSettings String The DNS configuration of the network interface, including DNS servers and domain name.
Azure.VirtualNetworks.NetworkInterfaces.properties.enableIPForwarding String Indicates whether IP forwarding is enabled for the network interface.

azure-vn-public-ip-address-get


Gets the properties of a given public IP address. Permissions required: Microsoft.Network/publicIPAddresses/read.

Base Command

azure-vn-public-ip-address-get

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group to which the IP address belongs. Required
address_name The IP address name. Required

Context Output

Path Type Description
Azure.VirtualNetworks.PublicIPAddresses.name String The public IP address’s name.
Azure.VirtualNetworks.PublicIPAddresses.id String The public IP address’s ID.
Azure.VirtualNetworks.PublicIPAddresses.location String The location of the public IP address.
Azure.VirtualNetworks.PublicIPAddresses.sku String The public IP address’s SKU.
Azure.VirtualNetworks.PublicIPAddresses.type String The type of the public IP address.
Azure.VirtualNetworks.PublicIPAddresses.etag String The public IP address’s ETag.
Azure.VirtualNetworks.PublicIPAddresses.properties.provisioningState String The public IP address’s provisioning state.
Azure.VirtualNetworks.PublicIPAddresses.properties.publicIPAddressVersion String The public IP address’s version.
Azure.VirtualNetworks.PublicIPAddresses.properties.ipAddress String The public IP address’s IP address.
Azure.VirtualNetworks.PublicIPAddresses.properties.publicIPAllocationMethod String The public IP address’s allocation method.
Azure.VirtualNetworks.PublicIPAddresses.properties.resourceGuid String The public IP address’s resource GUID.
Azure.VirtualNetworks.PublicIPAddresses.sku.name String The public IP address’s SKU name.
Azure.VirtualNetworks.PublicIPAddresses.sku.tier String The public IP address’s SKU tier.
Azure.VirtualNetworks.PublicIPAddresses.properties.ipConfiguration String The reference to another IP configuration associated with this resource.

azure-storage-blob-container-update


Updates container properties as specified in request body. Properties not mentioned in the request will be unchanged. Update fails if the specified container doesn’t already exist. Required permissions: Microsoft.Storage/storageAccounts/blobServices/containers/write.

Base Command

azure-storage-blob-container-update

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group name. Required
account_name The storage account name. Required
container_name The container name. Required
default_encryption_scope Uses the specified encryption scope by default for all writes to the container. Optional
deny_encryption_scope_override Blocks overriding the container’s default encryption scope. Possible values are: true, false. Optional
public_access Specifies the access level. Possible values are: Blob, Container, None. Optional

Context Output

Path Type Description
Azure.Storage.BlobContainers.id String Fully qualified resource ID for the resource.
Azure.Storage.BlobContainers.name String The name of the resource.
Azure.Storage.BlobContainers.type String The resource type.
Azure.Storage.BlobContainers.properties.metadata String A name-value pair to associate with the container as metadata.
Azure.Storage.BlobContainers.properties.publicAccess String Specifies whether data in the container may be accessed publicly and the access level.
Azure.Storage.BlobContainers.properties.hasImmutabilityPolicy Boolean The hasImmutabilityPolicy property is set to true by SRP if an ImmutabilityPolicy exists for this container, and false if it does not.
Azure.Storage.BlobContainers.properties.hasLegalHold Boolean The hasLegalHold property is set to true by SRP if at least one legal hold tag exists, and false if all tags are cleared.

azure-storage-blob-create


Create a new Blob under the specified Container. Required permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write.

Base Command

azure-storage-blob-create

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group name. Required
account_name The storage account name. Required
container_name The name of the Blob Container. Required
file_entry_id The entry ID of the file to upload as a new blob. Available from the war room while the context data contains file output. Required
blob_name The name of the Blob to create. Default is the file name. Optional

Context Output

There is no context output for this command.

azure-storage-blob-get


Retrieve a Blob from a Container. Required permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read.

Base Command

azure-storage-blob-get

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group name. Required
account_name The storage account name. Required
container_name The name of the Blob Container. Required
blob_name The name of the Blob to retrieve. Required

Context Output

Path Type Description
File.Size String The size of the file.
File.SHA1 String The SHA1 hash of the file.
File.SHA256 String The SHA256 hash of the file.
File.Name String The name of the file.
File.SSDeep String The SSDeep hash of the file.
File.EntryID String The entry ID of the file.
File.Info String File information.
File.Type String The file type.
File.MD5 String The MD5 hash of the file.
File.Extension String The file extension.

azure-storage-blob-tag-set


Updates the tags for the specified Blob. The command can replace the entire tags of the Blob and can be used to remove tags. Required permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/write.

Base Command

azure-storage-blob-tag-set

Input

Argument Name Description Required
container_name The name of the Blob Container. Required
blob_name The name of the blob. Required
tags Tags fields in JSON format: {“tag-name-1”: “tag-value-1”, “tag-name-2”: “tag-value-2”}. The tags fields may contain at most 10 tags. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group name. Required
account_name The storage account name. Required
append Whether to append tags to the existing tags or not. Default is false. Possible values are: true, false. Optional

Context Output

There is no context output for this command.

azure-storage-blob-property-set


Set Blob properties. Required permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write.

Base Command

azure-storage-blob-property-set

Input

Argument Name Description Required
container_name The name of the Blob Container. Required
blob_name The name of the blob. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group name. Required
account_name The storage account name. Required
content_type Blob content type. Indicates the media type of the blob. Optional
content_md5 Blob MD5 hash value. Can be used by the client to check for content integrity. Optional
content_encoding Blob content encoding. Used to specify the compression algorithm of the blob content. Possible values are: identity, gzip, deflate, br, compress, zstd, aes128gcm, dcb, dcz, exi, pack200-gzip, x-compress, x-gzip. Optional
content_language Blob content language. Describes the human languages of the blob content. Optional
content_disposition Blob content disposition. Conveys additional information about how to process the response payload, and also can be used to attach additional metadata. Optional
cache_control Modifies the cache control string for the blob. Indicates directives for caching in both requests and responses. Optional
request_id Request ID generated by the client and recorded in the analytics logs when storage analytics logging is enabled. Optional
lease_id Required if the blob has an active lease. Optional

Context Output

There is no context output for this command.

azure-appservice-webapp-config-update


Updates the configuration settings of an existing Azure Web App. Required permissions: Microsoft.Web/sites/config/write, Microsoft.Web/sites/config/read.

Base Command

azure-appservice-webapp-config-update

Input

Argument Name Description Required
resource_group_name The resource group name. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
name Name of the Web App. Required
http20_enabled Configures a web site to allow clients to connect over http2.0. Possible values are: true, false. Optional
remote_debugging_enabled True if remote debugging is enabled; otherwise, false. Possible values are: true, false. Optional
min_tls_version Configures the minimum version of TLS required for SSL requests. Possible values are: 1.0, 1.1, 1.2, 1.3. Optional

Context Output

Path Type Description
Azure.AppService.WebAppConfiguration.id String Resource ID.
Azure.AppService.WebAppConfiguration.name String Resource name.
Azure.AppService.WebAppConfiguration.type String Resource type.
Azure.AppService.WebAppConfiguration.location String Resource location.
Azure.AppService.WebAppConfiguration.properties.numberOfWorkers Number Number of workers.
Azure.AppService.WebAppConfiguration.properties.defaultDocuments Unknown List of default documents.
Azure.AppService.WebAppConfiguration.properties.netFrameworkVersion String .NET Framework version.
Azure.AppService.WebAppConfiguration.properties.phpVersion String PHP version.
Azure.AppService.WebAppConfiguration.properties.pythonVersion String Python version.
Azure.AppService.WebAppConfiguration.properties.nodeVersion String Node.js version.
Azure.AppService.WebAppConfiguration.properties.powerShellVersion String PowerShell version.
Azure.AppService.WebAppConfiguration.properties.linuxFxVersion String Linux app framework and version.
Azure.AppService.WebAppConfiguration.properties.windowsFxVersion String Windows container image name.
Azure.AppService.WebAppConfiguration.properties.requestTracingEnabled Boolean Indicates whether request tracing is enabled.
Azure.AppService.WebAppConfiguration.properties.remoteDebuggingEnabled Boolean Indicates whether remote debugging is enabled.
Azure.AppService.WebAppConfiguration.properties.remoteDebuggingVersion String Remote debugging version.
Azure.AppService.WebAppConfiguration.properties.http20Enabled Boolean Indicates whether HTTP/2 is enabled.
Azure.AppService.WebAppConfiguration.properties.minTlsVersion String Minimum TLS version required.
Azure.AppService.WebAppConfiguration.properties.ftpsState String State of FTP / FTPS service.
Azure.AppService.WebAppConfiguration.properties.webSocketsEnabled Boolean Indicates whether WebSockets are enabled.
Azure.AppService.WebAppConfiguration.properties.alwaysOn Boolean Indicates whether Always On is enabled.
Azure.AppService.WebAppConfiguration.properties.managedPipelineMode String Managed pipeline mode.
Azure.AppService.WebAppConfiguration.properties.loadBalancing String Site load balancing mode.
Azure.AppService.WebAppConfiguration.properties.autoHealEnabled Boolean Indicates whether Auto Heal is enabled.
Azure.AppService.WebAppConfiguration.properties.autoHealRules Unknown Auto Heal rules configuration.
Azure.AppService.WebAppConfiguration.properties.cors Unknown Cross-Origin Resource Sharing (CORS) settings.
Azure.AppService.WebAppConfiguration.properties.apiDefinition.url String URL of the API definition.
Azure.AppService.WebAppConfiguration.properties.apiManagementConfig.id String Azure API management integration ID.

azure-appservice-webapp-auth-settings-update


Updates the authentication and authorization settings of an existing Azure Web App. Required permissions: Microsoft.Web/sites/config/read, Microsoft.Web/sites/config/write.

Base Command

azure-appservice-webapp-auth-settings-update

Input

Argument Name Description Required
resource_group_name The resource group name. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
name Name of the Web App. Required
enabled True if the Authentication / Authorization feature is enabled for the current app; otherwise, false. Possible values are: true, false. Optional

Context Output

Path Type Description
Azure.AppService.WebAppAuthSettings.id String Resource ID.
Azure.AppService.WebAppAuthSettings.name String Resource Name.
Azure.AppService.WebAppAuthSettings.type String Resource type.
Azure.AppService.WebAppAuthSettings.properties.enabled Boolean Indicates whether Authentication/Authorization is enabled for the app.
Azure.AppService.WebAppAuthSettings.properties.runtimeVersion String The RuntimeVersion of the Authentication/Authorization feature.
Azure.AppService.WebAppAuthSettings.properties.unauthenticatedClientAction String The action to take when an unauthenticated client attempts to access the app.
Azure.AppService.WebAppAuthSettings.properties.tokenStoreEnabled Boolean Indicates whether the Azure App Service Authentication platform’s token store is enabled.
Azure.AppService.WebAppAuthSettings.properties.allowedExternalRedirectUrls Unknown External URLs that are allowed to be redirected to as part of logging in or logging out of the app.
Azure.AppService.WebAppAuthSettings.properties.defaultProvider String The default authentication provider to use when multiple providers are configured.
Azure.AppService.WebAppAuthSettings.properties.clientId String The Client ID of the app used for AAD login.
Azure.AppService.WebAppAuthSettings.properties.clientSecret String The client secret associated with the AAD app.
Azure.AppService.WebAppAuthSettings.properties.clientSecretSettingName String The app setting that contains the client secret.
Azure.AppService.WebAppAuthSettings.properties.issuer String The OpenID Connect Issuer URI that represents the entity that issues access tokens.
Azure.AppService.WebAppAuthSettings.properties.allowedAudiences Unknown The list of audiences that can receive the authentication tokens.
Azure.AppService.WebAppAuthSettings.properties.additionalLoginParams Unknown Additional parameters to send to the authentication provider.
Azure.AppService.WebAppAuthSettings.properties.isAadAutoProvisioned Boolean True if AAD is auto-provisioned; otherwise false.
Azure.AppService.WebAppAuthSettings.properties.googleClientId String The Client ID of the app used for Google login.
Azure.AppService.WebAppAuthSettings.properties.googleClientSecret String The client secret associated with the Google app.
Azure.AppService.WebAppAuthSettings.properties.googleClientSecretSettingName String The app setting that contains the client secret.
Azure.AppService.WebAppAuthSettings.properties.facebookAppId String The App ID of the Facebook app used for login.
Azure.AppService.WebAppAuthSettings.properties.facebookAppSecret String The app secret associated with the Facebook app.
Azure.AppService.WebAppAuthSettings.properties.facebookAppSecretSettingName String The app setting that contains the Facebook app secret.
Azure.AppService.WebAppAuthSettings.properties.twitterConsumerKey String The OAuth 1.0a consumer key of the Twitter application used for login.
Azure.AppService.WebAppAuthSettings.properties.twitterConsumerSecret String The consumer secret associated with the Twitter application.
Azure.AppService.WebAppAuthSettings.properties.twitterConsumerSecretSettingName String The app setting that contains the Twitter consumer secret.
Azure.AppService.WebAppAuthSettings.properties.microsoftAccountClientId String The OAuth 2.0 client ID for the Microsoft account provider.
Azure.AppService.WebAppAuthSettings.properties.microsoftAccountClientSecret String The client secret for the Microsoft account provider.
Azure.AppService.WebAppAuthSettings.properties.microsoftAccountClientSecretSettingName String The app setting that contains the Microsoft account client secret.
Azure.AppService.WebAppAuthSettings.properties.appleClientId String The client ID for the Apple provider.
Azure.AppService.WebAppAuthSettings.properties.appleClientSecret String The client secret for the Apple provider.
Azure.AppService.WebAppAuthSettings.properties.appleClientSecretSettingName String The app setting that contains the Apple provider client secret.
Azure.AppService.WebAppAuthSettings.properties.authFilePath String The path to the authentication configuration file.

azure-compute-disk-update


Updates a disk. Required permissions: Microsoft.Compute/disks/read, Microsoft.Compute/disks/write.

Base Command

azure-compute-disk-update

Input

Argument Name Description Required
resource_group_name The resource group name. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
disk_name The name of the managed disk that is being created. Supported characters for the name are a-z, A-Z, 0-9, _ and -. The maximum name length is 80 characters. Required
public_network_access Policy for controlling export on the disk. Possible values are: Disabled, Enabled. Optional
network_access_policy Policy for accessing the disk via network. Possible values are: AllowAll, AllowPrivate, DenyAll. Optional
data_access_auth_mode Additional authentication requirements when exporting or uploading to a disk or snapshot. Possible values are: AzureActiveDirectory. Optional

Context Output

Path Type Description
Azure.Compute.Disks.id String Resource ID of the disk.
Azure.Compute.Disks.name String Name of the disk.
Azure.Compute.Disks.type String Type of the resource.
Azure.Compute.Disks.location String Location of the disk.
Azure.Compute.Disks.tags Unknown Resource tags.
Azure.Compute.Disks.managedBy String ARM ID of the resource that manages the disk.
Azure.Compute.Disks.sku unknown The disk SKU name.
Azure.Compute.Disks.zones unknown A list of availability zones.
Azure.Compute.Disks.properties.timeCreated String The time when the disk was created.
Azure.Compute.Disks.properties.diskSizeGB Number Size of the disk in GB.
Azure.Compute.Disks.properties.diskIopsReadWrite Number The number of IOPS allowed for this disk.
Azure.Compute.Disks.properties.diskMBpsReadWrite Number The bandwidth allowed for this disk in MBps.
Azure.Compute.Disks.properties.diskIOPSReadOnly Number The number of read-only IOPS for this disk.
Azure.Compute.Disks.properties.diskMBpsReadOnly Number The read-only bandwidth for this disk in MBps.
Azure.Compute.Disks.properties.diskSizeBytes Number The size of the disk in bytes.
Azure.Compute.Disks.properties.networkAccessPolicy String Policy for accessing the disk via network.
Azure.Compute.Disks.properties.publicNetworkAccess String Policy for export on the disk.
Azure.Compute.Disks.properties.burstingEnabled Boolean Whether bursting is enabled on the disk.
Azure.Compute.Disks.properties.optimization String The disk optimization setting.
Azure.Compute.Disks.properties.diskState String The current state of the disk.
Azure.Compute.Disks.properties.supportedCapabilities unknown Supported capabilities of the disk.
Azure.Compute.Disks.properties.supportedPerformanceTiers unknown Supported performance tiers of the disk.
Azure.Compute.Disks.properties.supportedDiskTypes unknown Supported disk types for the disk.
Azure.Compute.Disks.properties.provisioningState unknown The provisioning state of the disk.
Azure.Compute.Disks.properties.timeModified unknown The time when the disk was last modified.
Azure.Compute.Disks.properties.diskAccessId String The ARM ID of the DiskAccess resource.
Azure.Compute.Disks.properties.networkProfile unknown The network profile of the disk.
Azure.Compute.Disks.properties.creationData unknown Disk creation data.
Azure.Compute.Disks.properties.encryption unknown Encryption settings for the disk.
Azure.Compute.Disks.properties.encryptionSettingsCollection unknown A collection of encryption settings.
Azure.Compute.Disks.properties.encryptionType String The type of key used to encrypt the data on the disk.
Azure.Compute.Disks.properties.securityProfile unknown Security profile for the disk.
Azure.Compute.Disks.properties.tieringProfile unknown Tiering profile for the disk.
Azure.Compute.Disks.properties.supportedTierList unknown List of supported tiers for the disk.
Azure.Compute.Disks.properties.availabilityZone String Availability zone of the disk.
Azure.Compute.Disks.properties.dataAccessAuthMode String Additional authentication requirements when exporting or uploading to a disk.
Azure.Compute.Disks.properties.osType String The operating system type.
Azure.Compute.Disks.properties.hyperVGeneration String The HyperVGenerationType of the virtual machine.
Azure.Compute.Disks.properties.lastOwnershipUpdateTime String The last time ownership of the disk was updated.

azure-appservice-webapp-update


Updates an Azure Web App. The required permissions are: Microsoft.Web/sites/read, Microsoft.Web/sites/write.

Base Command

azure-appservice-webapp-update

Input

Argument Name Description Required
resource_group_name The resource group name. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
name Name of the Web App. Required
identity_type Managed service identity type. Possible values are: None, SystemAssigned. Optional
https_only Configures the web site to accept only https requests. Possible values are: true, false. Optional
client_cert_enabled Whether client certificates are enabled. Possible values are: true, false. Optional

Context Output

Path Type Description
Azure.AppService.WebApp.id String Fully qualified resource ID for the web app.
Azure.AppService.WebApp.name String The name of the web app.
Azure.AppService.WebApp.type String The resource type, e.g., Microsoft.Web/sites.
Azure.AppService.WebApp.location String Geographic location of the web app.
Azure.AppService.WebApp.kind String The kind of the app, e.g., app, functionapp, etc.
Azure.AppService.WebApp.tags Unknown Resource tags as key-value pairs.
Azure.AppService.WebApp.identity.type String The type of managed identity (SystemAssigned, UserAssigned, etc.).
Azure.AppService.WebApp.identity.principalId String The principal ID of the system-assigned identity.
Azure.AppService.WebApp.identity.tenantId String The tenant ID of the system-assigned identity.
Azure.AppService.WebApp.identity.userAssignedIdentities Unknown The list of user-assigned identities associated with the web app.
Azure.AppService.WebApp.properties.state String Current state of the web app (Running, Stopped, etc.).
Azure.AppService.WebApp.properties.enabled Boolean Whether the web app is enabled.
Azure.AppService.WebApp.properties.defaultHostName String Default host name of the web app.
Azure.AppService.WebApp.properties.hostNames String List of host names associated with the web app.
Azure.AppService.WebApp.properties.repositorySiteName String Name of the repository site.
Azure.AppService.WebApp.properties.clientAffinityEnabled Boolean Whether client affinity is enabled.
Azure.AppService.WebApp.properties.clientCertEnabled Boolean Whether client certificates are enabled.
Azure.AppService.WebApp.properties.clientCertExclusionPaths String Paths to exclude from client certificate authentication.
Azure.AppService.WebApp.properties.hostingEnvironment String App Service Environment to use for the web app.
Azure.AppService.WebApp.properties.serverFarmId String Resource ID of the associated App Service plan.
Azure.AppService.WebApp.properties.reserved Boolean Whether the web app is on a Linux plan.
Azure.AppService.WebApp.properties.isXenon Boolean Whether the web app is hosted in Xenon.
Azure.AppService.WebApp.properties.hyperV Boolean Whether Hyper-V is enabled for the web app.
Azure.AppService.WebApp.properties.siteConfig Unknown Configuration of the app.

azure-cr-registry-update


Updates a container registry. Required permissions: Microsoft.ContainerRegistry/registries/read, Microsoft.ContainerRegistry/registries/write.

Base Command

azure-cr-registry-update

Input

Argument Name Description Required
resource_group_name The resource group name. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
registry_name The name of the container registry. Required
allow_exports Whether artifacts can be exported. Possible values are: disabled, enabled. Optional
public_network_access Whether public network access is allowed for the container registry. Possible values are: disabled, enabled. Optional
anonymous_pull_enabled Whether to enable registry-wide pulls from unauthenticated clients. Possible values are: true, false. Optional
authentication_as_arm_policy Whether the policy is enabled or not. Possible values are: disabled, enabled. Optional

Context Output

Path Type Description
Azure.ContainerRegistry.Registries.id String The resource ID.
Azure.ContainerRegistry.Registries.identity Unknown The identity of the container registry.
Azure.ContainerRegistry.Registries.location String The location of the resource.
Azure.ContainerRegistry.Registries.name String The name of the resource.
Azure.ContainerRegistry.Registries.properties.adminUserEnabled Boolean The value that indicates whether the admin user is enabled.
Azure.ContainerRegistry.Registries.properties.anonymousPullEnabled Boolean Enables registry-wide pull from unauthenticated clients.
Azure.ContainerRegistry.Registries.properties.creationDate String The creation date of the container registry in ISO8601 format.
Azure.ContainerRegistry.Registries.properties.dataEndpointEnabled Boolean Enable a single data endpoint per region for serving data.
Azure.ContainerRegistry.Registries.properties.dataEndpointHostNames Unknown List of host names that will serve data when dataEndpointEnabled is true.
Azure.ContainerRegistry.Registries.properties.encryption Unknown The encryption settings of container registry.
Azure.ContainerRegistry.Registries.properties.loginServer String The URL that can be used to log into the container registry.
Azure.ContainerRegistry.Registries.properties.networkRuleBypassOptions String Whether to allow trusted Azure services to access a network restricted registry.
Azure.ContainerRegistry.Registries.properties.networkRuleSet Unknown The network rule set for a container registry.
Azure.ContainerRegistry.Registries.properties.policies Unknown The policies for a container registry.
Azure.ContainerRegistry.Registries.properties.privateEndpointConnections Unknown List of private endpoint connections for a container registry.
Azure.ContainerRegistry.Registries.properties.provisioningState String The provisioning state of the container registry at the time the operation was called.
Azure.ContainerRegistry.Registries.properties.publicNetworkAccess String Whether or not public network access is allowed for the container registry.
Azure.ContainerRegistry.Registries.properties.status Unknown The status of the container registry at the time the operation was called.
Azure.ContainerRegistry.Registries.properties.zoneRedundancy String Whether or not zone redundancy is enabled for this container registry.
Azure.ContainerRegistry.Registries.sku Unknown The SKU of the container registry.
Azure.ContainerRegistry.Registries.systemData Unknown Metadata pertaining to creation and last modification of the resource.
Azure.ContainerRegistry.Registries.tags Unknown The tags of the resource.
Azure.ContainerRegistry.Registries.type String The type of the resource.

azure-storage-blob-service-property-get


Run this command to get the blob service properties of a specific account storage. Required permissions: Microsoft.Storage/storageAccounts/blobServices/read.

Base Command

azure-storage-blob-service-property-get

Input

Argument Name Description Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
resource_group_name The resource group name. Required
account_name The storage account name. Required

Context Output

Path Type Description
Azure.Storage.BlobServices.id String Fully qualified resource ID for the resource.
Azure.Storage.BlobServices.name String The name of the resource.
Azure.Storage.BlobServices.type String The resource type.
Azure.Storage.BlobServices.properties.lastAccessTimeTrackingPolicy Unknown The blob service property to configure last access time based tracking policy.
Azure.Storage.BlobServices.properties.changeFeed Unknown The blob service properties for change feed events.
Azure.Storage.BlobServices.properties.containerDeleteRetentionPolicy Unknown The blob service properties for container soft delete.
Azure.Storage.BlobServices.properties.cors Unknown The CORS rules for the Blob service.
Azure.Storage.BlobServices.properties.defaultServiceVersion String The default version to use for requests to the Blob service if an incoming request’s version is not specified. Possible values include version 2008-10-27 and all more recent versions.
Azure.Storage.BlobServices.properties.deleteRetentionPolicy Unknown The blob service properties for blob soft delete.
Azure.Storage.BlobServices.properties.isVersioningEnabled Boolean Whether versioning is enabled.
Azure.Storage.BlobServices.properties.restorePolicy Unknown The blob service properties for blob restore policy.
Azure.Storage.BlobServices.sku.name String The SKU name.
Azure.Storage.BlobServices.sku.tier String The SKU tier.

azure-storage-blob-service-property-set


Sets properties for the blob service in a specific account storage. Required permissions: Microsoft.Storage/storageAccounts/blobServices/read, Microsoft.Storage/storageAccounts/blobServices/write.

Base Command

azure-storage-blob-service-property-set

Input

Argument Name Description Required
resource_group_name The resource group name. Required
subscription_id The Azure subscription ID. Required for Cortex Platform (which includes Cortex XSIAM version >=3.0 and Cortex Cloud). Optional for Cortex XSOAR and Cortex XSIAM version < 3.0, where it can be retrieved from the integration configuration. Optional
account_name The name of the storage account. Required
delete_retention_policy_enabled Whether DeleteRetentionPolicy is enabled. Possible values are: true, false. Optional
delete_retention_policy_days The number of days the deleted item should be retained. Optional

Context Output

Path Type Description
Azure.Storage.BlobServices.id String The resource ID.
Azure.Storage.BlobServices.name String The name of the resource.
Azure.Storage.BlobServices.type String The type of the resource.
Azure.Storage.BlobServices.properties.cors Unknown The CORS rules for the Blob service.
Azure.Storage.BlobServices.properties.defaultServiceVersion String The default version to use for requests to the Blob service if an incoming request’s version is not specified. Possible values include version 2008-10-27 and all more recent versions.
Azure.Storage.BlobServices.properties.deleteRetentionPolicy Unknown The service properties for soft delete.
Azure.Storage.BlobServices.properties.isVersioningEnabled Boolean Whether versioning is enabled.
Azure.Storage.BlobServices.properties.changeFeed Unknown The blob service properties for change feed events.
Azure.Storage.BlobServices.properties.containerDeleteRetentionPolicy Unknown The blob service properties for container soft delete.
Azure.Storage.BlobServices.properties.lastAccessTimeTrackingPolicy Unknown The blob service property to configure last access time based tracking policy.
Azure.Storage.BlobServices.properties.restorePolicy Unknown The blob service properties for blob restore policy.
Azure.Storage.BlobServices.sku.name String The SKU name.
Azure.Storage.BlobServices.sku.tier String The SKU tier.

azure-auth-test


Tests the connectivity to Azure. Relevant for the Device Code and Authorization Code authentication flows (used instead of the Test button for these interactive flows).

Base Command

azure-auth-test

Input

There are no input arguments for this command.

Context Output

There is no context output for this command.

azure-generate-login-url


Generates the login URL used for authorization. Relevant only for the Authorization Code authentication flow.

Base Command

azure-generate-login-url

Input

There are no input arguments for this command.

Context Output

There is no context output for this command.

azure-auth-complete


Completes the authorization process for the Device Code flow. Should be used after running the azure-auth-start command.

Base Command

azure-auth-complete

Input

There are no input arguments for this command.

Context Output

There is no context output for this command.

azure-auth-reset


Resets the authentication process. Relevant for the Device Code and Authorization Code authentication flows.

Base Command

azure-auth-reset

Input

There are no input arguments for this command.

Context Output

There is no context output for this command.

azure-auth-start


Starts the authorization process for the Device Code / Authorization Code flows. Follow the instructions in the command results.

Base Command

azure-auth-start

Input

There are no input arguments for this command.

Context Output

There is no context output for this command.

Configuration parameters

  • app_id — Application ID
  • subscription_id — Default Subscription ID (required)
  • resource_group_name — Default Resource Group Name
  • azure_ad_endpoint — Azure AD endpoint
  • auth_type — Authentication Type
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings
  • tenant_id — Tenant ID
  • credentials — Client Secret
  • redirect_uri — Application redirect URI
  • auth_code — Authorization code
  • managed_identities_client_id — Azure Managed Identities Client ID

Commands (131)

  • azure-acr-disable-anonymous-pull-quick-action Deprecated

    Disables anonymous pull access for the Azure Container Registry (ACR), requiring clients to authenticate before pulling images. Deprecated. Use Disable Anonymous Pull for ACR instead. Required permissions: Microsoft.ContainerRegistry/registries/read, Microsoft.ContainerRegistry/registries/write.

  • azure-acr-disable-authentication-as-arm-quick-action Deprecated

    Disables the legacy 'authentication as ARM' feature for the Azure Container Registry (ACR). Deprecated. Use Disable ACR ARM Authentication instead. Required permissions: Microsoft.ContainerRegistry/registries/read, Microsoft.ContainerRegistry/registries/write.

  • azure-acr-disable-public-private-access-quick-action Deprecated

    Disables public network access and content exports for the Azure Container Registry (ACR) to enhance security. Deprecated. Use Disable Public Access & Exports on ACR instead. Required permissions: Microsoft.ContainerRegistry/registries/read, Microsoft.ContainerRegistry/registries/write.

  • azure-acr-update Deprecated

    Updates a container registry. Deprecated. Use the azure-cr-registry-update command instead. Required permissions: Microsoft.ContainerRegistry/registries/read, Microsoft.ContainerRegistry/registries/write.

  • azure-appservice-webapp-auth-settings-update

    Updates the authentication and authorization settings of an existing Azure Web App. Required permissions: Microsoft.Web/sites/config/read, Microsoft.Web/sites/config/write.

  • azure-appservice-webapp-auth-settings-update-quick-action

    Enables App Service Authentication for the web app. Required permissions: Microsoft.Web/sites/config/read, Microsoft.Web/sites/config/write.

  • azure-appservice-webapp-config-disable-remote-debugging-quick-action

    Disables remote debugging for the web app to reduce the risk of unauthorized code access. Required permissions: Microsoft.Web/sites/config/read, Microsoft.Web/sites/config/write.

  • azure-appservice-webapp-config-update

    Updates the configuration settings of an existing Azure Web App. Required permissions: Microsoft.Web/sites/config/write, Microsoft.Web/sites/config/read.

  • azure-appservice-webapp-config-update-http2-quick-action

    Enables HTTP 2.0 for the web app. Required permissions: Microsoft.Web/sites/config/read, Microsoft.Web/sites/config/write.

  • azure-appservice-webapp-config-update-min-tls-version-quick-action

    Sets the web app's minimum accepted TLS version to 1.2 to enhance security. Required permissions: Microsoft.Web/sites/config/read, Microsoft.Web/sites/config/write.

  • azure-appservice-webapp-update

    Updates an Azure Web App. The required permissions are: Microsoft.Web/sites/read, Microsoft.Web/sites/write.

  • azure-appservice-webapp-update-quick-action

    Assigns a system-assigned managed identity to the web app, enabling secure access to other Azure services without managing credentials. Required permissions: Microsoft.Web/sites/read, Microsoft.Web/sites/write.

  • azure-auth-complete

    Completes the authorization process for the Device Code flow. Should be used after running the azure-auth-start command.

  • azure-auth-reset

    Resets the authentication process. Relevant for the Device Code and Authorization Code authentication flows.

  • azure-auth-start

    Starts the authorization process for the Device Code / Authorization Code flows. Follow the instructions in the command results.

  • azure-auth-test

    Tests the connectivity to Azure. Relevant for the Device Code and Authorization Code authentication flows (used instead of the Test button for these interactive flows).

  • azure-billing-budgets-list

    Lists configured budgets at the subscription or resource group level. Required permission: Microsoft.Consumption/budgets/read.

  • azure-billing-forecast-list

    Returns cost forecast for a subscription over a given time range. Required permission: Microsoft.CostManagement/forecast/read.

  • azure-billing-usage-list

    Returns actual usage and cost details for a given time period, optionally filtered by service name. Required permission: Microsoft.Consumption/usageDetails/read.

  • azure-compute-disk-update

    Updates a disk. Required permissions: Microsoft.Compute/disks/read, Microsoft.Compute/disks/write.

  • azure-compute-disk-update-data-access-ad-quick-action

    Sets the data access authentication mode for the managed disk to Azure Active Directory. Required permissions: Microsoft.Compute/disks/read, Microsoft.Compute/disks/write.

  • azure-compute-vm-get

    Gets the properties of a given virtual machine. Required Permissions: Microsoft.Compute/virtualMachines/read.

  • azure-compute-vm-list

    Lists all the virtual machines in the specified subscription. Use the next_token argument to view the next page of results. Required Permissions: Microsoft.Compute/virtualMachines/read.

  • azure-compute-vm-power-off

    Powers off a given virtual machine. Required Permissions: Microsoft.Compute/virtualMachines/poweroff/action.

  • azure-compute-vm-start

    Powers on a given virtual machine. Required Permissions: Microsoft.Compute/virtualMachines/start/action.

  • azure-cosmos-db-disable-key-quick-action

    Disables key-based write access for Cosmos DB metadata to enhance security.

  • azure-cosmos-db-update Deprecated

    Updates the properties of an existing Azure Cosmos DB database account. Deprecated. Use the azure-cosmosdb-db-account-update command instead. Required permissions: Microsoft.DocumentDB/databaseAccounts/read, Microsoft.DocumentDB/databaseAccounts/write.

  • azure-cosmosdb-db-account-update

    Updates the properties of an existing Azure Cosmos DB database account. The required permissions are: Microsoft.DocumentDB/databaseAccounts/read, Microsoft.DocumentDB/databaseAccounts/write.

  • azure-cr-disable-anonymous-pull-quick-action

    Disables anonymous pull access for the Azure Container Registry (ACR), requiring clients to authenticate before pulling images. Required permissions: Microsoft.ContainerRegistry/registries/read, Microsoft.ContainerRegistry/registries/write.

  • azure-cr-disable-authentication-as-arm-quick-action

    Disables the legacy 'authentication as ARM' feature for the Azure Container Registry (ACR). Required permissions: Microsoft.ContainerRegistry/registries/read, Microsoft.ContainerRegistry/registries/write.

  • azure-cr-disable-public-private-access-quick-action

    Disables public network access and content exports for the Azure Container Registry (ACR) to enhance security.

  • azure-cr-registry-update

    Updates a container registry. Required permissions: Microsoft.ContainerRegistry/registries/read, Microsoft.ContainerRegistry/registries/write.

  • azure-disable-public-n-private-access-vm-disk-quick-action

    Disables all public and private network access for the managed disk. Required permissions: Microsoft.Compute/disks/read, Microsoft.Compute/disks/write.

  • azure-disable-public-private-access-vm-disk-quick-action Deprecated

    Disables all public and private network access for a managed disk. Deprecated. Use Disable Public and Private Access to VM Disk instead. Required permissions: Microsoft.Compute/disks/read, Microsoft.Compute/disks/write.

  • azure-disk-set-data-access-ad-quick-action Deprecated

    Sets the data access authentication mode for the managed disk to Azure Active Directory. Deprecated. Use Set Disk Data Access to Azure AD instead. Required permissions: Microsoft.Compute/disks/read, Microsoft.Compute/disks/write.

  • azure-disk-update Deprecated

    Updates a disk. Deprecated. Use the azure-compute-disk-update command instead. Required permissions: Microsoft.Compute/disks/read, Microsoft.Compute/disks/write.

  • azure-function-app-set-min-tls-version-quick-action Deprecated

    Sets the Function App's minimum accepted TLS version to 1.2 to enhance security. Deprecated. Use Set Web App Minimum TLS Version instead. Required permissions: Microsoft.Web/sites/config/read, Microsoft.Web/sites/config/write.

  • azure-generate-login-url

    Generates the login URL used for authorization. Relevant only for the Authorization Code authentication flow.

  • azure-key-vault-purge-and-soft-delete-enable-quick-action

    Enables soft delete and purge protection for the Key Vault to prevent the permanent loss of keys and secrets. Note: Once purge-protection and soft-delete is enabled for a key vault, the action is irreversible.

  • azure-key-vault-update Deprecated

    Updates a key vault in a specific subscription. Deprecated. Use the azure-keyvault-vault-update command instead. Required permissions: Microsoft.KeyVault/vaults/read, Microsoft.KeyVault/vaults/write.

  • azure-keyvault-vault-update

    Updates a key vault in the specified subscription. The required permissions are: Microsoft.KeyVault/vaults/read, Microsoft.KeyVault/vaults/write.

  • azure-monitor-log-profile-update

    Updates a log profile in Azure Monitoring REST API. Required permissions: Microsoft.Insights/logprofiles/read, Microsoft.Insights/logprofiles/write.

  • azure-monitor-log-retention-period-quick-action

    Sets the log profile’s retention policy to 365 days and enables it across all supported locations. Required permissions: Microsoft.Insights/logprofiles/read, Microsoft.Insights/logprofiles/write.

  • azure-mysql-flexible-server-param-set

    Updates a server configuration. Required permissions: Microsoft.DBforMySQL/flexibleServers/configurations/read, Microsoft.DBforMySQL/flexibleServers/configurations/write.

  • azure-mysql-set-secure-transport-quick-action

    Enforces secure transport (SSL/TLS) for connections to the MySQL Flexible Server. Required permissions: Microsoft.DBforMySQL/flexibleServers/configurations/read, Microsoft.DBforMySQL/flexibleServers/configurations/write.

  • azure-network-disable-storage-account-access-quick-action

    Sets the storage account’s default network action to Deny. Only explicitly allowed IPs, subnets, or trusted Azure services will have access. Required permissions: Microsoft.Storage/storageAccounts/read, Microsoft.Storage/storageAccounts/write.

  • azure-nsg-network-interfaces-list Deprecated

    Gets network interfaces in a resource group. The command is deprecated, please use azure-vn-network-interfaces-list.

  • azure-nsg-public-ip-addresses-list Deprecated

    Gets public IP addresses in a resource group. The command is deprecated, please use azure-vn-public-ip-addresses-list.

  • azure-nsg-resource-group-list Deprecated

    Gets all resource groups for a subscription. The command is deprecated, please use azure-rm-resource-groups-list.

  • azure-nsg-security-groups-list Deprecated

    Lists all network security groups. Deprecated. Use the azure-vn-security-groups-list command instead. Required permission: Microsoft.Network/networkSecurityGroups/read.

  • azure-nsg-security-rule-create Deprecated

    Creates a security rule. Deprecated. Use the azure-vn-security-rule-create command instead. Required permissions: Microsoft.Network/networkSecurityGroups/securityRules/read, Microsoft.Network/networkSecurityGroups/securityRules/write.

  • azure-nsg-security-rule-delete Deprecated

    Delete a security rule. The command is deprecated, please use azure-vn-security-rule-delete.

  • azure-nsg-security-rule-delete-quick-action

    Deletes a network security group (NSG) rule. Required permission: Microsoft.Network/networkSecurityGroups/securityRules/delete.

  • azure-nsg-security-rule-get Deprecated

    Retrieves a specific rule. Deprecated. Use the azure-vn-security-rule-get command instead. Required permission: Microsoft.Network/networkSecurityGroups/securityRules/read.

  • azure-nsg-security-rule-update Deprecated

    Updates a security rule or creates one if it does not exist. Deprecated. Use the azure-vn-security-rule-update command instead. Required permissions: Microsoft.Network/networkSecurityGroups/securityRules/read, Microsoft.Network/networkSecurityGroups/securityRules/write.

  • azure-nsg-security-rules-list Deprecated

    Retrieves all security rules in a network security group. Deprecated. Use the azure-vn-security-rules-list command instead. Required permission: Microsoft.Network/networkSecurityGroups/securityRules/read.

  • azure-policy-assignment-create

    Creates a policy assignment. Required permission: Microsoft.Authorization/policyAssignments/read, Microsoft.Authorization/policyAssignments/write.

  • azure-policy-assignment-create-quick-action

    Applies Microsoft Defender for Cloud built-in recommendations by creating a policy assignment for the SecurityCenterBuiltIn initiative. This sets the following policies to 'AuditIfNotExists': disk encryption monitoring (Windows and Linux), system updates monitoring, and JIT network access monitoring. Rules for adaptive application controls, endpoint protection, and security configuration are excluded. Required permissions: Microsoft.Authorization/policyAssignments/read, Microsoft.Authorization/policyAssignments/write.

  • azure-postgres-config-set Deprecated

    Updates a server configuration. Deprecated due to the retirement of Azure PostgreSQL Single Server. Required permissions: Microsoft.DBforPostgreSQL/servers/configurations/read, Microsoft.DBforPostgreSQL/servers/configurations/write.

  • azure-postgres-config-set-checkpoint-logging-quick-action Deprecated

    Enables checkpoint logging on the PostgreSQL server. Deprecated due to the retirement of Azure PostgreSQL Single Server. Required permissions: Microsoft.DBforPostgreSQL/servers/configurations/read, Microsoft.DBforPostgreSQL/servers/configurations/write.

  • azure-postgres-config-set-connection-throttling-quick-action Deprecated

    Enables connection throttling on the PostgreSQL server to manage log verbosity for concurrent connection queries and errors. Deprecated due to the retirement of Azure PostgreSQL Single Server. Required permissions: Microsoft.DBforPostgreSQL/servers/configurations/read, Microsoft.DBforPostgreSQL/servers/configurations/write.

  • azure-postgres-config-set-disconnection-logging-quick-action Deprecated

    Enables logging client disconnections on the PostgreSQL server. Deprecated due to the retirement of Azure PostgreSQL Single Server. Required permissions: Microsoft.DBforPostgreSQL/servers/configurations/read, Microsoft.DBforPostgreSQL/servers/configurations/write.

  • azure-postgres-config-set-log-retention-period-quick-action Deprecated

    Sets the log retention period for the PostgreSQL server to 4 days. NOTE: The recommended log retention period can be from 4 to 7 days. Deprecated due to the retirement of Azure PostgreSQL Single Server. Required permissions: Microsoft.DBforPostgreSQL/servers/configurations/read, Microsoft.DBforPostgreSQL/servers/configurations/write.

  • azure-postgres-config-set-session-connection-logging-quick-action Deprecated

    Enables logging client connections on the PostgreSQL. Deprecated due to the retirement of Azure PostgreSQL Single Server. Required permissions: Microsoft.DBforPostgreSQL/servers/configurations/read, Microsoft.DBforPostgreSQL/servers/configurations/write.

  • azure-postgres-config-set-statement-logging-quick-action Deprecated

    Enables logging statement execution duration on the PostgreSQL server to help with performance analysis. Deprecated due to the retirement of Azure PostgreSQL Single Server. Required permissions: Microsoft.DBforPostgreSQL/servers/configurations/read, Microsoft.DBforPostgreSQL/servers/configurations/write.

  • azure-postgres-server-update Deprecated

    Updates an existing server. Deprecated due to the retirement of Azure PostgreSQL Single Server. Required permissions: Microsoft.DBforPostgreSQL/servers/read, Microsoft.DBforPostgreSQL/servers/write.

  • azure-postgres-server-update-ssl-enforcement-quick-action Deprecated

    Enforces SSL/TLS connections for the PostgreSQL server to reject unencrypted traffic. Deprecated due to the retirement of Azure PostgreSQL Single Server. Required permissions: Microsoft.DBforPostgreSQL/servers/read, Microsoft.DBforPostgreSQL/servers/write.

  • azure-rm-resource-groups-list

    Gets all resource groups for a subscription. Required Permissions: Microsoft.Resources/subscriptions/resourceGroups/read.

  • azure-set-function-app-http-version2-0-quick-action Deprecated

    Enables HTTP 2.0 for the Function App. Deprecated. Use Set Web App HTTP Version to 2.0 instead. Required permissions: Microsoft.Web/sites/config/read, Microsoft.Web/sites/config/write.

  • azure-set-storage-account-https-only-quick-action

    Enforces HTTPS-only traffic for the storage account, rejecting any requests made over HTTP. Required permissions: Microsoft.Storage/storageAccounts/read, Microsoft.Storage/storageAccounts/write.

  • azure-sql-db-threat-policy-update Deprecated

    Updates the database's threat detection policy. Deprecated. Use the azure-sqldb-security-alert-policy-update command instead. Required permissions: Microsoft.Sql/servers/databases/securityAlertPolicies/read, Microsoft.Sql/servers/databases/securityAlertPolicies/write.

  • azure-sql-db-threat-policy-update-quick-action

    Enables email notifications to account administrators for SQL database threat detection alerts.

  • azure-sql-db-transparent-data-encryption-enable-tde-quick-action

    Enables Transparent Data Encryption (TDE) for the SQL database to encrypt data at rest.

  • azure-sql-db-transparent-data-encryption-set

    Updates a logical database's transparent data encryption configuration. Required permissions: Microsoft.Sql/servers/databases/transparentDataEncryption/read, Microsoft.Sql/servers/databases/transparentDataEncryption/write.

  • azure-sqldb-security-alert-policy-update

    Updates a database's security alert policy. The required permissions are: Microsoft.Sql/servers/databases/securityAlertPolicies/read, Microsoft.Sql/servers/databases/securityAlertPolicies/write.

  • azure-storage-account-update

    Updates a specific account storage. Required permissions: Microsoft.Storage/storageAccounts/read, Microsoft.Storage/storageAccounts/write.

  • azure-storage-allow-access-quick-action

    Configures the storage account's network rules to allow traffic from trusted Azure services. Required permissions: Microsoft.Storage/storageAccounts/read, Microsoft.Storage/storageAccounts/write.

  • azure-storage-blob-container-update

    Updates container properties as specified in request body. Properties not mentioned in the request will be unchanged. Update fails if the specified container doesn't already exist. Required permissions: Microsoft.Storage/storageAccounts/blobServices/containers/write.

  • azure-storage-blob-containers-update Deprecated

    Run this command to update a specific blob container. The command is deprecated, please use azure-storage-blob-container-update.

  • azure-storage-blob-create

    Create a new Blob under the specified Container. Required permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write.

  • azure-storage-blob-enable-soft-delete-quick-action Deprecated

    Enables blob soft delete for the storage account to retain deleted blobs for 30 days. The quick action is now deprecated, please use Enable Blob Soft Deletion. Required permissions: Microsoft.Storage/storageAccounts/blobServices/read, Microsoft.Storage/storageAccounts/blobServices/write.

  • azure-storage-blob-get

    Retrieve a Blob from a Container. Required permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read.

  • azure-storage-blob-property-get

    Retrieve Blob properties. Required Permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read.

  • azure-storage-blob-property-set

    Set Blob properties. Required permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write.

  • azure-storage-blob-service-properties-get Deprecated

    Run this command to get the blob service properties of a specific account storage. The command is deprecated, please use azure-storage-blob-service-property-get.

  • azure-storage-blob-service-properties-set Deprecated

    Sets properties for the blob service in a specific account storage. The command is deprecated, please use azure-storage-blob-service-property-set.Required permissions: Microsoft.Storage/storageAccounts/blobServices/read, Microsoft.Storage/storageAccounts/blobServices/write.

  • azure-storage-blob-service-property-get

    Run this command to get the blob service properties of a specific account storage. Required permissions: Microsoft.Storage/storageAccounts/blobServices/read.

  • azure-storage-blob-service-property-set

    Sets properties for the blob service in a specific account storage. Required permissions: Microsoft.Storage/storageAccounts/blobServices/read, Microsoft.Storage/storageAccounts/blobServices/write.

  • azure-storage-blob-soft-deletion-enable-quick-action

    Enables blob soft delete for the storage account to retain deleted blobs for 30 days. Required permissions: Microsoft.Storage/storageAccounts/blobServices/read, Microsoft.Storage/storageAccounts/blobServices/write.

  • azure-storage-blob-tag-get

    Retrieve the tags of the specified Blob. Required Permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/read.

  • azure-storage-blob-tag-set

    Updates the tags for the specified Blob. The command can replace the entire tags of the Blob and can be used to remove tags. Required permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/write.

  • azure-storage-container-blob-create Deprecated

    Creates a new Blob under the specified Container. Deprecated. Use the azure-storage-blob-create command instead. Required permission: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write.

  • azure-storage-container-blob-get Deprecated

    Retrieves a Blob from a Container. Deprecated. Use the azure-storage-blob-get command instead. Required permission: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read.

  • azure-storage-container-blob-property-get Deprecated

    Retrieves Blob properties. Deprecated. Use the azure-storage-blob-property-get command instead. Required permission: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read.

  • azure-storage-container-blob-property-set Deprecated

    Sets Blob properties. Deprecated. Use the azure-storage-blob-property-set command instead. Required permission: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write.

  • azure-storage-container-blob-tag-get Deprecated

    Retrieves the tags of a specific Blob. Deprecated. Use the azure-storage-blob-tag-get command instead. Required permission: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/read.

  • azure-storage-container-blob-tag-set Deprecated

    Updates the tags for a specific Blob. Replaces all existing tags or removes them if none are provided. Deprecated. Use the azure-storage-blob-tag-set command instead. Required permissions: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/read, Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/write.

  • azure-storage-container-create

    Creates a new Container under the specified account. Required permission: Microsoft.Storage/storageAccounts/blobServices/containers/write.

  • azure-storage-container-delete

    Marks a specific Container for deletion. The Container and any Blobs contained within it will be deleted during garbage collection. Required permission: Microsoft.Storage/storageAccounts/blobServices/containers/delete.

  • azure-storage-container-property-get

    Retrieves properties for a specific Container. Required permission: Microsoft.Storage/storageAccounts/blobServices/containers/read.

  • azure-storage-container-public-access-block

    Blocks public access to a container. Required permission: Microsoft.Storage/storageAccounts/blobServices/containers/setAcl/action.

  • azure-storage-disable-cross-tenant-replication-quick-action

    Disables cross-tenant object replication for the storage account, preventing data from being copied to other Azure AD tenants. Required permissions: Microsoft.Storage/storageAccounts/read, Microsoft.Storage/storageAccounts/write.

  • azure-storage-disable-storage-account-public-access-quick-action

    Disables public access to blobs for the storage account, blocking anonymous/public read access to containers and blobs. Required permissions: Microsoft.Storage/storageAccounts/read, Microsoft.Storage/storageAccounts/write.

  • azure-vm-instance-details-get Deprecated

    Retrieves the properties of a specific virtual machine. Deprecated. Use the azure-compute-vm-get command instead. Required permission: Microsoft.Compute/virtualMachines/read.

  • azure-vm-instance-power-off Deprecated

    Powers off a specific virtual machine. Deprecated. Use the azure-compute-vm-power-off command instead. Required permissions: Microsoft.Compute/virtualMachines/read, Microsoft.Compute/virtualMachines/poweroff/action.

  • azure-vm-instance-start Deprecated

    Powers on a specific virtual machine. Deprecated. Use the azure-compute-vm-start command instead. Required permissions: Microsoft.Compute/virtualMachines/read, Microsoft.Compute/virtualMachines/start/action.

  • azure-vm-network-interface-details-get Deprecated

    Retrieves the properties of a specific network interface. Deprecated. Use the azure-vn-network-interface-get command instead. Required permission: Microsoft.Network/networkInterfaces/read.

  • azure-vm-public-ip-details-get Deprecated

    Retrieves the properties of a specific public IP address. Deprecated. Use the azure-vn-public-ip-address-get command instead. Required permission: Microsoft.Network/publicIPAddresses/read.

  • azure-vn-network-interface-get

    Gets the properties of a given network interface. Required permissions: Microsoft.Network/networkInterfaces/read.

  • azure-vn-network-interface-update

    Updates a network interface. Required Permissions: Microsoft.Network/networkInterfaces/read, Microsoft.Network/networkInterfaces/write, Microsoft.Network/virtualNetworks/subnets/join/action, Microsoft.Network/publicIPAddresses/join/action, Microsoft.Network/networkSecurityGroups/join/action, Microsoft.Network/loadBalancers/backendAddressPools/join/action.

  • azure-vn-network-interfaces-list

    Gets network interfaces in a resource group. Required permissions: Microsoft.Network/networkInterfaces/read.

  • azure-vn-public-ip-address-get

    Gets the properties of a given public IP address. Permissions required: Microsoft.Network/publicIPAddresses/read.

  • azure-vn-public-ip-addresses-list

    Gets public IP addresses in a resource group. Required permissions: Microsoft.Network/publicIPAddresses/read.

  • azure-vn-security-group-create

    Creates a network security group. Required Permissions: Microsoft.Network/networkSecurityGroups/write.

  • azure-vn-security-groups-list

    List all network security groups. Required permissions: Microsoft.Network/networkSecurityGroups/read.

  • azure-vn-security-rule-create

    Create a security rule. Required permissions: Microsoft.Network/networkSecurityGroups/securityRules/read, Microsoft.Network/networkSecurityGroups/securityRules/write.

  • azure-vn-security-rule-delete

    Delete a security rule. Required permissions: Microsoft.Network/networkSecurityGroups/securityRules/delete.

  • azure-vn-security-rule-get

    Get a specific rule. Required permissions: Microsoft.Network/networkSecurityGroups/securityRules/read.

  • azure-vn-security-rule-update

    Update a security rule. If one does not exist, it will be created. Required permissions: Microsoft.Network/networkSecurityGroups/securityRules/read, Microsoft.Network/networkSecurityGroups/securityRules/write.

  • azure-vn-security-rules-list

    Gets all security rules in a network security group. Required permissions: Microsoft.Network/networkSecurityGroups/securityRules/read.

  • azure-webapp-assign-managed-identity-quick-action Deprecated

    Assigns a system managed identity to the web app, enabling secure access to other Azure services without managing credentials. Deprecated. Use Assign Web App Managed Identity instead. Required permission: Microsoft.Web/sites/read, Microsoft.Web/sites/write.

  • azure-webapp-auth-update Deprecated

    Updates the authentication and authorization settings of an existing Azure Web App. Deprecated. Use the azure-appservice-webapp-auth-settings-update command instead. Required permissions: Microsoft.Web/sites/config/read, Microsoft.Web/sites/config/write.

  • azure-webapp-auth-update-quick-action Deprecated

    Enables App Service Authentication for the web app. Deprecated. Use Enable Azure App Service Authentication instead. Required permissions: Microsoft.Web/sites/config/read, Microsoft.Web/sites/config/write.

  • azure-webapp-config-set Deprecated

    Updates the configuration settings of an existing Azure Web App. Deprecated. Use the azure-appservice-webapp-config-update command instead. Required permissions: Microsoft.Web/sites/config/read, Microsoft.Web/sites/config/write.

  • azure-webapp-disable-remote-debugging-quick-action Deprecated

    Disables remote debugging for the web app to reduce the risk of unauthorized code access. Deprecated. Use Disable Remote Debugging on Web App instead. Required permissions: Microsoft.Web/sites/config/read, Microsoft.Web/sites/config/write.

  • azure-webapp-enable-client-cert-quick-action

    Enables client certificate authentication for the App Service to secure incoming requests. Only clients that have a valid certificate will be able to reach the app.

  • azure-webapp-set-http2-quick-action Deprecated

    Enables HTTP 2.0 for the web app. Deprecated. Use Set Web App HTTP Version to 2.0 instead. Required permissions: Microsoft.Web/sites/config/read, Microsoft.Web/sites/config/write.

  • azure-webapp-set-min-tls-version-quick-action Deprecated

    Sets the web app's minimum accepted TLS version to 1.2 to enhance security. Deprecated. Use Set Web App Minimum TLS Version instead. Required permissions: Microsoft.Web/sites/config/read, Microsoft.Web/sites/config/write.

  • azure-webapp-set-webapp-to-https-only-quick-action

    Enforces HTTPS-only traffic for the App Service.

  • azure-webapp-update Deprecated

    Updates an Azure Web App. Deprecated. Use the azure-appservice-webapp-update command instead. Required permissions: Microsoft.Web/sites/read, Microsoft.Web/sites/write.

  • azure-webapp-update-assign-managed-identity-quick-action Deprecated

    Assigns a system-managed identity to the identified Function App, enabling secure access to Azure services without manual credential management. Deprecated. Use Assign Web App Managed Identity instead. Required permissions: Microsoft.Web/sites/read, Microsoft.Web/sites/write.

import ast
import json
from pathlib import Path
from unittest.mock import MagicMock, patch

import demistomock as demisto
import pytest
import yaml
import Azure
from Azure import (
    AzureClient,
    format_rule,
    update_security_rule_command,
    storage_account_update_command,
    storage_blob_service_properties_set_command,
    create_policy_assignment_command,
    set_postgres_config_command,
    set_webapp_config_command,
    update_webapp_auth_command,
    mysql_flexible_server_param_set_command,
    monitor_log_profile_update_command,
    disk_update_command,
    webapp_update_command,
    acr_update_command,
    update_key_vault_command,
    sql_db_threat_policy_update_command,
    sql_db_tde_set_command,
    cosmosdb_update_command,
    remove_member_from_group_command,
    get_azure_client,
    remove_member_from_role,
    postgres_server_update_command,
    extract_azure_resource_info,
    WEBAPP_API_VERSION,
    FLEXIBLE_API_VERSION,
    CommandResults,
    DemistoException,
    API_VERSION,
    SCOPE_BY_CONNECTION,
    PREFIX_URL_AZURE,
    storage_container_property_get_command,
    storage_container_create_command,
    storage_container_delete_command,
    storage_container_blob_get_command,
    storage_container_blob_tag_get_command,
    storage_container_blob_property_get_command,
    storage_container_blob_tag_set_command,
    storage_container_blob_property_set_command,
    storage_container_block_public_access_command,
    DEFAULT_RESOURCE,
    DEFAULT_SCOPE,
    TokenScope,
    get_command_resource,
    STORAGE_RESOURCE,
    STORAGE_SCOPE,
    STORAGE_DATE_FORMAT,
    get_command_and_token_scopes,
    create_set_tags_request_body,
    nsg_security_rules_list_command,
)
from MicrosoftApiModule import Resources
from requests import Response
from requests.structures import CaseInsensitiveDict
from COOCApiModule import CloudTypes


INTEGRATION_DIR = Path(__file__).parent
YML_PATH = INTEGRATION_DIR / "Azure.yml"
PY_PATH = INTEGRATION_DIR / "Azure.py"


@pytest.fixture
def mock_params():
    return {
        "app_id": "test_app_id",
        "subscription_id": "test_subscription_id",
        "resource_group_name": "test_resource_group",
        "insecure": False,
        "proxy": False,
        "auth_type": "Client Credentials",
        "tenant_id": "test_tenant_id",
        "credentials": {"password": "test_enc_key"},
    }


@pytest.fixture
def client(mocker, mock_params):
    mocker.patch("MicrosoftApiModule.MicrosoftClient.http_request")
    mocker.patch("MicrosoftApiModule.MicrosoftClient.get_access_token")
    return AzureClient(
        app_id=mock_params.get("app_id", ""),
        subscription_id=mock_params.get("subscription_id", ""),
        resource_group_name=mock_params.get("resource_group_name", ""),
        verify=not mock_params.get("insecure", False),
        proxy=mock_params.get("proxy", False),
        tenant_id=mock_params.get("tenant_id"),
        enc_key=mock_params.get("credentials", {}).get("password"),
        headers={},
    )


def util_load_json(path):
    with open(path, encoding="utf-8") as f:
        return json.loads(f.read())


def test_update_security_rule_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to update a security rule.
    When: The update_security_rule_command function is called with valid parameters.
    Then: The function should return the updated rule information in the expected format.
    """

    # Prepare mock responses
    rule_response = {
        "name": "test-rule",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-sg/"
        "securityRules/test-rule",
        "properties": {
            "protocol": "Tcp",
            "sourcePortRange": "*",
            "destinationPortRange": "443",
            "sourceAddressPrefix": "Internet",
            "destinationAddressPrefix": "10.0.0.0/24",
            "access": "Allow",
            "priority": 100,
            "direction": "Inbound",
            "description": "Test rule",
        },
    }

    mocker.patch.object(client, "get_rule", return_value=rule_response)
    mocker.patch.object(client, "create_or_update_rule", return_value=rule_response)
    mocker.patch("Azure.demisto.command", return_value="azure-vn-security-rule-update")

    # Call the function
    args = {
        "security_group_name": "test-sg",
        "security_rule_name": "test-rule",
        "action": "Allow",
        "direction": "Inbound",
        "protocol": "Tcp",
        "source": "Internet",
        "destination": "10.0.0.0/24",
        "destination_ports": "443",
        "priority": "100",
        "description": "Test rule",
        "access": "Allow",
    }

    result = update_security_rule_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == "Azure.VirtualNetworks.SecurityRules"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "test-rule"
    assert result.outputs.get("properties", {}).get("access") == "Allow"


def test_update_security_rule_command_deprecated(mocker, client, mock_params):
    """
    Given: An Azure client and a request to update a security rule using the deprecated command.
    When: The update_security_rule_command function is called with the deprecated command name.
    Then: The function should return the updated rule information with the deprecated prefix.
    """

    # Prepare mock responses
    access = "Allow"
    rule_response = {
        "name": "test-rule",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-sg/"
        "securityRules/test-rule",
        "properties": {
            "protocol": "Tcp",
            "sourcePortRange": "*",
            "destinationPortRange": "443",
            "sourceAddressPrefix": "Internet",
            "destinationAddressPrefix": "10.0.0.0/24",
            "access": access,
            "priority": 100,
            "direction": "Inbound",
            "description": "Test rule",
        },
    }

    mocker.patch.object(client, "get_rule", return_value=rule_response)
    mocker.patch.object(client, "create_or_update_rule", return_value=rule_response)
    mocker.patch("Azure.demisto.command", return_value="azure-nsg-security-rule-update")

    # Call the function
    args = {
        "security_group_name": "test-sg",
        "security_rule_name": "test-rule",
        "action": "Allow",
        "direction": "Inbound",
        "protocol": "Tcp",
        "source": "Internet",
        "destination": "10.0.0.0/24",
        "destination_ports": "443",
        "priority": "100",
        "description": "Test rule",
        "access": access,
    }

    result = update_security_rule_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == "Azure.NSGRule"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "test-rule"
    assert result.outputs.get("access") == access


def test_storage_account_update_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to update a storage account.
    When: The storage_account_update_command function is called with valid parameters.
    Then: The function should return the updated storage account information in the expected format.
    """
    # Prepare mock response
    storage_response = {
        "name": "teststorage",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Storage/storageAccounts/teststorage",
        "properties": {
            "networkAcls": {"bypass": "AzureServices", "defaultAction": "Deny"},
            "allowCrossTenantReplication": False,
            "supportsHttpsTrafficOnly": True,
        },
    }

    # Create a mock response object without using MagicMock
    class MockResponse:
        def __init__(self, json_data, text):
            self._json_data = json_data
            self.text = text

        def json(self):
            return self._json_data

    mock_response = MockResponse(storage_response, json.dumps(storage_response))

    mocker.patch.object(client, "storage_account_update_request", return_value=mock_response)

    # Call the function
    args = {
        "account_name": "teststorage",
        "sku": "Standard_LRS",
        "kind": "StorageV2",
        "location": "eastus",
        "network_ruleset_bypass": "AzureServices",
        "network_ruleset_default_action": "Deny",
        "allow_cross_tenant_replication": "false",
        "supports_https_traffic_only": "true",
    }

    result = storage_account_update_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == "Azure.Storage.StorageAccounts"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "teststorage"
    assert result.outputs["properties"]["supportsHttpsTrafficOnly"] is True


def test_storage_blob_service_properties_set_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to set blob service properties.
    When: The storage_blob_service_properties_set_command function is called with valid parameters.
    Then: The function should return the updated blob service properties in the expected format.
    """

    # Prepare mock response
    properties_response = {
        "name": "default",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Storage/storageAccounts/teststorage/blobServices/\
            default",
        "properties": {"deleteRetentionPolicy": {"enabled": True, "days": 7}},
    }

    mocker.patch.object(client, "storage_blob_service_properties_set_request", return_value=properties_response)
    mocker.patch("Azure.demisto.command", return_value="azure-storage-blob-service-properties-set")

    # Call the function
    args = {"account_name": "teststorage", "delete_rentention_policy_enabled": "true", "delete_rentention_policy_days": "7"}

    result = storage_blob_service_properties_set_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == "Azure.StorageAccountBlobServiceProperties"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "default"
    assert result.outputs["properties"]["deleteRetentionPolicy"]["enabled"] is True
    assert result.outputs["properties"]["deleteRetentionPolicy"]["days"] == 7


def test_create_policy_assignment_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to create a policy assignment.
    When: The create_policy_assignment_command function is called with valid parameters.
    Then: The function should return the created policy assignment in the expected format.
    """

    # Prepare mock response
    policy_response = {
        "name": "test-policy",
        "id": "/subscriptions/sub-id/providers/Microsoft.Authorization/policyAssignments/test-policy",
        "properties": {
            "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/policy-def-id",
            "displayName": "Test Policy",
            "description": "Test policy description",
            "parameters": {},
        },
    }

    mocker.patch.object(client, "create_policy_assignment", return_value=policy_response)

    # Call the function
    args = {
        "name": "test-policy",
        "scope": "sub-id",
        "policy_definition_id": "/providers/Microsoft.Authorization/policyDefinitions/policy-def-id",
        "display_name": "Test Policy",
        "description": "Test policy description",
        "parameters": "{}",
    }

    result = create_policy_assignment_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == "Azure.Policy.PolicyAssignments"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "test-policy"
    assert result.outputs["properties"]["displayName"] == "Test Policy"


def test_set_postgres_config_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to set PostgreSQL configurations.
    When: The set_postgres_config_command function is called with valid parameters.
    Then: The function should return a success message.
    """

    # Prepare mock
    mocker.patch.object(client, "set_postgres_config", return_value=None)

    # Call the function
    args = {"server_name": "test-postgres", "configuration_name": "log_checkpoints", "source": "user-override", "value": "on"}

    result = set_postgres_config_command(client, mock_params, args)

    # Verify results
    assert "Updated the configuration log_checkpoints of the server test-postgres" in result.readable_output


@pytest.mark.parametrize(
    "command, expected_prefix",
    [
        ("azure-webapp-config-set", "Azure.WebAppConfig"),
        ("azure-webapp-set-http2-quick-action", "Azure.WebAppConfig"),
        ("azure-set-function-app-http-version2-0-quick-action", "Azure.WebAppConfig"),
        ("azure-webapp-disable-remote-debugging-quick-action", "Azure.WebAppConfig"),
        ("azure-webapp-set-min-tls-version-quick-action", "Azure.WebAppConfig"),
        ("azure-function-app-set-min-tls-version-quick-action", "Azure.WebAppConfig"),
        ("azure-appservice-webapp-config-update", "Azure.AppService.WebAppConfiguration"),
        ("azure-appservice-webapp-config-update-http2-quick-action", "Azure.AppService.WebAppConfiguration"),
        ("azure-appservice-webapp-config-disable-remote-debugging-quick-action", "Azure.AppService.WebAppConfiguration"),
        ("azure-appservice-webapp-config-update-min-tls-version-quick-action", "Azure.AppService.WebAppConfiguration"),
    ],
)
def test_set_webapp_config_command(mocker, client, mock_params, command, expected_prefix):
    """
    Given: An Azure client and a request to set WebApp configurations.
    When: The set_webapp_config_command function is called with valid parameters.
    Then: The function should return the updated WebApp configurations in the expected format.
    """

    # Prepare mock response
    webapp_response = {
        "name": "test-webapp",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-webapp",
        "properties": {"http20Enabled": True, "remoteDebuggingEnabled": False, "minTlsVersion": "1.2"},
    }

    mocker.patch.object(client, "set_webapp_config", return_value=webapp_response)
    mocker.patch.object(demisto, "command", return_value=command)

    # Call the function
    args = {"name": "test-webapp", "http20_enabled": "true", "remote_debugging_enabled": "false", "min_tls_version": "1.2"}

    result = set_webapp_config_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == expected_prefix
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "test-webapp"
    assert result.outputs["properties"]["http20Enabled"] is True


@pytest.mark.parametrize(
    "command, expected_prefix",
    [
        ("azure-webapp-auth-update", "Azure.WebAppAuth"),
        ("azure-webapp-auth-update-quick-action", "Azure.WebAppAuth"),
        ("azure-appservice-webapp-auth-settings-update", "Azure.AppService.WebAppAuthSettings"),
        ("azure-appservice-webapp-auth-settings-update-quick-action", "Azure.AppService.WebAppAuthSettings"),
    ],
)
def test_update_webapp_auth_command(mocker, client, mock_params, command, expected_prefix):
    """
    Given: An Azure client and a request to update WebApp authentication settings.
    When: The update_webapp_auth_command function is called with valid parameters.
    Then: The function should return the updated WebApp authentication settings in the expected format.
    """

    # Prepare mock responses
    current_auth = {
        "name": "authsettings",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-webapp/config/authsettings",
        "properties": {"enabled": False},
    }

    updated_auth = {
        "name": "authsettings",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-webapp/config/authsettings",
        "properties": {"enabled": True},
    }

    mocker.patch.object(client, "get_webapp_auth", return_value=current_auth)
    mocker.patch.object(client, "update_webapp_auth", return_value=updated_auth)
    mocker.patch.object(demisto, "command", return_value=command)

    # Call the function
    args = {"name": "test-webapp", "enabled": "true"}

    result = update_webapp_auth_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == expected_prefix
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "authsettings"
    assert result.outputs["properties"]["enabled"] is True


def test_mysql_flexible_server_param_set_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to set MySQL flexible server parameters.
    When: The mysql_flexible_server_param_set_command function is called with valid parameters.
    Then: The function should return a success message.
    """

    # Prepare mock
    mocker.patch.object(client, "flexible_server_param_set", return_value=None)

    # Call the function
    args = {
        "server_name": "test-mysql",
        "configuration_name": "require_secure_transport",
        "source": "user-override",
        "value": "ON",
    }

    result = mysql_flexible_server_param_set_command(client, mock_params, args)

    # Verify results
    assert "Updated the configuration require_secure_transport of the server test-mysql" in result.readable_output


def test_monitor_log_profile_update_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to update monitor log profile.
    When: The monitor_log_profile_update_command function is called with valid parameters.
    Then: The function should return the updated log profile in the expected format.
    """

    # Prepare mock responses
    current_profile = {
        "name": "test-profile",
        "id": "/subscriptions/sub-id/providers/Microsoft.Insights/logprofiles/test-profile",
        "location": "eastus",
        "properties": {"retentionPolicy": {"enabled": False, "days": 0}},
    }
    updated_profile = {
        "name": "test-profile",
        "id": "/subscriptions/sub-id/providers/Microsoft.Insights/logprofiles/test-profile",
        "location": "westus",
        "properties": {"retentionPolicy": {"enabled": True, "days": 30}},
    }

    mocker.patch.object(client, "get_monitor_log_profile", return_value=current_profile)
    mocker.patch.object(client, "monitor_log_profile_update", return_value=updated_profile)

    # Call the function
    args = {
        "log_profile_name": "test-profile",
        "location": "westus",
        "subscription_id": "sub-id",
        "retention_policy_days": "30",
        "retention_policy_enabled": "true",
    }

    result = monitor_log_profile_update_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == "Azure.Monitor.LogProfiles"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "test-profile"
    assert result.outputs["location"] == "westus"
    assert result.outputs["properties"]["retentionPolicy"]["enabled"] is True
    assert result.outputs["properties"]["retentionPolicy"]["days"] == 30


@pytest.mark.parametrize(
    "command, expected_prefix",
    [
        ("azure-disk-update", "Azure.Disk"),
        ("azure-disk-set-data-access-ad-quick-action", "Azure.Disk"),
        ("azure-disable-public-private-access-vm-disk-quick-action", "Azure.Disk"),
        ("azure-compute-disk-update", "Azure.Compute.Disks"),
        ("azure-disable-public-n-private-access-vm-disk-quick-action", "Azure.Compute.Disks"),
        ("azure-compute-disk-update-data-access-ad-quick-action", "Azure.Compute.Disks"),
    ],
)
def test_disk_update_command(mocker, client, mock_params, command, expected_prefix):
    """
    Given: An Azure client and a request to update disk properties.
    When: The disk_update_command function is called with valid parameters.
    Then: The function should return the updated disk properties in the expected format.
    """

    # Prepare mock response
    disk_response = {
        "name": "test-disk",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Compute/disks/test-disk",
        "properties": {
            "publicNetworkAccess": "Disabled",
            "networkAccessPolicy": "DenyAll",
            "dataAccessAuthMode": "AzureActiveDirectory",
        },
    }

    mocker.patch.object(client, "disk_update", return_value=disk_response)
    mocker.patch.object(demisto, "command", return_value=command)

    # Call the function
    args = {
        "disk_name": "test-disk",
        "public_network_access": "Disabled",
        "network_access_policy": "DenyAll",
        "data_access_auth_mode": "AzureActiveDirectory",
    }

    result = disk_update_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == expected_prefix
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "test-disk"
    assert result.outputs["properties"]["publicNetworkAccess"] == "Disabled"
    assert result.outputs["properties"]["networkAccessPolicy"] == "DenyAll"
    assert result.outputs["properties"]["dataAccessAuthMode"] == "AzureActiveDirectory"


@pytest.mark.parametrize(
    "command, expected_prefix",
    [
        ("azure-webapp-update", "Azure.WebApp"),
        ("azure-webapp-assign-managed-identity-quick-action", "Azure.WebApp"),
        ("azure-webapp-update-assign-managed-identity-quick-action", "Azure.WebApp"),
        ("azure-appservice-webapp-update", "Azure.AppService.WebApp"),
        ("azure-appservice-webapp-update-quick-action", "Azure.AppService.WebApp"),
    ],
)
def test_webapp_update_command(mocker, client, mock_params, command, expected_prefix):
    """
    Given: An Azure client and a request to update webapp properties.
    When: The webapp_update_command function is called with valid parameters.
    Then: The function should return the updated webapp properties in the expected format.
    """

    # Prepare mock response
    webapp_response = {
        "name": "test-webapp",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-webapp",
        "identity": {"type": "SystemAssigned"},
        "properties": {"httpsOnly": True, "clientCertEnabled": True},
    }

    mocker.patch.object(client, "webapp_update", return_value=webapp_response)
    mocker.patch.object(demisto, "command", return_value=command)

    # Call the function
    args = {"name": "test-webapp", "identity_type": "SystemAssigned", "https_only": "true", "client_cert_enabled": "true"}

    result = webapp_update_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == expected_prefix
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "test-webapp"
    assert result.outputs["identity"]["type"] == "SystemAssigned"
    assert result.outputs["properties"]["httpsOnly"] is True
    assert result.outputs["properties"]["clientCertEnabled"] is True


@pytest.mark.parametrize(
    "command, expected_prefix",
    [
        ("azure-acr-update", "Azure.ACR"),
        ("azure-acr-disable-public-private-access-quick-action", "Azure.ACR"),
        ("azure-acr-disable-authentication-as-arm-quick-action", "Azure.ACR"),
        ("azure-acr-disable-anonymous-pull-quick-action", "Azure.ACR"),
        ("azure-cr-registry-update", "Azure.ContainerRegistry.Registries"),
        ("azure-cr-disable-public-private-access-quick-action", "Azure.ContainerRegistry.Registries"),
        ("azure-cr-disable-anonymous-pull-quick-action", "Azure.ContainerRegistry.Registries"),
        ("azure-cr-disable-authentication-as-arm-quick-action", "Azure.ContainerRegistry.Registries"),
    ],
)
def test_acr_update_command(mocker, client, mock_params, command, expected_prefix):
    """
    Given: An Azure client and a request to update Azure Container Registry properties.
    When: The acr_update_command function is called with valid parameters.
    Then: The function should return the updated ACR properties in the expected format.
    """

    # Prepare mock response
    acr_response = {
        "name": "testregistry",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.ContainerRegistry/registries/testregistry",
        "properties": {
            "publicNetworkAccess": "Disabled",
            "anonymousPullEnabled": False,
            "policies": {"exportPolicy": {"status": "disabled"}, "azureADAuthenticationAsArmPolicy": {"status": "enabled"}},
        },
    }

    mocker.patch.object(client, "acr_update", return_value=acr_response)
    mocker.patch.object(demisto, "command", return_value=command)

    # Call the function
    args = {
        "registry_name": "testregistry",
        "allow_exports": "disabled",
        "public_network_access": "Disabled",
        "anonymous_pull_enabled": "false",
        "authentication_as_arm_policy": "enabled",
    }

    result = acr_update_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == expected_prefix
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "testregistry"
    assert result.outputs["properties"]["publicNetworkAccess"] == "Disabled"
    assert result.outputs["properties"]["anonymousPullEnabled"] is False
    assert result.outputs["properties"]["policies"]["exportPolicy"]["status"] == "disabled"
    assert result.outputs["properties"]["policies"]["azureADAuthenticationAsArmPolicy"]["status"] == "enabled"


def test_postgres_server_update_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to update PostgreSQL server properties.
    When: The postgres_server_update_command function is called with valid parameters.
    Then: The function should successfully call the server update method.
    """

    # Prepare mock response
    postgres_response = {
        "name": "test-postgres",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.DBforPostgreSQL/servers/test-postgres",
        "properties": {"sslEnforcement": "Enabled"},
    }

    mocker.patch.object(client, "postgres_server_update", return_value=postgres_response)

    # Call the function
    args = {"server_name": "test-postgres", "ssl_enforcement": "Enabled"}

    # This command doesn't have a return value to test, just ensure it calls the client method
    postgres_server_update_command(client, mock_params, args)

    # Verify the client's method was called with the correct parameters
    client.postgres_server_update.assert_called_once_with(
        mock_params.get("subscription_id"), mock_params.get("resource_group_name"), "test-postgres", "Enabled"
    )


def test_update_key_vault_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to update Key Vault properties.
    When: The update_key_vault_command function is called with valid parameters.
    Then: The function should return the updated Key Vault properties in the expected format.
    """

    # Prepare mock response
    keyvault_response = {
        "name": "test-keyvault",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-keyvault",
        "properties": {"enableSoftDelete": True, "enablePurgeProtection": True},
    }

    mocker.patch.object(client, "update_key_vault_request", return_value=keyvault_response)

    # Call the function
    args = {"vault_name": "test-keyvault", "enable_soft_delete": "true", "enable_purge_protection": "true"}

    result = update_key_vault_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == "Azure.KeyVault.Vault"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "test-keyvault"
    assert result.outputs["properties"]["enableSoftDelete"] is True
    assert result.outputs["properties"]["enablePurgeProtection"] is True


def test_update_key_vault_command_deprecated(mocker, client, mock_params):
    """
    Given: An Azure client and a request to update Key Vault properties using the deprecated command.
    When: The update_key_vault_command function is called with the deprecated command name.
    Then: The function should return the updated Key Vault properties with the deprecated prefix.
    """

    # Prepare mock response
    keyvault_response = {
        "name": "test-keyvault",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-keyvault",
        "properties": {"enableSoftDelete": True, "enablePurgeProtection": True},
    }

    mocker.patch.object(client, "update_key_vault_request", return_value=keyvault_response)
    mocker.patch("Azure.demisto.command", return_value="azure-key-vault-update")

    # Call the function
    args = {"vault_name": "test-keyvault", "enable_soft_delete": "true", "enable_purge_protection": "true"}

    result = update_key_vault_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == "Azure.KeyVault"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "test-keyvault"
    assert result.outputs["properties"]["enableSoftDelete"] is True
    assert result.outputs["properties"]["enablePurgeProtection"] is True


def test_sql_db_threat_policy_update_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to update SQL database threat policy.
    When: The sql_db_threat_policy_update_command function is called with valid parameters.
    Then: The function should return the updated threat policy in the expected format.
    """

    # Prepare mock responses
    current_policy = {
        "name": "default",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server/databases/test-db/"
        "securityAlertPolicies/default",
        "properties": {"emailAccountAdmins": False},
    }

    updated_policy = {
        "name": "default",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server/databases/test-db/"
        "securityAlertPolicies/default",
        "properties": {"emailAccountAdmins": True},
    }

    mocker.patch.object(client, "sql_db_threat_policy_get", return_value=current_policy)
    mocker.patch.object(client, "sql_db_threat_policy_update", return_value=updated_policy)

    # Call the function
    args = {"server_name": "test-server", "db_name": "test-db", "email_account_admins_enabled": "true"}

    result = sql_db_threat_policy_update_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == "Azure.SqlDB.SecurityAlertPolicies"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "default"
    assert result.outputs["properties"]["emailAccountAdmins"] is True


def test_sql_db_threat_policy_update_command_deprecated(mocker, client, mock_params):
    """
    Given: An Azure client and a request to update SQL database threat policy using the deprecated command.
    When: The sql_db_threat_policy_update_command function is called with the deprecated command name.
    Then: The function should return the updated threat policy with the deprecated prefix.
    """

    # Prepare mock responses
    current_policy = {
        "name": "default",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server/databases/test-db/"
        "securityAlertPolicies/default",
        "properties": {"emailAccountAdmins": False},
    }

    updated_policy = {
        "name": "default",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Sql/servers/test-server/databases/test-db/"
        "securityAlertPolicies/default",
        "properties": {"emailAccountAdmins": True},
    }

    mocker.patch.object(client, "sql_db_threat_policy_get", return_value=current_policy)
    mocker.patch.object(client, "sql_db_threat_policy_update", return_value=updated_policy)
    mocker.patch("Azure.demisto.command", return_value="azure-sql-db-threat-policy-update")

    # Call the function
    args = {"server_name": "test-server", "db_name": "test-db", "email_account_admins_enabled": "true"}

    result = sql_db_threat_policy_update_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == "Azure.SqlDBThreatPolicy"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "default"
    assert result.outputs["properties"]["emailAccountAdmins"] is True


def test_sql_db_threat_policy_update_command_not_found(mocker, client, mock_params):
    """
    Given: An Azure client and a request to update SQL database threat policy for a non-existent database.
    When: The sql_db_threat_policy_update_command function is called with invalid parameters.
    Then: The function should handle the error case properly.
    """

    # Mock a realistic 404 error response
    def mock_get_threat_policy(*args, **kwargs):
        # Simulate what the actual Azure API would return
        raise DemistoException("Resource not found - Database 'test-db' does not exist on server 'test-server'")

    mocker.patch.object(client, "sql_db_threat_policy_get", side_effect=mock_get_threat_policy)

    # Call the function
    args = {"server_name": "test-server", "db_name": "test-db", "email_account_admins_enabled": "true"}

    # Test that the function handles the exception appropriately
    with pytest.raises(DemistoException) as excinfo:
        sql_db_threat_policy_update_command(client, mock_params, args)

    # Verify the error message contains expected information
    assert "test-db" in str(excinfo.value)
    assert "test-server" in str(excinfo.value)


def test_sql_db_tde_set_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to set transparent data encryption for a SQL database.
    When: The sql_db_tde_set_command function is called with valid parameters.
    Then: The function should return a success message.
    """

    # Prepare mock
    mocker.patch.object(client, "sql_db_tde_set", return_value=None)

    # Call the function
    args = {"server_name": "test-server", "db_name": "test-db", "state": "Enabled"}

    result = sql_db_tde_set_command(client, mock_params, args)

    # Verify results
    assert "Updated SQL database test-db of the server test-server" in result.readable_output


def test_cosmosdb_update_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to update Cosmos DB settings.
    When: The cosmosdb_update_command function is called with valid parameters.
    Then: The function should return the updated Cosmos DB settings in the expected format.
    """

    # Prepare mock response
    cosmos_response = {
        "name": "test-cosmos",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.DocumentDB/databaseAccounts/test-cosmos",
        "properties": {"disableKeyBasedMetadataWriteAccess": True},
    }

    mocker.patch.object(client, "cosmos_db_update", return_value=cosmos_response)

    # Call the function
    args = {"account_name": "test-cosmos", "disable_key_based_metadata_write_access": "true"}

    result = cosmosdb_update_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == "Azure.CosmosDB.DBAccounts"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "test-cosmos"
    assert result.outputs["properties"]["disableKeyBasedMetadataWriteAccess"] is True


def test_cosmosdb_update_command_deprecated(mocker, client, mock_params):
    """
    Given: An Azure client and a request to update Cosmos DB settings using the deprecated command.
    When: The cosmosdb_update_command function is called with the deprecated command name.
    Then: The function should return the updated Cosmos DB settings with the deprecated prefix.
    """

    # Prepare mock response
    cosmos_response = {
        "name": "test-cosmos",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.DocumentDB/databaseAccounts/test-cosmos",
        "properties": {"disableKeyBasedMetadataWriteAccess": True},
    }

    mocker.patch.object(client, "cosmos_db_update", return_value=cosmos_response)
    mocker.patch("Azure.demisto.command", return_value="azure-cosmos-db-update")

    # Call the function
    args = {"account_name": "test-cosmos", "disable_key_based_metadata_write_access": "true"}

    result = cosmosdb_update_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == "Azure.CosmosDB"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "test-cosmos"
    assert result.outputs["properties"]["disableKeyBasedMetadataWriteAccess"] is True


def test_storage_account_update_command_empty_response(mocker, client, mock_params):
    """
    Given: An Azure client and a request to update a storage account that returns an empty response.
    When: The storage_account_update_command function is called with valid parameters.
    Then: The function should return a message indicating the account will be created shortly.
    """

    # Prepare mock response with empty text
    class MockResponse:
        def __init__(self, text=""):
            self.text = text

    mock_response = MockResponse("")

    mocker.patch.object(client, "storage_account_update_request", return_value=mock_response)

    # Call the function
    args = {"account_name": "teststorage", "sku": "Standard_LRS", "kind": "StorageV2", "location": "eastus"}

    result = storage_account_update_command(client, mock_params, args)

    # Verify results
    assert isinstance(result, str)
    assert "The request was accepted - the account teststorage will be created shortly" in result


def test_update_security_rule_command_rule_not_found(mocker, client, mock_params):
    """
    Given: An Azure client and a request to update a non-existent security rule.
    When: The update_security_rule_command function is called with invalid parameters.
    Then: The function should handle the error case properly by raising a ValueError.
    """

    # Mock a 404 error response by raising a ValueError with 404 in it
    error_message = 'Rule test-rule under subscription ID "test_subscription_id" and resource group "test_resource_group" was\
        not found.'
    mocker.patch.object(client, "get_rule", side_effect=ValueError(error_message))

    # Call the function and expect it to raise the ValueError
    args = {"security_group_name": "test-sg", "security_rule_name": "test-rule"}

    with pytest.raises(ValueError) as e:
        update_security_rule_command(client, mock_params, args)

    # Verify the error message
    assert error_message in str(e.value)


def test_main_function_success(mocker):
    """
    Given: A command and valid parameters.
    When: The main function is called.
    Then: The appropriate command function should be called and results returned.
    """
    from Azure import main

    # Mock demisto functions
    mocker.patch.object(demisto, "command", return_value="azure-storage-account-update")
    mocker.patch.object(
        demisto,
        "params",
        return_value={
            "app_id": "test_app_id",
            "subscription_id": "test_subscription_id",
            "resource_group_name": "test_resource_group",
            "auth_type": "Client Credentials",
            "tenant_id": "test_tenant_id",
            "credentials": {"password": "test_enc_key"},
        },
    )
    mocker.patch.object(
        demisto,
        "args",
        return_value={"account_name": "teststorage", "sku": "Standard_LRS", "kind": "StorageV2", "location": "eastus"},
    )

    # mock is_gov_account
    mocker.patch("Azure.is_gov_account", return_value=False)

    # Mock return_results
    mock_return_results = mocker.patch("Azure.return_results")

    # Mock AzureClient
    mock_client = mocker.Mock()
    mocker.patch("Azure.AzureClient", return_value=mock_client)

    # Mock storage_account_update_command to return a CommandResults object
    mock_cmd_result = mocker.Mock()
    mock_storage_account_update = mocker.patch("Azure.storage_account_update_command", return_value=mock_cmd_result)

    # Call main function
    main()

    # Verify that storage_account_update_command was called and results returned
    mock_storage_account_update.assert_called_once()
    mock_return_results.assert_called_once_with(mock_cmd_result)


def test_storage_blob_service_properties_set_command_empty_values(mocker, client, mock_params):
    """
    Given: An Azure client and a request to set blob service properties with empty values.
    When: The storage_blob_service_properties_set_command function is called with minimal parameters.
    Then: The function should make the API call with only the specified parameters.
    """

    # Prepare mock response
    properties_response = {
        "name": "default",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Storage/storageAccounts/teststorage/blobServices/\
            default",
        "properties": {},
    }

    mocker.patch.object(client, "storage_blob_service_properties_set_request", return_value=properties_response)
    mocker.patch("Azure.demisto.command", return_value="azure-storage-blob-service-property-set")

    # Call the function with minimal args
    args = {"account_name": "teststorage"}

    result = storage_blob_service_properties_set_command(client, mock_params, args)

    # Verify results
    assert result.outputs_prefix == "Azure.Storage.BlobServices"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "default"

    # Verify client method was called with None values for optional parameters
    client.storage_blob_service_properties_set_request.assert_called_once_with(
        mock_params.get("subscription_id"), mock_params.get("resource_group_name"), "teststorage", None, None
    )


def test_remove_member_from_role(mocker, client):
    """
    Given: An Azure client and arguments for removing a member from a role.
    When: The remove_member_from_role function is called.
    Then: The function should call the client's remove_member_from_role method and return a success message.
    """
    # Mock arguments
    args = {"role_id": "12345678-1234-1234-1234-123456789012", "user_id": "87654321-4321-4321-4321-210987654321"}

    # Mock the client's remove_member_from_role method
    mocker.patch.object(client, "remove_member_from_role")

    # Call the function
    result = remove_member_from_role(client, args)

    # Verify results
    assert isinstance(result, CommandResults)
    assert f"User ID {args['user_id']} has been removed from role {args['role_id']}" in result.readable_output
    client.remove_member_from_role.assert_called_once_with(args["role_id"], args["user_id"])


def test_remove_member_from_group_command(mocker, client):
    """
    Given: An Azure client and arguments for removing a member from a group.
    When: The remove_member_from_group_command function is called.
    Then: The function should call the client's remove_member_from_group method and return a success message.
    """
    # Mock arguments
    args = {"group_id": "11111111-2222-3333-4444-555555555555", "user_id": "87654321-4321-4321-4321-210987654321"}

    # Mock the client's remove_member_from_group method
    mocker.patch.object(client, "remove_member_from_group")

    # Call the function
    result = remove_member_from_group_command(client, args)

    # Verify results
    assert isinstance(result, CommandResults)
    assert f"User {args['user_id']} was removed from the Group \"{args['group_id']}\" successfully." in result.readable_output
    client.remove_member_from_group.assert_called_once_with(args["group_id"], args["user_id"])


def test_get_azure_client_no_token(mocker, mock_params):
    """
    Given: Platform (connector) path where cloud credentials return no token.
    When: The get_azure_client function is called.
    Then: The function should raise an exception about the missing token.
    """
    # Setup mocks
    args = {"subscription_id": "arg_subscription_id"}
    command = "command"

    mocker.patch("Azure.get_connector_id", return_value="connector-123")  # Platform path
    mocker.patch("Azure.get_from_args_or_params", return_value="mocked_subscription_id")
    mocker.patch("Azure.get_cloud_credentials", return_value={})  # No token

    # Test without credentials and no token
    params = mock_params.copy()
    params["credentials"] = {}

    # Verify exception is raised
    with pytest.raises(DemistoException) as excinfo:
        get_azure_client(params, args, command)

    assert "Failed to retrieve AZURE access token" in str(excinfo.value)


def test_get_azure_client_marketplace_missing_secret(mocker, mock_params):
    """
    Given: Marketplace path (no connector) with the Client Credentials flow and no Client Secret.
    When: The get_azure_client function is called.
    Then: The function should raise a clear DemistoException about the missing Client Secret.
    """
    args = {"subscription_id": "arg_subscription_id"}
    command = "command"

    mocker.patch("Azure.get_connector_id", return_value=None)  # Marketplace path

    params = mock_params.copy()
    params["credentials"] = {}
    params["auth_type"] = "Client Credentials"

    with pytest.raises(DemistoException) as excinfo:
        get_azure_client(params, args, command)

    assert "Client Secret" in str(excinfo.value)


def test_get_azure_client_with_stored_credentials(mocker, mock_params):
    """
    Given: Marketplace path with a Client Secret configured (Client Credentials flow).
    When: The get_azure_client function is called.
    Then: The function should return an initialized Azure client using the secret without cloud (CTS) authentication.
    """
    # Setup mocks
    args = {"subscription_id": "arg_subscription_id"}
    command = "command"
    mock_client = mocker.Mock()

    mocker.patch("Azure.get_connector_id", return_value=None)  # Marketplace path
    mock_get_managed = mocker.patch("Azure.get_azure_managed_identities_client_id", return_value=None)
    mock_azure_client_constructor = mocker.patch("Azure.AzureClient", return_value=mock_client)

    # Test with credentials (stored credentials path)
    params = mock_params.copy()
    params["credentials"] = {"password": "test_password"}

    # Call the function
    result = get_azure_client(params, args, command)

    # Verify results
    assert result == mock_client

    # Verify AzureClient was instantiated with correct parameters
    mock_azure_client_constructor.assert_called_once_with(
        app_id=params["app_id"],
        subscription_id=params["subscription_id"],
        resource_group_name=params["resource_group_name"],
        verify=not params["insecure"],
        proxy=params["proxy"],
        tenant_id=params["tenant_id"],
        enc_key="test_password",
        resource=Resources.management_azure,
        scope=SCOPE_BY_CONNECTION.get("Client Credentials"),
        headers={},
        connection_type="Client Credentials",
        azure_ad_endpoint="https://login.microsoftonline.com",
        auth_code=None,
        redirect_uri=None,
        managed_identities_client_id=mock_get_managed.return_value,
    )


def test_get_azure_client_with_cloud_credentials_azure_command(mocker, mock_params):
    """
    Given: Platform (connector) path without stored credentials.
    When: The get_azure_client function is called.
    Then: The function should retrieve cloud credentials and return a client with proper headers and scope.
    """
    # Setup mocks
    args = {"subscription_id": "arg_subscription_id"}
    command = "command"
    mock_client = mocker.Mock()
    mock_token = "mock_access_token"

    mocker.patch("Azure.get_connector_id", return_value="connector-123")  # Platform path
    mock_get_managed = mocker.patch("Azure.get_azure_managed_identities_client_id", return_value=None)
    mocker.patch("Azure.get_from_args_or_params", return_value="test_subscription_id")
    mocker.patch("Azure.get_cloud_credentials", return_value={"access_token": mock_token})
    mock_azure_client_constructor = mocker.patch("Azure.AzureClient", return_value=mock_client)

    # Test without stored credentials (cloud credentials path)
    params = mock_params.copy()
    params["credentials"] = {}  # No stored credentials

    # Call the function
    result = get_azure_client(params, args, command)

    # Verify results
    assert result == mock_client

    # Verify cloud credentials were retrieved with correct parameters
    Azure.get_cloud_credentials.assert_called_once_with(CloudTypes.AZURE.value, "test_subscription_id", scopes=["DEFAULT"])

    # Verify AzureClient was instantiated with correct parameters including headers
    expected_headers = {"Authorization": f"Bearer {mock_token}", "Content-Type": "application/json", "Accept": "application/json"}
    mock_azure_client_constructor.assert_called_once_with(
        app_id=params["app_id"],
        subscription_id=params["subscription_id"],
        resource_group_name=params["resource_group_name"],
        verify=not params["insecure"],
        proxy=params["proxy"],
        tenant_id=params["tenant_id"],
        enc_key=None,
        resource=Resources.management_azure,
        scope=SCOPE_BY_CONNECTION.get("Client Credentials"),
        headers=expected_headers,
        connection_type="Client Credentials",
        azure_ad_endpoint="https://login.microsoftonline.com",
        auth_code=None,
        redirect_uri=None,
        managed_identities_client_id=mock_get_managed.return_value,
    )


def test_get_azure_client_no_token_raises_exception(mocker, mock_params):
    """
    Given: Platform (connector) path with cloud credentials that return no token.
    When: The get_azure_client function is called.
    Then: The function should raise a DemistoException about missing token.
    """
    # Setup mocks
    args = {"subscription_id": "arg_subscription_id"}
    command = "command"
    mocker.patch("Azure.get_connector_id", return_value="connector-123")  # Platform path
    mocker.patch("Azure.get_from_args_or_params", return_value="test_subscription_id")
    mocker.patch("Azure.get_cloud_credentials", return_value={})  # No access_token

    # Test without credentials and no token
    params = mock_params.copy()
    params["credentials"] = {}

    # Verify exception is raised
    with pytest.raises(DemistoException) as excinfo:
        get_azure_client(params, args, command)

    assert "Failed to retrieve AZURE access token - token is missing from credentials" in str(excinfo.value)


def test_get_azure_client_insecure_and_proxy_settings(mocker, mock_params):
    """
    Given: Parameters with insecure=True and proxy=True settings.
    When: The get_azure_client function is called.
    Then: The function should pass the correct verify and proxy parameters to AzureClient.
    """
    # Setup mocks
    args = {"subscription_id": "arg_subscription_id"}
    command = "command"
    mock_client = mocker.Mock()

    mock_azure_client_constructor = mocker.patch("Azure.AzureClient", return_value=mock_client)

    # Test with insecure and proxy settings
    params = mock_params.copy()
    params["insecure"] = True
    params["proxy"] = True
    params["credentials"] = {"password": "test_password"}

    # Call the function
    result = get_azure_client(params, args, command)

    # Verify results
    assert result == mock_client

    # Verify correct verify and proxy parameters
    call_args = mock_azure_client_constructor.call_args
    assert call_args[1]["verify"] is False  # insecure=True means verify=False
    assert call_args[1]["proxy"] is True


def test_get_azure_client_missing_optional_params(mocker):
    """
    Given: The mandatory Client Credentials params are provided, but the truly optional fields
           (resource_group_name, insecure, proxy) are omitted.
    When: The get_azure_client function is called.
    Then: The function builds the client using default values for the omitted optional fields.
    """
    # Setup mocks
    args = {}
    mock_client = mocker.Mock()
    command = "command"

    mocker.patch("Azure.get_connector_id", return_value=None)  # Marketplace path
    mock_azure_client_constructor = mocker.patch("Azure.AzureClient", return_value=mock_client)

    # Mandatory params for Client Credentials present; optional fields omitted.
    params = {
        "app_id": "test_app_id",
        "subscription_id": "test_subscription_id",
        "tenant_id": "test_tenant_id",
        "credentials": {"password": "test_password"},
    }

    # Call the function
    result = get_azure_client(params, args, command)

    # Verify results
    assert result == mock_client

    # Verify default values were used for the optional fields
    call_args = mock_azure_client_constructor.call_args
    assert call_args[1]["resource_group_name"] == ""
    assert call_args[1]["verify"] is True  # Default for insecure=False
    assert call_args[1]["proxy"] is False  # Default


def test_format_rule_dict_input(mocker):
    """
    Given: A rule JSON as dictionary and security rule name.
    When: The format_rule function is called.
    Then: The function should format the rule properly and return CommandResults.
    """
    # Prepare test data
    rule_json = {
        "name": "test-rule",
        "id": (
            "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-sg/"
            "securityRules/test-rule"
        ),
        "properties": {
            "protocol": "Tcp",
            "sourcePortRange": "*",
            "destinationPortRange": "443",
            "access": "Allow",
            "priority": 100,
            "direction": "Inbound",
        },
    }
    security_rule_name = "test-rule"

    # Mock tableToMarkdown
    mock_table = mocker.patch("Azure.tableToMarkdown", return_value="Mock Table")

    # Call the function
    result = format_rule(rule_json, security_rule_name)

    # Verify results
    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.NSGRule"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "test-rule"
    assert result.outputs["protocol"] == "Tcp"
    assert result.outputs["access"] == "Allow"
    assert "properties" not in result.outputs  # Properties should be flattened

    # Verify tableToMarkdown was called
    mock_table.assert_called_once()


def test_format_rule_list_input(mocker):
    """
    Given: A rule JSON as list and security rule name.
    When: The format_rule function is called.
    Then: The function should format all rules properly and return CommandResults.
    """
    # Prepare test data
    rule_json = [
        {
            "name": "rule1",
            "id": (
                "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-sg/"
                "securityRules/rule1"
            ),
            "properties": {"protocol": "Tcp", "access": "Allow"},
        },
        {
            "name": "rule2",
            "id": (
                "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-sg/"
                "securityRules/rule2"
            ),
            "properties": {"protocol": "Udp", "access": "Deny"},
        },
    ]
    security_rule_name = "test-rules"

    # Mock tableToMarkdown
    mocker.patch("Azure.tableToMarkdown", return_value="Mock Table")

    # Call the function
    result = format_rule(rule_json, security_rule_name)

    # Verify results
    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.NSGRule"
    assert result.outputs_key_field == "id"
    assert len(result.outputs) == 2
    assert result.outputs[0]["name"] == "rule1"
    assert result.outputs[0]["protocol"] == "Tcp"
    assert result.outputs[1]["name"] == "rule2"
    assert result.outputs[1]["protocol"] == "Udp"

    # Verify properties were flattened for all rules
    for rule in result.outputs:
        assert "properties" not in rule


def test_azure_client_handle_azure_error_404(mocker, client):
    """
    Given: An Azure client and a 404 error.
    When: The handle_azure_error method is called.
    Then: The function should raise a ValueError with appropriate message.
    """
    # Prepare test data
    error = Exception("404 - Not Found")
    resource_name = "test-resource"
    resource_type = "Storage Account"
    subscription_id = "test-subscription"
    resource_group_name = "test-rg"

    # Verify ValueError is raised for 404 errors
    with pytest.raises(ValueError) as excinfo:
        client.handle_azure_error(
            e=error,
            resource_name=resource_name,
            resource_type=resource_type,
            api_function_name="test",
            subscription_id=subscription_id,
            resource_group_name=resource_group_name,
        )

    assert 'Storage Account "test-resource"' in str(excinfo.value)
    assert 'subscription ID "test-subscription"' in str(excinfo.value)
    assert 'resource group "test-rg"' in str(excinfo.value)
    assert "was not found" in str(excinfo.value)


def test_azure_client_handle_azure_error_using_return_multiple_permissions_error_function(mocker):
    """
    Test the permission lookup logic and return_multiple_permissions_error call in handle_azure_error.

    Tests:
    1. Permission found via API function mapping
    2. Permission found via fallback method
    """
    from Azure import AzureClient

    mock_get_permissions_from_api = mocker.patch("Azure.get_permissions_from_api_function_name")
    mock_get_permissions_from_required = mocker.patch("Azure.get_permissions_from_required_role_permissions_list")
    mock_return_multiple_permissions_error = mocker.patch("Azure.return_multiple_permissions_error")
    client = AzureClient("tenant_id", "client_id", "client_secret")

    # Test case 1: Permission found via API function mapping
    mock_get_permissions_from_api.return_value = ["Microsoft.Network/networkInterfaces/read"]
    mock_get_permissions_from_required.return_value = None
    exception_403 = Exception("403 Forbidden: Access denied")

    client.handle_azure_error(
        e=exception_403,
        resource_name="test-nic",
        resource_type="Network Interface",
        api_function_name="list_networks_interfaces_request",
        subscription_id="sub123",
    )

    mock_get_permissions_from_api.assert_called_with("list_networks_interfaces_request", "403 forbidden: access denied")
    mock_get_permissions_from_required.assert_not_called()

    expected_error_entries = [
        {"account_id": "sub123", "message": "403 forbidden: access denied", "name": "Microsoft.Network/networkInterfaces/read"}
    ]
    mock_return_multiple_permissions_error.assert_called_once_with(expected_error_entries)

    mock_get_permissions_from_api.reset_mock()
    mock_get_permissions_from_required.reset_mock()
    mock_return_multiple_permissions_error.reset_mock()

    # Test case 2: Permission found via fallback method
    mock_get_permissions_from_api.return_value = None
    mock_get_permissions_from_required.return_value = ["Microsoft.Storage/storageAccounts/write"]
    exception_401 = Exception("401 Unauthorized")

    client.handle_azure_error(
        e=exception_401,
        resource_name="test-storage",
        resource_type="Storage Account",
        api_function_name="storage_account_update_request",
        subscription_id="sub456",
    )

    mock_get_permissions_from_api.assert_called_with("storage_account_update_request", "401 unauthorized")
    mock_get_permissions_from_required.assert_called_with("401 unauthorized")
    expected_error_entries = [
        {"account_id": "sub456", "message": "401 unauthorized", "name": "Microsoft.Storage/storageAccounts/write"}
    ]
    mock_return_multiple_permissions_error.assert_called_once_with(expected_error_entries)


def test_azure_client_handle_azure_error_400(mocker, client):
    """
    Given: An Azure client and a 400 error.
    When: The handle_azure_error method is called.
    Then: The function should raise a DemistoException with bad request error message.
    """
    # Prepare test data
    error = Exception("400 - Bad Request")
    resource_name = "test-resource"
    resource_type = "Disk"

    # Verify DemistoException is raised for 400 errors
    with pytest.raises(DemistoException) as excinfo:
        client.handle_azure_error(e=error, resource_name=resource_name, resource_type=resource_type, api_function_name="test")

    assert 'Invalid request for Disk "test-resource"' in str(excinfo.value)


def test_azure_client_handle_azure_error_generic(mocker, client):
    """
    Given: An Azure client and a generic error.
    When: The handle_azure_error method is called.
    Then: The function should raise a DemistoException with the original error.
    """
    # Prepare test data
    error = Exception("Some other error")
    resource_name = "test-resource"
    resource_type = "Virtual Machine"

    # Verify DemistoException is raised for generic errors
    with pytest.raises(DemistoException) as excinfo:
        client.handle_azure_error(e=error, resource_name=resource_name, resource_type=resource_type, api_function_name="test")

    assert 'Failed to access Virtual Machine "test-resource"' in str(excinfo.value)
    assert "Some other error" in str(excinfo.value)


def test_azure_client_http_request_with_headers(mocker, mock_params):
    """
    Given: An Azure client with headers and request parameters.
    When: The http_request method is called.
    Then: The function should make the request with proper headers and proxy settings.
    """
    # Setup mocks
    headers = {"Authorization": "Bearer token", "Content-Type": "application/json"}
    mock_base_client = mocker.Mock()
    mocker.patch("Azure.get_proxydome_token", return_value="proxy_token")
    mocker.patch("Azure.BaseClient", return_value=mock_base_client)

    # Create client with headers
    client = AzureClient(headers=headers)

    # Call the function
    client.http_request(method="GET", url_suffix="/test", params={"param1": "value1"})

    # Verify BaseClient was used and proxydome token was added
    expected_headers = headers.copy()
    expected_headers["x-caller-id"] = "proxy_token"

    mock_base_client._http_request.assert_called_once()
    call_args = mock_base_client._http_request.call_args
    assert call_args[1]["headers"] == expected_headers
    assert "proxies" in call_args[1]


def test_azure_client_http_request_without_headers(mocker, mock_params):
    """
    Given: An Azure client without headers.
    When: The http_request method is called.
    Then: The function should use MicrosoftClient for the request.
    """
    # Setup mocks
    mock_ms_client = mocker.Mock()
    mocker.patch("Azure.MicrosoftClient", return_value=mock_ms_client)

    # Create client without headers
    client = AzureClient()

    # Call the function
    client.http_request(method="GET", url_suffix="/test")

    # Verify MicrosoftClient was used
    mock_ms_client.http_request.assert_called_once_with(
        method="GET", url_suffix="/test", full_url=None, json_data=None, params={"api-version": "2022-09-01"}, resp_type="json"
    )


def test_azure_client_http_request_api_version_override(mocker, mock_params):
    """
    Given: An Azure client and request parameters with custom api-version.
    When: The http_request method is called.
    Then: The function should use the provided api-version instead of default.
    """
    # Setup mocks
    mock_ms_client = mocker.Mock()
    mocker.patch("Azure.MicrosoftClient", return_value=mock_ms_client)

    # Create client
    client = AzureClient()

    # Call the function with custom api-version
    custom_params = {"api-version": "2023-01-01", "other-param": "value"}
    client.http_request(method="GET", url_suffix="/test", params=custom_params)

    # Verify custom api-version was preserved
    mock_ms_client.http_request.assert_called_once()
    call_args = mock_ms_client.http_request.call_args
    assert call_args[1]["params"]["api-version"] == "2023-01-01"
    assert call_args[1]["params"]["other-param"] == "value"


def test_azure_client_initialization_without_refresh_token(mocker):
    """
    Given: An app_id without a refresh token.
    When: AzureClient is initialized.
    Then: The client should not modify the integration context.
    """
    # Mock integration context functions
    mocker.patch("Azure.get_integration_context", return_value={})
    mock_set_context = mocker.patch("Azure.set_integration_context")
    mocker.patch("Azure.MicrosoftClient")

    # Initialize client without refresh token
    AzureClient(app_id="test_app_id")

    # Verify integration context was not modified
    mock_set_context.assert_not_called()


def test_azure_client_http_request_with_base_client(mocker):
    """
    Given: An Azure client with headers configured.
    When: The http_request method is called.
    Then: The function should use BaseClient with proper headers and proxy settings.
    """
    # Setup mocks
    headers = {"Authorization": "Bearer token", "Content-Type": "application/json"}
    mock_base_client = mocker.Mock()
    mock_base_client._http_request.return_value = {"result": "success"}
    mocker.patch("Azure.BaseClient", return_value=mock_base_client)
    mocker.patch("Azure.get_proxydome_token", return_value="proxy_token")

    # Create client with headers
    client = AzureClient(headers=headers)

    # Call the function
    result = client.http_request(method="GET", url_suffix="/test")

    # Verify BaseClient was used with correct parameters
    expected_headers = headers.copy()
    expected_headers["x-caller-id"] = "proxy_token"

    mock_base_client._http_request.assert_called_once()
    call_args = mock_base_client._http_request.call_args
    assert call_args[1]["headers"] == expected_headers
    assert "proxies" in call_args[1]
    assert result == {"result": "success"}


def test_azure_client_http_request_with_microsoft_client(mocker):
    """
    Given: An Azure client without headers configured.
    When: The http_request method is called.
    Then: The function should use MicrosoftClient.
    """
    # Setup mocks
    mock_ms_client = mocker.Mock()
    mock_ms_client.http_request.return_value = {"result": "success"}
    mocker.patch("Azure.MicrosoftClient", return_value=mock_ms_client)

    # Create client without headers
    client = AzureClient()

    # Call the function
    result = client.http_request(method="POST", url_suffix="/test", json_data={"key": "value"})

    # Verify MicrosoftClient was used
    mock_ms_client.http_request.assert_called_once_with(
        method="POST",
        url_suffix="/test",
        full_url=None,
        json_data={"key": "value"},
        params={"api-version": "2022-09-01"},
        resp_type="json",
    )
    assert result == {"result": "success"}


def test_azure_client_get_rule(mocker, client):
    """
    Given: An Azure client and security rule parameters.
    When: The get_rule method is called.
    Then: The function should make the correct API call.
    """
    # Setup mock response
    mock_response = {
        "name": "test-rule",
        "id": (
            "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-sg/"
            "securityRules/test-rule"
        ),
        "properties": {"access": "Allow", "protocol": "Tcp"},
    }
    mocker.patch.object(client, "http_request", return_value=mock_response)

    # Call the function
    result = client.get_rule("test-sg", "test-rule", "sub-id", "test-rg")

    # Verify correct API call was made
    expected_url = (
        f"{PREFIX_URL_AZURE}sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-sg/"
        "securityRules/test-rule"
    )
    client.http_request.assert_called_once_with("GET", full_url=expected_url)
    assert result == mock_response


def test_azure_client_create_policy_assignment(mocker, client):
    """
    Given: An Azure client and policy assignment parameters.
    When: The create_policy_assignment method is called.
    Then: The function should make the correct API call with policy properties.
    """
    # Setup mock response
    mock_response = {
        "name": "test-policy",
        "properties": {"policyDefinitionId": "/providers/Microsoft.Authorization/policySetDefinitions/test-def"},
    }
    mocker.patch.object(client, "http_request", return_value=mock_response)

    # Call the function
    client.create_policy_assignment(
        name="test-policy",
        policy_definition_id="test-def",
        display_name="Test Policy",
        description="Test description",
        parameters={"param1": "value1"},
        scope="scope",
    )

    # Verify correct API call was made
    expected_url = "https://management.azure.com/scope/providers/Microsoft.Authorization/policyAssignments/test-policy"
    client.http_request.assert_called_once()
    call_args = client.http_request.call_args
    assert call_args[1]["method"] == "PUT"
    assert call_args[1]["full_url"] == expected_url

    # Verify policy properties were included
    json_data = call_args[1]["json_data"]
    properties = json_data["properties"]
    assert properties["policyDefinitionId"] == "/providers/Microsoft.Authorization/policySetDefinitions/test-def"
    assert properties["displayName"] == "Test Policy"
    assert properties["description"] == "Test description"
    assert properties["parameters"] == {"param1": "value1"}


def test_azure_client_create_rule_success(mocker, client):
    """
    Given: An Azure client and valid rule creation parameters.
    When: The create_or_update_rule method is called.
    Then: The function should make the correct API call with rule properties and return the response.
    """
    # Setup mock response
    mock_response = {
        "name": "test-rule",
        "id": (
            "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-sg/"
            "securityRules/test-rule"
        ),
        "properties": {
            "protocol": "Tcp",
            "sourcePortRange": "*",
            "destinationPortRange": "443",
            "sourceAddressPrefix": "Internet",
            "destinationAddressPrefix": "10.0.0.0/24",
            "access": "Allow",
            "priority": 100,
            "direction": "Inbound",
            "description": "Test rule",
        },
    }
    mocker.patch.object(client, "http_request", return_value=mock_response)

    # Prepare rule properties
    properties = {
        "protocol": "Tcp",
        "sourcePortRange": "*",
        "destinationPortRange": "443",
        "sourceAddressPrefix": "Internet",
        "destinationAddressPrefix": "10.0.0.0/24",
        "access": "Allow",
        "priority": 100,
        "direction": "Inbound",
        "description": "Test rule",
    }

    # Call the function
    result = client.create_or_update_rule(
        security_group="test-sg",
        rule_name="test-rule",
        properties=properties,
        subscription_id="sub-id",
        resource_group_name="test-rg",
    )

    # Verify correct API call was made
    expected_url = (
        f"{PREFIX_URL_AZURE}sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-sg/"
        "securityRules/test-rule?"
    )
    client.http_request.assert_called_once_with("PUT", full_url=expected_url, json_data={"properties": properties})

    # Verify response
    assert result == mock_response
    assert result["name"] == "test-rule"
    assert result["properties"]["protocol"] == "Tcp"
    assert result["properties"]["access"] == "Allow"


def test_azure_client_create_rule_with_complex_properties(mocker, client):
    """
    Given: An Azure client and complex rule properties with multiple ports and addresses.
    When: The create_or_update_rule method is called.
    Then: The function should handle complex properties correctly.
    """
    # Setup mock response
    mock_response = {
        "name": "complex-rule",
        "id": (
            "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-sg/"
            "securityRules/complex-rule"
        ),
        "properties": {
            "protocol": "*",
            "sourcePortRanges": ["80", "443", "8080-8090"],
            "destinationPortRanges": ["22", "3389"],
            "sourceAddressPrefixes": ["10.0.0.0/24", "192.168.1.0/24"],
            "destinationAddressPrefixes": ["172.16.0.0/16"],
            "access": "Deny",
            "priority": 200,
            "direction": "Outbound",
            "description": "Complex rule with multiple ranges",
        },
    }
    mocker.patch.object(client, "http_request", return_value=mock_response)

    # Prepare complex rule properties
    properties = {
        "protocol": "*",
        "sourcePortRanges": ["80", "443", "8080-8090"],
        "destinationPortRanges": ["22", "3389"],
        "sourceAddressPrefixes": ["10.0.0.0/24", "192.168.1.0/24"],
        "destinationAddressPrefixes": ["172.16.0.0/16"],
        "access": "Deny",
        "priority": 200,
        "direction": "Outbound",
        "description": "Complex rule with multiple ranges",
    }

    # Call the function
    result = client.create_or_update_rule(
        security_group="test-sg",
        rule_name="complex-rule",
        properties=properties,
        subscription_id="sub-id",
        resource_group_name="test-rg",
    )

    # Verify correct API call was made
    expected_url = (
        f"{PREFIX_URL_AZURE}sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-sg/"
        "securityRules/complex-rule?"
    )
    client.http_request.assert_called_once_with("PUT", full_url=expected_url, json_data={"properties": properties})

    # Verify response contains complex properties
    assert result == mock_response
    assert result["properties"]["sourcePortRanges"] == ["80", "443", "8080-8090"]
    assert result["properties"]["destinationPortRanges"] == ["22", "3389"]
    assert result["properties"]["sourceAddressPrefixes"] == ["10.0.0.0/24", "192.168.1.0/24"]


def test_azure_client_storage_account_update_request_success(mocker, client):
    """
    Given: An Azure client and valid storage account update parameters.
    When: The storage_account_update_request method is called.
    Then: The function should make the correct API call with storage account properties and return the response.
    """
    # Setup mock response
    mock_response = mocker.Mock()
    mock_response.text = '{"name": "teststorage", "properties": {"supportsHttpsTrafficOnly": true}}'
    mock_response.json.return_value = {
        "name": "teststorage",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Storage/storageAccounts/teststorage",
        "properties": {"supportsHttpsTrafficOnly": True, "networkAcls": {"bypass": "AzureServices", "defaultAction": "Deny"}},
    }
    mocker.patch.object(client, "http_request", return_value=mock_response)

    # Prepare arguments
    args = {
        "account_name": "teststorage",
        "sku": "Standard_LRS",
        "kind": "StorageV2",
        "location": "eastus",
        "supports_https_traffic_only": "true",
        "network_ruleset_bypass": "AzureServices",
        "network_ruleset_default_action": "Deny",
    }

    # Call the function
    result = client.storage_account_update_request(subscription_id="sub-id", resource_group_name="test-rg", args=args)

    # Verify correct API call was made
    expected_url = f"{PREFIX_URL_AZURE}sub-id/resourceGroups/test-rg/providers/Microsoft.Storage/storageAccounts/teststorage"
    client.http_request.assert_called_once()
    call_args = client.http_request.call_args

    assert call_args[1]["method"] == "PATCH"
    assert call_args[1]["full_url"] == expected_url
    assert call_args[1]["params"]["api-version"] == API_VERSION
    assert call_args[1]["resp_type"] == "response"

    # Verify JSON data structure
    json_data = call_args[1]["json_data"]
    assert json_data["sku"]["name"] == "Standard_LRS"
    assert json_data["kind"] == "StorageV2"
    assert json_data["location"] == "eastus"
    assert json_data["properties"]["supportsHttpsTrafficOnly"] == "true"
    assert json_data["properties"]["networkAcls"]["bypass"] == "AzureServices"
    assert json_data["properties"]["networkAcls"]["defaultAction"] == "Deny"

    # Verify response
    assert result == mock_response


def test_azure_client_storage_blob_service_properties_set_request_success(mocker, client):
    """
    Given: An Azure client and valid blob service properties parameters.
    When: The storage_blob_service_properties_set_request method is called.
    Then: The function should make the correct API call with blob properties and return the response.
    """
    # Setup mock response
    mock_response = {
        "name": "default",
        "id": (
            "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Storage/storageAccounts/teststorage/"
            "blobServices/default"
        ),
        "properties": {"deleteRetentionPolicy": {"enabled": True, "days": 7}},
    }
    mocker.patch.object(client, "http_request", return_value=mock_response)

    # Call the function
    result = client.storage_blob_service_properties_set_request(
        subscription_id="sub-id",
        resource_group_name="test-rg",
        account_name="teststorage",
        delete_rentention_policy_enabled="true",
        delete_rentention_policy_days="7",
    )

    # Verify correct API call was made
    expected_url = (
        f"{PREFIX_URL_AZURE}sub-id/resourceGroups/test-rg/providers/Microsoft.Storage/storageAccounts/teststorage/"
        "blobServices/default"
    )
    client.http_request.assert_called_once()
    call_args = client.http_request.call_args

    assert call_args[1]["method"] == "PUT"
    assert call_args[1]["full_url"] == expected_url
    assert call_args[1]["params"]["api-version"] == API_VERSION

    # Verify JSON data structure
    json_data = call_args[1]["json_data"]
    assert json_data["properties"]["deleteRetentionPolicy"]["enabled"] == "true"
    assert json_data["properties"]["deleteRetentionPolicy"]["days"] == "7"

    # Verify response
    assert result == mock_response
    assert result["name"] == "default"
    assert result["properties"]["deleteRetentionPolicy"]["enabled"] is True
    assert result["properties"]["deleteRetentionPolicy"]["days"] == 7


def test_azure_client_handle_azure_error_other(client):
    """
    Given: An unknown error from Azure API.
    When: handle_azure_error is called.
    Then: The function should raise DemistoException with generic message.
    """
    error = Exception("500 - Internal Server Error")

    with pytest.raises(DemistoException) as excinfo:
        client.handle_azure_error(e=error, resource_name="test-resource", resource_type="SQL Database", api_function_name="test")

    assert 'Failed to access SQL Database "test-resource"' in str(excinfo.value)
    assert "500 - Internal Server Error" in str(excinfo.value)


def test_azure_client_update_webapp_auth_success(mocker, client):
    """
    Given: An Azure client and webapp authentication update parameters.
    When: The update_webapp_auth method is called.
    Then: The function should make the correct API call and return updated settings.
    """
    # Setup mock response
    enabled = True
    mock_response = {"name": "authsettings", "properties": {"enabled": enabled}}
    mocker.patch.object(client, "http_request", return_value=mock_response)

    # Call the function
    result = client.update_webapp_auth(
        name="test-webapp", subscription_id="sub-id", resource_group_name="test-rg", enabled=enabled
    )

    # Verify correct API call
    expected_url = (
        f"{PREFIX_URL_AZURE}sub-id/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-webapp/config/authsettings"
    )
    client.http_request.assert_called_once_with(
        method="PUT",
        full_url=expected_url,
        json_data={"properties": {"enabled": True}},
        params={"api-version": WEBAPP_API_VERSION},
    )

    # Verify response
    assert result == mock_response


def test_azure_client_flexible_server_param_set_success(mocker, client):
    """
    Given: An Azure client and valid MySQL flexible server parameters.
    When: The flexible_server_param_set method is called.
    Then: The function should make the correct API call with proper parameters and return the response.
    """
    # Setup mock response
    mock_response = {
        "name": "require_secure_transport",
        "id": (
            "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.DBforMySQL/flexibleServers/test-mysql/"
            "configurations/require_secure_transport"
        ),
        "properties": {"value": "ON", "source": "user-override", "description": "Whether to require SSL connections"},
    }
    mocker.patch.object(client, "http_request", return_value=mock_response)

    # Call the function
    result = client.flexible_server_param_set(
        server_name="test-mysql",
        configuration_name="require_secure_transport",
        subscription_id="sub-id",
        resource_group_name="test-rg",
        source="user-override",
        value="ON",
    )

    # Verify correct API call was made
    expected_url = (
        f"{PREFIX_URL_AZURE}sub-id/resourceGroups/test-rg/providers/Microsoft.DBforMySQL/flexibleServers/test-mysql/"
        "configurations/require_secure_transport"
    )
    client.http_request.assert_called_once_with(
        method="PUT",
        full_url=expected_url,
        json_data={"properties": {"source": "user-override", "value": "ON"}},
        params={"api-version": FLEXIBLE_API_VERSION},
    )

    # Verify response
    assert result == mock_response
    assert result["name"] == "require_secure_transport"
    assert result["properties"]["value"] == "ON"
    assert result["properties"]["source"] == "user-override"


def test_set_webapp_config(mocker, client):
    """
    Given: An Azure client and arguments for setting webapp configuration.
    When: The set_webapp_config method is called.
    Then: The method should make the correct HTTP request with proper parameters and handle the response.
    """
    # Mock arguments
    name = "test-webapp"
    subscription_id = "12345678-1234-1234-1234-123456789012"
    resource_group_name = "test-resource-group"
    http20_enabled = "true"
    remote_debugging_enabled = "false"
    min_tls_version = "1.2"

    # Mock response
    mock_response = {
        "id": (
            f"/subscriptions/{subscription_id}/resourceGroups/{resource_group_name}/providers/Microsoft.Web/sites/{name}/config/"
            "web"
        ),
        "name": "web",
        "properties": {"http20Enabled": True, "remoteDebuggingEnabled": False, "minTlsVersion": "1.2"},
    }

    # Mock the client's http_request method
    mocker.patch.object(client, "http_request", return_value=mock_response)

    # Call the method
    result = client.set_webapp_config(
        name=name,
        subscription_id=subscription_id,
        resource_group_name=resource_group_name,
        http20_enabled=http20_enabled,
        remote_debugging_enabled=remote_debugging_enabled,
        min_tls_version=min_tls_version,
    )

    # Verify the HTTP request was called with correct parameters
    expected_url = (
        f"https://management.azure.com/subscriptions/{subscription_id}/resourceGroups/{resource_group_name}"
        f"/providers/Microsoft.Web/sites/{name}/config/web"
    )
    expected_data = {
        "properties": {
            "http20Enabled": http20_enabled,
            "remoteDebuggingEnabled": remote_debugging_enabled,
            "minTlsVersion": min_tls_version,
        }
    }
    expected_params = {"api-version": "2024-04-01"}

    client.http_request.assert_called_once_with(
        method="PATCH", full_url=expected_url, json_data=expected_data, params=expected_params
    )

    # Verify the result matches the mock response
    assert result == mock_response


def test_get_webapp_auth_error_handling(mocker, client):
    """
    Given: An Azure client and arguments for getting webapp authentication settings.
    When: The get_webapp_auth method is called and an exception occurs.
    Then: The method should call handle_azure_error with appropriate parameters.
    """
    # Mock arguments
    name = "test-webapp"
    subscription_id = "12345678-1234-1234-1234-123456789012"
    resource_group_name = "test-resource-group"

    # Mock exception
    mock_exception = Exception("404 Not Found")

    # Mock the client's methods
    mocker.patch.object(client, "http_request", side_effect=mock_exception)
    mocker.patch.object(client, "handle_azure_error", side_effect=ValueError("Web App not found"))

    # Call the method and expect it to raise an exception
    with pytest.raises(ValueError, match="Web App not found"):
        client.get_webapp_auth(name=name, subscription_id=subscription_id, resource_group_name=resource_group_name)

    # Verify handle_azure_error was called with correct parameters
    client.handle_azure_error.assert_called_once_with(
        e=mock_exception,
        resource_name=name,
        api_function_name="get_webapp_auth",
        resource_type="Web App",
        subscription_id=subscription_id,
        resource_group_name=resource_group_name,
    )


def test_update_webapp_auth_error_handling(mocker, client):
    """
    Given: An Azure client and arguments for updating webapp authentication settings.
    When: The update_webapp_auth method is called and an exception occurs.
    Then: The method should call handle_azure_error with appropriate parameters.
    """
    # Mock arguments
    name = "test-webapp"
    enabled = True
    subscription_id = "12345678-1234-1234-1234-123456789012"
    resource_group_name = "test-resource-group"

    # Mock exception
    mock_exception = Exception("403 Forbidden")

    # Mock the client's methods
    mocker.patch.object(client, "http_request", side_effect=mock_exception)
    mocker.patch.object(client, "handle_azure_error", side_effect=DemistoException("Insufficient permissions"))

    # Call the method and expect it to raise an exception
    with pytest.raises(DemistoException, match="Insufficient permissions"):
        client.update_webapp_auth(
            name=name, subscription_id=subscription_id, resource_group_name=resource_group_name, enabled=enabled
        )

    # Verify handle_azure_error was called with correct parameters
    client.handle_azure_error.assert_called_once_with(
        e=mock_exception,
        resource_name=name,
        api_function_name="update_webapp_auth",
        resource_type="Web App",
        subscription_id=subscription_id,
        resource_group_name=resource_group_name,
    )


def test_flexible_server_param_set(mocker, client):
    """
    Given: An Azure client and arguments for setting MySQL flexible server parameters.
    When: The flexible_server_param_set method is called.
    Then: The method should make the correct HTTP request with proper parameters.
    """
    # Mock arguments
    server_name = "test-mysql-server"
    configuration_name = "max_connections"
    subscription_id = "12345678-1234-1234-1234-123456789012"
    resource_group_name = "test-resource-group"
    source = "user-override"
    value = "1000"

    # Mock response
    mock_response = {
        "id": (
            f"/subscriptions/{subscription_id}/resourceGroups/{resource_group_name}/providers/Microsoft.DBforMySQL/"
            f"flexibleServers/{server_name}/configurations/{configuration_name}"
        ),
        "name": configuration_name,
        "properties": {"source": source, "value": value},
    }

    # Mock the client's http_request method
    mocker.patch.object(client, "http_request", return_value=mock_response)

    # Call the method
    result = client.flexible_server_param_set(
        server_name=server_name,
        configuration_name=configuration_name,
        subscription_id=subscription_id,
        resource_group_name=resource_group_name,
        source=source,
        value=value,
    )

    # Verify the HTTP request was called with correct parameters
    expected_url = (
        f"https://management.azure.com/subscriptions/{subscription_id}/resourceGroups/{resource_group_name}"
        f"/providers/Microsoft.DBforMySQL/flexibleServers/{server_name}/configurations/{configuration_name}"
    )
    expected_data = {"properties": {"source": source, "value": value}}
    expected_params = {"api-version": "2023-12-30"}

    client.http_request.assert_called_once_with(
        method="PUT", full_url=expected_url, json_data=expected_data, params=expected_params
    )

    # Verify the result matches the mock response
    assert result == mock_response


def test_flexible_server_param_set_error_handling(mocker, client):
    """
    Given: An Azure client and arguments for setting MySQL flexible server parameters.
    When: The flexible_server_param_set method is called and an exception occurs.
    Then: The method should call handle_azure_error with appropriate parameters.
    """
    # Mock arguments
    server_name = "test-mysql-server"
    configuration_name = "max_connections"
    subscription_id = "12345678-1234-1234-1234-123456789012"
    resource_group_name = "test-resource-group"
    source = "user-override"
    value = "1000"

    # Mock exception
    mock_exception = Exception("404 Not Found")

    # Mock the client's methods
    mocker.patch.object(client, "http_request", side_effect=mock_exception)
    mocker.patch.object(client, "handle_azure_error", side_effect=ValueError("MySQL Flexible Server Configuration not found"))

    # Call the method and expect it to raise an exception
    with pytest.raises(ValueError, match="MySQL Flexible Server Configuration not found"):
        client.flexible_server_param_set(
            server_name=server_name,
            configuration_name=configuration_name,
            subscription_id=subscription_id,
            resource_group_name=resource_group_name,
            source=source,
            value=value,
        )

    # Verify handle_azure_error was called with correct parameters
    client.handle_azure_error.assert_called_once_with(
        e=mock_exception,
        resource_name=f"{server_name}/{configuration_name}",
        resource_type="MySQL Flexible Server Configuration",
        api_function_name="flexible_server_param_set",
        subscription_id=subscription_id,
        resource_group_name=resource_group_name,
    )


def test_get_monitor_log_profile(mocker, client):
    """
    Given: An Azure client and arguments for getting a monitor log profile.
    When: The get_monitor_log_profile method is called.
    Then: The method should make the correct HTTP request and return the log profile.
    """
    # Mock arguments
    subscription_id = "12345678-1234-1234-1234-123456789012"
    log_profile_name = "test-log-profile"

    # Mock response
    mock_response = {
        "id": f"/subscriptions/{subscription_id}/providers/Microsoft.Insights/logprofiles/{log_profile_name}",
        "name": log_profile_name,
        "location": "global",
        "properties": {
            "storageAccountId": "/subscriptions/test/resourceGroups/test/providers/Microsoft.Storage/storageAccounts/test",
            "retentionPolicy": {"enabled": True, "days": 30},
        },
    }

    # Mock the client's http_request method
    mocker.patch.object(client, "http_request", return_value=mock_response)

    # Call the method
    result = client.get_monitor_log_profile(subscription_id=subscription_id, log_profile_name=log_profile_name)

    # Verify the HTTP request was called with correct parameters
    expected_url = f"https://management.azure.com/subscriptions/{subscription_id}/providers/Microsoft.Insights/logprofiles/{log_profile_name}"
    expected_params = {"api-version": "2016-03-01"}

    client.http_request.assert_called_once_with(method="GET", full_url=expected_url, params=expected_params)

    # Verify the result matches the mock response
    assert result == mock_response


def test_get_monitor_log_profile_error_handling(mocker, client):
    """
    Given: An Azure client and arguments for getting a monitor log profile.
    When: The get_monitor_log_profile method is called and an exception occurs.
    Then: The method should call handle_azure_error with appropriate parameters.
    """
    # Mock arguments
    subscription_id = "12345678-1234-1234-1234-123456789012"
    log_profile_name = "test-log-profile"

    # Mock exception
    mock_exception = Exception("404 Not Found")

    # Mock the client's methods
    mocker.patch.object(client, "http_request", side_effect=mock_exception)
    mocker.patch.object(client, "handle_azure_error", side_effect=ValueError("Monitor Log Profile not found"))

    # Call the method and expect it to raise an exception
    with pytest.raises(ValueError, match="Monitor Log Profile not found"):
        client.get_monitor_log_profile(subscription_id=subscription_id, log_profile_name=log_profile_name)

    # Verify handle_azure_error was called with correct parameters
    client.handle_azure_error.assert_called_once_with(
        e=mock_exception,
        resource_name=log_profile_name,
        api_function_name="get_monitor_log_profile",
        resource_type="Monitor Log Profile",
        subscription_id=subscription_id,
        resource_group_name=None,
    )


def test_format_rule():
    """
    Given: rule data and rule name
    Then: Command outputs is returned as expected and flattens the `properties` field.

    """
    from Azure import format_rule

    rule = util_load_json("test_data/get_rule_response.json")
    cr = format_rule(rule_json=rule, security_rule_name="RuleName")
    assert cr.raw_response["name"] == "wow"
    assert cr.raw_response["sourceAddressPrefix"] == "3.2.3.2"
    assert "### Rules RuleName" in cr.readable_output


def test_nsg_public_ip_addresses_list_command(mocker):
    """
    Given: An Azure client mock and the list_public_ip_addresses_response.json file.
    When: nsg_public_ip_addresses_list_command is called
          1. With a limit of 2 (all_results=False).
          2. With all_results=True.
    Then:
          1. It should return only 2 results when limited.
          2. It should return all results when all_results=True.
          3. The results should contain expected fields such as name, id, fqdn.
          4. The etag field should be cleaned up (first 3 chars and last char removed).
    """
    from Azure import nsg_public_ip_addresses_list_command

    mock_response = util_load_json("test_data/list_public_ip_addresses_response.json")

    mock_client = mocker.Mock()
    mock_client.list_public_ip_addresses_request.return_value = mock_response

    params = {"subscription_id": "subid", "resource_group_name": "rg1"}

    args = {"limit": "2", "all_results": "false"}
    result: CommandResults = nsg_public_ip_addresses_list_command(mock_client, params, args)

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.VirtualNetworks.PublicIPAddresses"
    assert result.outputs_key_field == "id"
    assert len(result.outputs) == 2
    assert "name" in result.outputs[0]
    assert "id" in result.outputs[0]

    # "123etag3" should become "etag" after [3:-1]
    first_item_with_etag = result.outputs[0]  # First item has etag "123etag3"
    if first_item_with_etag.get("etag"):
        assert first_item_with_etag.get("etag") == "etag"

    args = {"all_results": "true"}
    result_all: CommandResults = nsg_public_ip_addresses_list_command(mock_client, params, args)

    assert isinstance(result_all, CommandResults)
    assert len(result_all.outputs) == len(mock_response["value"])  # Should be 3 items

    fqdn_values = [
        out.get("properties", {}).get("dnsSettings", {}).get("fqdn")
        for out in result_all.outputs
        if out.get("properties", {}).get("dnsSettings", {}).get("fqdn")
    ]

    assert len(fqdn_values) == 2
    assert "testlbl.westus.cloudapp.azure.com" in fqdn_values
    assert "testlbl.hxdwgjcdfgbhgebs.eastus.sysgen.cloudapp.azure.com" in fqdn_values

    # Check readable_output is generated
    assert result_all.readable_output
    assert "Public IP Addresses List" in result_all.readable_output


def test_nsg_public_ip_addresses_list_command_deprecated(mocker):
    """
    Given: An Azure client mock and the list_public_ip_addresses_response.json file using the deprecated command.
    When: nsg_public_ip_addresses_list_command is called with the deprecated command name.
    Then: It should return the public IP addresses data with the deprecated prefix.
    """
    from Azure import nsg_public_ip_addresses_list_command

    mock_response = util_load_json("test_data/list_public_ip_addresses_response.json")

    mock_client = mocker.Mock()
    mock_client.list_public_ip_addresses_request.return_value = mock_response

    params = {"subscription_id": "subid", "resource_group_name": "rg1"}
    args = {"limit": "2", "all_results": "false"}

    mocker.patch("Azure.demisto.command", return_value="azure-nsg-public-ip-addresses-list")

    result: CommandResults = nsg_public_ip_addresses_list_command(mock_client, params, args)

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.NSGPublicIPAddress"
    assert result.outputs_key_field == "id"
    assert len(result.outputs) == 2
    assert "name" in result.outputs[0]
    assert "id" in result.outputs[0]


def test_nsg_network_interfaces_list_command(mocker):
    """
    Given: An Azure client mock and the list_networks_interfaces_response.json file.
    When: nsg_network_interfaces_list_command is called
          1. With a limit of 1 (all_results=False).
          2. With all_results=True.
    Then:
          1. It should return only 1 result when limited.
          2. It should return all results when all_results=True.
          3. The results should contain expected fields such as name, id.
          4. The etag field should be cleaned up (first 3 chars and last char removed).
    """
    from Azure import nsg_network_interfaces_list_command

    mock_response = util_load_json("test_data/list_networks_interfaces_response.json")

    mock_client = mocker.Mock()
    mock_client.list_networks_interfaces_request.return_value = mock_response

    params = {"subscription_id": "subid", "resource_group_name": "rg1"}

    # --- Case 1: with limit=1 ---
    args = {"limit": "1", "all_results": "false"}
    result: CommandResults = nsg_network_interfaces_list_command(mock_client, params, args)

    assert result.outputs_prefix == "Azure.VirtualNetworks.NetworkInterfaces"
    assert result.outputs_key_field == "id"
    assert len(result.outputs) == 1
    first = result.outputs[0]

    assert first["name"] == "test-nic"
    assert first["id"] == "/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.Network/networkInterfaces/test-nic"

    # --- Case 2: with all_results=True ---
    args = {"all_results": "true"}
    result_all: CommandResults = nsg_network_interfaces_list_command(mock_client, params, args)

    assert isinstance(result_all, CommandResults)
    assert len(result_all.outputs) == len(mock_response["value"])  # Should be 2 items
    assert len(result_all.outputs) == 2

    names = [item["name"] for item in result_all.outputs]
    assert "test-nic" in names
    assert "test-nic2" in names

    for item in result_all.outputs:
        if item.get("etag"):
            assert item["etag"] == "etag"

    assert result_all.readable_output
    assert "Network Interfaces List" in result_all.readable_output


def test_nsg_network_interfaces_list_command_deprecated(mocker):
    """
    Given: An Azure client mock and the list_networks_interfaces_response.json file using the deprecated command.
    When: nsg_network_interfaces_list_command is called with the deprecated command name.
    Then: It should return the network interfaces data with the deprecated prefix.
    """
    from Azure import nsg_network_interfaces_list_command

    mock_response = util_load_json("test_data/list_networks_interfaces_response.json")

    mock_client = mocker.Mock()
    mock_client.list_networks_interfaces_request.return_value = mock_response

    params = {"subscription_id": "subid", "resource_group_name": "rg1"}
    args = {"limit": "1", "all_results": "false"}

    mocker.patch("Azure.demisto.command", return_value="azure-nsg-network-interfaces-list")

    result: CommandResults = nsg_network_interfaces_list_command(mock_client, params, args)

    assert result.outputs_prefix == "Azure.NSGNetworkInterfaces"
    assert result.outputs_key_field == "id"
    assert len(result.outputs) == 1


def test_nsg_resource_group_list_command(mocker):
    """
    Given: An Azure client mock and the list_resource_groups_response.json file.
    When: nsg_resource_group_list_command is called
          1. With a limit of 1.
          2. Without limit (default).
    Then:
          1. It should respect the limit argument.
          2. It should return the resource group data with expected fields.
          3. It should generate proper readable output.
    """
    from Azure import nsg_resource_group_list_command

    mock_response = util_load_json("test_data/list_resource_groups_response.json")

    mock_client = mocker.Mock()
    mock_client.list_resource_groups_request.return_value = mock_response

    params = {"subscription_id": "subscription1"}

    # --- Case 1: with limit=1 ---
    args = {"limit": "1"}
    result: CommandResults = nsg_resource_group_list_command(mock_client, params, args)

    # Check that client method was called with correct parameters including limit
    mock_client.list_resource_groups_request.assert_called_with(subscription_id="subscription1", filter_by_tag="", limit="1")

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.ResourceManagement.ResourceGroups"
    assert result.outputs_key_field == "id"
    assert len(result.outputs) == 1

    first = result.outputs[0]
    assert first["name"] == "resourceGroup1"
    assert first["location"] == "centralus"
    assert "tags" in first
    assert "properties" in first
    assert first["properties"]["provisioningState"] == "Succeeded"

    # Check readable_output is generated
    assert result.readable_output
    assert "Resource Groups List" in result.readable_output

    # --- Case 2: no limit (default) ---
    args = {}
    result_default: CommandResults = nsg_resource_group_list_command(mock_client, params, args)

    assert isinstance(result_default, CommandResults)
    assert len(result_default.outputs) == 1
    assert result_default.outputs[0]["id"] == "/subscriptions/subscription1/resourceGroups/resourceGroup1"


def test_nsg_resource_group_list_command_deprecated(mocker):
    """
    Given: An Azure client mock and the list_resource_groups_response.json file using the deprecated command.
    When: nsg_resource_group_list_command is called with the deprecated command name.
    Then: It should return the resource group data with the deprecated prefix.
    """
    from Azure import nsg_resource_group_list_command

    mock_response = util_load_json("test_data/list_resource_groups_response.json")

    mock_client = mocker.Mock()
    mock_client.list_resource_groups_request.return_value = mock_response

    params = {"subscription_id": "subscription1"}
    args = {"limit": "1"}

    mocker.patch("Azure.demisto.command", return_value="azure-nsg-resource-group-list")

    result: CommandResults = nsg_resource_group_list_command(mock_client, params, args)

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.NSGResourceGroup"
    assert result.outputs_key_field == "id"
    assert len(result.outputs) == 1

    first = result.outputs[0]
    assert first["name"] == "resourceGroup1"
    assert first["location"] == "centralus"


def test_nsg_security_rule_create_command(mocker):
    """
    Given: An Azure client mock and arguments for creating a security rule.
    When: nsg_security_rule_create_command is called.
    Then:
        1. It should call create_or_update_rule with correct properties.
        2. The returned CommandResults should include the created rule data.
        3. The etag should be cleaned up.
        4. Readable output should be generated.
    """
    from Azure import nsg_security_rule_create_command

    mock_response = util_load_json("test_data/create_or_update_rule_response.json")

    mock_client = mocker.Mock()
    mock_client.create_or_update_rule.return_value = mock_response

    params = {"subscription_id": "subid", "resource_group_name": "rg1"}
    args = {
        "security_group_name": "testnsg",
        "security_rule_name": "rule1",
        "action": "Deny",
        "direction": "Outbound",
        "priority": 100,
        "protocol": "Any",
        "source": "10.0.0.0/8",
        "destination": "11.0.0.0/8",
        "destination_ports": "8080",
    }

    result: CommandResults = nsg_security_rule_create_command(mock_client, params, args)

    # --- Check the properties passed to create_or_update_rule ---
    expected_properties = {
        "protocol": "*",
        "access": "Deny",
        "priority": 100,
        "direction": "Outbound",
        "sourcePortRange": "*",
        "destinationPortRange": "8080",
        "sourceAddressPrefix": "10.0.0.0/8",
        "destinationAddressPrefix": "11.0.0.0/8",
    }

    mock_client.create_or_update_rule.assert_called_once_with(
        security_group="testnsg",
        rule_name="rule1",
        properties=expected_properties,
        subscription_id="subid",
        resource_group_name="rg1",
    )

    # --- Check the returned CommandResults ---
    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.VirtualNetworks.SecurityRules"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "rule1"

    # Check that etag is cleaned up
    if result.outputs.get("etag"):
        assert result.outputs.get("etag") == "etag"

    # Check readable_output is generated
    assert result.readable_output
    assert f"The security rule {args['security_rule_name']} was created successfully" in result.readable_output


def test_nsg_security_rule_create_command_deprecated(mocker):
    """
    Given: An Azure client mock and arguments for creating a security rule using the deprecated command.
    When: nsg_security_rule_create_command is called with the deprecated command name.
    Then: It should return the created rule data with the deprecated prefix.
    """
    from Azure import nsg_security_rule_create_command

    mock_response = util_load_json("test_data/create_or_update_rule_response.json")

    mock_client = mocker.Mock()
    mock_client.create_or_update_rule.return_value = mock_response

    params = {"subscription_id": "subid", "resource_group_name": "rg1"}
    args = {
        "security_group_name": "testnsg",
        "security_rule_name": "rule1",
        "action": "Deny",
        "direction": "Outbound",
        "priority": 100,
        "protocol": "Any",
        "source": "10.0.0.0/8",
        "destination": "11.0.0.0/8",
        "destination_ports": "8080",
    }

    mocker.patch("Azure.demisto.command", return_value="azure-nsg-security-rule-create")

    result: CommandResults = nsg_security_rule_create_command(mock_client, params, args)

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.NSGRule"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "rule1"


def test_nsg_security_rule_get_command(mocker):
    """
    Given: An Azure client mock and a security rule JSON.
    When: nsg_security_rule_get_command is called.
    Then:
        1. It should call client.get_rule with correct arguments.
        2. The returned CommandResults should contain the rule data.
        3. The etag should be cleaned up.
        4. Readable output should be generated.
    """
    from Azure import nsg_security_rule_get_command

    mock_rule = util_load_json("test_data/get_rule_response.json")

    mock_client = mocker.Mock()
    mock_client.get_rule.return_value = mock_rule

    params = {"subscription_id": "subid", "resource_group_name": "rg1"}
    args = {"security_group_name": "testnsg", "security_rule_name": "wow"}

    result: CommandResults = nsg_security_rule_get_command(mock_client, params, args)

    # Check that get_rule was called correctly
    mock_client.get_rule.assert_called_once_with(
        security_group="testnsg",
        rule_name="wow",
        subscription_id="subid",
        resource_group_name="rg1",
    )

    # Check the returned CommandResults
    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.VirtualNetworks.SecurityRules"
    assert result.outputs_key_field == "id"
    assert result.outputs == mock_rule

    # Check that etag is cleaned up
    if result.outputs.get("etag"):
        assert result.outputs["etag"] == "etag"

    # Check readable_output is generated
    assert result.readable_output
    assert f"Rule {args['security_rule_name']}" in result.readable_output


def test_nsg_security_rule_get_command_deprecated(mocker):
    """
    Given: An Azure client mock and a security rule JSON using the deprecated command.
    When: nsg_security_rule_get_command is called with the deprecated command name.
    Then: It should return the rule data with the deprecated prefix.
    """
    from Azure import nsg_security_rule_get_command

    mock_rule = util_load_json("test_data/get_rule_response.json")

    mock_client = mocker.Mock()
    mock_client.get_rule.return_value = mock_rule

    params = {"subscription_id": "subid", "resource_group_name": "rg1"}
    args = {"security_group_name": "testnsg", "security_rule_name": "wow"}

    mocker.patch("Azure.demisto.command", return_value="azure-nsg-security-rule-get")

    result: CommandResults = nsg_security_rule_get_command(mock_client, params, args)

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.NSGRule"
    assert result.outputs_key_field == "id"
    assert result.outputs["name"] == "wow"


def test_nsg_security_groups_list_command(mocker):
    """
    Given: An Azure client mock and the list_network_security_groups_response.json file.
    When: nsg_security_groups_list_command is called.
    Then:
        1. It should call client.list_network_security_groups with correct parameters.
        2. The etag fields should be cleaned up for both groups and default security rules.
        3. The CommandResults should have correct outputs and readable_output.
    """
    from Azure import nsg_security_groups_list_command

    mock_response = util_load_json("test_data/list_network_security_groups_response.json")

    mock_client = mocker.Mock()
    mock_client.list_network_security_groups.return_value = mock_response

    params = {"subscription_id": "subid", "resource_group_name": "rg1"}
    args = {}

    result: CommandResults = nsg_security_groups_list_command(mock_client, params, args)

    mock_client.list_network_security_groups.assert_called_once_with(subscription_id="subid", resource_group_name="rg1")

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.VirtualNetworks.SecurityGroups"
    assert result.outputs_key_field == "id"
    assert len(result.outputs) == len(mock_response["value"])

    # Check that etag fields are cleaned up
    for group in result.outputs:
        if group.get("etag"):
            assert group["etag"] == "etag"
        for rule in group.get("defaultSecurityRules", []):
            if rule.get("etag"):
                assert rule["etag"] == "etag"

        assert "name" in group
        assert "id" in group
        assert "location" in group

    # Check readable_output is generated
    assert result.readable_output
    assert "Network Security Groups" in result.readable_output

    # The readable_output should contain the NSG names
    for group in result.outputs:
        assert group["name"] in result.readable_output


def test_nsg_security_groups_list_command_deprecated(mocker):
    """
    Given: An Azure client mock and the list_network_security_groups_response.json file using the deprecated command.
    When: nsg_security_groups_list_command is called with the deprecated command name.
    Then: It should return the security groups data with the deprecated prefix.
    """
    from Azure import nsg_security_groups_list_command

    mock_response = util_load_json("test_data/list_network_security_groups_response.json")

    mock_client = mocker.Mock()
    mock_client.list_network_security_groups.return_value = mock_response

    params = {"subscription_id": "subid", "resource_group_name": "rg1"}
    args = {}

    mocker.patch("Azure.demisto.command", return_value="azure-nsg-security-groups-list")

    result: CommandResults = nsg_security_groups_list_command(mock_client, params, args)

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.NSGSecurityGroup"
    assert result.outputs_key_field == "id"
    assert len(result.outputs) == len(mock_response["value"])


def test_nsg_security_rule_delete_command(mocker):
    """
    Given: An Azure client mock and various scenarios.
    When: nsg_security_rule_delete_command is called.
    Then:
        1. It should call client.delete_rule with correct arguments for valid inputs.
        2. It should return appropriate messages based on status codes (200=success, 202=async, 204=not found).
        3. It should call return_error when required parameters are missing or empty.
    """
    from Azure import nsg_security_rule_delete_command

    mock_client = mocker.Mock()
    params = {"subscription_id": "subid", "resource_group_name": "rg1"}

    mock_response = mocker.Mock()
    mock_response.status_code = 202
    mock_client.delete_rule.return_value = mock_response

    args = {"security_group_name": "testnsg", "security_rule_name": "testrule"}
    result = nsg_security_rule_delete_command(mock_client, params, args)

    mock_client.delete_rule.assert_called_with(
        security_group_name="testnsg",
        security_rule_name="testrule",
        subscription_id="subid",
        resource_group_name="rg1",
    )
    assert isinstance(result, CommandResults)
    assert "was accepted and the operation will complete asynchronously" in result.readable_output

    mock_response.status_code = 200
    result = nsg_security_rule_delete_command(mock_client, params, args)
    assert "was successfully deleted" in result.readable_output

    mock_response.status_code = 204
    result = nsg_security_rule_delete_command(mock_client, params, args)
    assert "was not found" in result.readable_output


def test_get_permissions_from_api_function_name(mocker):
    """
    Given: An API function name and an error message.
    When: get_permissions_from_api_function_name is called.
    Then:
          1. It should return the matching permission found in the error message.
          2. It should return None if no permission is found in the error message.
          3. It should be case-insensitive when matching.
          4. Multiple permissions in function, return all matched permissions.
    """
    from Azure import get_permissions_from_api_function_name

    # Test case 1: Permission found in error message
    api_function_name = "list_networks_interfaces_request"
    error_msg = "Access denied. Missing permission: Microsoft.Network/networkInterfaces/read"
    result = get_permissions_from_api_function_name(api_function_name, error_msg)
    assert result == ["Microsoft.Network/networkInterfaces/read"]

    # Test case 2: Case-insensitive matching
    error_msg_upper = "Access denied. Missing permission: MICROSOFT.NETWORK/NETWORKINTERFACES/READ"
    result = get_permissions_from_api_function_name(api_function_name, error_msg_upper)
    assert result == ["Microsoft.Network/networkInterfaces/read"]

    # Test case 3: No permission found in error message
    error_msg_no_match = "Some unrelated error message"
    result = get_permissions_from_api_function_name(api_function_name, error_msg_no_match)
    assert result == []

    # Test case 4: Multiple permissions in function, return all matched permissions
    api_function_name_multi = "acr_update"  # Has both read and write permissions
    error_msg_write = (
        "Missing Microsoft.ContainerRegistry/registries/read, Microsoft.ContainerRegistry/registries/write permissions"
    )
    result = get_permissions_from_api_function_name(api_function_name_multi, error_msg_write)
    assert result == ["Microsoft.ContainerRegistry/registries/read", "Microsoft.ContainerRegistry/registries/write"]


def test_get_permissions_from_required_role_permissions_list(mocker):
    """
    Given: An error message.
    When: get_permissions_from_required_role_permissions_list is called.
    Then:
          1. It should return the first matching permission found in the error message.
          2. It should return None if no permission is found in the error message.
          3. It should be case-insensitive when matching.
          4. It should search through all required role permissions.
    """
    from Azure import get_permissions_from_required_role_permissions_list

    # Test case 1: Permission found in error message
    error_msg = "Access denied. Missing permission: Microsoft.Network/networkSecurityGroups/read"
    result = get_permissions_from_required_role_permissions_list(error_msg)
    assert result == ["Microsoft.Network/networkSecurityGroups/read"]

    # Test case 2: Case-insensitive matching
    error_msg_mixed_case = "Access denied. Missing permission: microsoft.network/networksecuritygroups/READ"
    result = get_permissions_from_required_role_permissions_list(error_msg_mixed_case)
    assert result == ["Microsoft.Network/networkSecurityGroups/read"]

    # Test case 3: No permission found in error message
    error_msg_no_match = "Some completely unrelated error message without permissions"
    result = get_permissions_from_required_role_permissions_list(error_msg_no_match)
    assert result == ["N/A"]

    # Test case 4: Empty error message
    error_msg_empty = ""
    result = get_permissions_from_required_role_permissions_list(error_msg_empty)
    assert result == ["N/A"]


def test_handle_azure_error_forbidden_text_match(mocker, client):
    """
    Given: An Azure client and an error containing "forbidden" text.
    When: The handle_azure_error method is called.
    Then: The function should trigger permission error handling.
    """
    mock_get_permissions_from_api = mocker.patch(
        "Azure.get_permissions_from_api_function_name", return_value=["Microsoft.ContainerRegistry/registries/read"]
    )
    mock_get_permissions_from_required = mocker.patch("Azure.get_permissions_from_required_role_permissions_list")
    mock_return_multiple_permissions_error = mocker.patch("Azure.return_multiple_permissions_error")

    error = Exception("Access forbidden - insufficient privileges")
    resource_name = "test"
    resource_type = "test resource"
    subscription_id = "test-sub"

    client.handle_azure_error(
        e=error,
        resource_name=resource_name,
        resource_type=resource_type,
        api_function_name="acr_update",
        subscription_id=subscription_id,
    )

    mock_get_permissions_from_api.assert_called_once_with("acr_update", "access forbidden - insufficient privileges")
    mock_get_permissions_from_required.assert_not_called()

    expected_error_entries = [
        {
            "account_id": "test-sub",
            "message": "access forbidden - insufficient privileges",
            "name": "Microsoft.ContainerRegistry/registries/read",
        }
    ]
    mock_return_multiple_permissions_error.assert_called_once_with(expected_error_entries)


def test_handle_azure_error_permission_error_no_permissions_found(mocker, client):
    """
    Given: An Azure client and a permission error where no permissions are found.
    When: The handle_azure_error method is called.
    Then: The function should call return_multiple_permissions_error with empty list.
    """
    mock_get_permissions_from_api = mocker.patch("Azure.get_permissions_from_api_function_name", return_value=None)
    mock_get_permissions_from_required = mocker.patch(
        "Azure.get_permissions_from_required_role_permissions_list", return_value=["N/A"]
    )
    mock_return_multiple_permissions_error = mocker.patch("Azure.return_multiple_permissions_error")

    error = Exception("403 Forbidden")
    resource_name = "test-resource"
    resource_type = "Unknown Resource"

    client.handle_azure_error(
        e=error,
        resource_name=resource_name,
        resource_type=resource_type,
        api_function_name="unknown_function",
    )

    mock_get_permissions_from_api.assert_not_called()
    mock_get_permissions_from_required.assert_called_once()
    mock_return_multiple_permissions_error.assert_called_once_with(
        [{"account_id": None, "message": str(error).lower(), "name": "N/A"}]
    )


def test_handle_azure_error_permission_error_multiple_permissions(mocker, client):
    """
    Given: An Azure client and a permission error with multiple permissions found.
    When: The handle_azure_error method is called.
    Then: The function should call return_multiple_permissions_error with all permissions.
    """
    mock_return_multiple_permissions_error = mocker.patch("Azure.return_multiple_permissions_error")

    error = Exception("401 Unauthorized missing Microsoft.Storage/storageAccounts/read")
    resource_name = "test-storage"
    resource_type = "Storage Account"
    subscription_id = "sub-123"
    resource_group_name = "rg-test"

    client.handle_azure_error(
        e=error,
        resource_name=resource_name,
        resource_type=resource_type,
        api_function_name="storage_account_update_request",
        subscription_id=subscription_id,
        resource_group_name=resource_group_name,
    )

    expected_error_entries = [
        {
            "account_id": "sub-123",
            "message": "401 unauthorized missing microsoft.storage/storageaccounts/read",
            "name": "Microsoft.Storage/storageAccounts/read",
        }
    ]
    mock_return_multiple_permissions_error.assert_called_once_with(expected_error_entries)


def test_storage_blob_service_properties_get_command(mocker):
    """
    Given: An Azure client mock and the get_blob_service_properties.json file.
    When: storage_blob_service_properties_get_command is called.
    Then:
        1. It should call client.storage_blob_service_properties_get_request with correct parameters.
        2. It should extract subscription_id, resource_group, and account_name from the response ID.
        3. The CommandResults should have correct outputs, readable_output, and metadata.
    """
    from Azure import storage_blob_service_properties_get_command

    mock_response = util_load_json("test_data/get_blob_service_properties.json")

    mock_client = mocker.Mock()
    mock_client.storage_blob_service_properties_get_request.return_value = mock_response
    mocker.patch("Azure.demisto.command", return_value="azure-storage-blob-service-properties-get")

    params = {"subscription_id": "subid", "resource_group_name": "rg1"}
    args = {"account_name": "teststorage"}

    result: CommandResults = storage_blob_service_properties_get_command(mock_client, params, args)

    mock_client.storage_blob_service_properties_get_request.assert_called_once_with(
        account_name="teststorage", resource_group_name="rg1", subscription_id="subid"
    )

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.StorageBlobServiceProperties"
    assert result.outputs_key_field == "id"
    assert result.outputs == mock_response
    assert result.raw_response == mock_response

    assert "Azure Storage Blob Service Properties" in result.readable_output
    assert "default" in result.readable_output
    assert "sto8607" in result.readable_output
    assert "subscription-id" in result.readable_output
    assert "res4410" in result.readable_output
    assert "true" in result.readable_output.lower()

    expected_headers = [
        "Name",
        "Account Name",
        "Subscription ID",
        "Resource Group",
        "Change Feed",
        "Delete Retention Policy",
        "Versioning",
    ]
    for header in expected_headers:
        assert header in result.readable_output


def test_storage_blob_containers_update_command(mocker):
    """
    Given: An Azure client mock and the update_blob_container.json file.
    When: storage_blob_containers_update_command is called.
    Then:
        1. It should call client.storage_blob_containers_create_update_request with correct parameters and PATCH method.
        2. It should extract subscription_id, resource_group, and account_name from the response ID.
        3. The CommandResults should have correct outputs, readable_output, and metadata.
    """
    from Azure import storage_blob_containers_update_command

    mock_response = util_load_json("test_data/update_blob_container.json")

    mock_client = mocker.Mock()
    mock_client.storage_blob_containers_create_update_request.return_value = mock_response

    params = {"subscription_id": "subid", "resource_group_name": "rg1"}
    args = {"account_name": "teststorage", "container_name": "testcontainer"}

    result: CommandResults = storage_blob_containers_update_command(mock_client, params, args)

    mock_client.storage_blob_containers_create_update_request.assert_called_once_with(
        subscription_id="subid", resource_group_name="rg1", args=args, method="PATCH"
    )

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.Storage.BlobContainers"
    assert result.outputs_key_field == "id"
    assert result.outputs == mock_response
    assert result.raw_response == mock_response

    assert "Azure Storage Blob Containers Properties" in result.readable_output
    assert "container6185" in result.readable_output
    assert "sto328" in result.readable_output
    assert "subscription-id" in result.readable_output
    assert "res3376" in result.readable_output
    assert "Container" in result.readable_output

    expected_headers = ["Name", "Account Name", "Subscription ID", "Resource Group", "Public Access"]
    for header in expected_headers:
        assert header in result.readable_output


def test_storage_blob_containers_update_command_deprecated(mocker):
    """
    Given: An Azure client mock and the update_blob_container.json file using the deprecated command.
    When: storage_blob_containers_update_command is called with the deprecated command name.
    Then: It should return the updated container data with the deprecated prefix.
    """
    from Azure import storage_blob_containers_update_command

    mock_response = util_load_json("test_data/update_blob_container.json")

    mock_client = mocker.Mock()
    mock_client.storage_blob_containers_create_update_request.return_value = mock_response

    params = {"subscription_id": "subid", "resource_group_name": "rg1"}
    args = {"account_name": "teststorage", "container_name": "testcontainer"}

    mocker.patch("Azure.demisto.command", return_value="azure-storage-blob-containers-update")

    result: CommandResults = storage_blob_containers_update_command(mock_client, params, args)

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.StorageBlobContainer"
    assert result.outputs_key_field == "id"
    assert result.outputs == mock_response


def test_extract_azure_resource_info():
    """
    Given: Various Azure resource ID formats.
    When: The extract_azure_resource_info function is called.
    Then: The function should correctly extract subscription_id, resource_group, and account_name components.
    """

    # Test case 1: Complete Azure storage blob service resource ID
    resource_id = "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/test-rg/providers/Microsoft.Storage/storageAccounts/teststorage/blobServices/default"  # noqa: E501
    subscription_id, resource_group, account_name = extract_azure_resource_info(resource_id)
    assert subscription_id == "12345678-1234-1234-1234-123456789012"
    assert resource_group == "test-rg"
    assert account_name == "teststorage"

    # Test case 2: Partial resource ID (only subscription and resource group)
    resource_id = "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/test-rg/providers/Microsoft.Compute/virtualMachines/test-vm"  # noqa: E501
    subscription_id, resource_group, account_name = extract_azure_resource_info(resource_id)
    assert subscription_id == "12345678-1234-1234-1234-123456789012"
    assert resource_group == "test-rg"
    assert account_name is None

    # Test case 3: Empty string
    resource_id = ""
    subscription_id, resource_group, account_name = extract_azure_resource_info(resource_id)
    assert subscription_id is None
    assert resource_group is None
    assert account_name is None

    # Test case 4: Invalid format
    resource_id = "invalid-resource-id-format"
    subscription_id, resource_group, account_name = extract_azure_resource_info(resource_id)
    assert subscription_id is None
    assert resource_group is None
    assert account_name is None

    # Test case 5: Only subscription information
    resource_id = "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups"
    subscription_id, resource_group, account_name = extract_azure_resource_info(resource_id)
    assert subscription_id == "12345678-1234-1234-1234-123456789012"
    assert resource_group is None
    assert account_name is None

    # Test case 6: Complex names with hyphens and underscores
    resource_id = "/subscriptions/abcd-efgh-1234-5678-ijkl/resourceGroups/my-resource-group_v2/providers/Microsoft.Storage/storageAccounts/my_storage_account123/blobServices/default"  # noqa: E501
    subscription_id, resource_group, account_name = extract_azure_resource_info(resource_id)
    assert subscription_id == "abcd-efgh-1234-5678-ijkl"
    assert resource_group == "my-resource-group_v2"
    assert account_name == "my_storage_account123"

    # Test case 7: Storage account without blob services suffix
    resource_id = "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/test-rg/providers/Microsoft.Storage/storageAccounts/teststorage"  # noqa: E501
    subscription_id, resource_group, account_name = extract_azure_resource_info(resource_id)
    assert subscription_id == "12345678-1234-1234-1234-123456789012"
    assert resource_group == "test-rg"
    assert account_name is None


def test_storage_container_blob_create_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to create a blob in a storage container.
    When: The storage_container_blob_create_command function is called with valid parameters.
    Then: The function should call the client's create_blob method and return a success message.
    """
    # Mock arguments
    args = {
        "container_name": "testcontainer",
        "account_name": "testaccount",
        "file_entry_id": "test_file_entry_id",
        "blob_name": "test_blob.txt",
    }

    # Mock demisto.getFilePath
    mocker.patch.object(demisto, "getFilePath", return_value={"path": "/tmp/test_file.txt", "name": "test_file.txt"})

    # Mock os.path.getsize
    mocker.patch("os.path.getsize", return_value=100)  # Simulate a file size of 100 bytes

    # Mock builtins.open
    mock_file_content = b"This is a test file content."
    mocker.patch("builtins.open", mocker.mock_open(read_data=mock_file_content))

    # Mock the client's storage_container_create_blob_request method
    mock_response = mocker.Mock(spec=Response)
    mock_response.status_code = 201
    mock_response.text = "Blob created"
    mocker.patch.object(client, "storage_container_create_blob_request", return_value=mock_response)

    # Call the function
    result = Azure.storage_container_blob_create_command(client, mock_params, args)

    # Verify results
    assert isinstance(result, CommandResults)
    assert result.readable_output == "Blob test_blob.txt successfully created."
    assert result.raw_response is None


def test_storage_container_property_get_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to get storage container properties.
    When: The storage_container_property_get_command function is called with valid parameters.
    Then:
        1. It should call client.get_storage_container_properties_request with correct parameters.
        2. It should transform the response headers into the expected format.
        3. The CommandResults should have correct outputs, readable_output, and raw_response.
    """
    # Mock arguments
    args = {"container_name": "testcontainer", "account_name": "testaccount"}

    # Prepare the mocked HTTP response object with headers
    mock_response = mocker.Mock()
    # The CaseInsensitiveDict is what the requests library returns for headers
    raw_response_data = {
        "Content-Length": "0",
        "Etag": "0x8DB7F5589F2DC4A",
        "Last-Modified": "Wed, 14 Aug 2024 10:00:00 GMT",
        "Date": "Wed, 14 Aug 2024 10:05:00 GMT",
        "X-Ms-Request-Id": "req-id-12345",
        "X-Ms-Lease-Status": "unlocked",
        "X-Ms-Lease-State": "available",
        "X-Ms-Has-Immutability-Policy": "false",
        "X-Ms-Has-Legal-Hold": "false",
    }
    mock_response.headers = CaseInsensitiveDict(raw_response_data)

    # Configure the client method to return this mock response
    mocker.patch.object(client, "get_storage_container_properties_request", return_value=mock_response)

    # Call the function
    result = storage_container_property_get_command(client, mock_params, args)

    # Verify client.get_storage_container_properties_request was called with correct parameters
    client.get_storage_container_properties_request.assert_called_once_with("testaccount", "testcontainer")

    assert result.outputs_prefix == "Azure.Storage.Container"
    assert result.outputs_key_field == "ContainerName"


def test_storage_container_create_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to create a storage container.
    When: The storage_container_create_command function is called with valid parameters.
    Then: The function should call the client's create_storage_container_request method and return a success message.
    """
    # Mock arguments
    args = {"container_name": "testcontainer", "account_name": "testaccount"}

    # Mock the client's create_storage_container_request method
    mock_response = mocker.Mock()
    mock_response.status_code = 201
    mocker.patch.object(client, "create_storage_container_request", return_value=mock_response)

    # Call the function
    result = storage_container_create_command(client, mock_params, args)

    # Verify client.create_storage_container_request was called with correct parameters
    client.create_storage_container_request.assert_called_once_with("testcontainer", "testaccount")

    # Verify results
    assert isinstance(result, CommandResults)
    assert result.readable_output == f"Container {args['container_name']} successfully created."


def test_storage_container_create_command_invalid_name(mocker, client, mock_params):
    """
    Given: An Azure client and a request to create a storage container with an invalid name.
    When: The storage_container_create_command function is called with invalid container name.
    Then: The function should raise an exception about the invalid container name.
    """
    # Mock arguments with invalid container name (uppercase not allowed)
    args = {"container_name": "TestContainer", "account_name": "testaccount"}

    # Call the function and expect an exception
    with pytest.raises(Exception) as excinfo:
        storage_container_create_command(client, mock_params, args)

    # Verify the exception message
    assert "The specified container name is invalid" in str(excinfo.value)


def test_storage_container_delete_command_success(mocker, client, mock_params):
    """
    Given: An Azure client and a request to delete a storage container.
    When: The storage_container_delete_command function is called with valid parameters.
    Then: The function should call the client's delete_storage_container_request method and return a success message.
    """
    # Mock arguments
    args = {"container_name": "testcontainer", "account_name": "testaccount"}

    # Mock the client's delete_storage_container_request method
    mocker.patch.object(client, "delete_storage_container_request")

    # Call the function
    result = storage_container_delete_command(client, mock_params, args)

    # Verify client.delete_storage_container_request was called with correct parameters
    client.delete_storage_container_request.assert_called_once_with("testcontainer", "testaccount")

    # Verify results
    assert isinstance(result, CommandResults)
    assert result.readable_output == f"Container {args['container_name']} successfully deleted."


def test_storage_container_delete_command_error(mocker, client, mock_params):
    """
    Given: An Azure client and a request to delete a storage container that fails.
    When: The storage_container_delete_command function is called and the API call raises an exception.
    Then: The function should propagate the exception.
    """
    # Mock arguments
    args = {"container_name": "testcontainer", "account_name": "testaccount"}

    # Mock the client's delete_storage_container_request method to raise an exception
    error_message = "Container not found or you don't have permission to delete it"
    mocker.patch.object(client, "delete_storage_container_request", side_effect=Exception(error_message))

    # Call the function and expect an exception
    with pytest.raises(Exception) as excinfo:
        storage_container_delete_command(client, mock_params, args)

    # Verify the exception message
    assert error_message in str(excinfo.value)


def test_storage_container_blob_get_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to get a blob from a storage container.
    When: The storage_container_blob_get_command function is called with valid parameters.
    Then: The function should call the client's storage_container_blob_get_request method and return a fileResult.
    """
    # Mock arguments
    args = {"container_name": "testcontainer", "blob_name": "testblob.txt", "account_name": "testaccount"}

    # Mock the client's storage_container_blob_get_request method
    mock_response = mocker.Mock()
    mock_response.content = b"Test blob content"
    mocker.patch.object(client, "storage_container_blob_get_request", return_value=mock_response)

    # Mock fileResult function
    mock_file_result = mocker.patch("Azure.fileResult", return_value="file_result_object")

    # Call the function
    result = storage_container_blob_get_command(client, mock_params, args)

    # Verify client.storage_container_blob_get_request was called with correct parameters
    client.storage_container_blob_get_request.assert_called_once_with("testcontainer", "testblob.txt", "testaccount")

    # Verify fileResult was called with correct parameters
    mock_file_result.assert_called_once_with(filename="testblob.txt", data=b"Test blob content")

    # Verify result
    assert result == "file_result_object"


def test_storage_container_blob_tag_get_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to get tags for a blob.
    When: The storage_container_blob_tag_get_command function is called with valid parameters.
    Then: The function should call the client's storage_container_blob_tag_get_request method and return the tags.
    """
    # Mock arguments
    args = {"container_name": "testcontainer", "blob_name": "testblob.txt", "account_name": "testaccount"}

    # Mock XML response
    xml_response = """<?xml version="1.0" encoding="utf-8"?>
    <Tags>
        <TagSet>
            <Tag>
                <Key>tag1</Key>
                <Value>value1</Value>
            </Tag>
            <Tag>
                <Key>tag2</Key>
                <Value>value2</Value>
            </Tag>
        </TagSet>
    </Tags>"""

    # Mock the client's storage_container_blob_tag_get_request method
    mocker.patch.object(client, "storage_container_blob_tag_get_request", return_value=xml_response)

    # Mock ElementTree parsing
    mock_tree = mocker.Mock()
    mock_root = mocker.Mock()
    mock_tree.getroot.return_value = mock_root

    # Create mock Tag elements
    tag1 = mocker.Mock()
    tag1.findtext.side_effect = lambda x: "tag1" if x == "Key" else "value1"
    tag2 = mocker.Mock()
    tag2.findtext.side_effect = lambda x: "tag2" if x == "Key" else "value2"

    # Set up the iteration over Tag elements
    mock_root.iter.return_value = [tag1, tag2]

    mocker.patch("Azure.ET.ElementTree", return_value=mock_tree)
    mocker.patch("Azure.defused_ET.fromstring", return_value=mock_root)

    # Mock tableToMarkdown
    mocker.patch("Azure.tableToMarkdown", return_value="Mocked Table")

    # Call the function
    result = storage_container_blob_tag_get_command(client, mock_params, args)

    # Verify client.storage_container_blob_tag_get_request was called with correct parameters
    client.storage_container_blob_tag_get_request.assert_called_once_with("testcontainer", "testblob.txt", "testaccount")

    # Verify result
    assert isinstance(result, CommandResults)
    assert result.readable_output == "Mocked Table"
    assert result.outputs_prefix == "Azure.Storage.Blob"
    assert result.outputs_key_field == "name"
    assert result.outputs["ContainerName"] == "testcontainer"
    assert result.outputs["name"] == "testblob.txt"
    assert "Tag" in result.outputs


def test_storage_container_blob_tag_get_command_deprecated(mocker, client, mock_params):
    """
    Given: An Azure client and a request to get tags for a blob using the deprecated command.
    When: The storage_container_blob_tag_get_command function is called with valid parameters and the deprecated command name.
    Then: The function should call the client's storage_container_blob_tag_get_request method and return the tags with the
    deprecated prefix.
    """
    # Mock arguments
    args = {"container_name": "testcontainer", "blob_name": "testblob.txt", "account_name": "testaccount"}

    # Mock XML response
    xml_response = """<?xml version="1.0" encoding="utf-8"?>
    <Tags>
        <TagSet>
            <Tag>
                <Key>tag1</Key>
                <Value>value1</Value>
            </Tag>
            <Tag>
                <Key>tag2</Key>
                <Value>value2</Value>
            </Tag>
        </TagSet>
    </Tags>"""

    # Mock the client's storage_container_blob_tag_get_request method
    mocker.patch.object(client, "storage_container_blob_tag_get_request", return_value=xml_response)

    # Mock ElementTree parsing
    mock_tree = mocker.Mock()
    mock_root = mocker.Mock()
    mock_tree.getroot.return_value = mock_root

    # Create mock Tag elements
    tag1 = mocker.Mock()
    tag1.findtext.side_effect = lambda x: "tag1" if x == "Key" else "value1"
    tag2 = mocker.Mock()
    tag2.findtext.side_effect = lambda x: "tag2" if x == "Key" else "value2"

    # Set up the iteration over Tag elements
    mock_root.iter.return_value = [tag1, tag2]

    mocker.patch("Azure.ET.ElementTree", return_value=mock_tree)
    mocker.patch("Azure.defused_ET.fromstring", return_value=mock_root)

    # Mock tableToMarkdown
    mocker.patch("Azure.tableToMarkdown", return_value="Mocked Table")

    # Mock demisto.command
    mocker.patch("Azure.demisto.command", return_value="azure-storage-container-blob-tag-get")

    # Call the function
    result = storage_container_blob_tag_get_command(client, mock_params, args)

    # Verify client.storage_container_blob_tag_get_request was called with correct parameters
    client.storage_container_blob_tag_get_request.assert_called_once_with("testcontainer", "testblob.txt", "testaccount")

    # Verify result
    assert isinstance(result, CommandResults)
    assert result.readable_output == "Mocked Table"
    assert result.outputs_prefix == "Azure.StorageContainer"
    assert result.outputs_key_field == "name"
    assert result.outputs["name"] == "testcontainer"
    assert result.outputs["Blob"]["name"] == "testblob.txt"
    assert "Tag" in result.outputs["Blob"]


def test_storage_container_blob_tag_set_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to set tags for a blob.
    When: The storage_container_blob_tag_set_command function is called with valid parameters.
    Then: The function should call the client's storage_container_blob_tags_set_request method.
    """
    # Mock arguments
    args = {
        "container_name": "testcontainer",
        "blob_name": "testblob.txt",
        "account_name": "testaccount",
        "tags": '{"tag1": "value1", "tag2": "value2"}',
    }

    # Mock the client's storage_container_blob_tags_set_request method
    mocker.patch.object(client, "storage_container_blob_tags_set_request")

    # Mock create_set_tags_request_body
    mock_xml_data = b'<?xml version="1.0" encoding="utf-8"?><Tags><TagSet><Tag><Key>tag1</Key><Value>value1</Value></Tag><Tag><Key>tag2</Key><Value>value2</Value></Tag></TagSet></Tags>'  # noqa: E501
    mocker.patch("Azure.create_set_tags_request_body", return_value=mock_xml_data)

    # Call the function
    result = storage_container_blob_tag_set_command(client, mock_params, args)

    # Verify create_set_tags_request_body was called with correct parameters
    Azure.create_set_tags_request_body.assert_called_once_with({"tag1": "value1", "tag2": "value2"})

    # Verify client.storage_container_blob_tags_set_request was called with correct parameters
    client.storage_container_blob_tags_set_request.assert_called_once_with(
        "testcontainer", "testblob.txt", mock_xml_data, "testaccount"
    )

    # Verify result
    assert isinstance(result, CommandResults)
    assert result.readable_output == "testblob.txt Tags successfully updated."


def test_storage_container_blob_tag_set_command_append(mocker, client, mock_params):
    """
    Given: An Azure client and a request to append tags for a blob.
    When: The storage_container_blob_tag_set_command function is called with valid parameters and append=True.
    Then: The function should call the client's storage_container_blob_tags_set_request method with the appended tags.
    """
    # Mock arguments
    args = {
        "container_name": "testcontainer",
        "blob_name": "testblob.txt",
        "account_name": "testaccount",
        "tags": '{"tag3": "value3"}',
        "append": "true",
    }

    # Mock the client's storage_container_blob_tags_set_request method
    mocker.patch.object(client, "storage_container_blob_tags_set_request")

    # Mock storage_container_blob_tag_get_command to return existing tags
    mock_get_results = CommandResults(outputs={"Tag": [{"Key": "tag1", "Value": "value1"}, {"Key": "tag2", "Value": "value2"}]})
    mocker.patch("Azure.storage_container_blob_tag_get_command", return_value=mock_get_results)

    # Mock create_set_tags_request_body
    mock_xml_data = b'<?xml version="1.0" encoding="utf-8"?><Tags><TagSet><Tag><Key>tag3</Key><Value>value3</Value></Tag><Tag><Key>tag1</Key><Value>value1</Value></Tag><Tag><Key>tag2</Key><Value>value2</Value></Tag></TagSet></Tags>'  # noqa: E501
    mocker.patch("Azure.create_set_tags_request_body", return_value=mock_xml_data)

    # Call the function
    result = storage_container_blob_tag_set_command(client, mock_params, args)

    # Verify create_set_tags_request_body was called with correct parameters (appended tags)
    Azure.create_set_tags_request_body.assert_called_once_with({"tag3": "value3", "tag1": "value1", "tag2": "value2"})

    # Verify client.storage_container_blob_tags_set_request was called with correct parameters
    client.storage_container_blob_tags_set_request.assert_called_once_with(
        "testcontainer", "testblob.txt", mock_xml_data, "testaccount"
    )

    # Verify result
    assert isinstance(result, CommandResults)
    assert result.readable_output == "testblob.txt Tags successfully updated."


def test_storage_container_blob_property_get_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to get properties for a blob.
    When: The storage_container_blob_property_get_command function is called with valid parameters.
    Then: The function should call the client's storage_container_blob_property_get_request method and return the properties.
    """
    # Mock arguments
    args = {"container_name": "testcontainer", "blob_name": "testblob.txt", "account_name": "testaccount"}

    # Mock response headers
    mock_headers = CaseInsensitiveDict(
        {
            "Content-Length": "1024",
            "Content-Type": "text/plain",
            "Etag": "0x8D8B92EFCFD9B41",
            "Last-Modified": "Wed, 14 Aug 2024 10:00:00 GMT",
            "x-ms-creation-time": "Wed, 14 Aug 2024 09:00:00 GMT",
        }
    )

    # Mock the client's storage_container_blob_property_get_request method
    mock_response = mocker.Mock()
    mock_response.headers = mock_headers
    mocker.patch.object(client, "storage_container_blob_property_get_request", return_value=mock_response)

    # Mock tableToMarkdown
    mocker.patch("Azure.tableToMarkdown", return_value="Mocked Table")

    # Call the function
    result = storage_container_blob_property_get_command(client, mock_params, args)

    # Verify client.storage_container_blob_property_get_request was called with correct parameters
    client.storage_container_blob_property_get_request.assert_called_once_with("testcontainer", "testblob.txt", "testaccount")

    # Verify result
    assert isinstance(result, CommandResults)
    assert result.readable_output == "Mocked Table"
    assert result.outputs_prefix == "Azure.Storage.Blob"
    assert result.outputs_key_field == "name"
    assert result.outputs["ContainerName"] == "testcontainer"
    assert result.outputs["name"] == "testblob.txt"
    assert "Property" in result.outputs


def test_storage_container_blob_property_get_command_deprecated(mocker, client, mock_params):
    """
    Given: An Azure client and a request to get properties for a blob using the deprecated command.
    When: The storage_container_blob_property_get_command function is called with valid parameters and the
        deprecated command name.
    Then: The function should call the client's storage_container_blob_property_get_request method and return the properties
        with the deprecated prefix.
    """
    # Mock arguments
    args = {"container_name": "testcontainer", "blob_name": "testblob.txt", "account_name": "testaccount"}

    # Mock response headers
    mock_headers = CaseInsensitiveDict(
        {
            "Content-Length": "1024",
            "Content-Type": "text/plain",
            "Etag": "0x8D8B92EFCFD9B41",
            "Last-Modified": "Wed, 14 Aug 2024 10:00:00 GMT",
            "x-ms-creation-time": "Wed, 14 Aug 2024 09:00:00 GMT",
        }
    )

    # Mock the client's storage_container_blob_property_get_request method
    mock_response = mocker.Mock()
    mock_response.headers = mock_headers
    mocker.patch.object(client, "storage_container_blob_property_get_request", return_value=mock_response)

    # Mock tableToMarkdown
    mocker.patch("Azure.tableToMarkdown", return_value="Mocked Table")

    # Mock demisto.command
    mocker.patch("Azure.demisto.command", return_value="azure-storage-container-blob-property-get")

    # Call the function
    result = storage_container_blob_property_get_command(client, mock_params, args)

    # Verify client.storage_container_blob_property_get_request was called with correct parameters
    client.storage_container_blob_property_get_request.assert_called_once_with("testcontainer", "testblob.txt", "testaccount")

    # Verify result
    assert isinstance(result, CommandResults)
    assert result.readable_output == "Mocked Table"
    assert result.outputs_prefix == "Azure.StorageContainer"
    assert result.outputs_key_field == "name"
    assert result.outputs["name"] == "testcontainer"
    assert result.outputs["Blob"]["name"] == "testblob.txt"
    assert "Property" in result.outputs["Blob"]


def test_storage_container_blob_property_set_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to set properties for a blob.
    When: The storage_container_blob_property_set_command function is called with valid parameters.
    Then: The function should call the client's storage_container_blob_properties_set_request method.
    """
    # Mock arguments
    args = {
        "container_name": "testcontainer",
        "blob_name": "testblob.txt",
        "account_name": "testaccount",
        "content_type": "application/json",
        "content_encoding": "gzip",
        "cache_control": "max-age=3600",
    }

    # Mock the client's storage_container_blob_properties_set_request method
    mocker.patch.object(client, "storage_container_blob_properties_set_request")

    # Mock remove_empty_elements
    expected_headers = {
        "x-ms-blob-cache-control": "max-age=3600",
        "x-ms-blob-content-type": "application/json",
        "x-ms-blob-content-encoding": "gzip",
        "Content-Length": "0",
    }
    mocker.patch("Azure.remove_empty_elements", return_value=expected_headers)

    # Call the function
    result = storage_container_blob_property_set_command(client, mock_params, args)

    # Verify remove_empty_elements was called with correct parameters
    Azure.remove_empty_elements.assert_called_once()

    # Verify client.storage_container_blob_properties_set_request was called with correct parameters
    client.storage_container_blob_properties_set_request.assert_called_once_with(
        "testcontainer", "testblob.txt", "testaccount", expected_headers
    )

    # Verify result
    assert isinstance(result, CommandResults)
    assert result.readable_output == "Blob testblob.txt properties successfully updated."


def test_storage_container_block_public_access_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to block public access to a container.
    When: The storage_container_block_public_access_command function is called with valid parameters.
    Then: The function should call the client's storage_container_block_public_access_request method.
    """
    # Mock arguments
    args = {"container_name": "testcontainer", "account_name": "testaccount"}

    # Mock the client's storage_container_block_public_access_request method
    mock_response = mocker.Mock()
    mocker.patch.object(client, "storage_container_block_public_access_request", return_value=mock_response)

    # Mock debug log
    mocker.patch.object(demisto, "debug")

    # Call the function
    result = storage_container_block_public_access_command(client, mock_params, args)

    # Verify client.storage_container_block_public_access_request was called with correct parameters
    client.storage_container_block_public_access_request.assert_called_once_with("testaccount", "testcontainer")

    # Verify debug was called
    demisto.debug.assert_called_once()

    # Verify result
    assert isinstance(result, CommandResults)
    assert result.readable_output == "Public access to container 'testcontainer' has been successfully blocked"


class TestGetCommandAndTokenScopes:
    """Tests for the get_command_and_token_scopes function."""

    def test_default_command(self):
        """Test that a default command returns DEFAULT_SCOPE and [TokenScope.DEFAULT]."""
        command = "azure-nsg-security-rule-update"
        client_scope, token_scopes = get_command_and_token_scopes(command)
        assert client_scope == DEFAULT_SCOPE
        assert token_scopes == [TokenScope.DEFAULT]

    def test_storage_container_command(self):
        """Test that a storage-container command returns STORAGE_SCOPE and [TokenScope.STORAGE]."""
        command = "azure-storage-container-create"
        client_scope, token_scopes = get_command_and_token_scopes(command)
        assert client_scope == STORAGE_SCOPE
        assert token_scopes == [TokenScope.STORAGE]

    def test_storage_blob_command(self):
        """Test that a storage-container-blob command returns STORAGE_SCOPE and [TokenScope.STORAGE]."""
        command = "azure-storage-container-blob-get"
        client_scope, token_scopes = get_command_and_token_scopes(command)
        assert client_scope == STORAGE_SCOPE
        assert token_scopes == [TokenScope.STORAGE]


class TestGetCommandResource:
    """Tests for the get_command_resource function."""

    def test_default_command(self):
        """Test that a default command returns DEFAULT_RESOURCE."""
        command = "azure-nsg-security-rule-update"
        resource = get_command_resource(command)
        assert resource == DEFAULT_RESOURCE

    def test_storage_container_command(self):
        """Test that a storage-container command returns STORAGE_RESOURCE."""
        command = "azure-storage-container-create"
        resource = get_command_resource(command)
        assert resource == STORAGE_RESOURCE

    def test_storage_blob_command(self):
        """Test that a storage-container-blob command returns STORAGE_RESOURCE."""
        command = "azure-storage-container-blob-get"
        resource = get_command_resource(command)
        assert resource == STORAGE_RESOURCE


@pytest.mark.parametrize(
    "command",
    [
        "azure-storage-container-list",
        "azure-storage-blob-property-get",
        "azure-storage-blob-property-set",
        "azure-storage-blob-tag-get",
        "azure-storage-blob-create",
        "azure-storage-blob-get",
        "azure-storage-blob-tag-set",
    ],
)
def test_get_command_and_token_scopes_storage(command):
    """
    Given:
        A storage-related Azure command name (e.g. 'azure-storage-container-list',
        'azure-storage-blob-get', etc.).

    When:
        Calling get_command_and_token_scopes with that command.

    Then:
        The returned scope equals STORAGE_SCOPE and the token scopes list
        contains only TokenScope.STORAGE.
    """
    scope, token_scopes = get_command_and_token_scopes(command)
    assert scope == STORAGE_SCOPE
    assert token_scopes == [TokenScope.STORAGE]


@pytest.mark.parametrize(
    "command",
    [
        "azure-storage-container-list",
        "azure-storage-blob-property-get",
        "azure-storage-blob-property-set",
        "azure-storage-blob-tag-get",
        "azure-storage-blob-create",
        "azure-storage-blob-get",
        "azure-storage-blob-tag-set",
    ],
)
def test_get_command_resource_storage(command):
    """
    Given:
        A storage-related Azure command name (e.g. 'azure-storage-container-list',
        'azure-storage-blob-get', etc.).

    When:
        Calling get_command_resource with that command.

    Then:
        The returned resource equals STORAGE_RESOURCE.
    """
    resource = get_command_resource(command)
    assert resource == STORAGE_RESOURCE


class TestGetAzureClient:
    """Tests for the get_azure_client function."""

    @patch("Azure.get_connector_id", return_value="connector-123")
    @patch("Azure.get_azure_managed_identities_client_id", return_value=None)
    @patch("Azure.get_from_args_or_params")
    @patch("Azure.get_cloud_credentials")
    @patch("Azure.AzureClient")
    def test_with_cloud_credentials(
        self,
        mock_azure_client,
        mock_get_cloud_credentials,
        mock_get_from_args_or_params,
        mock_get_managed,
        mock_get_connector_id,
    ):
        """Test get_azure_client with cloud credentials (Platform path)."""
        # Setup mocks
        mock_get_from_args_or_params.return_value = "test-subscription-id"
        mock_get_cloud_credentials.return_value = {"access_token": "test-token"}
        mock_client = MagicMock()
        mock_azure_client.return_value = mock_client

        # Test parameters
        params = {
            "app_id": "test-app-id",
            "subscription_id": "test-subscription-id",
            "resource_group_name": "test-resource-group",
            "insecure": False,
            "proxy": False,
            "tenant_id": "test-tenant-id",
            "credentials": {},  # Empty credentials to trigger cloud credentials path
        }
        args = {}
        command = "azure-nsg-security-rule-update"

        # Call the function
        result = get_azure_client(params, args, command)

        # Verify results
        assert result == mock_client
        mock_get_cloud_credentials.assert_called_once_with(
            CloudTypes.AZURE.value, "test-subscription-id", scopes=[TokenScope.DEFAULT]
        )
        mock_azure_client.assert_called_once_with(
            app_id="test-app-id",
            subscription_id="test-subscription-id",
            resource_group_name="test-resource-group",
            verify=True,
            proxy=False,
            tenant_id="test-tenant-id",
            enc_key=None,
            resource=DEFAULT_RESOURCE,
            scope=DEFAULT_SCOPE,
            headers={"Authorization": "Bearer test-token", "Content-Type": "application/json", "Accept": "application/json"},
            connection_type="Client Credentials",
            azure_ad_endpoint="https://login.microsoftonline.com",
            auth_code=None,
            redirect_uri=None,
            managed_identities_client_id=None,
        )

    @patch("Azure.get_connector_id", return_value="connector-123")
    @patch("Azure.get_azure_managed_identities_client_id", return_value=None)
    @patch("Azure.get_from_args_or_params")
    @patch("Azure.get_cloud_credentials")
    @patch("Azure.AzureClient")
    def test_with_storage_command(
        self,
        mock_azure_client,
        mock_get_cloud_credentials,
        mock_get_from_args_or_params,
        mock_get_managed,
        mock_get_connector_id,
    ):
        """Test get_azure_client with a storage command (Platform path)."""
        # Setup mocks
        mock_get_from_args_or_params.return_value = "test-subscription-id"
        mock_get_cloud_credentials.return_value = {"access_token": "test-token"}
        mock_client = MagicMock()
        mock_azure_client.return_value = mock_client

        # Test parameters
        params = {
            "app_id": "test-app-id",
            "subscription_id": "test-subscription-id",
            "resource_group_name": "test-resource-group",
            "insecure": False,
            "proxy": False,
            "tenant_id": "test-tenant-id",
            "credentials": {},  # Empty credentials to trigger cloud credentials path
        }
        args = {}
        command = "azure-storage-container-create"

        # Call the function
        result = get_azure_client(params, args, command)

        # Verify results
        assert result == mock_client
        mock_get_cloud_credentials.assert_called_once_with(
            CloudTypes.AZURE.value, "test-subscription-id", scopes=[TokenScope.STORAGE]
        )
        mock_azure_client.assert_called_once_with(
            app_id="test-app-id",
            subscription_id="test-subscription-id",
            resource_group_name="test-resource-group",
            verify=True,
            proxy=False,
            tenant_id="test-tenant-id",
            enc_key=None,
            resource=STORAGE_RESOURCE,
            scope=STORAGE_SCOPE,
            headers={"Authorization": "Bearer test-token", "Content-Type": "application/json", "Accept": "application/json"},
            connection_type="Client Credentials",
            azure_ad_endpoint="https://login.microsoftonline.com",
            auth_code=None,
            redirect_uri=None,
            managed_identities_client_id=None,
        )


def test_start_vm_command(mocker):
    """
    Given: A subscription, resource group, and VM name.
    When: start_vm_command is called with these parameters.
    Then: It should call validate_provisioning_state and start_vm_request,
          and return correct CommandResults with VM starting state.
    """
    from Azure import start_vm_command

    mock_client = mocker.Mock()
    params = {"subscription_id": "sub-id", "resource_group_name": "rg1"}
    args = {"subscription_id": "sub-id", "resource_group_name": "rg1", "virtual_machine_name": "vm1"}

    result = start_vm_command(mock_client, params, args)

    mock_client.validate_provisioning_state.assert_called_once_with("sub-id", "rg1", "vm1")
    mock_client.start_vm_request.assert_called_once_with("sub-id", "rg1", "vm1")

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.Compute.VirtualMachines"
    assert result.outputs_key_field == "name"
    assert result.outputs["name"] == "vm1"
    assert result.outputs["resourceGroup"] == "rg1"
    assert result.outputs["powerState"] == "VM starting"
    assert "vm1" in result.readable_output


def test_start_vm_command_deprecated(mocker):
    """
    Given: A subscription, resource group, and VM name using the deprecated command.
    When: start_vm_command is called with the deprecated command name.
    Then: It should call validate_provisioning_state and start_vm_request,
          and return correct CommandResults with the deprecated prefix.
    """
    from Azure import start_vm_command

    mock_client = mocker.Mock()
    params = {"subscription_id": "sub-id", "resource_group_name": "rg1"}
    args = {"subscription_id": "sub-id", "resource_group_name": "rg1", "virtual_machine_name": "vm1"}

    mocker.patch("Azure.demisto.command", return_value="azure-vm-instance-start")

    result = start_vm_command(mock_client, params, args)

    mock_client.validate_provisioning_state.assert_called_once_with("sub-id", "rg1", "vm1")
    mock_client.start_vm_request.assert_called_once_with("sub-id", "rg1", "vm1")

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.Compute"
    assert result.outputs_key_field == "name"
    assert result.outputs["name"] == "vm1"
    assert result.outputs["resourceGroup"] == "rg1"
    assert result.outputs["powerState"] == "VM starting"
    assert "vm1" in result.readable_output


def test_poweroff_vm_command(mocker):
    """
    Given: A subscription, resource group, VM name, and optional skip_shutdown.
    When: poweroff_vm_command is called.
    Then: It should call validate_provisioning_state and poweroff_vm_request,
          and return correct CommandResults with VM stopping state.
    """
    from Azure import poweroff_vm_command

    mock_client = mocker.Mock()
    params = {"subscription_id": "sub-id", "resource_group_name": "rg1"}
    args = {"subscription_id": "sub-id", "resource_group_name": "rg1", "virtual_machine_name": "vm1", "skip_shutdown": True}

    result = poweroff_vm_command(mock_client, params, args)

    mock_client.validate_provisioning_state.assert_called_once_with("sub-id", "rg1", "vm1")
    mock_client.poweroff_vm_request.assert_called_once_with("sub-id", "rg1", "vm1", True)

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.Compute.VirtualMachines"
    assert result.outputs_key_field == "name"
    assert result.outputs["name"] == "vm1"
    assert result.outputs["resourceGroup"] == "rg1"
    assert result.outputs["powerState"] == "VM stopping"
    assert "vm1" in result.readable_output


def test_poweroff_vm_command_deprecated(mocker):
    """
    Given: A subscription, resource group, VM name, and optional skip_shutdown using the deprecated command.
    When: poweroff_vm_command is called with the deprecated command name.
    Then: It should call validate_provisioning_state and poweroff_vm_request,
          and return correct CommandResults with the deprecated prefix.
    """
    from Azure import poweroff_vm_command

    mock_client = mocker.Mock()
    params = {"subscription_id": "sub-id", "resource_group_name": "rg1"}
    args = {"subscription_id": "sub-id", "resource_group_name": "rg1", "virtual_machine_name": "vm1", "skip_shutdown": True}

    mocker.patch("Azure.demisto.command", return_value="azure-vm-instance-power-off")

    result = poweroff_vm_command(mock_client, params, args)

    mock_client.validate_provisioning_state.assert_called_once_with("sub-id", "rg1", "vm1")
    mock_client.poweroff_vm_request.assert_called_once_with("sub-id", "rg1", "vm1", True)

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.Compute"
    assert result.outputs_key_field == "name"
    assert result.outputs["name"] == "vm1"
    assert result.outputs["resourceGroup"] == "rg1"
    assert result.outputs["powerState"] == "VM stopping"
    assert "vm1" in result.readable_output


def test_get_vm_command(mocker):
    """
    Given: A subscription, resource group, and VM name.
    When: get_vm_command is called.
    Then: It should call get_vm_request and return correct CommandResults
          including OS, size, power state, and network interfaces.
    """
    from Azure import get_vm_command

    mock_client = mocker.Mock()
    params = {"subscription_id": "sub-id", "resource_group_name": "rg1"}
    args = {"subscription_id": "sub-id", "resource_group_name": "rg1", "virtual_machine_name": "vm1", "expand": ""}

    mock_response = {
        "location": "eastus",
        "tags": {"env": "prod"},
        "properties": {
            "vmId": "vm123",
            "provisioningState": "Succeeded",
            "storageProfile": {"osDisk": {"diskSizeGB": 128, "osType": "Linux"}},
            "instanceView": {"statuses": [{"code": "PowerState/running", "displayStatus": "VM running"}]},
            "networkProfile": {"networkInterfaces": [{"id": "nic1"}]},
            "userData": "userdata",
        },
    }

    mocker.patch.object(mock_client, "get_vm_request", return_value=mock_response)

    result = get_vm_command(mock_client, params, args)

    mock_client.get_vm_request.assert_called_once_with("sub-id", "rg1", "vm1", expand="")

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.Compute.VirtualMachines"
    assert result.outputs_key_field == "name"
    assert result.outputs["properties"]["vmId"] == "vm123"
    assert result.outputs["properties"]["provisioningState"] == "Succeeded"
    assert result.outputs["properties"]["storageProfile"]["osDisk"]["osType"] == "Linux"
    assert result.outputs["properties"]["instanceView"]["statuses"][0]["displayStatus"] == "VM running"
    assert "vm1" in result.readable_output


def test_get_vm_command_deprecated(mocker):
    """
    Given: A subscription, resource group, and VM name using the deprecated command.
    When: get_vm_command is called with the deprecated command name.
    Then: It should call get_vm_request and return correct CommandResults
          with the deprecated prefix.
    """
    from Azure import get_vm_command

    mock_client = mocker.Mock()
    params = {"subscription_id": "sub-id", "resource_group_name": "rg1"}
    args = {"subscription_id": "sub-id", "resource_group_name": "rg1", "virtual_machine_name": "vm1", "expand": ""}

    mock_response = {
        "location": "eastus",
        "tags": {"env": "prod"},
        "properties": {
            "vmId": "vm123",
            "provisioningState": "Succeeded",
            "storageProfile": {"osDisk": {"diskSizeGB": 128, "osType": "Linux"}},
            "instanceView": {"statuses": [{"code": "PowerState/running", "displayStatus": "VM running"}]},
            "networkProfile": {"networkInterfaces": [{"id": "nic1"}]},
            "userData": "userdata",
        },
    }

    mocker.patch.object(mock_client, "get_vm_request", return_value=mock_response)
    mocker.patch("Azure.demisto.command", return_value="azure-vm-instance-details-get")

    result = get_vm_command(mock_client, params, args)

    mock_client.get_vm_request.assert_called_once_with("sub-id", "rg1", "vm1", expand="")

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.Compute"
    assert result.outputs_key_field == "name"
    assert result.outputs["properties"]["vmId"] == "vm123"
    assert result.outputs["properties"]["provisioningState"] == "Succeeded"
    assert result.outputs["properties"]["storageProfile"]["osDisk"]["osType"] == "Linux"
    assert result.outputs["properties"]["instanceView"]["statuses"][0]["displayStatus"] == "VM running"
    assert "vm1" in result.readable_output


def test_get_network_interface_command(mocker):
    """
    Given: A subscription, resource group, and network interface name.
    When: get_network_interface_command is called with these parameters.
    Then: It should call get_network_interface_request and return correct CommandResults
          with properly formatted network interface details.
    """
    from Azure import get_network_interface_command

    mock_client = mocker.Mock()
    mock_params = {"subscription_id": "sub-id", "resource_group_name": "rg1"}
    args = {"subscription_id": "sub-id", "resource_group_name": "rg1", "network_interface_name": "nic1"}

    mock_response = {
        "id": "/subscriptions/sub-id/resourceGroups/rg1/providers/Microsoft.Network/networkInterfaces/nic1",
        "name": "nic1",
        "location": "eastus",
        "properties": {
            "macAddress": "00:11:22:33:44:55",
            "primary": True,
            "networkSecurityGroup": {"id": "nsg-id"},
            "nicType": "Standard",
            "virtualMachine": {"id": "vm-id"},
            "dnsSettings": {"internalDomainNameSuffix": "internal.local"},
            "ipConfigurations": [
                {
                    "name": "ipconfig1",
                    "id": "ipconfig-id",
                    "properties": {"privateIPAddress": "10.0.0.4", "publicIPAddress": {"id": "public-ip-id"}},
                    "etag": 'W/"12345"',
                }
            ],
        },
    }

    mocker.patch.object(mock_client, "get_network_interface_request", return_value=mock_response)

    result = get_network_interface_command(mock_client, mock_params, args)

    mock_client.get_network_interface_request.assert_called_once_with("sub-id", "rg1", "nic1")

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.VirtualNetworks.NetworkInterfaces"
    assert result.outputs_key_field == "name"
    assert result.outputs["name"] == "nic1"
    assert result.outputs["properties"]["macAddress"] == "00:11:22:33:44:55"
    assert result.outputs["properties"]["ipConfigurations"][0]["properties"]["privateIPAddress"] == "10.0.0.4"
    assert result.outputs["properties"]["ipConfigurations"][0]["properties"]["publicIPAddress"]["id"] == "public-ip-id"
    assert result.outputs["properties"]["ipConfigurations"][0]["etag"] == "12345"  # etag cleaned
    assert "nic1" in result.readable_output


def test_get_network_interface_command_deprecated(mocker):
    """
    Given: A subscription, resource group, and network interface name using the deprecated command.
    When: get_network_interface_command is called with the deprecated command name.
    Then: It should call get_network_interface_request and return correct CommandResults
          with the deprecated prefix.
    """
    from Azure import get_network_interface_command

    mock_client = mocker.Mock()
    mock_params = {"subscription_id": "sub-id", "resource_group_name": "rg1"}
    args = {"subscription_id": "sub-id", "resource_group_name": "rg1", "network_interface_name": "nic1"}

    mock_response = {
        "id": "/subscriptions/sub-id/resourceGroups/rg1/providers/Microsoft.Network/networkInterfaces/nic1",
        "name": "nic1",
        "location": "eastus",
        "properties": {
            "macAddress": "00:11:22:33:44:55",
            "primary": True,
            "networkSecurityGroup": {"id": "nsg-id"},
            "nicType": "Standard",
            "virtualMachine": {"id": "vm-id"},
            "dnsSettings": {"internalDomainNameSuffix": "internal.local"},
            "ipConfigurations": [
                {
                    "name": "ipconfig1",
                    "id": "ipconfig-id",
                    "properties": {"privateIPAddress": "10.0.0.4", "publicIPAddress": {"id": "public-ip-id"}},
                    "etag": 'W/"12345"',
                }
            ],
        },
    }

    mocker.patch.object(mock_client, "get_network_interface_request", return_value=mock_response)
    mocker.patch("Azure.demisto.command", return_value="azure-vm-network-interface-details-get")

    result = get_network_interface_command(mock_client, mock_params, args)

    mock_client.get_network_interface_request.assert_called_once_with("sub-id", "rg1", "nic1")

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.Network.Interfaces"
    assert result.outputs_key_field == "name"
    assert result.outputs["name"] == "nic1"


def test_get_single_ip_details_from_list_of_ip_details():
    """
    Given: A subscription, resource group, and public IP name.
    When: get_public_ip_details_command is called with these parameters.
    Then: It should call get_public_ip_details_request and return correct CommandResults.
    """
    from Azure import get_single_ip_details_from_list_of_ip_details

    list_of_ips = [
        {"properties": {"ipAddress": "1.1.1.1"}},
        {"properties": {"ipAddress": "2.2.2.2"}},
        {"properties": {"nested": {"ipAddress": "3.3.3.3"}}},
    ]

    ip1 = get_single_ip_details_from_list_of_ip_details(list_of_ips, "1.1.1.1")
    ip3 = get_single_ip_details_from_list_of_ip_details(list_of_ips, "3.3.3.3")
    ip_missing = get_single_ip_details_from_list_of_ip_details(list_of_ips, "4.4.4.4")

    assert ip1 == {"properties": {"ipAddress": "1.1.1.1"}}
    assert ip3 == {"properties": {"nested": {"ipAddress": "3.3.3.3"}}}
    assert ip_missing is None


def test_get_public_ip_details_command_with_resource_group(mocker):
    """
    Given: A subscription, resource group, and public IP name.
    When: get_public_ip_details_command is called with these parameters.
    Then: It should call get_public_ip_details_request and return correct CommandResults.
    """
    from Azure import get_public_ip_details_command

    mock_client = mocker.Mock()
    mock_params = {"subscription_id": "sub-id", "resource_group_name": "rg1"}
    args = {"subscription_id": "sub-id", "resource_group_name": "rg1", "address_name": "ip1"}

    mock_response = {
        "id": "/subscriptions/sub-id/resourceGroups/rg1/providers/Microsoft.Network/publicIPAddresses/ip1",
        "name": "ip1",
        "location": "eastus",
        "etag": 'W/"12345"',
        "properties": {
            "ipAddress": "1.2.3.4",
            "publicIPAddressVersion": "IPv4",
            "publicIPAllocationMethod": "Static",
            "ipConfiguration": {"id": "config-id"},
            "dnsSettings": {"domainNameLabel": "label1", "fqdn": "ip1.eastus.cloudapp.azure.com"},
        },
    }

    mocker.patch.object(mock_client, "get_public_ip_details_request", return_value=mock_response)

    result = get_public_ip_details_command(mock_client, mock_params, args)

    mock_client.get_public_ip_details_request.assert_called_once_with("sub-id", "rg1", "ip1")

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.VirtualNetworks.PublicIPAddresses"
    assert result.outputs_key_field == "id"
    assert result.outputs["properties"]["ipAddress"] == "1.2.3.4"
    assert result.outputs["properties"]["publicIPAddressVersion"] == "IPv4"
    assert result.outputs["properties"]["publicIPAllocationMethod"] == "Static"
    assert result.outputs["etag"] == "12345"
    assert "ip1" in result.readable_output


def test_get_public_ip_details_command_deprecated(mocker):
    """
    Given: A subscription, resource group, and public IP name using the deprecated command.
    When: get_public_ip_details_command is called with the deprecated command name.
    Then: It should call get_public_ip_details_request and return correct CommandResults
          with the deprecated prefix.
    """
    from Azure import get_public_ip_details_command

    mock_client = mocker.Mock()
    mock_params = {"subscription_id": "sub-id", "resource_group_name": "rg1"}
    args = {"subscription_id": "sub-id", "resource_group_name": "rg1", "address_name": "ip1"}

    mock_response = {
        "id": "/subscriptions/sub-id/resourceGroups/rg1/providers/Microsoft.Network/publicIPAddresses/ip1",
        "name": "ip1",
        "location": "eastus",
        "etag": 'W/"12345"',
        "properties": {
            "ipAddress": "1.2.3.4",
            "publicIPAddressVersion": "IPv4",
            "publicIPAllocationMethod": "Static",
            "ipConfiguration": {"id": "config-id"},
            "dnsSettings": {"domainNameLabel": "label1", "fqdn": "ip1.eastus.cloudapp.azure.com"},
        },
    }

    mocker.patch.object(mock_client, "get_public_ip_details_request", return_value=mock_response)
    mocker.patch("Azure.demisto.command", return_value="azure-vm-public-ip-details-get")

    result = get_public_ip_details_command(mock_client, mock_params, args)

    mock_client.get_public_ip_details_request.assert_called_once_with("sub-id", "rg1", "ip1")

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.Network.IPConfigurations"
    assert result.outputs_key_field == "id"
    assert "ip1" in result.readable_output


def test_get_public_ip_details_command_without_resource_group(mocker):
    """
    Given: A subscription and public IP name, but no resource group.
    When: get_public_ip_details_command is called.
    Then: It should call get_all_public_ip_details_request, find the matching IP, and return details.
    """
    from Azure import get_public_ip_details_command

    mock_client = mocker.Mock()
    mock_params = {"subscription_id": "sub-id"}
    args = {"subscription_id": "sub-id", "address_name": "ip1"}

    mock_all_ips = {
        "value": [
            {
                "id": "/subscriptions/sub-id/resourceGroups/rg1/providers/Microsoft.Network/publicIPAddresses/ip1",
                "name": "ip1",
                "location": "eastus",
                "etag": 'W/"999"',
                "properties": {
                    "ipAddress": "5.6.7.8",
                    "publicIPAddressVersion": "IPv4",
                    "publicIPAllocationMethod": "Dynamic",
                },
            },
            {
                "id": "/subscriptions/sub-id/resourceGroups/rg2/providers/Microsoft.Network/publicIPAddresses/ip2",
                "name": "ip2",
                "location": "westus",
                "etag": 'W/"888"',
                "properties": {
                    "ipAddress": "9.9.9.9",
                    "publicIPAddressVersion": "IPv6",
                    "publicIPAllocationMethod": "Static",
                },
            },
        ]
    }

    # Mock the client and helper functions
    mocker.patch.object(mock_client, "get_all_public_ip_details_request", return_value=mock_all_ips)
    mocker.patch("Azure.get_single_ip_details_from_list_of_ip_details", return_value=mock_all_ips["value"][0])

    result = get_public_ip_details_command(mock_client, mock_params, args)

    mock_client.get_all_public_ip_details_request.assert_called_once_with("sub-id")

    assert isinstance(result, CommandResults)
    assert result.outputs["properties"]["ipAddress"] == "5.6.7.8"
    assert result.outputs["etag"] == "999"
    assert "ip1" in result.readable_output
    assert "rg1" in result.readable_output


def test_azure_billing_usage_list_command_success(mocker, client, mock_params):
    """
    Given: An Azure client and valid billing usage arguments.
    When: azure_billing_usage_list_command is called successfully.
    Then: It should return CommandResults with usage data and proper outputs.
    """
    from Azure import azure_billing_usage_list_command

    mock_response = {
        "value": [
            {
                "name": "usage-item-1",
                "properties": {
                    "product": "Virtual Machines",
                    "meterName": "D2s v3",
                    "paygCost": {"amount": 125.75},
                    "quantity": 24.5,
                    "billingPeriodStartDate": "2025-10-01T00:00:00.0000000Z",
                    "billingPeriodEndDate": "2025-10-01T23:59:59.0000000Z",
                },
            }
        ],
        "nextLink": "https://management.azure.com/subscriptions/test/providers/Microsoft.Consumption/usageDetails?$skiptoken=abc123",
    }
    mocker.patch.object(client, "http_request", return_value=mock_response)

    args = {"subscription_id": "test-subscription-id", "max_results": "50", "filter": "properties/usageStart ge '2023-10-01'"}
    params = mock_params

    result = azure_billing_usage_list_command(client, params, args)

    assert isinstance(result, CommandResults)
    assert "Azure Billing Usage" in result.readable_output
    assert "Azure.Billing.Usage(val.name && val.name == obj.name)" in result.outputs
    assert "Azure.Billing(true)" in result.outputs
    assert (
        "https://management.azure.com/subscriptions/test/providers/Microsoft.Consumption/usageDetails?$skiptoken=abc123"
        in result.outputs["Azure.Billing(true)"]["UsageNextToken"]
    )
    assert len(result.outputs["Azure.Billing.Usage(val.name && val.name == obj.name)"]) == 1
    assert (
        result.outputs["Azure.Billing.Usage(val.name && val.name == obj.name)"][0]["properties"]["product"] == "Virtual Machines"
    )
    assert result.raw_response == mock_response


def test_azure_billing_forecast_list_command_success(mocker, client, mock_params):
    """
    Given: An Azure client and valid billing forecast arguments.
    When: azure_billing_forecast_list_command is called successfully.
    Then: It should return CommandResults with forecast data and proper outputs.
    """
    from Azure import azure_billing_forecast_list_command

    # The current implementation expects a table-like response under properties with columns and rows,
    # and it calls client.billing_forecast_list (not http_request) directly.
    mock_response = {
        "properties": {
            "columns": [
                {"name": "UsageDate"},
                {"name": "CostStatus"},
                {"name": "Currency"},
                {"name": "Pre Tax Cost USD"},
            ],
            "rows": [
                [20231015, "Forecast", "USD", 250.50],
            ],
        }
    }
    mocker.patch.object(client, "billing_forecast_list", return_value=mock_response)

    args = {
        "subscription_id": "test-subscription-id",
        "type": "Usage",
        "aggregation_function_name": "Pre Tax Cost USD",
        "filter": "properties/UsageDate ge '2023-10-15'",
    }
    params = mock_params

    result = azure_billing_forecast_list_command(client, params, args)

    assert isinstance(result, CommandResults)
    assert "Azure Billing Forecast" in result.readable_output

    # Validate context structure and parsed forecasts
    assert "Azure.Billing.Forecast" in result.outputs
    forecast_ctx = result.outputs["Azure.Billing.Forecast"]
    assert isinstance(forecast_ctx, list)
    assert len(forecast_ctx) == 1

    row = forecast_ctx[0]
    # The command uses aggregation_function_name as a key in the result rows
    assert row["Pre Tax Cost USD"] == 250.50
    assert row["CostStatus"] == "Forecast"
    assert row["Currency"] == "USD"
    # UsageDate should be formatted as YYYY-MM-DD from 20231015
    assert row["UsageDate"] == "2023-10-15"

    # Raw response should be the original mock response
    assert result.raw_response == mock_response


def test_azure_billing_budgets_list_command_success(mocker, client, mock_params):
    """
    Given: An Azure client and valid billing budgets arguments.
    When: azure_billing_budgets_list_command is called successfully.
    Then: It should return CommandResults with budget data and proper outputs.
    """
    from Azure import azure_billing_budgets_list_command

    mock_response = {
        "value": [
            {
                "name": "test-budget",
                "type": "Microsoft.Consumption/budgets",
                "properties": {
                    "timePeriod": {"startDate": "2023-10-01T00:00:00Z", "endDate": "2023-10-31T23:59:59Z"},
                    "amount": 1000.0,
                    "currentSpend": {"amount": 750.25},
                },
            }
        ]
    }
    mocker.patch.object(client, "http_request", return_value=mock_response)

    args = {"subscription_id": "test-subscription-id"}
    params = mock_params

    result = azure_billing_budgets_list_command(client, params, args)

    assert isinstance(result, CommandResults)
    assert "Azure Budgets" in result.readable_output
    assert "Azure.Billing.Budget" in result.outputs
    assert len(result.outputs["Azure.Billing.Budget"]) == 1
    assert result.outputs["Azure.Billing.Budget"][0]["name"] == "test-budget"
    assert result.outputs["Azure.Billing.Budget"][0]["properties"]["amount"] == 1000.0
    assert result.outputs["Azure.Billing.Budget"][0]["properties"]["currentSpend"]["amount"] == 750.25
    assert result.raw_response == mock_response


def test_azure_billing_budgets_list_command_single_budget(mocker, client, mock_params):
    """
    Given: An Azure client and arguments for retrieving a single budget by name.
    When: azure_billing_budgets_list_command is called with budget_name parameter.
    Then: It should return CommandResults with single budget data.
    """
    from Azure import azure_billing_budgets_list_command

    mock_response = {
        "name": "specific-budget",
        "type": "Microsoft.Consumption/budgets",
        "properties": {
            "timePeriod": {"startDate": "2023-11-01T00:00:00Z", "endDate": "2023-11-30T23:59:59Z"},
            "amount": 500.0,
            "currentSpend": {"amount": 200.75},
        },
    }
    mocker.patch.object(client, "http_request", return_value=mock_response)

    args = {"subscription_id": "test-subscription-id", "budget_name": "specific-budget"}
    params = mock_params

    result = azure_billing_budgets_list_command(client, params, args)

    assert isinstance(result, CommandResults)
    assert "Azure Budgets" in result.readable_output
    assert "Azure.Billing.Budget" in result.outputs
    assert len(result.outputs["Azure.Billing.Budget"]) == 1
    assert result.outputs["Azure.Billing.Budget"][0]["name"] == "specific-budget"
    assert result.outputs["Azure.Billing.Budget"][0]["properties"]["amount"] == 500.0
    assert result.raw_response == mock_response


def test_azure_billing_usage_list_command_no_next_token(mocker, client, mock_params):
    """
    Given: An Azure client with response containing no next token.
    When: azure_billing_usage_list_command is called successfully.
    Then: It should return CommandResults without next token in outputs.
    """
    from Azure import azure_billing_usage_list_command

    mock_response = {
        "value": [
            {
                "name": "usage-item-2",
                "properties": {
                    "product": "Storage",
                    "paygCost": {"amount": 15.25},
                    "quantity": 100.0,
                    "billingPeriodStartDate": "2025-10-01T00:00:00.0000000Z",
                    "billingPeriodEndDate": "2025-10-02T23:59:59.0000000Z",
                },
            }
        ]
    }
    mocker.patch.object(client, "http_request", return_value=mock_response)

    args = {"subscription_id": "test-subscription-id", "max_results": "10"}
    params = mock_params

    result = azure_billing_usage_list_command(client, params, args)

    assert isinstance(result, CommandResults)
    assert result.outputs["Azure.Billing(true)"]["UsageNextToken"] == ""
    assert "Next Page Token" not in result.readable_output
    assert result.outputs["Azure.Billing.Usage(val.name && val.name == obj.name)"][0]["properties"]["product"] == "Storage"


def test_azure_billing_usage_list_command_with_pagination_token(mocker, client, mock_params):
    """
    Given: An Azure client and arguments with next page token.
    When: azure_billing_usage_list_command is called with pagination token.
    Then: It should include the token in the request parameters.
    """
    from Azure import azure_billing_usage_list_command

    mock_response = {
        "value": [
            {
                "name": "usage-item-page-2",
                "properties": {
                    "product": "Networking",
                    "paygCost": {"amount": 5.50},
                    "quantity": 10.0,
                    "billingPeriodStartDate": "2025-10-04T00:00:00.0000000Z",
                    "billingPeriodEndDate": "2025-10-04T23:59:59.0000000Z",
                },
            }
        ]
    }
    mocker.patch.object(client, "http_request", return_value=mock_response)

    args = {"subscription_id": "test-subscription-id", "next_page_token": "existing-skiptoken"}
    params = mock_params

    result = azure_billing_usage_list_command(client, params, args)

    # Verify the token was passed to the client
    client.http_request.assert_called_once()
    call_args = client.http_request.call_args[1]
    assert call_args["params"].keys() == {"api-version"}

    assert isinstance(result, CommandResults)
    assert result.outputs["Azure.Billing.Usage(val.name && val.name == obj.name)"][0]["properties"]["product"] == "Networking"


def test_parse_forecast_table_to_dict_success():
    """
    Given: A table-like Azure Cost Management response with columns and rows.
    When: parse_forecast_table_to_dict is invoked.
    Then: It should return a list of dict rows mapping column names to values.
    """
    from Azure import parse_forecast_table_to_dict

    response = {
        "properties": {
            "columns": [
                {"name": "UsageDate"},
                {"name": "CostUSD"},
                {"name": "CostStatus"},
            ],
            "rows": [
                ["2025-10-01", 12.34, "Forecast"],
                ["2025-10-02", 56.78, "Actual"],
            ],
        }
    }

    parsed = parse_forecast_table_to_dict(response)
    assert isinstance(parsed, list)
    assert parsed[0]["UsageDate"] == "2025-10-01"
    assert parsed[0]["CostUSD"] == 12.34
    assert parsed[0]["CostStatus"] == "Forecast"
    assert parsed[1]["UsageDate"] == "2025-10-02"


def test_parse_forecast_table_to_dict_mismatch_row_length(mocker):
    """
    Given: Response where one row length doesn't match columns length.
    When: parse_forecast_table_to_dict runs.
    Then: It should skip the mismatched row and parse the valid one.
    """
    from Azure import parse_forecast_table_to_dict

    mocker.patch.object(demisto, "debug")

    response = {
        "properties": {
            "columns": [{"name": "A"}, {"name": "B"}],
            "rows": [
                [1],  # mismatched (len 1 vs 2 columns) -> should be skipped
                [2, 3],  # valid
            ],
        }
    }

    parsed = parse_forecast_table_to_dict(response)
    assert parsed == [{"A": 2, "B": 3}]


def test_parse_forecast_table_to_dict_malformed_raises():
    """
    Given: Malformed response (columns missing 'name').
    When: parse_forecast_table_to_dict runs.
    Then: It should raise DemistoException.
    """
    from Azure import parse_forecast_table_to_dict, DemistoException

    bad_response = {
        "properties": {
            "columns": [{"wrong": "UsageDate"}],  # will cause KeyError in parsing
            "rows": [["2025-10-01"]],
        }
    }

    with pytest.raises(DemistoException):
        parse_forecast_table_to_dict(bad_response)


def test_remove_query_param_from_url_basic():
    """
    Given: A URL with multiple query parameters including duplicates for a key.
    When: remove_query_param_from_url is used to remove that key.
    Then: The resulting URL should not contain the removed parameter and others remain.
    """
    from Azure import remove_query_param_from_url
    from urllib.parse import urlparse, parse_qs

    url = "https://example.com/path?a=1&b=2&b=3&c=x"
    out = remove_query_param_from_url(url, "b")
    parsed = urlparse(out)
    qs = parse_qs(parsed.query)
    assert "b" not in qs
    assert qs == {"a": ["1"], "c": ["x"]}


def test_remove_query_param_from_url_param_absent():
    """
    Given: A URL without the specified parameter.
    When: remove_query_param_from_url is called.
    Then: The URL query mapping remains logically the same.
    """
    from Azure import remove_query_param_from_url
    from urllib.parse import urlparse, parse_qs

    url = "https://example.com/path?a=1&c=x"
    out = remove_query_param_from_url(url, "b")
    assert parse_qs(urlparse(out).query) == {"a": ["1"], "c": ["x"]}


def test_remove_query_param_from_url_no_query():
    """
    Given: A URL without any query string.
    When: remove_query_param_from_url is called.
    Then: The URL remains unchanged.
    """
    from Azure import remove_query_param_from_url

    url = "https://example.com/path"
    out = remove_query_param_from_url(url, "b")
    assert out == url


def test_storage_container_set_headers(mocker):
    """
    Given: An Azure client instance
    When: The storage_container_set_headers function is called
    Then: The headers should be properly set with the correct values
    """
    # Create a client instance
    client = AzureClient()

    # Mock datetime to get consistent test results
    mock_datetime = mocker.patch("Azure.dt.datetime")
    mock_datetime.utcnow.return_value.strftime.return_value = "Wed, 17 Nov 2025 09:30:00 GMT"

    # Call the function
    client.storage_container_set_headers(custom_headers={"x-custom-header": "test-value"})

    # Verify headers were set correctly
    expected_headers = {
        "x-ms-version": "2023-11-03",
        "x-ms-date": "Wed, 17 Nov 2025 09:30:00 GMT",
        "x-custom-header": "test-value",
    }

    assert client.headers == expected_headers
    mock_datetime.utcnow.assert_called_once()
    mock_datetime.utcnow.return_value.strftime.assert_called_once_with(STORAGE_DATE_FORMAT)


def test_create_set_tags_request_body():
    """
    Given: A dictionary of tags
    When: The create_set_tags_request_body function is called
    Then: The function should return a properly formatted XML string
    """
    # Test data
    tags = {"key1": "value1", "key2": "value2"}

    # Call the function
    result = create_set_tags_request_body(tags)

    # Verify the result is bytes
    assert isinstance(result, bytes)

    # Convert to string for easier assertion
    result_str = result.decode("utf-8")

    # Verify XML structure
    assert "<?xml version='1.0' encoding='utf-8'?>" in result_str
    assert "<Tags>" in result_str
    assert "<TagSet>" in result_str
    assert "<Tag>" in result_str
    assert "<Key>key1</Key>" in result_str
    assert "<Value>value1</Value>" in result_str
    assert "<Key>key2</Key>" in result_str
    assert "<Value>value2</Value>" in result_str

    # Parse XML to verify structure
    import xml.etree.ElementTree as ET

    root = ET.fromstring(result)

    # Check structure
    assert root.tag == "Tags"
    tag_set = root.find("TagSet")
    assert tag_set is not None

    # Check tags
    tags_elements = tag_set.findall("Tag")
    assert len(tags_elements) == 2

    # Check first tag
    tag1 = tags_elements[0]
    assert tag1.find("Key").text in ["key1", "key2"]
    if tag1.find("Key").text == "key1":
        assert tag1.find("Value").text == "value1"
    else:
        assert tag1.find("Value").text == "value2"


def test_nsg_security_rules_list_command_success(mocker):
    """
    Given: The command arguments.
    When: Calling azure-nsg-security-rules-list command.
    Then: The command should successfully process and return network security rules.
    """
    mock_client = mocker.Mock()
    mock_response = {
        "value": [
            {
                "name": "rule1",
                "id": "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Network/networkSecurityGroups/nsg1"
                "/securityRules/rule1",
                "properties": {"direction": "Inbound", "priority": 100, "access": "Allow"},
            },
            {
                "name": "rule2",
                "id": "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Network/networkSecurityGroups/nsg1"
                "/securityRules/rule2",
                "properties": {"direction": "Outbound", "priority": 200, "access": "Deny"},
            },
        ]
    }
    mock_client.list_security_rules.return_value = mock_response

    params = {}
    args = {"subscription_id": "test-sub-id", "resource_group_name": "test-rg", "network_security_group_name": "test-nsg"}

    result = nsg_security_rules_list_command(mock_client, params, args)

    assert isinstance(result, CommandResults)
    assert result.outputs == mock_response["value"]
    assert "Security Groups List" in result.readable_output
    assert "rule1" in result.readable_output
    assert "rule2" in result.readable_output
    mock_client.list_security_rules.assert_called_once_with("test-sub-id", "test-rg", "test-nsg")


def test_nsg_security_rules_list_command_deprecated(mocker):
    """
    Given: The command arguments using the deprecated command.
    When: Calling azure-nsg-security-rules-list command with the deprecated command name.
    Then: The command should successfully process and return network security rules with the deprecated prefix.
    """
    mock_client = mocker.Mock()
    mock_response = {
        "value": [
            {
                "name": "rule1",
                "id": "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Network/networkSecurityGroups/nsg1"
                "/securityRules/rule1",
                "properties": {"direction": "Inbound", "priority": 100, "access": "Allow"},
            },
            {
                "name": "rule2",
                "id": "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Network/networkSecurityGroups/nsg1"
                "/securityRules/rule2",
                "properties": {"direction": "Outbound", "priority": 200, "access": "Deny"},
            },
        ]
    }
    mock_client.list_security_rules.return_value = mock_response

    params = {}
    args = {"subscription_id": "test-sub-id", "resource_group_name": "test-rg", "network_security_group_name": "test-nsg"}

    mocker.patch("Azure.demisto.command", return_value="azure-nsg-security-rules-list")

    result = nsg_security_rules_list_command(mock_client, params, args)

    assert isinstance(result, CommandResults)
    assert result.outputs_prefix == "Azure.NSGRule"
    assert result.outputs_key_field == "id"
    assert result.outputs == mock_response["value"]


def test_nsg_security_rules_list_command_empty_response(mocker):
    """
    Given: The command arguments.
    When: Calling azure-nsg-security-rules-list command.
    Then: The command should successfully process and return an empty list of network security rules.
    """
    mock_client = mocker.Mock()
    mock_client.list_security_rules.return_value = {"value": []}

    params = {}
    args = {"subscription_id": "test-sub-id", "resource_group_name": "test-rg", "network_security_group_name": "test-nsg"}

    result = nsg_security_rules_list_command(mock_client, params, args)

    assert isinstance(result, CommandResults)
    assert result.outputs == []
    assert result.raw_response == []


def test_nsg_security_rules_list_command_no_value_key(mocker):
    """
    Given: The command arguments.
    When: Calling azure-nsg-security-rules-list command.
    Then: The command should return an empty list.
    """
    mock_client = mocker.Mock()
    mock_client.list_security_rules.return_value = {}

    params = {}
    args = {"network_security_group_name": "test-nsg", "subscription_id": "test-sub-id", "resource_group_name": "test-rg"}

    result = nsg_security_rules_list_command(mock_client, params, args)

    assert isinstance(result, CommandResults)
    assert result.outputs == []


def test_nsg_security_rules_list_command_missing_properties(mocker):
    """
    Given: The command arguments.
    When: Calling azure-nsg-security-rules-list command.
    Then: Test handling of rules with missing properties. The command should successfully process and return network
    security rules.
    """
    mock_client = mocker.Mock()
    mock_response = {
        "value": [
            {
                "name": "rule1",
                "id": "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Network/networkSecurityGroups/nsg1"
                "/securityRules/rule1",
            },
            {
                "name": "rule2",
                "id": "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Network/networkSecurityGroups/nsg1"
                "/securityRules/rule2",
                "properties": {},
            },
        ]
    }
    mock_client.list_security_rules.return_value = mock_response

    params = {}
    args = {"subscription_id": "test-sub-id", "resource_group_name": "test-rg", "network_security_group_name": "test-nsg"}

    result = nsg_security_rules_list_command(mock_client, params, args)

    assert isinstance(result, CommandResults)
    assert len(result.outputs) == 2


def test_storage_blob_service_properties_set_command_new(mocker, client, mock_params):
    """
    Given: An Azure client and a request to set blob service properties.
    When: The storage_blob_service_properties_set_command function is called with valid parameters with
        azure-storage-blob-service-property-set.
    Then: The function should return the updated blob service properties in the expected format,
        including backward compatibility outputs.
    """
    from Azure import storage_blob_service_properties_set_command

    # Prepare mock response
    properties_response = {
        "name": "default",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Storage/storageAccounts/teststorage/blobServices"
        "/default",
        "properties": {"deleteRetentionPolicy": {"enabled": True, "days": 7}},
    }

    mocker.patch.object(client, "storage_blob_service_properties_set_request", return_value=properties_response)
    mocker.patch("Azure.demisto.command", return_value="azure-storage-blob-service-property-set")

    # Call the function
    args = {"account_name": "teststorage", "delete_rentention_policy_enabled": "true", "delete_rentention_policy_days": "7"}

    result = storage_blob_service_properties_set_command(client, mock_params, args)

    assert result.outputs_prefix == "Azure.Storage.BlobServices"
    assert result.outputs_key_field == "id"
    assert result.outputs == properties_response
    assert result.raw_response == properties_response


def test_storage_blob_service_properties_get_command_new(mocker):
    """
    Given: An Azure client mock and the get_blob_service_properties.json file.
    When: storage_blob_service_properties_get_command is called with azure-storage-blob-service-property-get.
    Then: The CommandResults should have correct outputs, readable_output, and metadata, including backward compatibility outputs.
    """
    from Azure import storage_blob_service_properties_get_command

    mock_response = util_load_json("test_data/get_blob_service_properties.json")

    mock_client = mocker.Mock()
    mock_client.storage_blob_service_properties_get_request.return_value = mock_response
    mocker.patch("Azure.demisto.command", return_value="azure-storage-blob-service-property-get")

    params = {"subscription_id": "subid", "resource_group_name": "rg1"}
    args = {"account_name": "teststorage"}

    result = storage_blob_service_properties_get_command(mock_client, params, args)

    assert result.outputs_prefix == "Azure.Storage.BlobServices"
    assert result.outputs_key_field == "id"
    assert result.outputs == mock_response
    assert result.raw_response == mock_response


def test_create_network_security_group(mocker, client):
    """
    Given: An Azure client and a request to create a network security group.
    When: The create_network_security_group function is called with valid parameters.
    Then: The function should return the created network security group information in the expected format.
    """
    # Prepare mock response
    nsg_response = {
        "name": "test-nsg",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg",
        "location": "eastus",
        "properties": {},
    }

    mocker.patch.object(client, "http_request", return_value=nsg_response)

    result = client.create_network_security_group(
        subscription_id="sub-id",
        resource_group_name="test-rg",
        security_group_name="test-nsg",
        location="eastus",
    )

    assert result == nsg_response
    client.http_request.assert_called_once_with(
        method="PUT",
        full_url="https://management.azure.com/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg",
        params={"api-version": "2025-05-01"},
        json_data={"location": "eastus"},
    )


def test_create_network_security_group_error(mocker, client):
    """
    Given: An Azure client and a request to create a network security group.
    When: The create_network_security_group function is called and an exception is raised.
    Then: The function should call handle_azure_error.
    """
    mocker.patch.object(client, "http_request", side_effect=Exception("test error"))
    mocker.patch.object(client, "handle_azure_error")

    client.create_network_security_group(
        subscription_id="sub-id",
        resource_group_name="test-rg",
        security_group_name="test-nsg",
        location="eastus",
    )

    client.handle_azure_error.assert_called_once()


def test_list_vm_request(mocker, client):
    """
    Given: An Azure client and a request to list virtual machines.
    When: The list_vm_request function is called with valid parameters.
    Then: The function should return the list of virtual machines in the expected format.
    """
    # Prepare mock response
    vm_response = {
        "value": [
            {
                "name": "test-vm",
                "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Compute/virtualMachines/test-vm",
                "location": "eastus",
                "properties": {},
            }
        ]
    }

    mocker.patch.object(client, "http_request", return_value=vm_response)

    result = client.list_vm_request(
        subscription_id="sub-id",
        resource_group_name="test-rg",
        next_token="",
    )

    assert result == vm_response
    client.http_request.assert_called_once_with(
        method="GET",
        full_url="https://management.azure.com/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Compute/virtualMachines",
        params={"api-version": "2025-04-01"},
    )


def test_list_vm_request_with_next_token(mocker, client):
    """
    Given: An Azure client and a request to list virtual machines with a next token.
    When: The list_vm_request function is called with a next token.
    Then: The function should return the list of virtual machines using the next token.
    """
    # Prepare mock response
    vm_response = {
        "value": [
            {
                "name": "test-vm2",
                "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Compute/virtualMachines/test-vm2",
                "location": "eastus",
                "properties": {},
            }
        ]
    }

    mocker.patch.object(client, "http_request", return_value=vm_response)

    result = client.list_vm_request(
        subscription_id="sub-id",
        resource_group_name="test-rg",
        next_token="https://management.azure.com/next-page-url",
    )

    assert result == vm_response
    client.http_request.assert_called_once_with(
        method="GET",
        full_url="https://management.azure.com/next-page-url",
        params={},
    )


def test_list_vm_request_error(mocker, client):
    """
    Given: An Azure client and a request to list virtual machines.
    When: The list_vm_request function is called and an exception is raised.
    Then: The function should call handle_azure_error.
    """
    mocker.patch.object(client, "http_request", side_effect=Exception("test error"))
    mocker.patch.object(client, "handle_azure_error")

    client.list_vm_request(
        subscription_id="sub-id",
        resource_group_name="test-rg",
        next_token="",
    )

    client.handle_azure_error.assert_called_once()


def test_update_network_interface_request(mocker, client):
    """
    Given: An Azure client and a request to update a network interface.
    When: The update_network_interface_request function is called with valid parameters.
    Then: The function should return the updated network interface information in the expected format.
    """
    # Prepare mock response
    network_interface_response = {
        "name": "test-nic",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-nic",
        "properties": {"ipConfigurations": []},
    }

    mocker.patch.object(client, "http_request", return_value=network_interface_response)

    result = client.update_network_interface_request(
        subscription_id="sub-id",
        resource_group_name="test-rg",
        interface_name="test-nic",
        network_interface_data={"properties": {"ipConfigurations": []}},
    )

    assert result == network_interface_response
    client.http_request.assert_called_once_with(
        method="PUT",
        full_url="https://management.azure.com/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-nic",
        params={"api-version": "2023-05-01"},
        json_data={"properties": {"ipConfigurations": []}},
    )


def test_update_network_interface_request_error(mocker, client):
    """
    Given: An Azure client and a request to update a network interface.
    When: The update_network_interface_request function is called and an exception is raised.
    Then: The function should call handle_azure_error.
    """
    mocker.patch.object(client, "http_request", side_effect=Exception("test error"))
    mocker.patch.object(client, "handle_azure_error")

    client.update_network_interface_request(
        subscription_id="sub-id",
        resource_group_name="test-rg",
        interface_name="test-nic",
        network_interface_data={"properties": {"ipConfigurations": []}},
    )

    client.handle_azure_error.assert_called_once()


def test_nsg_security_group_create_command(mocker, client, mock_params):
    """
    Given: An Azure client and a request to create a network security group.
    When: The nsg_security_group_create_command function is called with valid parameters.
    Then: The function should return the created network security group information in the expected format.
    """
    from Azure import nsg_security_group_create_command

    # Prepare mock response
    nsg_response = {
        "name": "test-nsg",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg",
        "location": "eastus",
        "type": "Microsoft.Network/networkSecurityGroups",
        "etag": 'W/"test-etag"',
        "properties": {},
    }

    mocker.patch.object(client, "create_network_security_group", return_value=nsg_response)

    args = {
        "subscription_id": "sub-id",
        "resource_group_name": "test-rg",
        "security_group_name": "test-nsg",
        "location": "eastus",
    }

    result = nsg_security_group_create_command(client=client, params=mock_params, args=args)

    assert result.outputs_prefix == "Azure.VirtualNetworks.SecurityGroups"
    assert result.outputs_key_field == "id"
    assert result.outputs == {
        "name": "test-nsg",
        "id": "/subscriptions/sub-id/resourceGroups/test-rg/providers/Microsoft.Network/networkSecurityGroups/test-nsg",
        "location": "eastus",
        "type": "Microsoft.Network/networkSecurityGroups",
        "etag": "test-etag",
        "properties": {},
    }
    assert "The network security group test-nsg was created successfully" in result.readable_output
    client.create_network_security_group.assert_called_once_with(
        subscription_id="sub-id",
        resource_group_name="test-rg",
        security_group_name="test-nsg",
        location="eastus",
    )


def test_list_vm_command_success(mocker):
    """
    Given:
        - Valid arguments for listing virtual machines.
    When:
        - Calling list_vm_command.
    Then:
        - Ensure the command returns the expected CommandResults object with the correct outputs.
    """
    from Azure import list_vm_command

    client = mocker.MagicMock()
    client.list_vm_request.return_value = {"value": [{"id": "vm1", "name": "test-vm"}], "nextLink": "next_token_value"}

    args = {
        "subscription_id": "sub1",
        "resource_group_name": "rg1",
    }
    params = {}

    result = list_vm_command(client, params, args)

    assert result.outputs == {
        "Azure.Compute.VirtualMachines(val.id && val.id == obj.id)": [{"id": "vm1", "name": "test-vm"}],
        "Azure.Compute(true)": {"VirtualMachinesNextToken": "next_token_value"},
    }
    client.list_vm_request.assert_called_once_with("sub1", "rg1", "")


def test_list_vm_command_no_vms(mocker):
    """
    Given:
        - Valid arguments but no virtual machines are returned.
    When:
        - Calling list_vm_command.
    Then:
        - Ensure the command returns a CommandResults object with a "No Virtual Machines found." message.
    """
    from Azure import list_vm_command

    client = mocker.MagicMock()
    client.list_vm_request.return_value = {"value": []}

    args = {"subscription_id": "sub1", "resource_group_name": "rg1"}
    params = {}

    result = list_vm_command(client, params, args)

    assert result.readable_output == "No Virtual Machines found."
    client.list_vm_request.assert_called_once_with("sub1", "rg1", "")


def test_network_interface_update_command_success(mocker):
    """
    Given:
        - Valid arguments for updating a network interface.
    When:
        - Calling network_interface_update_command.
    Then:
        - Ensure the command returns the expected CommandResults object with the correct outputs.
    """
    from Azure import network_interface_update_command

    client = mocker.MagicMock()
    client.get_network_interface_request.return_value = {
        "id": "nic1",
        "name": "test-nic",
        "location": "eastus",
        "properties": {"enableIPForwarding": False, "enableAcceleratedNetworking": False},
    }
    client.update_network_interface_request.return_value = {
        "id": "nic1",
        "name": "test-nic",
        "location": "eastus",
        "etag": 'W/"etag-value"',
        "properties": {
            "enableIPForwarding": True,
            "enableAcceleratedNetworking": True,
            "dnsSettings": {"internalDnsNameLabel": "test-label", "dnsServers": ["1.1.1.1"]},
        },
    }

    args = {
        "subscription_id": "sub1",
        "resource_group_name": "rg1",
        "network_interface_name": "test-nic",
        "enable_ip_forwarding": "true",
        "enable_accelerate_networking": "true",
        "internal_dns_name_label": "test-label",
        "dns_servers": "1.1.1.1",
    }
    params = {}

    result = network_interface_update_command(client, params, args)

    assert result.outputs == {
        "id": "nic1",
        "name": "test-nic",
        "location": "eastus",
        "etag": "etag-value",
        "properties": {
            "enableIPForwarding": True,
            "enableAcceleratedNetworking": True,
            "dnsSettings": {"internalDnsNameLabel": "test-label", "dnsServers": ["1.1.1.1"]},
        },
    }
    assert result.outputs_prefix == "Azure.VirtualNetworks.NetworkInterfaces"
    assert result.outputs_key_field == "id"
    client.get_network_interface_request.assert_called_once_with("sub1", "rg1", "test-nic")
    client.update_network_interface_request.assert_called_once_with(
        subscription_id="sub1",
        resource_group_name="rg1",
        interface_name="test-nic",
        network_interface_data={
            "id": "nic1",
            "name": "test-nic",
            "location": "eastus",
            "properties": {
                "enableIPForwarding": True,
                "enableAcceleratedNetworking": True,
                "dnsSettings": {"internalDnsNameLabel": "test-label", "dnsServers": ["1.1.1.1"]},
            },
        },
    )


def test_network_interface_update_command_add_nsg(mocker):
    """
    Given:
        - Valid arguments for updating a network interface, including adding a new NSG.
    When:
        - Calling network_interface_update_command.
    Then:
        - Ensure the command adds the NSG to the properties.
    """
    from Azure import network_interface_update_command

    client = mocker.MagicMock()
    client.get_network_interface_request.return_value = {"id": "nic1", "name": "test-nic", "location": "eastus", "properties": {}}
    client.update_network_interface_request.return_value = {
        "id": "nic1",
        "name": "test-nic",
        "location": "eastus",
        "etag": 'W/"etag-value"',
        "properties": {
            "networkSecurityGroup": {
                "id": "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Network/networkSecurityGroups/nsg1"
            }
        },
    }

    expected_updated_nic = {
        "id": "nic1",
        "name": "test-nic",
        "location": "eastus",
        "properties": {
            "networkSecurityGroup": {
                "id": "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Network/networkSecurityGroups/nsg1"
            }
        },
    }

    args = {
        "subscription_id": "sub1",
        "resource_group_name": "rg1",
        "network_interface_name": "test-nic",
        "network_security_group_name": "nsg1",
    }
    params = {}

    result = network_interface_update_command(client, params, args)

    assert (
        result.outputs.get("properties", {}).get("networkSecurityGroup", {}).get("id")
        == "/subscriptions/sub1/resourceGroups/rg1/providers/Microsoft.Network/networkSecurityGroups/nsg1"
    )
    client.get_network_interface_request.assert_called_once_with("sub1", "rg1", "test-nic")
    client.update_network_interface_request.assert_called_once_with(
        subscription_id="sub1", resource_group_name="rg1", interface_name="test-nic", network_interface_data=expected_updated_nic
    )


def test_network_interface_update_command_remove_nsg(mocker):
    """
    Given:
        - Valid arguments for updating a network interface, including removing the NSG.
    When:
        - Calling network_interface_update_command.
    Then:
        - Ensure the command removes the NSG from the properties.
    """
    from Azure import network_interface_update_command

    client = mocker.MagicMock()
    client.get_network_interface_request.return_value = {
        "id": "nic1",
        "name": "test-nic",
        "location": "eastus",
        "properties": {"networkSecurityGroup": {"id": "nsg1"}},
    }
    client.update_network_interface_request.return_value = {
        "id": "nic1",
        "name": "test-nic",
        "location": "eastus",
        "etag": 'W/"etag-value"',
        "properties": {},
    }

    args = {
        "subscription_id": "sub1",
        "resource_group_name": "rg1",
        "network_interface_name": "test-nic",
        "remove_network_security_group": "yes",
    }
    params = {}

    result = network_interface_update_command(client, params, args)

    assert "networkSecurityGroup" not in result.outputs.get("properties", {})
    client.get_network_interface_request.assert_called_once_with("sub1", "rg1", "test-nic")
    client.update_network_interface_request.assert_called_once_with(
        subscription_id="sub1",
        resource_group_name="rg1",
        interface_name="test-nic",
        network_interface_data={
            "id": "nic1",
            "name": "test-nic",
            "location": "eastus",
            "properties": {},
        },
    )


def test_network_interface_update_command_conflict_nsg(mocker):
    """
    Given:
        - Conflicting arguments for updating a network interface (both setting and removing NSG).
    When:
        - Calling network_interface_update_command.
    Then:
        - Ensure the command raises a DemistoException.
    """
    from Azure import network_interface_update_command
    from CommonServerPython import DemistoException
    import pytest

    client = mocker.MagicMock()

    args = {
        "subscription_id": "sub1",
        "resource_group_name": "rg1",
        "network_interface_name": "test-nic",
        "network_security_group_name": "nsg1",
        "remove_network_security_group": "yes",
    }
    params = {}

    with pytest.raises(
        DemistoException, match="The remove_network_security_group option cannot be used with network_security_group_name."
    ):
        network_interface_update_command(client, params, args)


def test_test_module_device_code_flow(mocker):
    """
    Given: A client configured with the Device Code authentication type.
    When: test_module is called (Test button).
    Then: A DemistoException is raised, because the Device Code token lives in the saved instance
          context and the Test button cannot validate it. The user is directed to `!azure-auth-test`.
          No API call is made.
    """
    client = AzureClient(app_id="test_app_id", connection_type="Device Code")
    mock_http = mocker.patch.object(client, "http_request", return_value={})

    with pytest.raises(DemistoException) as excinfo:
        Azure.test_module(client)

    assert "azure-auth-test" in str(excinfo.value)
    mock_http.assert_not_called()


def test_test_module_authorization_code_flow(mocker):
    """
    Given: A client configured with the Authorization Code authentication type.
    When: test_module is called (Test button).
    Then: It validates directly via the roleAssignments call (the authorization code is in the
          instance parameters, so a token can be obtained on demand) and returns "ok".
    """
    client = AzureClient(app_id="test_app_id", connection_type="Authorization Code")
    mock_http = mocker.patch.object(client, "http_request", return_value={})

    assert Azure.test_module(client) == "ok"
    mock_http.assert_called_once()


def test_test_module_client_credentials_ok(mocker, client):
    """
    Given: A client configured with the Client Credentials flow (default) and a successful API call.
    When: test_module is called.
    Then: It returns "ok".
    """
    mocker.patch.object(client, "connection_type", "Client Credentials")
    mocker.patch.object(client, "http_request", return_value={})

    assert Azure.test_module(client) == "ok"


def test_test_module_managed_identities_uses_resource_groups(mocker):
    """
    Given: A client configured with the Azure Managed Identities authentication type.
    When: test_module is called (Test button).
    Then: It validates via the lightweight resource-groups list call (not the roleAssignments call),
          because a Managed Identity often lacks the roleAssignments/read permission while still being
          able to run other commands. It returns "ok".
    """
    client = AzureClient(app_id="test_app_id", connection_type="Azure Managed Identities")
    client.subscription_id = "sub-123"
    mock_http = mocker.patch.object(client, "http_request", return_value={})

    assert Azure.test_module(client) == "ok"

    mock_http.assert_called_once()
    _, kwargs = mock_http.call_args
    assert kwargs["full_url"].endswith("/subscriptions/sub-123/resourcegroups")
    assert "roleAssignments" not in kwargs["full_url"]


def test_test_connection_success(mocker, client):
    """
    Given: A client whose MicrosoftClient can fetch an access token.
    When: test_connection is called.
    Then: A success message is returned.
    """
    mocker.patch.object(client.ms_client, "get_access_token")

    assert "Success" in Azure.test_connection(client)


def test_start_auth(mocker, client):
    """
    Given: A client.
    When: start_auth is called.
    Then: It returns CommandResults wrapping the MicrosoftClient start_auth output.
    """
    mocker.patch.object(client.ms_client, "start_auth", return_value="follow these steps")

    result = Azure.start_auth(client)

    assert result.readable_output == "follow these steps"


def test_complete_auth(mocker, client):
    """
    Given: A client.
    When: complete_auth is called.
    Then: It fetches the access token and returns a success message.
    """
    mock_get_token = mocker.patch.object(client.ms_client, "get_access_token")

    result = Azure.complete_auth(client)

    mock_get_token.assert_called_once()
    assert "completed successfully" in result


def test_get_azure_client_device_code_no_secret(mocker, mock_params):
    """
    Given: Marketplace path (no connector) with the Device Code flow and no Client Secret.
    When: get_azure_client is called.
    Then: It does NOT raise the missing-secret error and builds a client with the Device Code connection type.
    """
    mocker.patch("Azure.get_connector_id", return_value=None)
    mocker.patch("Azure.get_azure_managed_identities_client_id", return_value=None)
    mock_azure_client = mocker.patch("Azure.AzureClient", return_value=mocker.Mock())

    params = mock_params.copy()
    params["credentials"] = {}
    params["auth_type"] = "Device Code"

    get_azure_client(params, {}, "command")

    # The connection_type must be propagated to the client (no missing-secret exception raised).
    _, kwargs = mock_azure_client.call_args
    assert kwargs["connection_type"] == "Device Code"


def test_get_azure_client_marketplace_storage_scope(mocker, mock_params):
    """
    Given: Marketplace path (no connector), Client Credentials, and a storage-container command.
    When: get_azure_client is called.
    Then: The AzureClient is built with the STORAGE scope and STORAGE resource (not the management
          scope), so the storage-scoped token is requested. Regression test for the scope-override bug.
    """
    from Azure import STORAGE_SCOPE, STORAGE_RESOURCE

    mocker.patch("Azure.get_connector_id", return_value=None)
    mocker.patch("Azure.get_azure_managed_identities_client_id", return_value=None)
    mock_azure_client = mocker.patch("Azure.AzureClient", return_value=mocker.Mock())

    params = mock_params.copy()
    params["credentials"] = {"password": "secret"}
    params["auth_type"] = "Client Credentials"

    get_azure_client(params, {}, "azure-storage-container-create")

    _, kwargs = mock_azure_client.call_args
    assert kwargs["scope"] == STORAGE_SCOPE
    assert kwargs["resource"] == STORAGE_RESOURCE
    assert kwargs["connection_type"] == "Client Credentials"


def test_azure_client_client_credentials_does_not_send_resource_to_v2_endpoint(mocker):
    """
    Given: A Client Credentials client (uses the v2.0 token endpoint with a `.default` scope).
    When: AzureClient builds the MicrosoftClient.
    Then: No `resource` is forwarded to MicrosoftClient, so the token request sends only `scope`.
          Sending both `scope` and `resource` to the v2.0 endpoint causes Microsoft to return
          "invalid_target: The resource parameter provided in the request doesn't match with the
          requested scopes". Only Device Code (v1.0-style) uses `resource`.
    """
    from Azure import DEFAULT_SCOPE, DEFAULT_RESOURCE

    captured = {}

    def fake_ms_client(**kwargs):
        captured.update(kwargs)
        return mocker.Mock()

    mocker.patch("Azure.MicrosoftClient", side_effect=fake_ms_client)
    AzureClient(
        app_id="app",
        connection_type="Client Credentials",
        tenant_id="my-tenant",
        scope=DEFAULT_SCOPE,
        resource=DEFAULT_RESOURCE,
    )

    assert captured["scope"] == DEFAULT_SCOPE
    # resource must not be forwarded for the v2.0 client-credentials flow.
    assert captured.get("resource") is None


def test_azure_client_device_code_default_resource_derives_management_scope(mocker):
    """
    Given: A Device Code client for a management (default) command, i.e. resource=DEFAULT_RESOURCE.
    When: AzureClient builds the MicrosoftClient.
    Then: The MicrosoftClient receives the management resource (no trailing slash) and a Device Code
          delegated scope derived from it. Regression test: the branch derives scope/resource from
          the per-command resource instead of hardcoding management-only values.
    """
    from Azure import DEFAULT_RESOURCE

    captured = {}

    def fake_ms_client(**kwargs):
        captured.update(kwargs)
        return mocker.Mock()

    mocker.patch("Azure.MicrosoftClient", side_effect=fake_ms_client)
    AzureClient(app_id="app", connection_type="Device Code", resource=DEFAULT_RESOURCE)

    expected_resource = DEFAULT_RESOURCE.rstrip("/")
    assert captured["resource"] == expected_resource
    assert captured["scope"] == f"{expected_resource}/user_impersonation offline_access user.read"
    assert captured["token_retrieval_url"] is not None


def test_azure_client_device_code_storage_resource_derives_storage_scope(mocker):
    """
    Given: A Device Code client for a storage-container command, i.e. resource=STORAGE_RESOURCE.
    When: AzureClient builds the MicrosoftClient.
    Then: The MicrosoftClient receives the storage resource (no trailing slash) and a Device Code
          delegated scope derived from it, so storage commands are storage-scoped under Device Code
          auth instead of always management-scoped.
    """
    from Azure import STORAGE_RESOURCE

    captured = {}

    def fake_ms_client(**kwargs):
        captured.update(kwargs)
        return mocker.Mock()

    mocker.patch("Azure.MicrosoftClient", side_effect=fake_ms_client)
    AzureClient(app_id="app", connection_type="Device Code", resource=STORAGE_RESOURCE)

    expected_resource = STORAGE_RESOURCE.rstrip("/")
    assert captured["resource"] == expected_resource
    assert captured["scope"] == f"{expected_resource}/user_impersonation offline_access user.read"
    assert captured["token_retrieval_url"] is not None


def test_azure_client_client_credentials_gov_endpoint_builds_gov_token_url(mocker):
    """
    Given: A Client Credentials client configured with a US Gov Azure AD endpoint
           (https://login.microsoftonline.us).
    When: AzureClient builds the MicrosoftClient.
    Then: The token_retrieval_url points to the same (gov) authority so the confidential-client token
          request is not sent cross-cloud. Regression test for the Microsoft error
          "Confidential Client is not supported in Cross Cloud request".
    """
    captured = {}

    def fake_ms_client(**kwargs):
        captured.update(kwargs)
        return mocker.Mock()

    mocker.patch("Azure.MicrosoftClient", side_effect=fake_ms_client)
    AzureClient(
        app_id="app",
        connection_type="Client Credentials",
        tenant_id="my-tenant",
        azure_ad_endpoint="https://login.microsoftonline.us",
    )

    assert captured["token_retrieval_url"] == "https://login.microsoftonline.us/my-tenant/oauth2/v2.0/token"


def test_azure_client_client_credentials_default_endpoint_builds_commercial_token_url(mocker):
    """
    Given: A Client Credentials client using the default (commercial) Azure AD endpoint.
    When: AzureClient builds the MicrosoftClient.
    Then: The token_retrieval_url points to the commercial login.microsoftonline.com authority.
    """
    from Azure import DEFAULT_AZURE_AD_ENDPOINT

    captured = {}

    def fake_ms_client(**kwargs):
        captured.update(kwargs)
        return mocker.Mock()

    mocker.patch("Azure.MicrosoftClient", side_effect=fake_ms_client)
    AzureClient(
        app_id="app",
        connection_type="Client Credentials",
        tenant_id="my-tenant",
        azure_ad_endpoint=DEFAULT_AZURE_AD_ENDPOINT,
    )

    assert captured["token_retrieval_url"] == "https://login.microsoftonline.com/my-tenant/oauth2/v2.0/token"


def test_azure_client_managed_identities_passes_mi_args_to_ms_client(mocker):
    """
    Given: A client constructed with the Azure Managed Identities flow and a user-assigned client ID.
    When: AzureClient builds the MicrosoftClient.
    Then: The MicrosoftClient receives the managed_identities_client_id and the management Azure
          resource URI, matching the reference Azure packs (e.g. AzureNetworkSecurityGroups). The
          grant_type is None (the managed-identities path is selected by managed_identities_client_id,
          not by grant_type). No device-code token URL is set.
    """
    from Azure import DEFAULT_RESOURCE, DEFAULT_SCOPE

    captured = {}

    def fake_ms_client(**kwargs):
        captured.update(kwargs)
        return mocker.Mock()

    mocker.patch("Azure.MicrosoftClient", side_effect=fake_ms_client)
    AzureClient(
        app_id="app",
        connection_type="Azure Managed Identities",
        managed_identities_client_id="my-mi-client-id",
        scope=DEFAULT_SCOPE,
        resource=DEFAULT_RESOURCE,
    )

    assert captured["managed_identities_client_id"] == "my-mi-client-id"
    # The MI resource URI is the management Azure resource with the trailing slash stripped
    # (the MI branch derives it from `(resource or DEFAULT_RESOURCE).rstrip("/")`).
    assert captured["managed_identities_resource_uri"] == DEFAULT_RESOURCE.rstrip("/")
    assert captured["managed_identities_resource_uri"] == "https://management.azure.com"
    # Managed Identities is not a grant_type flow; the path is chosen by managed_identities_client_id.
    assert captured.get("grant_type") is None
    # Device-code-only token retrieval URL must not be set for the MI flow.
    assert captured.get("token_retrieval_url") is None


def test_azure_client_client_credentials_empty_tenant_builds_token_url_without_none(mocker):
    """
    Given: A non-device-code client (Client Credentials) with no tenant_id configured.
    When: AzureClient builds the MicrosoftClient.
    Then: The token_retrieval_url is built with an empty tenant segment (no literal "None" in the URL).
          Regression test for None stringification in the token URL.
    """
    from Azure import DEFAULT_AZURE_AD_ENDPOINT

    captured = {}

    def fake_ms_client(**kwargs):
        captured.update(kwargs)
        return mocker.Mock()

    mocker.patch("Azure.MicrosoftClient", side_effect=fake_ms_client)
    AzureClient(
        app_id="app",
        connection_type="Client Credentials",
        tenant_id=None,
        azure_ad_endpoint=DEFAULT_AZURE_AD_ENDPOINT,
    )

    assert "None" not in captured["token_retrieval_url"]
    # urljoin collapses the empty tenant segment, so the authority host is followed by a single slash.
    assert captured["token_retrieval_url"] == "https://login.microsoftonline.com/oauth2/v2.0/token"


def test_azure_client_managed_identities_storage_resource_derives_storage_uri(mocker):
    """
    Given: A Managed Identities client for a storage-container command (per-command resource is the
           storage resource).
    When: AzureClient builds the MicrosoftClient.
    Then: managed_identities_resource_uri is the storage resource (not the management default), so the
          MI token is storage-scoped. Regression test for storage commands failing with 401/403 under
          MI auth because the token was always management-scoped.
    """
    from Azure import STORAGE_RESOURCE

    captured = {}

    def fake_ms_client(**kwargs):
        captured.update(kwargs)
        return mocker.Mock()

    mocker.patch("Azure.MicrosoftClient", side_effect=fake_ms_client)
    AzureClient(
        app_id="app",
        connection_type="Azure Managed Identities",
        managed_identities_client_id="my-mi-client-id",
        resource=STORAGE_RESOURCE,
    )

    assert captured["managed_identities_resource_uri"] == STORAGE_RESOURCE.rstrip("/")
    assert captured["managed_identities_resource_uri"] == "https://storage.azure.com"


def test_get_azure_client_managed_identities_resolves_client_id(mocker, mock_params):
    """
    Given: Marketplace path (no connector) with auth_type "Azure Managed Identities" and a configured
           managed_identities_client_id credential.
    When: get_azure_client is called.
    Then: get_azure_managed_identities_client_id resolves the client ID from params and it is passed to
          AzureClient. The Client Credentials missing-secret guard is NOT triggered (no Client Secret
          required for the MI flow).
    """
    mocker.patch("Azure.get_connector_id", return_value=None)
    mock_azure_client = mocker.patch("Azure.AzureClient", return_value=mocker.Mock())

    params = mock_params.copy()
    params["credentials"] = {}  # no client secret configured
    params["auth_type"] = "Azure Managed Identities"
    params["managed_identities_client_id"] = {"password": "resolved-mi-id"}

    get_azure_client(params, {}, "command")

    _, kwargs = mock_azure_client.call_args
    assert kwargs["connection_type"] == "Azure Managed Identities"
    assert kwargs["managed_identities_client_id"] == "resolved-mi-id"


def test_get_azure_client_managed_identities_system_assigned(mocker, mock_params):
    """
    Given: Marketplace path with auth_type "Azure Managed Identities" and no client ID configured.
    When: get_azure_client is called.
    Then: The system-assigned managed identity sentinel is resolved and passed to AzureClient.
    """
    from MicrosoftApiModule import MANAGED_IDENTITIES_SYSTEM_ASSIGNED

    mocker.patch("Azure.get_connector_id", return_value=None)
    mock_azure_client = mocker.patch("Azure.AzureClient", return_value=mocker.Mock())

    params = mock_params.copy()
    params["credentials"] = {}
    params["auth_type"] = "Azure Managed Identities"
    params["managed_identities_client_id"] = {}  # no client id -> system assigned

    get_azure_client(params, {}, "command")

    _, kwargs = mock_azure_client.call_args
    assert kwargs["managed_identities_client_id"] == MANAGED_IDENTITIES_SYSTEM_ASSIGNED


def test_get_azure_client_credentials_none(mocker, mock_params):
    """
    Given: Marketplace path, Client Credentials flow, and credentials explicitly set to None.
    When: get_azure_client is called.
    Then: It raises a missing-parameter DemistoException (listing the Client Secret) without an
          AttributeError.
    """
    mocker.patch("Azure.get_connector_id", return_value=None)

    params = mock_params.copy()
    params["credentials"] = None
    params["auth_type"] = "Client Credentials"

    with pytest.raises(DemistoException) as excinfo:
        get_azure_client(params, {}, "command")

    assert "Client Secret" in str(excinfo.value)
    assert "Client Credentials" in str(excinfo.value)


@pytest.mark.parametrize(
    "auth_type, missing_key, expected_in_message",
    [
        ("Client Credentials", "app_id", "Application ID"),
        ("Client Credentials", "tenant_id", "Tenant ID"),
        ("Client Credentials", "credentials", "Client Secret"),
        ("Client Credentials", "subscription_id", "Default Subscription ID"),
        ("Device Code", "app_id", "Application ID"),
        ("Device Code", "subscription_id", "Default Subscription ID"),
        ("Authorization Code", "app_id", "Application ID"),
        ("Authorization Code", "redirect_uri", "Application redirect URI"),
        ("Authorization Code", "auth_code", "Authorization code"),
        ("Authorization Code", "subscription_id", "Default Subscription ID"),
        ("Azure Managed Identities", "subscription_id", "Default Subscription ID"),
    ],
)
def test_validate_auth_params_missing(auth_type, missing_key, expected_in_message):
    """
    Given: A full set of params for an auth type, with exactly one mandatory param removed.
    When: validate_auth_params is called.
    Then: It raises a DemistoException naming the missing parameter and the auth type.
    """
    from Azure import validate_auth_params

    full_params = {
        "app_id": "app",
        "subscription_id": "sub",
        "tenant_id": "tenant",
        "credentials": {"password": "secret"},
        "auth_code": {"password": "code"},
        "redirect_uri": "redirect-uri",
        "managed_identities_client_id": {"password": "mi-id"},
        "auth_type": auth_type,
    }
    full_params.pop(missing_key)

    with pytest.raises(DemistoException) as excinfo:
        validate_auth_params(full_params, auth_type)

    assert expected_in_message in str(excinfo.value)
    assert auth_type in str(excinfo.value)


@pytest.mark.parametrize(
    "auth_type, params",
    [
        (
            "Client Credentials",
            {"app_id": "app", "subscription_id": "sub", "tenant_id": "t", "credentials": {"password": "s"}},
        ),
        ("Device Code", {"app_id": "app", "subscription_id": "sub"}),
        (
            "Authorization Code",
            {
                "app_id": "app",
                "subscription_id": "sub",
                "redirect_uri": "redirect-uri",
                "auth_code": {"password": "c"},
            },
        ),
        (
            "Azure Managed Identities",
            {"subscription_id": "sub", "managed_identities_client_id": {"password": "mi-id"}},
        ),
    ],
)
def test_validate_auth_params_valid(auth_type, params):
    """
    Given: A complete set of mandatory params for an auth type.
    When: validate_auth_params is called.
    Then: It does not raise.
    """
    from Azure import validate_auth_params

    params = {**params, "auth_type": auth_type}
    validate_auth_params(params, auth_type)  # Should not raise


def test_validate_auth_params_managed_identities_system_assigned():
    """
    Given: Azure Managed Identities with no explicit client ID (system-assigned) and a subscription.
    When: validate_auth_params is called.
    Then: It does not raise, because the system-assigned identity resolves to a sentinel client ID.
    """
    from Azure import validate_auth_params

    params = {
        "auth_type": "Azure Managed Identities",
        "subscription_id": "sub",
        "managed_identities_client_id": {},  # no password -> system assigned
    }
    validate_auth_params(params, "Azure Managed Identities")  # Should not raise


def test_main_auth_reset(mocker):
    """
    Given: The azure-auth-reset command on the marketplace path.
    When: main is called.
    Then: reset_auth is invoked and the client is not built.
    """
    from Azure import main

    mocker.patch.object(demisto, "command", return_value="azure-auth-reset")
    mocker.patch.object(demisto, "params", return_value={})
    mocker.patch.object(demisto, "args", return_value={})
    mocker.patch("Azure.get_connector_id", return_value=None)
    mock_reset = mocker.patch("Azure.reset_auth", return_value="reset done")
    mock_get_client = mocker.patch("Azure.get_azure_client")
    mocker.patch("Azure.return_results")

    main()

    mock_reset.assert_called_once()
    mock_get_client.assert_not_called()


# ---------------------------------------------------------------------------
# YAML <-> Python wiring tests
#
# These tests read Azure.yml, extract the command names, argument names and
# output prefixes, and assert that each one is actually wired up in Azure.py.
#
# Everything below is derived *statically* (yaml.safe_load + ast.parse). No
# integration code is imported, instantiated or executed, so these tests make
# no network calls, read no environment variables and do not depend on the
# clock, the OS or the execution order of other tests.
# ---------------------------------------------------------------------------

# The name of the dict inside main() that maps command name -> handler function.
DISPATCH_DICT_NAME = "commands_with_params_and_args"

# Commands intentionally excluded from these wiring tests.
#
# - "*-quick-action" commands and "test-module" are excluded by request.
# - Commands marked "deprecated: true" in the yml are excluded as well. They are
#   kept only so existing playbooks keep working, and are no longer expected to
#   hold their yml and their implementation in step.
# - The auth/control commands below are routed by explicit if/elif branches in
#   main() rather than through the dispatch dict, and expose no yml arguments
#   or context outputs of the kind these tests inspect.
QUICK_ACTION_SUFFIX = "-quick-action"

# Arguments that are legitimately not read by the command handler.
#
# These are consumed earlier in main(), when the AzureClient itself is built by
# get_azure_client(), and are also resolvable from the integration parameters
# rather than the command arguments. A handler may therefore never mention them
# even though the argument is fully wired up and honoured at runtime, so flagging
# them here would be a false positive rather than a real defect.
INFRASTRUCTURE_ARGUMENTS = frozenset(
    {
        "subscription_id",
        "resource_group_name",
    }
)
EXCLUDED_COMMANDS = frozenset(
    {
        "test-module",
        "azure-auth-start",
        "azure-auth-complete",
        "azure-auth-test",
        "azure-auth-reset",
        "azure-generate-login-url",
    }
)


def is_command_in_scope(command_name: str) -> bool:
    """Return True if the given command should be covered by the wiring tests.

    This is the single source of truth for test scope - every wiring test below
    filters through it, so the scope cannot drift between tests.

    Args:
        command_name (str): The command name as declared in Azure.yml or used as a
            key in the dispatch dict, for example "azure-storage-container-create".

    Returns:
        bool: True if the command should be checked by the wiring tests. False for
            "*-quick-action" commands, "test-module", and the auth/control commands
            listed in EXCLUDED_COMMANDS.
    """
    if command_name in EXCLUDED_COMMANDS:
        return False
    return not command_name.endswith(QUICK_ACTION_SUFFIX)


def load_raw_yml_commands() -> list[dict]:
    """Load Azure.yml and return its command list exactly as declared.

    Use the ``raw_yml_commands`` fixture rather than calling this directly, so Azure.yml
    is read and parsed only once for the whole module.

    Returns:
        list[dict]: Every command definition in the yml, with no filtering applied.
    """
    with YML_PATH.open(encoding="utf-8") as yml_file:
        yml_content = yaml.safe_load(yml_file)

    return yml_content.get("script", {}).get("commands") or []


def select_deprecated_command_names(raw_commands: list[dict]) -> set[str]:
    """Return the names of the commands marked ``deprecated: true``.

    Deprecated commands are excluded from the wiring tests, but they are still routed
    in main(), so the names are needed to keep test_dispatch_commands_exist_in_yml from
    reporting them as undocumented.

    Args:
        raw_commands (list[dict]): The unfiltered yml command list.

    Returns:
        set[str]: The names of every command whose yml definition sets
            ``deprecated: true`` at the command level.
    """
    return {command["name"] for command in raw_commands if command.get("deprecated") is True}


def select_in_scope_commands(raw_commands: list[dict]) -> dict[str, dict]:
    """Return the in-scope commands keyed by command name.

    Args:
        raw_commands (list[dict]): The unfiltered yml command list.

    Returns:
        dict[str, dict]: Mapping of command name to the raw yml command definition
            (including its "arguments" and "outputs" entries). Out-of-scope commands are
            filtered out via is_command_in_scope, and commands marked
            ``deprecated: true`` are dropped as well, since a deprecated command is no
            longer expected to keep its yml and its implementation in step.
    """
    return {
        command["name"]: command
        for command in raw_commands
        if is_command_in_scope(command.get("name", "")) and command.get("deprecated") is not True
    }


def visible_arguments(command: dict) -> list[dict]:
    """Return a command's declared arguments, excluding the hidden ones.

    Arguments marked ``hidden: true`` are not offered to the user, so they are outside
    the yml <-> py contract these tests enforce in either direction.

    Args:
        command (dict): A raw yml command definition.

    Returns:
        list[dict]: The command's argument definitions that are not marked hidden.
    """
    return [argument for argument in command.get("arguments") or [] if argument.get("hidden") is not True]


def load_py_source_and_tree() -> tuple[str, ast.Module]:
    """Read Azure.py and return its source text along with the parsed AST.

    Args:
        None. The Azure.py path is derived from this test file's own location.

    Returns:
        tuple[str, ast.Module]: The raw source text of Azure.py and its parsed AST.
            The module is only parsed, never imported or executed.
    """
    source = PY_PATH.read_text(encoding="utf-8")
    return source, ast.parse(source)


def extract_dispatch_map(tree: ast.Module) -> dict[str, str]:
    """Extract the command -> handler-function-name mapping from main().

    The dispatch dict is a local variable inside main(), which is marked
    "# pragma: no cover" and cannot be imported or safely executed, so it is
    lifted straight out of the AST instead.

    Args:
        tree (ast.Module): The parsed AST of Azure.py.

    Returns:
        dict[str, str]: Mapping of command name to the name of the handler function
            it is routed to, for example
            {"azure-storage-container-create": "storage_container_create_command"}.

    Raises:
        AssertionError: If the dispatch dict cannot be found in Azure.py, if any of its
            entries is in a shape this extractor cannot read (the offending entries are
            named in the message), or if it is found but yields no command -> handler
            pairs at all. In every case the dict shape has changed and this helper needs
            updating.
    """
    for node in ast.walk(tree):
        if not isinstance(node, ast.Assign):
            continue
        targets = [t.id for t in node.targets if isinstance(t, ast.Name)]
        if DISPATCH_DICT_NAME not in targets or not isinstance(node.value, ast.Dict):
            continue

        dispatch: dict[str, str] = {}
        unreadable: list[str] = []
        for key, value in zip(node.value.keys, node.value.values):
            if isinstance(key, ast.Constant) and isinstance(key.value, str) and isinstance(value, ast.Name):
                dispatch[key.value] = value.id
            else:
                # A dict-unpacking entry (**other) has no key node at all.
                key_source = "**" if key is None else ast.unparse(key)
                unreadable.append(f"{key_source}: {ast.unparse(value)}")

        # Guard against the dict being found but containing entries this extractor
        # cannot read (e.g. values changed to lambdas or partials). Dropping them
        # silently would report their commands as "not routed", wrongly blaming the
        # integration instead of the extractor, so name them explicitly instead.
        assert not unreadable, (
            f"Found '{DISPATCH_DICT_NAME}' in Azure.py but could not read the following "
            "entries, so the commands they route would be wrongly reported as unrouted. "
            "The dict shape has changed and this test helper needs updating:\n" + "\n".join(unreadable)
        )
        assert dispatch, (
            f"Found '{DISPATCH_DICT_NAME}' in Azure.py but could not extract any "
            "command -> handler pairs from it. The dict shape has changed and this "
            "test helper needs updating."
        )
        return dispatch

    raise AssertionError(f"Could not find the '{DISPATCH_DICT_NAME}' dict inside Azure.py")


def build_symbol_index(tree: ast.Module) -> dict[str, ast.FunctionDef]:
    """Index module-level functions and AzureClient methods by name.

    Client methods are indexed under their bare name so that a handler calling
    ``client.storage_account_update_request(...)`` can be resolved.

    Args:
        tree (ast.Module): The parsed AST of Azure.py.

    Returns:
        dict[str, ast.FunctionDef]: Mapping of function/method name to its AST node.
            Module-level functions take precedence over class methods of the same
            name, since a bare call in a handler resolves to the module-level one.
    """
    index: dict[str, ast.FunctionDef] = {}
    for node in tree.body:
        if isinstance(node, ast.FunctionDef):
            index[node.name] = node
        elif isinstance(node, ast.ClassDef):
            for child in node.body:
                if isinstance(child, ast.FunctionDef):
                    index.setdefault(child.name, child)
    return index


def collect_called_names(func_node: ast.FunctionDef) -> set[str]:
    """Return the names of every function/method directly called by func_node.

    Args:
        func_node (ast.FunctionDef): The AST node of the function to inspect.

    Returns:
        set[str]: The bare names of all called callables. Attribute calls contribute
            only the final attribute, so ``client.get_rule(...)`` yields "get_rule",
            which is what allows AzureClient methods to be looked up in the symbol index.
    """
    called: set[str] = set()
    for node in ast.walk(func_node):
        if not isinstance(node, ast.Call):
            continue
        func = node.func
        if isinstance(func, ast.Name):
            called.add(func.id)
        elif isinstance(func, ast.Attribute):
            called.add(func.attr)
    return called


def collect_string_constants(func_node: ast.FunctionDef) -> set[str]:
    """Return every string literal appearing anywhere inside func_node.

    Args:
        func_node (ast.FunctionDef): The AST node of the function to inspect.

    Returns:
        set[str]: All string constants in the function body, including argument keys
            such as "account_name" and docstring text. Docstrings may add harmless
            extra entries; they can only mask a failure, never invent one.
    """
    return {node.value for node in ast.walk(func_node) if isinstance(node, ast.Constant) and isinstance(node.value, str)}


def collect_reachable_strings(handler_name: str, symbol_index: dict[str, ast.FunctionDef]) -> set[str]:
    """Collect string literals in a handler plus those in its direct callees.

    One level of call following is required for correctness: several handlers
    (for example storage_account_update_command) hand the raw ``args`` dict to an
    AzureClient method, and it is that method - not the handler - which reads the
    individual argument keys.

    Args:
        handler_name (str): Name of the command handler function to start from.
        symbol_index (dict[str, ast.FunctionDef]): Index produced by build_symbol_index,
            used to resolve both the handler and the functions it calls.

    Returns:
        set[str]: Union of the string literals in the handler and in every function it
            calls directly (one level deep). Returns an empty set if the handler name is
            not present in the index.
    """
    handler = symbol_index.get(handler_name)
    if handler is None:
        return set()

    strings = collect_string_constants(handler)
    for callee_name in collect_called_names(handler):
        callee = symbol_index.get(callee_name)
        if callee is not None and callee is not handler:
            strings |= collect_string_constants(callee)
    return strings


def collect_read_argument_names(func_node: ast.FunctionDef) -> set[str]:
    """Return the command-argument names a function reads out of its ``args`` mapping.

    Unlike collect_string_constants, which returns every string literal, this looks only
    at the three shapes Azure.py uses to read a command argument: ``args.get("name")``,
    ``args["name"]`` and ``"name" in args``. That precision is what makes it safe to
    assert in the yml -> py direction: an unrelated literal such as a URL fragment or a
    response key can never be mistaken for a command argument.

    Args:
        func_node (ast.FunctionDef): The AST node of the function to inspect.

    Returns:
        set[str]: The argument names read from the ``args`` mapping. Dynamic reads such
            as ``args.get(key)`` contribute nothing, since the name is not a literal.
    """
    read: set[str] = set()
    for node in ast.walk(func_node):
        # args.get("name") / args.get("name", default)
        if (
            isinstance(node, ast.Call)
            and isinstance(node.func, ast.Attribute)
            and node.func.attr == "get"
            and isinstance(node.func.value, ast.Name)
            and node.func.value.id == "args"
            and node.args
            and isinstance(node.args[0], ast.Constant)
            and isinstance(node.args[0].value, str)
        ):
            read.add(node.args[0].value)

        # args["name"]
        elif (
            isinstance(node, ast.Subscript)
            and isinstance(node.value, ast.Name)
            and node.value.id == "args"
            and isinstance(node.slice, ast.Constant)
            and isinstance(node.slice.value, str)
        ):
            read.add(node.slice.value)

        # "name" in args
        elif isinstance(node, ast.Compare) and isinstance(node.left, ast.Constant) and isinstance(node.left.value, str):
            for operator, comparator in zip(node.ops, node.comparators):
                if isinstance(operator, ast.In) and isinstance(comparator, ast.Name) and comparator.id == "args":
                    read.add(node.left.value)

    return read


def collect_reachable_read_arguments(handler_name: str, symbol_index: dict[str, ast.FunctionDef]) -> set[str]:
    """Collect the argument names read by a handler and by its direct callees.

    Mirrors collect_reachable_strings, but uses collect_read_argument_names so that only
    genuine ``args`` reads are returned. One level of call following is required for the
    same reason: several handlers pass the raw ``args`` dict to an AzureClient method,
    and it is that method which reads the individual keys.

    Args:
        handler_name (str): Name of the command handler function to start from.
        symbol_index (dict[str, ast.FunctionDef]): Index produced by build_symbol_index.

    Returns:
        set[str]: Argument names read by the handler or by any function it calls directly.
            Empty if the handler name is not present in the index.
    """
    handler = symbol_index.get(handler_name)
    if handler is None:
        return set()

    read = collect_read_argument_names(handler)
    for callee_name in collect_called_names(handler):
        callee = symbol_index.get(callee_name)
        if callee is not None and callee is not handler:
            read |= collect_read_argument_names(callee)
    return read


def extract_fallback_prefix(handler_name: str, symbol_index: dict[str, ast.FunctionDef]) -> set[str]:
    """Return the output prefixes a handler can produce, ignoring the lookup map.

    Covers both shapes used in Azure.py: the ``COMMANDS_TO_OUTPUTS_PREFIX.get(command,
    "<fallback>")`` pattern and a prefix passed directly as ``outputs_prefix=``.

    Args:
        handler_name (str): Name of the command handler function to inspect.
        symbol_index (dict[str, ast.FunctionDef]): Index produced by build_symbol_index.

    Returns:
        set[str]: Every context prefix the handler may write to, for example
            {"Azure.VirtualNetworks.SecurityRules"}. Empty if the handler is unknown or
            builds its context another way, such as returning a plain outputs dict.
    """
    handler = symbol_index.get(handler_name)
    if handler is None:
        return set()

    prefixes: set[str] = set()
    for node in ast.walk(handler):
        if not isinstance(node, ast.Call):
            continue

        # COMMANDS_TO_OUTPUTS_PREFIX.get(command, "Azure.Something")
        func = node.func
        if (
            isinstance(func, ast.Attribute)
            and func.attr == "get"
            and isinstance(func.value, ast.Name)
            and func.value.id == "COMMANDS_TO_OUTPUTS_PREFIX"
            and len(node.args) == 2
            and isinstance(node.args[1], ast.Constant)
            and isinstance(node.args[1].value, str)
        ):
            prefixes.add(node.args[1].value)

        # CommandResults(outputs_prefix="Azure.Something", ...)
        for keyword in node.keywords:
            if (
                keyword.arg == "outputs_prefix"
                and isinstance(keyword.value, ast.Constant)
                and isinstance(keyword.value.value, str)
            ):
                prefixes.add(keyword.value.value)

    return prefixes


@pytest.fixture(scope="module")
def raw_yml_commands() -> list[dict]:
    """Every command declared in Azure.yml, unfiltered.

    Azure.yml is read and parsed here once per module, and every other yml-derived
    fixture is built from this one rather than re-reading the file.
    """
    return load_raw_yml_commands()


@pytest.fixture(scope="module")
def yml_commands(raw_yml_commands: list[dict]) -> dict[str, dict]:
    """The in-scope, non-deprecated commands declared in Azure.yml, keyed by command name."""
    return select_in_scope_commands(raw_yml_commands)


@pytest.fixture(scope="module")
def deprecated_commands(raw_yml_commands: list[dict]) -> set[str]:
    """The names of the commands marked deprecated in Azure.yml."""
    return select_deprecated_command_names(raw_yml_commands)


@pytest.fixture(scope="module")
def py_tree() -> ast.Module:
    """The parsed AST of Azure.py."""
    _, tree = load_py_source_and_tree()
    return tree


@pytest.fixture(scope="module")
def dispatch_map(py_tree: ast.Module) -> dict[str, str]:
    """Mapping of command name -> handler function name, lifted from main()."""
    return extract_dispatch_map(py_tree)


@pytest.fixture(scope="module")
def symbol_index(py_tree: ast.Module) -> dict[str, ast.FunctionDef]:
    """Index of module-level functions and AzureClient methods by name."""
    return build_symbol_index(py_tree)


# ---------------------------------------------------------------------------
# The wiring tests themselves: Azure.yml checked against Azure.py.
# ---------------------------------------------------------------------------


def test_py_read_arguments_are_declared_in_yml(yml_commands, raw_yml_commands, dispatch_map, symbol_index):
    """
    Given:
        - yml_commands (dict[str, dict]): The arguments declared for each in-scope command in Azure.yml.
        - raw_yml_commands (list[dict]): Every command in the yml, used to resolve arguments
          declared only by a deprecated sibling that shares a handler.
        - dispatch_map (dict[str, str]): The handler each command is routed to.
        - symbol_index (dict[str, ast.FunctionDef]): Used to resolve the handler and its direct callees.
    When:
        - Every argument the handler reads out of its args mapping is looked up in the
          command's declared yml arguments.
    Then:
        - No argument is consumed by the code without being documented, so a user can
          discover every argument the command honours. This is the reverse of
          test_command_arguments_are_read_by_handler, which checks the yml -> py
          direction.
        - Infrastructure arguments resolvable from the integration parameters are exempt,
          matching the exemption applied in the other direction. An argument declared
          ``hidden: true`` still counts as declared, so reading it is not a failure.
        - When several commands share one handler, an argument declared by any of them
          counts as declared for all of them, including by a deprecated sibling. A
          shared handler routinely reads a renamed argument on behalf of its deprecated
          predecessor - for example update_security_rule_command reads "action" for
          azure-nsg-security-rule-update, while its replacement declares "access" -
          and blaming the current command for that alias would be a false positive.
    """
    # Given: a cache so each handler's reachable argument reads are computed once
    reachable_reads_cache: dict[str, set[str]] = {}
    undeclared_arguments: list[str] = []

    # Given: every argument name declared by any command sharing the same handler.
    # This spans the raw yml rather than the filtered map, so an argument kept only for
    # a deprecated sibling still counts as declared for the handler they share.
    declared_per_handler: dict[str, set[str]] = {}
    for command in raw_yml_commands:
        handler_name = dispatch_map.get(command.get("name", ""))
        if handler_name is None:
            continue
        declared_per_handler.setdefault(handler_name, set()).update(
            argument.get("name") for argument in command.get("arguments") or []
        )

    for command_name in sorted(yml_commands):
        handler_name = dispatch_map.get(command_name)
        if handler_name is None:
            continue  # covered by test_yml_commands_are_wired_in_dispatch

        if handler_name not in reachable_reads_cache:
            reachable_reads_cache[handler_name] = collect_reachable_read_arguments(handler_name, symbol_index)

        declared = declared_per_handler.get(handler_name, set())

        # When: checking each argument the code reads against the declared ones
        for argument_name in sorted(reachable_reads_cache[handler_name]):
            if argument_name in declared or argument_name in INFRASTRUCTURE_ARGUMENTS:
                continue
            undeclared_arguments.append(f"{command_name}: '{argument_name}' (handler: {handler_name})")

    # Then: every argument the code consumes is documented in the yml
    assert not undeclared_arguments, "Arguments read by the command handler but not declared in Azure.yml:\n" + "\n".join(
        undeclared_arguments
    )


def test_yml_commands_are_wired_in_dispatch(yml_commands, dispatch_map, symbol_index):
    """
    Given:
        - yml_commands (dict[str, dict]): The in-scope commands declared in Azure.yml.
        - dispatch_map (dict[str, str]): The command dispatch dict extracted from main() in Azure.py.
        - symbol_index (dict[str, ast.FunctionDef]): The index of every function and method defined in Azure.py.
    When:
        - Each yml command name is looked up in the dispatch dict, and the handler
          it points to is looked up in the symbol index.
    Then:
        - Every command resolves to a handler, so none would raise
          NotImplementedError at runtime.
        - Every resolved handler actually exists as a function in Azure.py.
    """
    # Given: the yml command names and the dispatch table
    yml_command_names = set(yml_commands)

    # When: resolving each command to its handler, then confirming that handler is
    # a real function in Azure.py rather than a stale or dangling name
    unrouted = sorted(name for name in yml_command_names if name not in dispatch_map)
    missing_handlers = sorted(
        f"{name} -> {dispatch_map[name]}"
        for name in yml_command_names
        if name in dispatch_map and dispatch_map[name] not in symbol_index
    )

    # Then: every command is routed to a handler that exists
    assert not unrouted, f"Commands declared in Azure.yml but not routed in main(): {unrouted}"
    assert not missing_handlers, f"Commands routed to functions that do not exist in Azure.py: {missing_handlers}"


def test_dispatch_commands_exist_in_yml(yml_commands, dispatch_map, deprecated_commands):
    """
    Given:
        - The command dispatch dict extracted from main() in Azure.py.
        - The in-scope, non-deprecated commands declared in Azure.yml.
        - deprecated_commands (set[str]): The commands the yml marks deprecated.
    When:
        - Each in-scope dispatch key is looked up in the yml.
    Then:
        - No dispatch entry is orphaned, i.e. every routed command is documented.
        - Deprecated commands are exempt: they are still routed in main() so that
          existing playbooks keep working, but they are intentionally absent from the
          filtered yml command map.
    """
    # Given: the in-scope dispatch keys, excluding the deprecated ones still routed
    in_scope_dispatch = {name for name in dispatch_map if is_command_in_scope(name) and name not in deprecated_commands}

    # When: checking them against the declared yml commands
    undocumented = sorted(in_scope_dispatch - set(yml_commands))

    # Then: every routed command is declared in the yml
    assert not undocumented, f"Commands routed in main() but not declared in Azure.yml: {undocumented}"


def test_command_arguments_are_read_by_handler(yml_commands, dispatch_map, symbol_index):
    """
    Given:
        - yml_commands (dict[str, dict]): The arguments declared for each in-scope command in Azure.yml.
        - dispatch_map (dict[str, str]): The handler each command is routed to.
        - symbol_index (dict[str, ast.FunctionDef]): Used to resolve the handler and its direct callees.
    When:
        - Each argument name is searched for as a string literal in the handler
          and in any AzureClient method or helper it calls directly.
    Then:
        - Every documented argument is read somewhere on the command's code path,
          proving no advertised argument is silently ignored.
        - Infrastructure arguments consumed before the handler runs are exempt, as are
          arguments marked ``hidden: true``, which are not offered to the user.
    """
    # Given: a cache so each handler's reachable strings are computed once
    reachable_strings_cache: dict[str, set[str]] = {}
    unread_arguments: list[str] = []

    for command_name, command in sorted(yml_commands.items()):
        handler_name = dispatch_map.get(command_name)
        if handler_name is None:
            continue  # covered by test_yml_commands_are_wired_in_dispatch

        if handler_name not in reachable_strings_cache:
            reachable_strings_cache[handler_name] = collect_reachable_strings(handler_name, symbol_index)
        reachable_strings = reachable_strings_cache[handler_name]

        # When: checking each declared argument against the reachable literals
        for argument in visible_arguments(command):
            argument_name = argument.get("name")
            if not argument_name or argument_name in INFRASTRUCTURE_ARGUMENTS:
                continue
            if argument_name not in reachable_strings:
                unread_arguments.append(f"{command_name}: '{argument_name}' (handler: {handler_name})")

    # Then: no documented argument is ignored by the code serving the command
    assert not unread_arguments, "Arguments declared in Azure.yml but never read by the command handler:\n" + "\n".join(
        unread_arguments
    )


def test_command_output_prefixes_are_wired(yml_commands, dispatch_map, symbol_index):
    """
    Given:
        - The contextPath outputs declared for each in-scope command in Azure.yml.
        - The output prefixes produced by the command's handler, either via the
          COMMANDS_TO_OUTPUTS_PREFIX map or a fallback/literal outputs_prefix.
    When:
        - The yml context paths are compared against the prefixes in the code.
    Then:
        - Every command whose handler declares a prefix writes context under a
          path the yml actually documents.
    """
    # Given: the explicit command -> prefix lookup used by most handlers
    from Azure import COMMANDS_TO_OUTPUTS_PREFIX

    mismatches: list[str] = []

    for command_name, command in sorted(yml_commands.items()):
        handler_name = dispatch_map.get(command_name)
        outputs = command.get("outputs") or []
        if handler_name is None or not outputs:
            continue

        context_paths = [output.get("contextPath", "") for output in outputs]

        # When: resolving the prefix the code will actually use
        mapped_prefix = COMMANDS_TO_OUTPUTS_PREFIX.get(command_name)
        candidate_prefixes = {mapped_prefix} if mapped_prefix else extract_fallback_prefix(handler_name, symbol_index)
        if not candidate_prefixes:
            continue  # handler builds context another way, e.g. a plain outputs dict

        # Then: at least one produced prefix must match a documented context path
        if not any(path == prefix or path.startswith(f"{prefix}.") for prefix in candidate_prefixes for path in context_paths):
            mismatches.append(
                f"{command_name}: code writes to {sorted(candidate_prefixes)} "
                f"but Azure.yml documents "
                f"{sorted({path.split('.')[0] + '.' + path.split('.')[1] for path in context_paths if '.' in path})}"
            )

    assert not mismatches, "Output prefixes in Azure.py do not match the contextPath declared in Azure.yml:\n" + "\n".join(
        mismatches
    )


# ---------------------------------------------------------------------------
# Unit tests for the helpers above.
#
# These guard the extractors themselves, so that a helper which silently stops
# reading Azure.py is reported as a helper bug rather than surfacing as a
# misleading failure - or a vacuous pass - in the wiring tests above.
# ---------------------------------------------------------------------------


def test_select_in_scope_commands_is_not_vacuous(yml_commands, raw_yml_commands, deprecated_commands):
    """
    Given:
        - yml_commands (dict[str, dict]): The result of select_in_scope_commands() over the
          real Azure.yml, which filters out both out-of-scope and deprecated commands.
        - raw_yml_commands (list[dict]): The same yml before any filtering.
        - deprecated_commands (set[str]): The names the yml marks deprecated.
    When:
        - The loaded map is compared against the raw command list in Azure.yml.
    Then:
        - The map is not empty, so the wiring tests below cannot pass vacuously by
          silently iterating over nothing.
        - The out-of-scope and deprecated commands that really exist in the yml were
          dropped, and everything else was kept, proving both filters are applied.
        - The raw yml definitions are preserved intact, so the arguments and outputs
          the wiring tests inspect are present rather than skipped over.
    """
    # Given: the raw, unfiltered command list straight from the yml
    raw_names = {command["name"] for command in raw_yml_commands}
    out_of_scope_names = {name for name in raw_names if not is_command_in_scope(name)}

    # When / Then: the selector returned something for the other tests to work on
    assert yml_commands, f"select_in_scope_commands() returned no commands - is {YML_PATH.name} readable and non-empty?"

    # Then: both filters kept the right commands and dropped the wrong ones
    assert out_of_scope_names, (
        "Azure.yml no longer declares any out-of-scope commands, so this test can no "
        "longer prove that is_command_in_scope filtering is applied."
    )
    assert deprecated_commands, (
        "Azure.yml no longer declares any deprecated commands, so this test can no "
        "longer prove that deprecated commands are filtered out."
    )
    assert set(yml_commands) == raw_names - out_of_scope_names - deprecated_commands

    # Then: the definitions kept their arguments and outputs, which the wiring tests
    # below silently skip when absent
    assert any(
        command.get("arguments") for command in yml_commands.values()
    ), "No loaded command declares 'arguments' - test_command_arguments_are_read_by_handler would pass vacuously."
    assert any(
        command.get("outputs") for command in yml_commands.values()
    ), "No loaded command declares 'outputs' - test_command_output_prefixes_are_wired would pass vacuously."


def test_visible_arguments_drops_only_hidden_arguments():
    """
    Given:
        - A command declaring a plain argument, one explicitly marked hidden, and one
          explicitly marked not hidden.
    When:
        - visible_arguments is called on the command.
    Then:
        - Only the hidden argument is dropped. An argument the user cannot supply is
          outside the yml <-> py contract, while everything else must still be checked.
        - The surviving definitions are returned unchanged, so callers can still read
          their names.
    """
    # Given: a command mixing hidden and visible arguments
    command = {
        "name": "azure-disk-update",
        "arguments": [
            {"name": "disk_name"},
            {"name": "internal_token", "hidden": True},
            {"name": "public_network_access", "hidden": False},
        ],
    }

    # When: filtering out the hidden arguments
    visible = visible_arguments(command)

    # Then: only the hidden one is gone, and the rest are untouched
    assert [argument["name"] for argument in visible] == ["disk_name", "public_network_access"]


def test_visible_arguments_handles_command_without_arguments():
    """
    Given:
        - A command that declares no arguments at all, such as a simple list command.
    When:
        - visible_arguments is called on it.
    Then:
        - An empty list is returned rather than raising, so the wiring tests simply
          find nothing to check for that command.
    """
    # Given / When / Then: a command with no arguments key yields nothing
    assert visible_arguments({"name": "azure-resource-group-list"}) == []


def test_extract_dispatch_map_reads_command_to_handler_pairs():
    """
    Given:
        - A parsed main() containing a dispatch dict of the shape Azure.py uses,
          mapping string command names to bare handler function names.
    When:
        - extract_dispatch_map is called on the tree.
    Then:
        - Every command name is mapped to the exact handler identifier it points to,
          which is the contract the wiring tests below depend on.
    """
    # Given: a minimal main() holding a well-formed dispatch dict
    source = (
        "def main():\n"
        f"    {DISPATCH_DICT_NAME} = {{\n"
        "        'azure-storage-account-update': storage_account_update_command,\n"
        "        'azure-disk-update': disk_update_command,\n"
        "    }\n"
    )

    # When: lifting the dispatch table out of the AST
    dispatch = extract_dispatch_map(ast.parse(source))

    # Then: both commands resolve to their handler names
    assert dispatch == {
        "azure-storage-account-update": "storage_account_update_command",
        "azure-disk-update": "disk_update_command",
    }


def test_extract_dispatch_map_raises_naming_entries_it_cannot_read():
    """
    Given:
        - A dispatch dict mixing a readable "command": handler entry with entries this
          extractor does not support: a non-string key and a value that is a call
          expression rather than a bare function name.
    When:
        - extract_dispatch_map is called on the tree.
    Then:
        - An AssertionError is raised rather than the unsupported entries being dropped,
          so their commands are never wrongly reported as unrouted.
        - The message names every offending entry, pointing straight at what to fix.
    """
    # Given: a dispatch dict containing entry shapes the extractor cannot read
    source = (
        "def main():\n"
        f"    {DISPATCH_DICT_NAME} = {{\n"
        "        'azure-disk-update': disk_update_command,\n"
        "        SOME_CONSTANT: acr_update_command,\n"
        "        'azure-acr-update': partial(acr_update_command),\n"
        "    }\n"
    )

    # When: lifting the dispatch table out of the AST
    with pytest.raises(AssertionError) as error:
        extract_dispatch_map(ast.parse(source))

    # Then: both unreadable entries are named, and the readable one is not blamed
    message = str(error.value)
    assert "SOME_CONSTANT: acr_update_command" in message
    assert "'azure-acr-update': partial(acr_update_command)" in message
    assert "disk_update_command" not in message.split("updating:")[-1]


def test_extract_dispatch_map_raises_when_dict_is_missing():
    """
    Given:
        - A parsed main() that contains no dispatch dict at all, simulating the dict
          being renamed or removed from Azure.py.
    When:
        - extract_dispatch_map is called on the tree.
    Then:
        - An AssertionError naming the expected dict is raised, so the wiring tests
          fail loudly instead of reporting every command as unrouted.
    """
    # Given: a main() with no dispatch dict
    source = "def main():\n    some_other_mapping = {'azure-disk-update': disk_update_command}\n"

    # When / Then: the missing dict is reported explicitly
    with pytest.raises(AssertionError, match=DISPATCH_DICT_NAME):
        extract_dispatch_map(ast.parse(source))


def test_extract_dispatch_map_raises_when_dict_is_empty():
    """
    Given:
        - A dispatch dict that exists but is empty, simulating the routing being moved
          out of the dict entirely.
    When:
        - extract_dispatch_map is called on the tree.
    Then:
        - An AssertionError is raised rather than an empty map being returned, so the
          failure blames this helper instead of wrongly reporting every command in
          Azure.yml as unrouted.
    """
    # Given: a main() whose dispatch dict has no entries
    source = f"def main():\n    {DISPATCH_DICT_NAME} = {{}}\n"

    # When / Then: the empty dict is reported as a helper problem
    with pytest.raises(AssertionError, match="could not extract any"):
        extract_dispatch_map(ast.parse(source))


def test_build_symbol_index_indexes_module_functions_and_client_methods():
    """
    Given:
        - A module defining a top-level handler function alongside a client class whose
          methods are called as client.<method>(...) by that handler.
    When:
        - build_symbol_index is called on the tree.
    Then:
        - Both the module-level function and the class methods are indexed under their
          bare names, which is what lets an attribute call be resolved back to its
          definition.
        - Each entry is the FunctionDef node itself, since callers walk its body.
    """
    # Given: a module with a top-level function and a client class
    source = (
        "def disk_update_command(client, params, args):\n"
        "    pass\n"
        "\n"
        "class AzureClient:\n"
        "    def disk_update_request(self, args):\n"
        "        pass\n"
        "\n"
        "    def storage_account_update_request(self, args):\n"
        "        pass\n"
    )

    # When: indexing the module
    index = build_symbol_index(ast.parse(source))

    # Then: both kinds of definition are reachable by bare name, as AST nodes
    assert set(index) == {"disk_update_command", "disk_update_request", "storage_account_update_request"}
    assert all(isinstance(node, ast.FunctionDef) for node in index.values())
    assert index["disk_update_command"].name == "disk_update_command"


def test_build_symbol_index_prefers_module_function_over_class_method():
    """
    Given:
        - A module where a top-level function and a class method share the same name.
    When:
        - build_symbol_index is called on the tree.
    Then:
        - The module-level function wins, matching how Python resolves the bare call
          format_rule(...) inside a handler. Indexing the method instead would make the
          wiring tests inspect the wrong body.
    """
    # Given: a name defined both at module level and as a class method
    source = (
        "def format_rule(rule):\n"
        "    module_level_marker = 1\n"
        "\n"
        "class AzureClient:\n"
        "    def format_rule(self, rule):\n"
        "        class_level_marker = 2\n"
    )

    # When: indexing the module
    index = build_symbol_index(ast.parse(source))

    # Then: the module-level definition is the one that was kept
    assert "module_level_marker" in {
        target.id
        for node in ast.walk(index["format_rule"])
        if isinstance(node, ast.Assign)
        for target in node.targets
        if isinstance(target, ast.Name)
    }


def test_build_symbol_index_ignores_nested_functions():
    """
    Given:
        - A module-level function containing a nested inner function.
    When:
        - build_symbol_index is called on the tree.
    Then:
        - Only the outer function is indexed. Nested helpers are not callable by bare
          name from a handler, so indexing them could resolve a call to a definition
          that is not actually in scope at the call site.
    """
    # Given: a function with a closure defined inside it
    source = "def disk_update_command(client, args):\n    def inner_helper():\n        pass\n\n    return inner_helper()\n"

    # When: indexing the module
    index = build_symbol_index(ast.parse(source))

    # Then: the nested definition was not indexed
    assert set(index) == {"disk_update_command"}


def test_build_symbol_index_returns_empty_for_module_without_functions():
    """
    Given:
        - A module that defines no functions at all, only constants.
    When:
        - build_symbol_index is called on the tree.
    Then:
        - An empty index is returned without raising, since this helper reports what it
          finds and leaves the "handler does not exist" verdict to the wiring tests.
    """
    # Given: a module with no function definitions
    source = "API_VERSION = '2023-01-01'\nCOMMANDS_TO_OUTPUTS_PREFIX = {}\n"

    # When: indexing the module
    index = build_symbol_index(ast.parse(source))

    # Then: nothing is indexed, and no error is raised
    assert index == {}


def test_collect_called_names_collects_bare_and_attribute_calls():
    """
    Given:
        - A handler that calls a module-level helper by bare name and an AzureClient
          method through the client attribute, which are the two call shapes used
          throughout Azure.py.
    When:
        - collect_called_names is called on the handler.
    Then:
        - Both are returned, with the attribute call reduced to its final attribute.
          That reduction is what lets a client.<method>(...) call be looked up in the
          symbol index, which indexes methods under their bare names.
    """
    # Given: a handler using both call shapes
    source = (
        "def disk_update_command(client, params, args):\n"
        "    response = client.disk_update_request(args)\n"
        "    return format_rule(response)\n"
    )
    handler = ast.parse(source).body[0]

    # When: collecting the names it calls
    called = collect_called_names(handler)

    # Then: the bare call and the reduced attribute call are both present
    assert called == {"disk_update_request", "format_rule"}


def test_collect_called_names_reduces_chained_calls_to_final_attribute():
    """
    Given:
        - A function using the chained attribute calls that Azure.py really makes, such
          as self.ms_client.http_request(...) and urllib.parse.urljoin(...).
    When:
        - collect_called_names is called on it.
    Then:
        - Each call contributes only its final attribute, and the intermediate
          attributes are not reported as calls. Treating an intermediate such as
          'ms_client' or 'parse' as a call could resolve it to an unrelated same-named
          function in the symbol index.
    """
    # Given: a client method using the chained call shapes found in Azure.py
    source = (
        "def http_request(self, method, url_suffix, azure_ad_endpoint):\n"
        "    token_url = urllib.parse.urljoin(azure_ad_endpoint, url_suffix)\n"
        "    return self.ms_client.http_request(method=method, full_url=token_url)\n"
    )
    handler = ast.parse(source).body[0]

    # When: collecting the names it calls
    called = collect_called_names(handler)

    # Then: only the final attributes are reported, not 'parse' or 'ms_client'
    assert called == {"urljoin", "http_request"}


def test_collect_called_names_includes_nested_and_argument_calls():
    """
    Given:
        - A handler whose calls appear inside a nested block and as an argument to
          another call, rather than as plain top-level statements.
    When:
        - collect_called_names is called on the handler.
    Then:
        - Every call is found regardless of nesting depth, because the whole function
          body is walked. A handler that only reaches its client inside an if branch
          must still be seen, or the argument wiring test would report false failures.
    """
    # Given: a handler with calls nested in a branch and inside another call
    source = (
        "def acr_update_command(client, args):\n"
        "    if args.get('enabled'):\n"
        "        for item in build_items(args):\n"
        "            client.acr_update_request(format_rule(item))\n"
    )
    handler = ast.parse(source).body[0]

    # When: collecting the names it calls
    called = collect_called_names(handler)

    # Then: nested and nested-as-argument calls are all collected
    assert called == {"get", "build_items", "acr_update_request", "format_rule"}


def test_collect_called_names_returns_empty_for_handler_without_calls():
    """
    Given:
        - A handler that makes no calls at all.
    When:
        - collect_called_names is called on it.
    Then:
        - An empty set is returned without raising, so collect_reachable_strings simply
          falls back to the handler's own string literals.
    """
    # Given: a handler with no calls in its body
    source = "def disk_update_command(client, args):\n    return args\n"
    handler = ast.parse(source).body[0]

    # When / Then: nothing is collected, and no error is raised
    assert collect_called_names(handler) == set()


def test_collect_string_constants_collects_argument_keys_at_any_depth():
    """
    Given:
        - A handler that reads its argument keys inside a branch, a nested dict literal
          and a subscript, which is how Azure.py handlers build request payloads.
    When:
        - collect_string_constants is called on the handler.
    Then:
        - Every string literal is returned regardless of nesting depth, since the
          argument wiring test relies on finding an argument name anywhere on the
          handler's code path.
    """
    # Given: a handler reading argument keys at several nesting depths
    source = (
        "def disk_update_command(client, args):\n"
        '    if args.get("public_network_access"):\n'
        '        payload = {"properties": {"networkAccessPolicy": args["network_access_policy"]}}\n'
        "    return client.disk_update_request(payload)\n"
    )
    handler = ast.parse(source).body[0]

    # When: collecting its string literals
    strings = collect_string_constants(handler)

    # Then: keys nested in a branch, a dict literal and a subscript are all found
    assert strings == {"public_network_access", "properties", "networkAccessPolicy", "network_access_policy"}


def test_collect_string_constants_ignores_non_string_constants():
    """
    Given:
        - A handler containing numeric, boolean and None constants alongside a single
          argument key.
    When:
        - collect_string_constants is called on the handler.
    Then:
        - Only the string literal is returned. Non-string constants can never match an
          argument name, so including them would only add noise that might mask a real
          unread argument.
    """
    # Given: a handler mixing string and non-string constants
    source = (
        "def disk_update_command(client, args):\n"
        "    timeout = 30\n"
        "    enabled = True\n"
        "    missing = None\n"
        '    return client.disk_update_request(args["disk_name"], timeout, enabled, missing)\n'
    )
    handler = ast.parse(source).body[0]

    # When: collecting its string literals
    strings = collect_string_constants(handler)

    # Then: only the argument key is returned
    assert strings == {"disk_name"}


def test_collect_string_constants_includes_docstring_text():
    """
    Given:
        - A handler whose docstring mentions an argument name that the body never reads.
    When:
        - collect_string_constants is called on the handler.
    Then:
        - The docstring is returned along with the real literals, confirming the
          documented caveat that docstrings add harmless extra entries. They can only
          mask a failure, never invent one, so this is a known limitation of the
          argument wiring test rather than a defect.
    """
    # Given: a handler documenting an argument it does not actually read
    source = (
        "def disk_update_command(client, args):\n"
        '    """Update a disk, honouring data_access_auth_mode."""\n'
        '    return client.disk_update_request(args["disk_name"])\n'
    )
    handler = ast.parse(source).body[0]

    # When: collecting its string literals
    strings = collect_string_constants(handler)

    # Then: the real key is found, and the docstring text is included as documented
    assert "disk_name" in strings
    assert any("data_access_auth_mode" in text for text in strings)


def test_collect_string_constants_collects_fstring_literal_parts_only():
    """
    Given:
        - A client method building a URL with an f-string, the shape Azure.py uses for
          every request path.
    When:
        - collect_string_constants is called on it.
    Then:
        - The literal fragments around the placeholders are returned, and the
          interpolated names are not, since those are Name nodes rather than string
          constants. An argument referenced only by interpolation is therefore not
          matched by its fragment, which is why the handler must still read the
          argument key itself somewhere on the path.
    """
    # Given: a client method interpolating a value into a request path
    source = (
        "def disk_update_request(self, subscription_id, args):\n"
        '    url = f"/subscriptions/{subscription_id}/disks"\n'
        "    return self.http_request(url)\n"
    )
    handler = ast.parse(source).body[0]

    # When: collecting its string literals
    strings = collect_string_constants(handler)

    # Then: only the literal fragments are collected, not the interpolated name
    assert strings == {"/subscriptions/", "/disks"}


def test_collect_read_argument_names_collects_the_three_read_shapes():
    """
    Given:
        - A handler reading arguments via args.get("x"), args.get("x", default),
          args["x"] and "x" in args, which are the shapes Azure.py uses.
    When:
        - collect_read_argument_names is called on the handler.
    Then:
        - Every argument name is returned, so the py -> yml test below sees the full
          set of arguments the code actually consumes.
    """
    # Given: a handler using all four read forms
    source = (
        "def storage_account_update_command(client, args):\n"
        '    account_name = args.get("account_name", "")\n'
        '    kind = args.get("kind")\n'
        '    tags = args["tags"].split(",")\n'
        '    if "use_sub_domain_name" in args:\n'
        "        pass\n"
    )
    handler = ast.parse(source).body[0]

    # When: collecting the argument names it reads
    read = collect_read_argument_names(handler)

    # Then: all four are found
    assert read == {"account_name", "kind", "tags", "use_sub_domain_name"}


def test_collect_read_argument_names_ignores_unrelated_literals_and_mappings():
    """
    Given:
        - A handler containing string literals that are not command arguments: a read
          from the params mapping, a response key, a URL fragment, and a dynamic
          args.get(key) whose name is not a literal.
    When:
        - collect_read_argument_names is called on the handler.
    Then:
        - Only the genuine args read is returned. This precision is what makes the
          py -> yml assertion safe, since a stray literal would otherwise be reported
          as an argument missing from the yml.
    """
    # Given: a handler mixing a real args read with unrelated literals
    source = (
        "def disk_update_command(client, params, args, key):\n"
        '    subscription_id = params.get("subscription_id")\n'
        '    disk_name = args.get("disk_name")\n'
        "    dynamic = args.get(key)\n"
        '    url = "/providers/Microsoft.Compute/disks"\n'
        '    return response["properties"]["diskState"]\n'
    )
    handler = ast.parse(source).body[0]

    # When: collecting the argument names it reads
    read = collect_read_argument_names(handler)

    # Then: only the real args read is reported
    assert read == {"disk_name"}


def test_extract_fallback_prefix_reads_both_prefix_shapes():
    """
    Given:
        - A handler using the COMMANDS_TO_OUTPUTS_PREFIX.get(command, "<fallback>")
          lookup, and another passing outputs_prefix= directly to CommandResults, which
          are the two shapes Azure.py uses to declare a context prefix.
    When:
        - extract_fallback_prefix is called on each handler.
    Then:
        - The prefix is recovered from both shapes, so the output wiring test can
          compare it against the contextPath declared in the yml.
    """
    # Given: one handler per prefix shape, indexed as build_symbol_index would
    source = (
        "def disk_update_command(client, args):\n"
        '    prefix = COMMANDS_TO_OUTPUTS_PREFIX.get(command, "Azure.Compute.Disks")\n'
        "    return CommandResults(outputs_prefix=prefix, outputs=response)\n"
        "\n"
        "def acr_update_command(client, args):\n"
        '    return CommandResults(outputs_prefix="Azure.ContainerRegistry", outputs=response)\n'
    )
    symbol_index = build_symbol_index(ast.parse(source))

    # When / Then: each shape yields its prefix
    assert extract_fallback_prefix("disk_update_command", symbol_index) == {"Azure.Compute.Disks"}
    assert extract_fallback_prefix("acr_update_command", symbol_index) == {"Azure.ContainerRegistry"}


def test_extract_fallback_prefix_ignores_non_literal_and_unrelated_lookups():
    """
    Given:
        - A handler whose outputs_prefix is a variable rather than a literal, whose
          COMMANDS_TO_OUTPUTS_PREFIX lookup has no fallback argument, and which calls
          .get on an unrelated mapping.
    When:
        - extract_fallback_prefix is called on the handler.
    Then:
        - Nothing is returned, so the output wiring test skips the command rather than
          comparing the yml against a prefix that was never actually declared.
    """
    # Given: a handler declaring its prefix in ways this extractor cannot read
    source = (
        "def disk_update_command(client, args):\n"
        "    prefix = COMMANDS_TO_OUTPUTS_PREFIX.get(command)\n"
        '    other = SOME_OTHER_MAP.get(command, "Azure.NotAPrefix")\n'
        "    return CommandResults(outputs_prefix=prefix, outputs=response)\n"
    )
    symbol_index = build_symbol_index(ast.parse(source))

    # When / Then: no prefix is claimed
    assert extract_fallback_prefix("disk_update_command", symbol_index) == set()


def test_extract_fallback_prefix_collects_every_prefix_a_handler_may_write():
    """
    Given:
        - A handler that returns a different context prefix on each branch, so more
          than one prefix is reachable at runtime.
    When:
        - extract_fallback_prefix is called on the handler.
    Then:
        - Every reachable prefix is returned. The output wiring test then passes if any
          of them matches the yml, which is the intended behaviour for a handler that
          serves several commands.
    """
    # Given: a handler writing to two different prefixes
    source = (
        "def storage_account_update_command(client, args):\n"
        '    if args.get("container_name"):\n'
        '        return CommandResults(outputs_prefix="Azure.Storage.Containers", outputs=response)\n'
        '    return CommandResults(outputs_prefix="Azure.Storage.StorageAccounts", outputs=response)\n'
    )
    symbol_index = build_symbol_index(ast.parse(source))

    # When / Then: both branches contribute their prefix
    assert extract_fallback_prefix("storage_account_update_command", symbol_index) == {
        "Azure.Storage.Containers",
        "Azure.Storage.StorageAccounts",
    }


def test_extract_fallback_prefix_returns_empty_for_unknown_handler():
    """
    Given:
        - A handler name that is not present in the symbol index, which happens when a
          command is routed to a function that does not exist.
    When:
        - extract_fallback_prefix is called with that name.
    Then:
        - An empty set is returned rather than raising, leaving the missing-handler
          verdict to test_yml_commands_are_wired_in_dispatch, which reports it with a
          far clearer message.
    """
    # Given: an index that does not contain the requested handler
    symbol_index = build_symbol_index(ast.parse("def disk_update_command(client, args):\n    pass\n"))

    # When / Then: the unknown name yields nothing, and no error is raised
    assert extract_fallback_prefix("no_such_command", symbol_index) == set()