Azure Compute v2

Create and Manage Azure Virtual Machines.

IT Services · Azure Compute

Details

IDAzure Compute v2
ProviderMicrosoft
CategoryIT Services
From Version5.0.0
Docker Imagedemisto/crypto:1.0.0.5490413
Supported ModulesAgentix XSIAM EDR Cortex Cloud Cloud Runtime Security

README

You can use this integration to create and manage Azure Virtual Machines.
This integration was integrated and tested with Azure Compute API Version: 2017-12-01.

Authentication

For more details about the authentication used in this integration, see Microsoft Integrations - Authentication.

  • After authorizing the Demisto App or the Self-Deployed Application, you will get an ID, Token, and Key, which should be inserted in the integration instance configuration’s corresponding fields. After giving consent, the application has to have a role assigned so it can access the relevant resources per subscription.
  • In order to assign a role to the application after consent was given:
    • Go to the Azure Portal UI.
    • Go to Subscriptions, and then Access Control (IAM).
    • Click “Add role assignment”.
    • Create a new role or select a role that includes the following permissions:
      • Microsoft.Compute/virtualMachines/*
      • Microsoft.Network/networkInterfaces/read
      • Microsoft.Resources/subscriptions/resourceGroups/read
    • Select the Azure Compute application. By default, Azure AD applications aren’t displayed in the available options. To find your application, search for the name and select it.

Configure Azure Compute v2 in Cortex

Parameter Description Required
Host URL (e.g. https://management.azure.com)   True
ID (received from the admin consent - see Detailed Instructions (?)   True
Token (received from the admin consent - see Detailed Instructions (?) section)   True
Key (received from the admin consent - see Detailed Instructions (?)   False
Certificate Thumbprint Used for certificate authentication. As appears in the “Certificates & secrets” page of the app. False
ID (received from the admin consent - see Detailed Instructions (?)   False
Token (received from the admin consent - see Detailed Instructions (?) section)   False
Key (received from the admin consent - see Detailed Instructions (?)   True
Certificate Thumbprint Used for certificate authentication. As appears in the “Certificates & secrets” page of the app. False
Private Key Used for certificate authentication. The private key of the registered certificate. False
Default Subscription ID   False
Default Subscription ID   False
Default Resource Group Name This parameter can be overridden by the resource_group argument in any command. False
Use system proxy settings   False
Trust any certificate (not secure)   False
Use a self-deployed Azure Application Select this checkbox if you are using a self-deployed Azure application. 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-vm-list-instances


Lists the virtual machine instances in the given resource group.

Base Command

azure-vm-list-instances

Input

Argument Name Description Required
subscription_id The subscription ID. Note: This argument will override the instance parameter ‘Default Subscription ID’. Optional
resource_group The resource group of the virtual machines.
To see all the resource groups associated with your subscription, run the azure-list-resource-groups command. If none are present, navigate to the Azure Web Portal to create resource groups.
Note: This argument will override the instance parameter ‘Default Resource Group Name’.
.
Optional

Context Output

Path Type Description
Azure.Compute.Name string The name of the virtual machine.
Azure.Compute.Location string The location of the virtual machine.
Azure.Compute.ProvisioningState string The provisioning state of the virtual machine.
Azure.Compute.ResourceGroup string The resource group in which the virtual machine resides.
Azure.Compute.ID string The ID of the virtual machine.
Azure.Compute.Size number The size of the deployed virtual machine (in gigabytes).
Azure.Compute.OS string The OS running on the virtual machine.

Command example

!azure-vm-list-instances resource_group=Compute-Labs

Context Example

{
    "Azure": {
        "Compute": [
            {
                "ID": "d25e7ce9-258b-4d8d-a516-c2206eef08ef",
                "Location": "eastus",
                "Name": "test12",
                "OS": "Windows",
                "ProvisioningState": "Succeeded",
                "ResourceGroup": "Compute-Labs",
                "Size": 127
            },
            {
                "ID": "befbbbba-64a6-49e9-84f7-27f3cc27818d",
                "Location": "eastus",
                "Name": "test1234",
                "OS": "Windows",
                "ProvisioningState": "Succeeded",
                "ResourceGroup": "Compute-Labs",
                "Size": 127
            },
            {
                "ID": "xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx",
                "Location": "eastus",
                "Name": "webserver",
                "OS": "Windows",
                "ProvisioningState": "Succeeded",
                "ResourceGroup": "Compute-Labs",
                "Size": 127
            }
        ]
    }
}

Human Readable Output

Microsoft Azure - List of Virtual Machines in Resource Group “Compute-Labs”

Name ID Size OS Location ProvisioningState ResourceGroup
test12 d25e7ce9-258b-4d8d-a516-c2206eef08ef 127 Windows eastus Succeeded Compute-Labs
test1234 befbbbba-64a6-49e9-84f7-27f3cc27818d 127 Windows eastus Succeeded Compute-Labs
webserver xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx 127 Windows eastus Succeeded Compute-Labs

azure-vm-start-instance


Powers on a given virtual machine.

Base Command

azure-vm-start-instance

Input

Argument Name Description Required
subscription_id The subscription ID. Note: This argument will override the instance parameter ‘Default Subscription ID’. Optional
resource_group 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. If none are present, navigate to the Azure Web Portal to create resource groups.
Note: This argument will override the instance parameter ‘Default Resource Group Name’.
.
Optional
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-vm-list-instances command. 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.

Command example

!azure-vm-start-instance resource_group="Compute-Labs" virtual_machine_name="webserver"

Context Example

{
    "Azure": {
        "Compute": {
            "Name": "webserver",
            "PowerState": "VM starting",
            "ResourceGroup": "Compute-Labs"
        }
    }
}

Human Readable Output

Power-on of Virtual Machine “webserver” Successfully Initiated

Name PowerState ResourceGroup
webserver VM starting Compute-Labs

azure-vm-poweroff-instance


Powers off a given virtual machine.

Base Command

azure-vm-poweroff-instance

Input

Argument Name Description Required
subscription_id The subscription ID. Note: This argument will override the instance parameter ‘Default Subscription ID’. Optional
resource_group 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. If none are present, navigate to the Azure Web Portal to create resource groups.
Note: This argument will override the instance parameter ‘Default Resource Group Name’.
.
Optional
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-vm-list-instances command. Required
skip_shutdown Set to True to request non-graceful VM shutdown. Default value is False. 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.

Command example

!azure-vm-poweroff-instance resource_group=Compute-Labs virtual_machine_name=test12

Context Example

{
    "Azure": {
        "Compute": {
            "Name": "test12",
            "PowerState": "VM stopping",
            "ResourceGroup": "Compute-Labs"
        }
    }
}

Human Readable Output

Power-off of Virtual Machine “test12” Successfully Initiated

Name PowerState ResourceGroup
test12 VM stopping Compute-Labs

azure-vm-get-instance-details


Gets the properties of a given virtual machine.

Base Command

azure-vm-get-instance-details

Input

Argument Name Description Required
subscription_id The subscription ID. Note: This argument will override the instance parameter ‘Default Subscription ID’. Optional
resource_group 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. If none are present, navigate to the Azure Web Portal to create resource groups.
Note: This argument will override the instance parameter ‘Default Resource Group Name’.
.
Optional
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-vm-list-instances 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. 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.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.ProvisioningState string The provisioning state of the deployed virtual machine.
Azure.Compute.Location string The region in which the virtual machine is hosted.
Azure.Compute.PowerState string Whether the virtual machine instance is powered on or off.
Azure.Compute.ResourceGroup string The resource group to which the virtual machine belongs.
Azure.Compute.NetworkInterfaces Unknown The list of network interfaces attached to this machine.
Azure.Compute.UserData string UserData for the VM.
Azure.Compute.Tags string Tags associated with the VM.

Command example

!azure-vm-get-instance-details resource_group=Compute-Labs virtual_machine_name=webserver

Context Example

{
    "Azure": {
        "Compute": {
            "ID": "xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx",
            "Location": "eastus",
            "Name": "webserver",
            "NetworkInterfaces": [
                {
                    "id": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/networkInterfaces/webserver729",
                    "properties": {
                        "deleteOption": "Delete"
                    }
                }
            ],
            "OS": "Windows",
            "PowerState": "VM running",
            "ProvisioningState": "Succeeded",
            "ResourceGroup": "Compute-Labs",
            "Size": 127,
            "Tags": {
                "env": "dev",
                "owner" : "testuser"
            }
        }
    }
}

Human Readable Output

Properties of VM “webserver”

Name ID Size OS ProvisioningState Location PowerState
webserver xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx 127 Windows Succeeded eastus VM running

azure-vm-create-instance


Creates a virtual machine instance with the specified OS image.

Base Command

azure-vm-create-instance

Input

Argument Name Description Required
subscription_id The subscription ID. Note: This argument will override the instance parameter ‘Default Subscription ID’. Optional
resource_group The resource group to which the new virtual machine will belong.
To see all the resource groups associated with your subscription, run the azure-list-resource-groups command. If none are present, navigate to the Azure Web Portal to create resource groups.
Note: This argument will override the instance parameter ‘Default Resource Group Name’.
.
Optional
virtual_machine_name The name of the virtual machine to create. Required
virtual_machine_location The location in which to create the virtual machine. Possible values are: westus2, westus, westindia, westeurope, westcentralus, uksouth, ukwest, southeastasia, northcentralus, northeurope, southcentralus, southindia, francesouth, francecentral, japaneast, japanwest, koreacentral, koreasouth, brazilsouth, canadacentral, canadaeast, centralindia, eastus2, eastasia, westus, centralus, eastus, australiacentral, australiacentral2, australiaeast, australiasoutheast. Required
nic_name The name of the Network Interface to link the virtual machine with. Note that the virtual machine’s location property must match that of the Network Interface you choose to link it to. To see a list of available Network Interfaces visit the Azure Web Portal, navigate to the search bar at the top of the page, type “network interfaces”, and in the dynamic drop-down menu that appears, click the ‘Network interfaces’ option that appears under the ‘Services’ category. If none are present, you will need to create a new Network Interface. Required
vm_size The name of a VirtualMachineSize, which determines the size of the deployed virtual machine. For more information, see the Azure documentation at https://docs.microsoft.com/en-us/rest/api/compute/virtualmachines/listavailablesizes#virtualmachinesize. Possible values are: Standard_D1_v2, Standard_D2_v2, Standard_D2s_v3, Standard_B1ms, Standard_B1s, Standard_B2s, Standard_B4ms, Standard_D4s_v3, Standard_DS1_v2, Standard_DS2_v2, Standard_DS3_v2, Promo_DS2_v2, Promo_DS3_v2. Required
os_image The base operating system image of the virtual machine. Possible values are: Ubuntu Server 14.04 LTS, Ubuntu Server 16.04 LTS, Ubuntu Server 18.04 LTS, Red Hat Enterprise Linux 7.6, CentOS-based 7.5, Windows Server 2012 R2 Datacenter, Windows Server 2016 Datacenter, Windows 10 Pro Version 1803, Windows 10 Pro Version 1809. Optional
sku SKU of the OS image to be used. To see a list of available SKUs, visit your Azure Web Portal, click the symbol that looks similar to a ‘>’ on the top bar of the page. This should open a cloud shell, make sure it is a bash shell. At the command prompt enter az vm image list-skus along with the appropriate arguments that it will prompt you with to display the list of VM image SKUs available in the Azure Marketplace. Default is 2016-Datacenter. Optional
publisher Name of the publisher of the OS image. To see a list of available publishers, visit your Azure Web Portal, click the symbol that looks similar to a ‘>’ on the top bar of the page which should open a cloud shell, make sure it is a bash shell. At the command prompt enter az vm image list-publishers along with the appropriate arguments that it will prompt you with to display the list of VM image publishers available in the Azure Marketplace. Default is MicrosoftWindowsServer. Optional
version Version of the image to use. The supported formats are Major.Minor.Build or ‘latest’. Major, Minor, and Build are decimal numbers. Specify ‘latest’ to use the latest version of an image available at deploy time. Default is latest. Optional
offer Specifies the offer of the platform image or marketplace image used to create the virtual machine. To see a list of available offers, visit your Azure Web Portal, click the symbol that looks similar to a ‘>’ on the top bar of the page which should open a cloud shell, make sure it is a bash shell. At the command prompt enter az vm image list-offers along with the appropriate arguments that it will prompt you with to display the list of VM image offers available in the Azure Marketplace. Default is WindowsServer. Optional
admin_username The admin username to use when creating the virtual machine. Default is DemistoUser. Optional
admin_password The admin password to use when creating the virtual machine. Default is Passw0rd@123. Optional

Context Output

Path Type Description
Azure.Compute.Name string The name of the created virtual machine instance.
Azure.Compute.ResourceGroup string The resource group in which the virtual machine resides.
Azure.Compute.ID string The ID of the virtual machine.
Azure.Compute.Size number The size of the deployed virtual machine (in gigabytes).
Azure.Compute.OS string The OS running on the specified virtual machine.
Azure.Compute.ProvisioningState string The provisioning state of the deployed virtual machine.
Azure.Compute.Location string The region in which the virtual machine is hosted.

Command example

!azure-vm-create-instance nic_name=test_nic3 resource_group=Compute-Labs virtual_machine_location=eastus virtual_machine_name=test567 vm_size=Standard_D1_v2

Context Example

{
    "Azure": {
        "Compute": {
          "ID": "xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx",
          "Location": "eastus",
          "Name": "test567",
          "OS": "Windows",
          "ProvisioningState": "Creating",
          "ResourceGroup": "Compute-Labs",
          "Size": "127"

        }
    }
}

Human Readable Output

List of Resource Groups

ID Location Name OS ProvisioningState ResourceGroup Size
xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx eastus test567 Windows Creating Compute-Labs 127

azure-list-resource-groups


Lists all resource groups that belong to your Azure subscription.

Base Command

azure-list-resource-groups

Input

Argument Name Description Required
subscription_id Subscription ID to use. Can be retrieved from the azure-sc-list-subscriptions command. Note: This argument will override the instance parameter ‘Default Subscription ID’. Optional
tag A single tag in the form of ‘{“Tag Name”:”Tag Value”}’ to filter the list by. Optional
limit Limit on the number of resource-groups to return. Default value is 50. Default is 50. Optional

Context Output

Path Type Description
Azure.ResourceGroup.Name string The name of the resource group.
Azure.ResourceGroup.ID string The ID of the resource group.
Azure.ResourceGroup.Location string The location of the resource group.
Azure.ResourceGroup.ProvisioningState string The provisioning state of the resource group.

Command example


#### Context Example

```json
{
    "Azure": {
        "ResourceGroup": [
            {
                "ID": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs",
                "Location": "ukwest",
                "Name": "Compute-Labs",
                "ProvisioningState": "Succeeded"
            },
            {
                "ID": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/NetworkWatcherRG",
                "Location": "eastus",
                "Name": "NetworkWatcherRG",
                "ProvisioningState": "Succeeded"
            }
        ]
    }
}

Human Readable Output

List of Resource Groups

ID Location Name ProvisioningState
/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs ukwest Compute-Labs Succeeded
/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/NetworkWatcherRG eastus NetworkWatcherRG Succeeded

azure-vm-delete-instance


Deletes a specified virtual machine.

Base Command

azure-vm-delete-instance

Input

Argument Name Description Required
subscription_id The subscription ID. Note: This argument will override the instance parameter ‘Default Subscription ID’. Optional
resource_group 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. If none are present, navigate to the Azure Web Portal to create resource groups.
Note: This argument will override the instance parameter ‘Default Resource Group Name’.
.
Optional
virtual_machine_name The name of the virtual machine to delete. To see all the virtual machines with their associated names for a specific resource group, run the azure-vm-list-instances command. Optional

Context Output

There is no context output for this command.

Command example

!azure-vm-delete-instance resource_group=Compute-Labs virtual_machine_name=test1234

Human Readable Output

“test1234” VM Deletion Successfully Initiated

azure-list-subscriptions


Lists the subscriptions for this application.

Base Command

azure-list-subscriptions

Input

There are no input arguments for this command.

Context Output

Path Type Description
Azure.Subscription.ID String The ID of the subscription.
Azure.Subscription.Name String The name of the subscription.
Azure.Subscription.State String The state of the subscription.

Command example


#### Context Example

```json
{
    "Azure": {
        "Subscription": {
            "ID": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx",
            "Name": "Azure subscription 1",
            "State": "Enabled"
        }
    }
}

Human Readable Output

List of Subscriptions

ID Name State
/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx Azure subscription 1 Enabled

azure-vm-get-nic-details


Gets the properties of a given network interface.

Base Command

azure-vm-get-nic-details

Input

Argument Name Description Required
subscription_id The subscription ID. Note: This argument will override the instance parameter ‘Default Subscription ID’. Optional
resource_group 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. If none are present, navigate to the Azure Web Portal to create resource groups.
Note: This argument will override the instance parameter ‘Default Resource Group Name’.
.
Optional
nic_name The name of the network interface you want to view the details of. Required

Context Output

Path Type Description
Azure.Network.Interfaces.AttachedVirtualMachine String The attached virtual machine to this interface.
Azure.Network.Interfaces.IsPrimaryInterface String True if this interface is a primary interface of the attached virtual machine.
Azure.Network.Interfaces.NICType String The interface type.
Azure.Network.Interfaces.IPConfigurations.ConfigID String The interface IP configuration ID.
Azure.Network.Interfaces.IPConfigurations.ConfigName String The interface IP configuration name.
Azure.Network.Interfaces.IPConfigurations.PrivateIPAddress String The interface private IP address.
Azure.Network.Interfaces.IPConfigurations.PublicIPAddressID Unknown The interface public IP address ID.
Azure.Network.Interfaces.MACAddress String The interface MAC address.
Azure.Network.Interfaces.Name String The interface name.
Azure.Network.Interfaces.ResourceGroup String The interface resource group.
Azure.Network.Interfaces.NetworkSecurityGroup.id String The interface network security group ID.
Azure.Network.Interfaces.Location String The interface location.
Azure.Network.Interfaces.ID String The interface ID.

Command example

!azure-vm-get-nic-details resource_group=Compute-Labs nic_name=webserver729

Context Example

{
    "Azure": {
        "Network":{
          "Interfaces": {
            "AttachedVirtualMachine": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Compute/virtualMachines/webserver",
            "DNSSuffix": "test.bx.internal.cloudapp.net",
            "ID": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/networkInterfaces/webserver729",
            "IPConfigurations": [
              {
                "ConfigID": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/networkInterfaces/webserver729/ipConfigurations/ipconfig1",
                "ConfigName": "ipconfig1",
                "PrivateIPAddress": "10.0.0.4",
                "PublicIPAddressID": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/publicIPAddresses/webserver-ip"
              }
            ],
            "IsPrimaryInterface": true,
            "Location": "eastus",
            "MACAddress": "00-22-48-1C-73-AF",
            "NICType": "NA",
            "Name": "webserver729",
            "NetworkSecurityGroup": {
              "id": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/networkSecurityGroups/webserver-nsg"
            },
            "ResourceGroup": "Compute-Labs"
          }
        }
    }
}

Human Readable Output

Properties of Network Interface “webserver729”

Name ID MACAddress NetworkSecurityGroup NICType PrivateIPAddresses AttachedVirtualMachine
webserver729 /subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/networkInterfaces/webserver729 00-22-48-1C-73-AF id: /subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/networkSecurityGroups/webserver-nsg NA 10.0.0.4 sample-webserver

azure-vm-get-public-ip-details


Gets the properties of a given public IP address.

Base Command

azure-vm-get-public-ip-details

Input

Argument Name Description Required
subscription_id The subscription ID. Note: This argument will override the instance parameter ‘Default Subscription ID’. Optional
resource_group 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. If none are present, navigate to the Azure Web Portal to create resource groups.
Note: This argument will override the instance parameter ‘Default Resource Group Name’.
.
Optional
address_name The IP address name. Required

Context Output

Path Type Description
Azure.Network.IPConfigurations.PublicIPAddress String The public IP address.
Azure.Network.IPConfigurations.PublicIPAddressFQDN String The address fully-qualified domain name (FQDN).
Azure.Network.IPConfigurations.PublicIPAddressAllocationMethod String The address allocation method.
Azure.Network.IPConfigurations.PublicConfigID String The address configuration ID.
Azure.Network.IPConfigurations.ResourceGroup String The address resource group.
Azure.Network.IPConfigurations.PublicIPAddressDomainName String The address domain name.
Azure.Network.IPConfigurations.PublicIPAddressVersion String The address version.
Azure.Network.IPConfigurations.Location String The address location.
Azure.Network.IPConfigurations.PublicConfigName String The address configuration name.
Azure.Network.IPConfigurations.PublicIPAddressID String The address ID.

Command examples

!azure-vm-get-public-ip-details resource_group=Compute-Labs address_name=webserver-ip

!azure-vm-get-public-ip-details address_name=xx.xx.xx.xx

Context Example

{
    "Azure": {
        "Network": {
            "IPConfigurations": {
                "Location": "eastus",
                "PublicConfigID": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/networkInterfaces/webserver729/ipConfigurations/ipconfig1",
                "PublicConfigName": "webserver-ip",
                "PublicIPAddress": "xx.xx.xx.xx",
                "PublicIPAddressAllocationMethod": "Dynamic",
                "PublicIPAddressDomainName": "cortexmea-webserver",
                "PublicIPAddressFQDN": "test.eastus.cloudapp.azure.com",
                "PublicIPAddressID": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/publicIPAddresses/webserver-ip",
                "PublicIPAddressVersion": "IPv4",
                "ResourceGroup": "Compute-Labs"
            }
        }
    }
}

azure-vm-get-all-public-ip-details


Gets the properties of all public ip address in a subscription.

Base Command

azure-vm-get-all-public-ip-details

Input

Argument Name Description Required
subscription_id The subscription ID. Note: This argument will override the instance parameter ‘Default Subscription ID’. Optional

Context Output

Path Type Description
Azure.Network.IPConfigurations.PublicIPAddress String The public IP address.
Azure.Network.IPConfigurations.PublicIPAddressFQDN String The address fully-qualified domain name (FQDN).
Azure.Network.IPConfigurations.PublicIPAddressAllocationMethod String The address allocation method.
Azure.Network.IPConfigurations.PublicConfigID String The address configuration ID.
Azure.Network.IPConfigurations.ResourceGroup String The address resource group.
Azure.Network.IPConfigurations.PublicIPAddressDomainName String The address domain name.
Azure.Network.IPConfigurations.PublicIPAddressVersion String The address version.
Azure.Network.IPConfigurations.Location String The address location.
Azure.Network.IPConfigurations.PublicConfigName String The address configuration name.
Azure.Network.IPConfigurations.PublicIPAddressID String The address ID.

Command example


#### Context Example

```json
{
    "Azure": {
        "Network": [{
            "IPConfigurations": {
                "Location": "eastus",
                "PublicConfigID": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/networkInterfaces/webserver729/ipConfigurations/ipconfig1",
                "PublicConfigName": "webserver-ip",
                "PublicIPAddress": "xx.xx.xx.xx",
                "PublicIPAddressAllocationMethod": "Dynamic",
                "PublicIPAddressDomainName": "cortexmea-webserver",
                "PublicIPAddressFQDN": "test.eastus.cloudapp.azure.com",
                "PublicIPAddressID": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/publicIPAddresses/webserver-ip",
                "PublicIPAddressVersion": "IPv4",
                "ResourceGroup": "Compute-Labs"
            }
        }, {
            "IPConfigurations": {
                "Location": "eastus",
                "PublicConfigID": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/networkInterfaces/webserver145/ipConfigurations/ipconfig2",
                "PublicConfigName": "webserver-ip2",
                "PublicIPAddress": "xx.xx.xx.xx",
                "PublicIPAddressAllocationMethod": "Dynamic",
                "PublicIPAddressDomainName": "cortexmea-webserver",
                "PublicIPAddressFQDN": "test.eastus.cloudapp.azure.com",
                "PublicIPAddressID": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/publicIPAddresses/webserver-ip2",
                "PublicIPAddressVersion": "IPv4",
                "ResourceGroup": "Compute-Labs"
            }
        }, {
            "IPConfigurations": {
                "Location": "eastus",
                "PublicConfigID": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Other-Labs/providers/Microsoft.Network/networkInterfaces/webserver832/ipConfigurations/ipconfig3",
                "PublicConfigName": "webserver-ip3",
                "PublicIPAddress": "xx.xx.xx.xx",
                "PublicIPAddressAllocationMethod": "Dynamic",
                "PublicIPAddressDomainName": "cortexmea-webserver",
                "PublicIPAddressFQDN": "test.eastus.cloudapp.azure.com",
                "PublicIPAddressID": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Other-Labs/providers/Microsoft.Network/publicIPAddresses/webserver-ip3",
                "PublicIPAddressVersion": "IPv4",
                "ResourceGroup": "Compute-Labs"
            }
        }]
    }
}

Human Readable Output

Properties of Public Address “webserver-ip”

PublicConfigName PublicIPAddress Location PublicIPAddressVersion PublicIPAddressAllocationMethod
test-publicip1 xx.xx.xx.xx ukwest IPv4 Static

azure-vm-create-nic


Creates a virtual machine network interface.

Base Command

azure-vm-create-nic

Input

Argument Name Description Required
subscription_id The subscription ID. Note: This argument will override the instance parameter ‘Default Subscription ID’. Optional
resource_group The resource group to which the new network interface will belong.
To see all the resource groups associated with your subscription, run the azure-list-resource-groups command. If none are present, navigate to the Azure Web Portal to create resource groups.
Note: This argument will override the instance parameter ‘Default Resource Group Name’.
.
Optional
nic_name The network interface name. Required
nic_location The location in which to create the network interface. Possible values are: westus2, westus, westindia, westeurope, westcentralus, uksouth, ukwest, southeastasia, northcentralus, northeurope, southcentralus, southindia, francesouth, francecentral, japaneast, japanwest, koreacentral, koreasouth, brazilsouth, canadacentral, canadaeast, centralindia, eastus2, eastasia, westus, centralus, eastus, australiacentral, australiacentral2, australiaeast, australiasoutheast. Required
vnet_name The virtual network name of the interface. Required
subnet_name The subnet name of the interface. Required
address_assignment_method The address assignment method. Possible values are: Static, Dynamic. Default is Dynamic. Optional
private_ip_address The private IP address of the interface if you chose the static assignment method. Optional
ip_config_name The IP address configuration name. Required
network_security_group The network security group of the interface. Optional

Context Output

Path Type Description
Azure.Network.Interfaces.IPConfigurations.ConfigID String The interface IP configuration ID.
Azure.Network.Interfaces.IPConfigurations.ConfigName String The interface IP configuration name.
Azure.Network.Interfaces.IPConfigurations.PrivateIPAddress String The interface private IP address.
Azure.Network.Interfaces.IPConfigurations.PublicIPAddressID Unknown The interface public IP address ID.
Azure.Network.Interfaces.Name String The interface name.
Azure.Network.Interfaces.ResourceGroup String The interface resource group.
Azure.Network.Interfaces.NetworkSecurityGroup.id String The interface network security group ID.
Azure.Network.Interfaces.Location String The interface location.
Azure.Network.Interfaces.ID String The interface ID.

Command example

!azure-vm-create-nic nic_location=eastus nic_name=test_nic2 resource_group=Compute-Labs subnet_name=default vnet_name=Compute-Labs-vnet ip_config_name=ipconfigtest

Context Example

{
    "Azure": {
        "Network":{
          "Interfaces": {
            "DNSSuffix": "test.bx.internal.cloudapp.net",
            "ID": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/networkInterfaces/test_nic2",
            "IPConfigurations": [
              {
                "ConfigID": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/networkInterfaces/test_nic2/ipConfigurations/ipconfigtest",
                "ConfigName": "ipconfigtest",
                "PrivateIPAddress": "10.0.0.13",
                "PublicIPAddressID": "NA",
                "SubNet": "/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/virtualNetworks/Compute-Labs-vnet/subnets/default"
              }
            ],
            "Location": "eastus",
            "Name": "test_nic2",
            "NetworkSecurityGroup": "NA",
            "ProvisioningState": "Succeeded",
            "ResourceGroup": "Compute-Labs"
          }
        }
    }
}

Human Readable Output

Created Network Interface “test_nic2”

ID PrivateIPAddresses Location Name NetworkSecurityGroup
/subscriptions/xxxxxxxxx-xxxxx-xxxxx-xxxxx-xxxxxxxxxxxxx/resourceGroups/Compute-Labs/providers/Microsoft.Network/networkInterfaces/test_nic2 10.0.0.13 eastus test_nic2 NA

azure-vm-auth-reset


Run this command if for some reason you need to rerun the authentication process.

Base Command

azure-vm-auth-reset

Input

There are no input arguments for this command.

Context Output

There is no context output for this command.

Configuration parameters

  • host — Host URL (e.g. https://management.azure.com) (required)
  • auth_id — ID (received from the admin consent - see Detailed Instructions (?)
  • tenant_id — Token (received from the admin consent - see Detailed Instructions (?) section)
  • enc_key — Key (received from the admin consent - see Detailed Instructions (?)
  • certificate_thumbprint — Certificate Thumbprint
  • cred_auth_id
  • cred_token
  • cred_enc_key
  • cred_certificate_thumbprint
  • private_key — Private Key
  • subscription_id — Default Subscription ID
  • cred_subscription_id
  • resource_group — Default Resource Group Name
  • proxy — Use system proxy settings
  • unsecure — Trust any certificate (not secure)
  • self_deployed — Use a self-deployed Azure Application

Commands (13)

  • azure-list-resource-groups

    Lists all resource groups that belong to your Azure subscription.

  • azure-list-subscriptions

    Lists the subscriptions for this application.

  • azure-vm-auth-reset

    Run this command if for some reason you need to rerun the authentication process.

  • azure-vm-create-instance

    Creates a virtual machine instance with the specified OS image.

  • azure-vm-create-nic

    Creates a virtual machine network interface.

  • azure-vm-delete-instance

    Deletes a specified virtual machine.

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

    Gets the properties of all public ip address in a subscription.

  • azure-vm-get-instance-details

    Gets the properties of a given virtual machine.

  • azure-vm-get-nic-details

    Gets the properties of a given network interface.

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

    Gets the properties of a given public IP address.

  • azure-vm-list-instances

    Lists the virtual machine instances in the given resource group.

  • azure-vm-poweroff-instance

    Powers off a given virtual machine.

  • azure-vm-start-instance

    Powers on a given virtual machine.

import demistomock as demisto
from CommonServerPython import *
from MicrosoftApiModule import *  # noqa: E402

from CommonServerUserPython import *

"""GLOBAL VARS"""
API_VERSION = "2023-03-01"
APP_NAME = "ms-azure-compute"
DEFAULT_LIMIT = 50

# Image options to be used in the create_vm_command
IMAGES = {
    "ubuntu server 14.04 lts": {"publisher": "Canonical", "offer": "UbuntuServer", "sku": "14.04-LTS", "version": "latest"},
    "ubuntu server 16.04 lts": {"publisher": "Canonical", "offer": "UbuntuServer", "sku": "16.04-LTS", "version": "latest"},
    "ubuntu server 18.04 lts": {"publisher": "Canonical", "offer": "UbuntuServer", "sku": "18.04-LTS", "version": "latest"},
    "red hat enterprise linux 7.6": {"publisher": "RedHat", "offer": "RHEL", "sku": "7-RAW", "version": "latest"},
    "centos-based 7.5": {"publisher": "OpenLogic", "offer": "CentOS", "sku": "7.5", "version": "latest"},
    "windows server 2012 r2 datacenter": {
        "publisher": "MicrosoftWindowsServer",
        "offer": "WindowsServer",
        "sku": "2012-R2-Datacenter",
        "version": "latest",
    },
    "windows server 2016 datacenter": {
        "publisher": "MicrosoftWindowsServer",
        "offer": "WindowsServer",
        "sku": "2016-Datacenter",
        "version": "latest",
    },
    "windows 10 pro version 1803": {
        "publisher": "MicrosoftWindowsDesktop",
        "offer": "Windows-10",
        "sku": "rs4-pro",
        "version": "latest",
    },
    "windows 10 pro version 1809": {
        "publisher": "MicrosoftWindowsDesktop",
        "offer": "Windows-10",
        "sku": "rs5-pro",
        "version": "latest",
    },
}

# Error messages for different provisioning states
CREATING_OR_UPDATING_ERR = (
    "Please wait for the VM to finish being"
    " {} before executing this command. To retrieve the "
    "last known state of the VM, execute the "
    "`azure-vm-get-instance-details` command. "
)
DELETING_ERR = "You cannot execute this command because the VM is being deleted."
FAILED_ERR = (
    "Unable to power-off or power-on '{}' virtual machine "
    "because the following provisioning failure occurred during "
    'the vm\'s creation.\ncode: "{}"\nmessage: "{}"\nVisit the '
    "Azure Web Portal to take care of this issue."
)

# Error messages determined by the provisioning state of the VM
PROVISIONING_STATE_TO_ERRORS = {
    "creating": CREATING_OR_UPDATING_ERR.format("created"),
    "updating": CREATING_OR_UPDATING_ERR.format("updated"),
    "deleting": DELETING_ERR,
    "failed": FAILED_ERR,
}

"""HELPER FUNCTIONS"""


def screen_errors(error_message, *args, **kwargs):
    """
    Make sure that the values passed as args and the keys in kwargs do not appear in error messages

    parameter: (string) error_message
        The error message that needs to be screened for the values in args and the keys
        in kwargs

    parameter: (list) *args
        Arguments that need to be screened from error outputs and that will be replaced
        by x's enclosed by a '<' symbol on the left, and a '>' symbol on the right

    parameter: (dict) **kwargs
        Key-value pairs for each of which the user wishes to screen the key identifier string
        from the error_message and replace it with its assigned value string. Useful for
        when the user wishes to replace sensitive data with a value of their choosing
        instead of the default x's enclosed by '<', and '>' symbols on the left and right respectively

    returns:
        The error message free of sensitive information as determined by the values of
        args and the keys of kwargs
    """
    if isinstance(error_message, Exception):
        # Format Exception object as String
        error_as_dict = vars(error_message)
        updated_error_message = ""
        for key, val in error_as_dict.items():
            if updated_error_message != "":
                updated_error_message += "\n" + str(key) + ": " + str(val)
            else:
                updated_error_message += str(key) + ": " + str(val)
    elif not isinstance(error_message, str):
        # If not an Exception or a String, try to cast to a string
        updated_error_message = str(error_message)
    else:
        updated_error_message = error_message

    for argument in args:
        if argument != "" and argument in updated_error_message:
            length = len(argument)
            placeholder = "<" + "x" * length + ">"
            updated_error_message = updated_error_message.replace(argument, placeholder)

    for key, value in kwargs.items():
        if key != "" and key in updated_error_message:
            updated_error_message = updated_error_message.replace(key, value)

    return updated_error_message


def assign_image_attributes(image):
    """
    Retrieve image properties determined by the chosen image

    returns:
        Image Properties Tuple (sku, publisher, offer, version)
    """
    image = image.lower()
    image_properties = IMAGES.get(image)
    if not image_properties:
        err_msg = "Invalid value entered for the 'os_image' argument. "
        err_msg += "Only values from the provided options are accepted."
        raise Exception(err_msg)
    sku = image_properties.get("sku")
    publisher = image_properties.get("publisher")
    offer = image_properties.get("offer")
    version = image_properties.get("version")
    return sku, publisher, offer, version


def create_vm_parameters(args, subscription_id, resource_group):
    """
    Construct the VM object

    Use the actual parameters passed to the 'azure-vm-create-instance' command
    to build a vm object that will be sent in the body of the command's associated
    API call.

    parameter: (dict) args
        Dictionary that contains the actual parameters that were passed to the
        'azure-vm-create-instance' command

    returns:
        Virtual Machine Object
    """
    # Retrieve relevant command arguments
    location = args.get("virtual_machine_location")
    vm_size = args.get("vm_size")
    image = args.get("os_image")
    sku = args.get("sku")
    publisher = args.get("publisher")
    version = args.get("version")
    offer = args.get("offer")
    vm_name = args.get("virtual_machine_name")
    admin_username = args.get("admin_username")
    admin_password = args.get("admin_password")
    nic_name = args.get("nic_name")
    full_nic_id = f"/subscriptions/{subscription_id}/resourceGroups/"  # type: ignore
    full_nic_id += f"{resource_group}/providers/Microsoft.Network/networkInterfaces/{nic_name}"

    if not image and not (sku and publisher and version and offer):
        err_msg = "You must enter a value for the 'os_image' argument "
        err_msg += "or the group of arguments, 'sku', 'publisher', 'version', and 'offer'."
        raise Exception(err_msg)

    if image:
        sku, publisher, offer, version = assign_image_attributes(image)

    # Construct VM object
    vm = {
        "location": location,
        "properties": {
            "hardwareProfile": {"vmSize": vm_size},
            "storageProfile": {
                "imageReference": {"sku": sku, "publisher": publisher, "version": version, "offer": offer},
                "osDisk": {
                    "caching": "ReadWrite",
                    "managedDisk": {"storageAccountType": "Standard_LRS"},
                    "name": vm_name,
                    "createOption": "FromImage",
                },
            },
            "osProfile": {"adminUsername": admin_username, "computerName": vm_name, "adminPassword": admin_password},
            "networkProfile": {"networkInterfaces": [{"id": full_nic_id, "properties": {"primary": "true"}}]},
        },
        "name": vm_name,
    }

    return vm


def create_nic_parameters(resource_group, subscription_id, args):
    """
    Construct the NIC object

    Use the actual parameters passed to the 'azure-vm-create-nic' command
    to build a nic object that will be sent in the body of the command's associated
    API call.

    parameter: (dict) args
        Dictionary that contains the actual parameters that were passed to the
        'azure-vm-create-nic' command

    returns:
        NIC Object
    """
    # Retrieve relevant command arguments
    location = args.get("nic_location")
    address_assignment_method = args.get("address_assignment_method")
    private_ip_address = args.get("private_ip_address")
    network_security_group = args.get("network_security_group")
    vnet_name = args.get("vnet_name")
    subnet_name = args.get("subnet_name")
    ip_config_name = args.get("ip_config_name")
    subnet_id = (
        f"/subscriptions/{subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Network/"
        f"virtualNetworks/{vnet_name}/subnets/{subnet_name}"
    )

    # Construct NIC object
    nic = {
        "location": location,
        "properties": {
            "ipConfigurations": [
                {
                    "name": ip_config_name,
                    "properties": {"privateIPAllocationMethod": address_assignment_method, "subnet": {"id": subnet_id}},
                }
            ]
        },
    }

    if address_assignment_method == "Static":
        if not private_ip_address:
            err_msg = (
                'You have chosen to assign a "Static" IP address value to the interface, '
                'so you must enter a value for the "private_ip_address" argument.'
            )
            raise Exception(err_msg)
        nic["properties"]["ipConfigurations"][0]["properties"]["privateIPAddress"] = private_ip_address

    if network_security_group:
        network_security_group_id = (
            f"/subscriptions/{subscription_id}/resourceGroups/{resource_group}/providers"
            f"/Microsoft.Network/networkSecurityGroups/{network_security_group}"
        )
        nic["properties"]["networkSecurityGroup"]["id"] = network_security_group_id

    return nic


def get_single_ip_details_from_list_of_ip_details(list_of_ip_details: list, ip_address):
    """Finds the associated details of target IP Address from a list of PublicIPAddressListResult objects.

    Args:
        list_of_ip_details (list):  List of PublicIPAddressListResult objects.
        ip_address (list | dict): IP Address to search for in list of PublicIPAddressListResult objects.
    """

    def search_entry_for_ip(data, key, value):
        if isinstance(data, list):
            for item in data:
                result = search_entry_for_ip(item, key, value)
                if result:
                    return result
        elif isinstance(data, dict):
            if key in data and data[key] == value:
                return True
            for val in data.values():
                result = search_entry_for_ip(val, key, value)
                if result:
                    return result
        return None

    for entry in list_of_ip_details:
        result = search_entry_for_ip(entry, "ipAddress", ip_address)
        if result:
            return entry
    return None


class MsGraphClient:
    """
    Microsoft Graph Client enables authorized access to Create and Manage Azure Virtual Machines.
    """

    def __init__(
        self,
        tenant_id,
        auth_id,
        enc_key,
        app_name,
        base_url,
        verify,
        proxy,
        self_deployed,
        ok_codes,
        server,
        subscription_id,
        certificate_thumbprint,
        private_key,
    ):
        self.ms_client = MicrosoftClient(
            tenant_id=tenant_id,
            auth_id=auth_id,
            enc_key=enc_key,
            app_name=app_name,
            base_url=base_url,
            verify=verify,
            proxy=proxy,
            self_deployed=self_deployed,
            ok_codes=ok_codes,
            scope=Scopes.management_azure,
            certificate_thumbprint=certificate_thumbprint,
            private_key=private_key,
            command_prefix="azure-vm",
        )

        self.server = server
        self.subscription_id = subscription_id
        self.default_params = {"api-version": API_VERSION}

    def list_resource_groups(self, limit: int, tag: str = "", full_url: Optional[str] = ""):
        filter_by_tag = azure_tag_formatter(tag) if tag else None
        parameters = {"$filter": filter_by_tag, "$top": limit, "api-version": "2021-04-01"} if not full_url else {}
        return self.ms_client.http_request(method="GET", params=parameters, url_suffix="", full_url=full_url)

    def list_subscriptions(self):
        parameters = {"api-version": "2020-01-01"}
        url = self.server + "/subscriptions"
        return self.ms_client.http_request(method="GET", full_url=url, params=parameters, url_suffix="")

    def list_vms(self, resource_group, full_url):
        url_suffix = f"{resource_group}/providers/Microsoft.Compute/virtualMachines" if not full_url else ""
        params = self.default_params if not full_url else {}
        return self.ms_client.http_request(method="GET", url_suffix=url_suffix, params=params, full_url=full_url)

    def get_vm(self, resource_group, vm_name, expand="instanceView"):
        url_suffix = f"{resource_group}/providers/Microsoft.Compute/virtualMachines/{vm_name}"
        parameters = {"$expand": expand} | self.default_params
        return self.ms_client.http_request(method="GET", url_suffix=url_suffix, params=parameters)

    def create_vm(self, args, resource_group):
        # Retrieve relevant command argument
        vm_name = args.get("virtual_machine_name")

        url_suffix = f"{resource_group}/providers/Microsoft.Compute/virtualMachines/{vm_name}"

        # Construct VM object utilizing parameters passed as command arguments
        payload = create_vm_parameters(args, self.subscription_id, resource_group)
        return self.ms_client.http_request(method="PUT", url_suffix=url_suffix, params=self.default_params, json_data=payload)

    def delete_vm(self, resource_group, vm_name):
        # Construct endpoint URI suffix (for de-allocation of compute resources)
        url_suffix = f"{resource_group}/providers/Microsoft.Compute/virtualMachines/{vm_name}/deallocate"

        # Call API to deallocate compute resources
        self.ms_client.http_request(method="POST", url_suffix=url_suffix, params=self.default_params, resp_type="response")

        # Construct endpoint URI suffix (for deletion)
        url_suffix = f"{resource_group}/providers/Microsoft.Compute/virtualMachines/{vm_name}"

        # Call API to delete
        return self.ms_client.http_request(
            method="DELETE", url_suffix=url_suffix, params=self.default_params, resp_type="response"
        )

    def start_vm(self, resource_group, vm_name):
        # Retrieve relevant command arguments
        url_suffix = f"{resource_group}/providers/Microsoft.Compute/virtualMachines/{vm_name}/start"

        # Call API
        return self.ms_client.http_request(method="POST", url_suffix=url_suffix, params=self.default_params, resp_type="response")

    def poweroff_vm(self, resource_group, vm_name, skip_shutdown):
        url_suffix = f"{resource_group}/providers/Microsoft.Compute/virtualMachines/{vm_name}/powerOff"
        parameters = {"skipShutdown": skip_shutdown} | self.default_params

        return self.ms_client.http_request(method="POST", url_suffix=url_suffix, params=parameters, resp_type="response")

    def get_all_public_ip_details(self):
        """
        List all public IPs belonging to your Azure subscription

        Returns:
            List of PublicIPAddressListResult Objects

        Docs:
            https://learn.microsoft.com/en-us/rest/api/virtualnetwork/public-ip-addresses/list-all?tabs=HTTP
        """
        url_suffix = "/providers/Microsoft.Network/publicIPAddresses"
        parameters = {"api-version": "2022-09-01"}
        base_url = f"{self.server}/subscriptions/{self.subscription_id}"
        self.ms_client._base_url = base_url
        return self.ms_client.http_request(method="GET", url_suffix=url_suffix, params=parameters)

    def validate_provisioning_state(self, resource_group, vm_name):
        """
        Ensure that the provisioning state of a VM is 'Succeeded'

        For all provisioning states other than 'Succeeded', this method will raise an
        exception with an informative error message.

        parameter: (dict) args
            The command arguments passed to either the `azure-vm-start-instance` or
            `azure-vm-poweroff-instance` commands

        returns:
            None
        """
        response = self.get_vm(resource_group, vm_name)
        # Retrieve relevant properties for checking provisioning state and returning
        # informative error messages if necessary

        properties = response.get("properties")
        provisioning_state = properties.get("provisioningState")
        statuses = properties.get("instanceView", {}).get("statuses")

        # Check if the current ProvisioningState of the VM allows for executing this command
        if provisioning_state.lower() == "failed":
            for status in statuses:
                status_code = status.get("code")
                if "provisioningstate/failed" in status_code.lower():
                    message = status.get("message")
                    err_msg = PROVISIONING_STATE_TO_ERRORS.get("failed")
                    raise Exception(err_msg.format(vm_name, status_code, message))  # type: ignore
            # In the case that the microsoft API changes and the status code is no longer
            # relevant, preventing the above exception with its detailed error message from
            # being raised, then raise the below exception with a more general error message
            err_msg = "Cannot execute this command because the ProvisioningState of the VM is 'Failed'."
            raise Exception(err_msg)
        elif provisioning_state.lower() in PROVISIONING_STATE_TO_ERRORS:
            err_msg = PROVISIONING_STATE_TO_ERRORS.get(provisioning_state.lower())
            raise Exception(err_msg)

    def get_network_interface(self, resource_group, interface_name):
        url_suffix = f"{resource_group}/providers/Microsoft.Network/networkInterfaces/{interface_name}"
        return self.ms_client.http_request(method="GET", url_suffix=url_suffix, params={"api-version": "2023-05-01"})

    def get_public_ip_details(self, resource_group, address_name):
        url_suffix = f"{resource_group}/providers/Microsoft.Network/publicIPAddresses/{address_name}"
        return self.ms_client.http_request(method="GET", url_suffix=url_suffix, params={"api-version": "2023-05-01"})

    def create_nic(self, resource_group, args):
        # Retrieve relevant command argument
        nic_name = args.get("nic_name")
        url_suffix = f"{resource_group}/providers/Microsoft.Network/networkInterfaces/{nic_name}"

        # Construct VM object utilizing parameters passed as command arguments
        payload = create_nic_parameters(resource_group, self.subscription_id, args)
        return self.ms_client.http_request(
            method="PUT", url_suffix=url_suffix, params={"api-version": "2023-05-01"}, json_data=payload
        )


def test_module(client: MsGraphClient):
    # Implicitly will test tenant, enc_token and subscription_id
    client.list_resource_groups(1)
    return "ok"


# <-------- Resource Groups --------> #


def list_resource_groups_command(client: MsGraphClient, args: dict):
    """
    List all Resource Groups belonging to your Azure subscription

    returns:
        Resource-Group Objects
    """
    tag = args.get("tag", "")
    limit = arg_to_number(args.get("limit")) or DEFAULT_LIMIT

    resource_groups: List[dict] = []

    next_link = True
    while next_link and len(resource_groups) < limit:
        full_url = next_link if isinstance(next_link, str) else None
        response = client.list_resource_groups(limit, tag, full_url=full_url)
        # Retrieve relevant properties to return to context
        value = response.get("value")
        next_link = response.get("nextLink")

        for resource_group in value:
            resource_group_context = {
                "Name": resource_group.get("name"),
                "ID": resource_group.get("id"),
                "Location": resource_group.get("location"),
                "ProvisioningState": resource_group.get("properties", {}).get("provisioningState"),
            }
            resource_groups.append(resource_group_context)

    resource_groups = resource_groups[:limit]
    title = "List of Resource Groups"
    human_readable = tableToMarkdown(title, resource_groups, removeNull=True)

    return CommandResults(
        outputs_prefix="Azure.ResourceGroup",
        outputs_key_field="Name",
        outputs=resource_groups,
        readable_output=human_readable,
        raw_response=response,
    )


# <-------- Subscriptions --------> #


def list_subscriptions_command(client: MsGraphClient):
    """
    List all subscriptions for this application

    returns:
        Subscription Objects
    """
    response = client.list_subscriptions()
    # Retrieve relevant properties to return to context
    value = response.get("value")
    subscriptions = []
    for subscription in value:
        subscription_context = {
            "Name": subscription.get("displayName"),
            "ID": subscription.get("id"),
            "State": subscription.get("state"),
        }
        subscriptions.append(subscription_context)

    title = "List of Subscriptions"
    human_readable = tableToMarkdown(title, subscriptions, removeNull=True)

    return CommandResults(
        outputs_prefix="Azure.Subscription",
        outputs_key_field="ID",
        outputs=subscriptions,
        readable_output=human_readable,
        raw_response=response,
    )


# <-------- Virtual Machines --------> #


def list_vms_command(client: MsGraphClient, args: dict, params: dict):
    """
    List the VM instances in the specified Resource Group

    demisto parameter: (string) resource_group
        Resource Group of the VMs

    returns:
        Virtual Machine Objects
    """
    resource_group = get_from_args_or_params(args=args, params=params, key="resource_group")
    limit = int(args.get("limit", 50))
    vms: List[dict] = []

    next_link = True
    while next_link and len(vms) < limit:
        full_url = next_link if isinstance(next_link, str) else None
        response = client.list_vms(resource_group, full_url=full_url)
        # Retrieve relevant properties to return to context
        vm_objects_list = response.get("value")
        next_link = response.get("nextLink")

        for vm_object in vm_objects_list:
            vm_name = vm_object.get("name").lower()
            location = vm_object.get("location")
            properties = vm_object.get("properties")
            provisioning_state = properties.get("provisioningState")
            os_disk = properties.get("storageProfile", {}).get("osDisk")
            datadisk = os_disk.get("diskSizeGB", "NA")
            vm_id = properties.get("vmId")
            os_type = os_disk.get("osType")
            vm = {
                "Name": vm_name,
                "ID": vm_id,
                "Size": datadisk,
                "OS": os_type,
                "Location": location,
                "ProvisioningState": provisioning_state,
                "ResourceGroup": resource_group,
            }
            vms.append(vm)

    vms = vms[:limit]

    title = f'Microsoft Azure - List of Virtual Machines in Resource Group "{resource_group}"'
    table_headers = ["Name", "ID", "Size", "OS", "Location", "ProvisioningState", "ResourceGroup"]
    human_readable = tableToMarkdown(title, vms, headers=table_headers, removeNull=True)

    return CommandResults(
        outputs_prefix="Azure.Compute",
        outputs_key_field="Name",
        outputs=vms,
        readable_output=human_readable,
        raw_response=response,
    )


def get_vm_command(client: MsGraphClient, args: dict, params: dict):
    """
    Get the properties of a specified Virtual Machine

    demisto parameter: (string) resource_group
        Resource Group to which the virtual machine belongs

    demisto parameter: (string) virtual_machine_name
        Name of the virtual machine you wish to view the details of

    returns:
        Virtual Machine Object
    """
    resource_group = get_from_args_or_params(args=args, params=params, key="resource_group")
    vm_name = args.get("virtual_machine_name")
    expand = args.get("expand", "")
    response = client.get_vm(resource_group, vm_name, expand)
    # Retrieve relevant properties to return to context
    vm_name = vm_name.lower()  # type: ignore
    properties = response.get("properties")
    os_disk = properties.get("storageProfile", {}).get("osDisk")
    datadisk = os_disk.get("diskSizeGB", "NA")
    vm_id = properties.get("vmId")
    os_type = os_disk.get("osType")
    provisioning_state = properties.get("provisioningState")
    location = response.get("location")
    user_data = properties.get("userData")
    tags = response.get("tags")
    network_interfaces = properties.get("networkProfile", {}).get("networkInterfaces")
    statuses = properties.get("instanceView", {}).get("statuses", [])
    power_state = None
    for status in statuses:
        status_code = status.get("code")
        status_code_prefix = status_code[: status_code.find("/")]
        if status_code_prefix == "PowerState":
            power_state = status.get("displayStatus")

    vm = {
        "Name": vm_name,
        "ID": vm_id,
        "Size": datadisk,
        "OS": os_type,
        "ProvisioningState": provisioning_state,
        "Location": location,
        "PowerState": power_state,
        "ResourceGroup": resource_group,
        "NetworkInterfaces": network_interfaces,
        "UserData": user_data,
        "Tags": tags,
    }

    title = f'Properties of VM "{vm_name}"'
    table_headers = ["Name", "ID", "Size", "OS", "ProvisioningState", "Location", "PowerState"]
    human_readable = tableToMarkdown(title, vm, headers=table_headers, removeNull=True)

    return CommandResults(
        outputs_prefix="Azure.Compute",
        outputs_key_field="Name",
        outputs=vm,
        readable_output=human_readable,
        raw_response=response,
    )


def create_vm_command(client: MsGraphClient, args: dict, params: dict):
    """
    Create a virtual machine instance with the specified OS image

    demisto parameter: (string) resource_group
        Resource group to which the new VM will belong

    demisto parameter: (string) virtual_machine_name
        Name to assign to the new virtual machine

    demisto parameter: (string) virtual_machine_location
        Region in which the vm will be hosted

    demisto parameter: (string) nic_name
        The name of the Network Interface to link the VM with. This must be created from the Azure Portal

    demisto parameter: (string) vm_size
        The name of a VirtualMachineSize which determines the size of the deployed vm

    demisto parameter: (string) os_image
        Choose the base operating system image of the vm

    demisto parameter: (string) sku
        SKU of the image to be used

    demisto parameter: (string) publisher
        Name of the publisher of the image

    demisto parameter: (string) version
        Version of the image to use

    demisto parameter: (string) offer
        Specifies the offer of the platform image or marketplace image used
        to create the virtual machine

    demisto parameter: (string) admin_username
        Admin Username to be used when creating the VM

    demisto parameter: (string) admin_password
        Admin Password to be used when creating the VM

    returns:
        Virtual Machine Object
    """
    resource_group = get_from_args_or_params(args=args, params=params, key="resource_group")
    response = client.create_vm(args, resource_group)

    # Retrieve relevant properties to return to context
    vm_name = response.get("name").lower()
    properties = response.get("properties")
    os_disk = properties.get("storageProfile", {}).get("osDisk")
    datadisk = os_disk.get("diskSizeGB", "NA")
    vm_id = properties.get("vmId")
    os_type = os_disk.get("osType")
    provisioning_state = properties.get("provisioningState")
    location = response.get("location")

    vm = {
        "Name": vm_name,
        "ID": vm_id,
        "Size": datadisk,
        "OS": os_type,
        "ProvisioningState": provisioning_state,
        "Location": location,
        "ResourceGroup": resource_group,
    }

    title = f'Created Virtual Machine "{vm_name}"'
    human_readable = tableToMarkdown(title, vm, removeNull=True)

    return CommandResults(
        outputs_prefix="Azure.Compute",
        outputs_key_field="Name",
        outputs=vm,
        readable_output=human_readable,
        raw_response=response,
    )


def delete_vm_command(client: MsGraphClient, args: dict, params: dict):
    """
    Delete a specified Virtual Machine

    demisto parameter: (string) resource_group
        Resource Group to which the virtual machine belongs

    demisto parameter: (string) virtual_machine_name
        Name of the virtual machine to delete

    returns:
        Success message to the war room
    """
    resource_group = get_from_args_or_params(args=args, params=params, key="resource_group")
    vm_name = args.get("virtual_machine_name")

    client.delete_vm(resource_group, vm_name)
    return f'"{vm_name}" VM Deletion Successfully Initiated'


def start_vm_command(client: MsGraphClient, args: dict, params: dict):
    """
    Power-on a specified Virtual Machine

    demisto parameter: (string) resource_group
        Resource Group to which the virtual machine belongs

    demisto parameter: (string) virtual_machine_name
        Name of the virtual machine to power-on

    returns:
        Virtual Machine Object
    """
    resource_group = get_from_args_or_params(args=args, params=params, key="resource_group")
    vm_name = args.get("virtual_machine_name")

    # Raise an exception if the VM isn't in the proper provisioning state
    client.validate_provisioning_state(resource_group, vm_name)

    client.start_vm(resource_group, vm_name)
    vm_name = vm_name.lower()  # type: ignore
    vm = {"Name": vm_name, "ResourceGroup": resource_group, "PowerState": "VM starting"}

    title = f'Power-on of Virtual Machine "{vm_name}" Successfully Initiated'
    human_readable = tableToMarkdown(title, vm, removeNull=True)

    return CommandResults(
        outputs_prefix="Azure.Compute", outputs_key_field="Name", outputs=vm, readable_output=human_readable, raw_response=vm
    )


def poweroff_vm_command(client: MsGraphClient, args: dict, params: dict):
    """
    Power-off a specified Virtual Machine

    demisto parameter: (string) resource_group
        Resource Group to which the virtual machine belongs

    demisto parameter: (string) virtual_machine_name
        Name of the virtual machine to power-off

    returns:
        Virtual Machine Object
    """
    resource_group = get_from_args_or_params(args=args, params=params, key="resource_group")
    vm_name = args.get("virtual_machine_name")
    skip_shutdown = argToBoolean(args.get("skip_shutdown", False))

    # Raise an exception if the VM isn't in the proper provisioning state
    client.validate_provisioning_state(resource_group, vm_name)

    client.poweroff_vm(resource_group, vm_name, skip_shutdown)

    vm_name = vm_name.lower()  # type: ignore
    vm = {"Name": vm_name, "ResourceGroup": resource_group, "PowerState": "VM stopping"}

    title = f'Power-off of Virtual Machine "{vm_name}" Successfully Initiated'
    human_readable = tableToMarkdown(title, vm, removeNull=True)

    return CommandResults(
        outputs_prefix="Azure.Compute", outputs_key_field="Name", outputs=vm, readable_output=human_readable, raw_response=vm
    )


def get_network_interface_command(client: MsGraphClient, args: dict, params: dict):
    """
    Get the properties of a specified Network Interface

    demisto parameter: (string) resource_group
        Resource Group to which the network interface belongs

    demisto parameter: (string) nic_name
        Name of the network interface you wish to view the details of

    returns:
        Network Interface Object
    """
    resource_group = get_from_args_or_params(args=args, params=params, key="resource_group")
    interface_name = args.get("nic_name")
    response = client.get_network_interface(resource_group, interface_name)
    interface_name = interface_name.lower()  # type: ignore
    properties = response.get("properties")
    interface_id = response.get("id")
    mac_address = properties.get("macAddress", "NA")
    network_security_group = properties.get("networkSecurityGroup", "NA")
    is_primay_interface = properties.get("primary", "NA")
    attached_virtual_machine = properties.get("virtualMachine", {}).get("id", "NA")
    nic_type = properties.get("nicType", "NA")
    location = response.get("location")
    dns_suffix = properties.get("dnsSettings", {}).get("internalDomainNameSuffix")

    ip_configurations = properties.get("ipConfigurations", [])

    ip_configs = []

    for ip_configuration in ip_configurations:
        ip_configs.append(
            {
                "ConfigName": ip_configuration.get("name", "NA"),
                "ConfigID": ip_configuration.get("id", "NA"),
                "PrivateIPAddress": ip_configuration.get("properties", {}).get("privateIPAddress", "NA"),
                "PublicIPAddressID": ip_configuration.get("properties", {}).get("publicIPAddress", {}).get("id"),
            }
        )

    network_config = {
        "Name": interface_name,
        "ID": interface_id,
        "MACAddress": mac_address,
        "NetworkSecurityGroup": network_security_group,
        "IsPrimaryInterface": is_primay_interface,
        "Location": location,
        "AttachedVirtualMachine": attached_virtual_machine,
        "ResourceGroup": resource_group,
        "NICType": nic_type,
        "DNSSuffix": dns_suffix,
        "IPConfigurations": ip_configs,
    }

    human_readable_network_config = {
        "Name": interface_name,
        "ID": interface_id,
        "MACAddress": mac_address,
        "PrivateIPAddresses": [ip.get("PrivateIPAddress") for ip in ip_configs],
        "NetworkSecurityGroup": network_security_group,
        "Location": location,
        "NICType": nic_type,
        "AttachedVirtualMachine": attached_virtual_machine,
    }

    title = f'Properties of Network Interface "{interface_name}"'
    table_headers = [
        "Name",
        "ID",
        "MACAddress",
        "PrivateIPAddresses",
        "NetworkSecurityGroup",
        "Location",
        "NICType",
        "AttachedVirtualMachine",
    ]
    human_readable = tableToMarkdown(title, human_readable_network_config, headers=table_headers, removeNull=True)

    return CommandResults(
        outputs_prefix="Azure.Network.Interfaces",
        outputs_key_field="ID",
        outputs=network_config,
        readable_output=human_readable,
        raw_response=response,
    )


def get_public_ip_details_command(client: MsGraphClient, args: dict, params: dict):
    """
    Get the properties of a specified Public IP Address

    demisto parameter: (string) resource_group
        Resource Group to which the public IP address belongs

    demisto parameter: (string) address_name
        The IPv4 or Name of the public ip address you wish to view the details of.

    returns:
        Public IP Address Object
    """
    address_name = args.get("address_name")
    if resource_group := (args.get("resource_group") or params.get("resource_group")):
        response = client.get_public_ip_details(resource_group, address_name)
        address_id = response.get("id")
    else:
        response_for_all_ips = client.get_all_public_ip_details().get("value")
        response = get_single_ip_details_from_list_of_ip_details(response_for_all_ips, address_name)
        if not response:
            raise ValueError(
                f"'{address_name}' was not found. Please try specifying the resource group the IP would be associated with."
            )
        address_id = response.get("id")
        resource_group = address_id.split("resourceGroups/")[1].split("/providers")[0]

    # Retrieve relevant properties to return to context
    properties = response.get("properties")
    config_id = properties.get("ipConfiguration", {}).get("id")
    ip_address = properties.get("ipAddress", "NA")
    ip_address_version = properties.get("publicIPAddressVersion", "NA")
    ip_address_allocation_method = properties.get("publicIPAllocationMethod", "NA")
    address_domain_name = properties.get("dnsSettings", {}).get("domainNameLabel", "NA")
    address_fqdn = properties.get("dnsSettings", {}).get("fqdn", "NA")
    config_name = response.get("name")
    location = response.get("location")

    ip_config = {
        "PublicIPAddressID": address_id,
        "PublicConfigName": config_name,
        "Location": location,
        "PublicConfigID": config_id,
        "ResourceGroup": resource_group,
        "PublicIPAddress": ip_address,
        "PublicIPAddressVersion": ip_address_version,
        "PublicIPAddressAllocationMethod": ip_address_allocation_method,
        "PublicIPAddressDomainName": address_domain_name,
        "PublicIPAddressFQDN": address_fqdn,
    }

    human_readable_ip_config = {
        "PublicConfigName": config_name,
        "Location": location,
        "PublicIPAddress": ip_address,
        "PublicIPAddressVersion": ip_address_version,
        "PublicIPAddressAllocationMethod": ip_address_allocation_method,
        "ResourceGroup": resource_group,
    }

    title = f'Properties of Public Address "{address_name}"'
    table_headers = [
        "PublicConfigName",
        "Location",
        "PublicIPAddress",
        "PublicIPAddressVersion",
        "PublicIPAddressAllocationMethod",
        "ResourceGroup",
    ]
    human_readable = tableToMarkdown(title, human_readable_ip_config, headers=table_headers, removeNull=True)

    return CommandResults(
        outputs_prefix="Azure.Network.IPConfigurations",
        outputs_key_field="PublicIPAddressID",
        outputs=ip_config,
        readable_output=human_readable,
        raw_response=response,
    )


def get_all_public_ip_details_command(client: MsGraphClient):
    """
    Get the properties of all Public IP Addresses in the configured subscription

    returns:
        List of Public IP Address Objects
    """
    response = client.get_all_public_ip_details()

    ip_objects_list = response.get("value", [])

    ips = []

    for ip_object in ip_objects_list:
        # Retrieve relevant properties to return to context
        properties = ip_object.get("properties", {})
        address_id = ip_object.get("id", "")
        config_id = properties.get("ipConfiguration", {}).get("id", "")
        ip_address = properties.get("ipAddress", "NA")
        ip_address_version = properties.get("publicIPAddressVersion", "NA")
        ip_address_allocation_method = properties.get("publicIPAllocationMethod", "NA")
        address_domain_name = properties.get("dnsSettings", {}).get("domainNameLabel", "NA")
        address_fqdn = properties.get("dnsSettings", {}).get("fqdn", "NA")
        config_name = ip_object.get("name")
        location = ip_object.get("location")
        resource_group = address_id.split("resourceGroups/")[1].split("/providers")[0]
        ip_config = {
            "PublicIPAddressID": address_id,
            "PublicConfigName": config_name,
            "Location": location,
            "PublicConfigID": config_id,
            "ResourceGroup": resource_group,
            "PublicIPAddress": ip_address,
            "PublicIPAddressVersion": ip_address_version,
            "PublicIPAddressAllocationMethod": ip_address_allocation_method,
            "PublicIPAddressDomainName": address_domain_name,
            "PublicIPAddressFQDN": address_fqdn,
        }
        ips.append(ip_config)

    title = f'Microsoft Azure - List of Virtual Machines in Subscription "{client.subscription_id}"'
    table_headers = [
        "PublicConfigName",
        "Location",
        "PublicIPAddress",
        "PublicIPAddressVersion",
        "PublicIPAddressAllocationMethod",
    ]
    human_readable = tableToMarkdown(title, ips, headers=table_headers, removeNull=True)

    return CommandResults(
        outputs_prefix="Azure.Network.IPConfigurations",
        outputs_key_field="PublicIPAddressID",
        outputs=ips,
        readable_output=human_readable,
        raw_response=response,
    )


def create_nic_command(client: MsGraphClient, args: dict, params: dict):
    """
    Create a Network Interface with the specified interface parameters

    demisto parameter: (string) resource_group
        The resource group to which the new network interface will belong.

    demisto parameter: (string) nic_name
        The network interface name.

    demisto parameter: (string) nic_location
        The location in which to create the network interface.

    demisto parameter: (string) vnet_name
        The virtual network name of the inteface.

    demisto parameter: (string) subnet_name
        The subnet name of the inteface.

    demisto parameter: (string) address_assignment_method
         The address assignment method, the default is Dynamic.

    demisto parameter: (string) private_ip_address
        The private ip address of the interface incase you chose to use the static assignment method.

    demisto parameter: (string) ip_config_name
        The ip address config name.

    demisto parameter: (string) network_security_group
        The network security group of the interface.

    returns:
        Network Interface Object
    """
    resource_group = get_from_args_or_params(args=args, params=params, key="resource_group")
    response = client.create_nic(resource_group, args)

    # Retrieve relevant properties to return to context
    nic_name = response.get("name").lower()
    nic_id = response.get("id")
    location = response.get("location")
    properties = response.get("properties")
    network_security_group = properties.get("networkSecurityGroup", {}).get("id", "NA")
    provisioning_state = properties.get("provisioningState", "NA")
    ip_configurations = properties.get("ipConfigurations", [])
    dns_suffix = properties.get("dnsSettings", {}).get("internalDomainNameSuffix")

    ip_configs = []
    for ip_configuration in ip_configurations:
        ip_configs.append(
            {
                "ConfigName": ip_configuration.get("name", "NA"),
                "ConfigID": ip_configuration.get("id", "NA"),
                "PrivateIPAddress": ip_configuration.get("properties", {}).get("privateIPAddress", "NA"),
                "PublicIPAddressID": ip_configuration.get("properties", {}).get("publicIPAddress", {}).get("id", "NA"),
                "SubNet": ip_configuration.get("properties", {}).get("subnet", {}).get("id", "NA"),
            }
        )

    nic = {
        "Name": nic_name,
        "ID": nic_id,
        "IPConfigurations": ip_configs,
        "ProvisioningState": provisioning_state,
        "Location": location,
        "ResourceGroup": resource_group,
        "NetworkSecurityGroup": network_security_group,
        "DNSSuffix": dns_suffix,
    }

    human_readable_nic = {
        "Name": nic_name,
        "ID": nic_id,
        "PrivateIPAddresses": [ip.get("PrivateIPAddress") for ip in ip_configs],
        "NetworkSecurityGroup": network_security_group,
        "Location": location,
    }

    title = f'Created Network Interface "{nic_name}"'
    table_headers = ["Name", "ID", "PrivateIPAddresses", "NetworkSecurityGroup", "Location"]
    human_readable = tableToMarkdown(title, human_readable_nic, headers=table_headers, removeNull=True)

    return CommandResults(
        outputs_prefix="Azure.Network.Interfaces",
        outputs_key_field=["ID", "Name"],
        outputs=nic,
        readable_output=human_readable,
        raw_response=response,
    )


def main():
    params: dict = demisto.params()
    args = demisto.args()
    server = params.get("host", "https://management.azure.com").rstrip("/")
    tenant = params.get("cred_token", {}).get("password") or params.get("tenant_id")
    auth_and_token_url = params.get("cred_auth_id", {}).get("password") or params.get("auth_id")
    if not tenant or not auth_and_token_url:
        return_error("Token and ID must be provided.")
    enc_key = params.get("cred_enc_key", {}).get("password") or params.get("enc_key")
    certificate_thumbprint = params.get("cred_certificate_thumbprint", {}).get("password") or params.get("certificate_thumbprint")
    private_key = params.get("private_key")
    verify = not params.get("unsecure", False)
    subscription_id = (
        args.get("subscription_id") or params.get("cred_subscription_id", {}).get("password") or params.get("subscription_id")
    )
    proxy: bool = params.get("proxy", False)
    self_deployed: bool = params.get("self_deployed", False)
    if not self_deployed and not enc_key:
        raise DemistoException(
            "Key must be provided. For further information see "
            "https://xsoar.pan.dev/docs/reference/articles/microsoft-integrations---authentication"
        )
    elif not enc_key and not (certificate_thumbprint and private_key):
        raise DemistoException(
            "Key or Certificate Thumbprint and Private Key must be providedFor further information see "
            "https://xsoar.pan.dev/docs/reference/articles/microsoft-integrations---authentication"
        )
    ok_codes = (200, 201, 202, 204)

    commands_without_args = {
        "test-module": test_module,
        "azure-list-subscriptions": list_subscriptions_command,
        "azure-vm-get-all-public-ip-details": get_all_public_ip_details_command,
    }

    commands_with_args = {"azure-list-resource-groups": list_resource_groups_command}

    commands_with_args_and_params = {
        "azure-vm-list-instances": list_vms_command,
        "azure-vm-get-instance-details": get_vm_command,
        "azure-vm-start-instance": start_vm_command,
        "azure-vm-poweroff-instance": poweroff_vm_command,
        "azure-vm-create-instance": create_vm_command,
        "azure-vm-delete-instance": delete_vm_command,
        "azure-vm-get-public-ip-details": get_public_ip_details_command,
        "azure-vm-create-nic": create_nic_command,
        "azure-vm-get-nic-details": get_network_interface_command,
    }

    """EXECUTION"""
    command = demisto.command()
    LOG(f"Command being called is {command}")

    try:
        # Initial setup
        if not subscription_id:
            return_error("A subscription ID must be provided.")
        base_url = f"{server}/subscriptions/{subscription_id}/resourceGroups/"

        client = MsGraphClient(
            base_url=base_url,
            tenant_id=tenant,
            auth_id=auth_and_token_url,
            enc_key=enc_key,
            app_name=APP_NAME,
            verify=verify,
            proxy=proxy,
            self_deployed=self_deployed,
            ok_codes=ok_codes,
            server=server,
            subscription_id=subscription_id,
            certificate_thumbprint=certificate_thumbprint,
            private_key=private_key,
        )

        if command == "azure-vm-auth-reset":
            return_results(reset_auth())

        elif command in commands_without_args:
            return_results(commands_without_args[command](client))

        elif command in commands_with_args:
            return_results(commands_with_args[command](client, args))

        elif command in commands_with_args_and_params:
            return_results(commands_with_args_and_params[command](client, args, params))

    except Exception as e:
        screened_error_message = screen_errors(str(e), tenant)
        return_error(screened_error_message)


if __name__ in ["__main__", "builtin", "builtins"]:
    main()