anjuna-azure-cli instance create

anjuna-azure-cli instance create \
  --name <VM-instance-name> \
  --image-definition <image-definition> \
  --image-gallery <image-gallery> \
  --image-version <image-version> \
  --resource-group <resource-group> \
  --storage-account <storage-account> [OPTIONS...] \
  [-- AZ-OPTIONS...]

Creates AMD SEV instances on Microsoft Azure.

Creating an Azure Confidential VM requires an Azure-compatible disk image. See anjuna-azure-cli disk create for a description of the tools needed to create disk images.

anjuna-azure-cli instance create allows you to optionally specify a storage account to record the boot diagnostics logs. These logs are used to provide the serial console logs functionality in Azure. You can also enable the logs after the CVM has been started by using the az vm boot-diagnostics enable command.

If a network interface, virtual network, subnet, or network security group is not provided to anjuna-azure-cli instance create, Azure automatically creates the necessary resources in the resource group associated with the CVM. Alternatively, you can create the associated network resources in advance using the az commands or by using Terraform and attach them to the CVM with anjuna-azure-cli instance create.

You must be logged in to a valid Azure account permitted to create and manage Azure Confidential VMs. Use the az account show command to confirm that you are logged in. If you are not logged in, consider using the az login command to initialize your az session.
When the --nics option is used to attach one or more network interfaces, the other network related options cannot be used, or else Azure will report an error. The NSG, vnet, and subnet need to be configured in the NIC(s).

The following Azure CLI commands may be helpful:

  • You can create a public-ip-address resource using:

    $ az network public-ip create --name myPublicIp  \
        --resource-group myResourceGroup  \
        --allocation-method Dynamic  \
        --sku Basic
  • You can create a NIC with that public-ip-address resource using:

    $ az network nic create --name myNIC  \
        --resource-group myResourceGroup  \
        --vnet-name myVnet  \
        --subnet mySubnet  \
        --network-security-group myNSG  \
        --public-ip-address myPublicIp
  • The NIC and public-ip-address need to be created in the same region/location.

  • Delete the resources using:

    $ az network nic delete --name myNIC --resource-group myResourceGroup
    $ az network public-ip delete --name myPublicIp --resource-group myResourceGroup

Options

Usage

anjuna-azure-cli instance create \
  --name <VM-instance-name> \
  --image-definition <image-definition> \
  --image-gallery <image-gallery> \
  --image-version <image-version> \
  --resource-group <resource-group> \
  --storage-account <storage-account> [OPTIONS...]

--assign-id

Resource ID of the identity (use [system] for system assigned identity)

--image-definition

(Required) The Azure Image Definition to use

(Required) The Azure Image Definition’s parent shared image gallery

--image-version

(Required) The image version to use

--location

The location to associate with your resources

--name

(Required) Name of the VM instance to use

--resource-group

(Required) The Azure resource group to be used for the artifacts needed for this operation

--role

Role (name or resource ID) to be assigned to the system assigned identity

--scope

Scope, specified as a resource ID, of the role for the system assigned identity

--instance-type

Type of the VM instance to create (default: Standard_DC2as_v5)

--nics <nic> | nic0< nic1< nic2…​>

Names (<nic> | nic0< nic1< nic2…​>) of the network interfaces to attach (default: automatically created)

--nsg

Name of Network Security Group (default: automatically created). Use "" for none

--storage-account

(Required) Storage account for the boot-diagnostic logs

--subnet

Name of the subnet (default: automatically created)

--vnet

Name of the virtual network (default: automatically created)

-- AZ-OPTIONS

To utilize specific az functionality that might not be explicitly supported by anjuna-azure-cli, use the -- delimiter to pass flags directly to the underlying az vm create command. Flags placed after this delimiter are not processed by anjuna-azure-cli but are forwarded directly. In case a flag is provided for both anjuna-azure-cli and az, the forwarded flag will take precedence.

For example:

$ anjuna-azure-cli instance create \
  --name my-cvm-instance \
  --image-gallery myimagegallery \
  --image-definition hello-world-boot-disk \
  --image-version 1.0.0 \
  --resource-group myresourcegroup \
  --storage-account mystorageaccount \
  -- \
  --tags project=example stage=prod

In the example, --tags is directed to az, tagging the VM instance with project=example and stage=prod.

Global options

The following options are available for all anjuna-azure-cli subcommands.

Global options

-h, --help

Prints the help information for the command

--debug

Prints debug messaging

-v, --version

Prints the anjuna-azure-cli version

When the --storage-account flag is specified, the Anjuna CLI will enable the Azure boot diagnostics mechanism, which writes VM system boot logs to the given storage account. The boot diagnostics can also be enabled after an instance is created, using the anjuna-azure-cli instance log-enable command.

When an Azure Confidential VM is created, Azure automatically creates a new OS disk from the specified image and attaches it to the instance. During its runtime, the instance uses the disk for ephemeral storage on an encrypted partition that cannot be accessed from outside of the instance. (For more details, read about encryption of a Confidential VM’s disk.)

Azure also automatically creates and associates network resources with a VM if they are not explicitly specified. Resources such as Virtual Networks and Network Security Groups are not automatically deleted, because they can be shared among many Azure Confidential VMs. They will continue to consume resource quotas.

anjuna-azure-cli instance delete can be used to automatically delete the VM along with the attached resources including the OS disk, network interfaces, and public IPs.

During instance creation, if the anjuna-azure-cli reports an error indicating that the deployment failed, a VM may have been created, which will need to be deleted manually. This can be performed with the az deployment group delete command, using the target reported in the error message to identify the related deployment.

The following provides an example of the type of message returned when a deployment has failed:

{
  "status": "Failed",
  "error": {
    "code": "DeploymentFailed",
    "target": "/subscriptions/137014eb-bb41-4f84-9939-35393af2f98a/resourceGroups/resgroup/providers/Microsoft.Resources/deployments/vm_deploy_eWZv8jdj3ht4W0rrVZJd8kN1PEV8T5AN",
    "message": "At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/arm-deployment-operations for usage details.",
    "details": [
      {
        "code": "ResourceDeploymentFailure",
        "target": "/subscriptions/137014eb-bb41-4f84-9939-35393af2f98a/resourceGroups/resgroup/providers/Microsoft.Compute/virtualMachines/podvm-test-pod",
        "message": "The resource write operation failed to complete successfully, because it reached terminal provisioning state 'Failed'.",
        "details": [
          {
            "code": "InternalDiskManagementError",
            "message": "An unexpected error occurred while processing disk. Please retry later."
          }
        ]
      }
    ]
  }
}

Assign managed identities to Azure Confidential VMs

The anjuna-azure-cli allows an identity to be assigned to the Anjuna Confidential Container when it is created. --assign-id can be used to configure identities on the Anjuna Confidential Container at the time of instantiation. Multiple identities can be added, including the "system-assigned" identity (system) and managed identities. This gives the Anjuna Confidential Container the rights to access any resource or service included in the scope defined for the identity. Additionally, credentials will not need to be embedded in the code or retrieved from the Anjuna Policy Manager. The --scope and --role command line options can be used to customize the access with the system created identity.

Additional References:

The assigned identity can be queried as shown below. In this example, a system created identity was assigned to the Anjuna Confidential Container

$ az vm show --name <vm-name> --resource-group <resource-group-name> --query .identity

It will return something similar to:
{
  "principalId": "0sdfeef-8ad6-4344-808c-b0b0b0b0b07e",
  "tenantId": "29098345-4cc9-4a53-a086-bfefefe89789",
  "type": "SystemAssigned",
  "userAssignedIdentities": null
}

This Microsoft Azure documentation defines the two types of identities as follows:

  There are two types of managed identities:
    System-assigned. Some Azure resources, such as virtual machines, allow you to enable a managed identity directly on the resource. When you enable a system-assigned managed identity:
        A service principal of a special type is created in Azure AD for the identity. The service principal is tied to the lifecycle of that Azure resource. When the Azure resource is deleted, Azure automatically deletes the service principal for you.
        By design, only that Azure resource can use this identity to request tokens from Azure AD.
        You authorize the managed identity to have access to one or more services.
        The name of the system-assigned service principal is always the same as the name of the Azure resource it is created for. For a deployment slot, the name of its system-assigned identity is `<app-name>/slots/<slot-name>`.
    User-assigned. You may also create a managed identity as a standalone Azure resource. You can create a user-assigned managed identity and assign it to one or more Azure Resources. When you enable a user-assigned managed identity:
        A service principal of a special type is created in Azure AD for the identity. The service principal is managed separately from the resources that use it.
        User-assigned identities can be used by multiple resources.
        You authorize the managed identity to have access to one or more services.

Exit status

  • 0 on success

  • 1 on error

Examples

The example below creates an Azure Confidential VM called my-cvm-instance in westus using the image hello-world-boot-disk version 1.0.0. The CVM is attached to the network interface (NIC) called example-nic, which has been previously created using the terraform script below. The NIC is attached to the example-subnet and has been configured with a public IP address (using example-pip). By virtue of being attached to example-subnet, it also uses example-vnet and example-nsg.

$ anjuna-azure-cli instance create \
  --name my-cvm-instance \
  --location westus \
  --image-gallery myimagegallery \
  --image-definition hello-world-boot-disk \
  --image-version 1.0.0 \
  --resource-group myresourcegroup \
  --storage-account mystorageaccount \
  --nics example-nic
$ cat network.tf
# Terraform script for creating a permissive network configuration
# Network Security Group
resource "azurerm_network_security_group" "nsg" {
  name                = "example-nsg"
  location            = example.location
  resource_group_name = example.resource_group

  security_rule {
    name                       = "SSH"
    priority                   = 1001
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }

  security_rule {
    name                       = "HTTP"
    priority                   = 1020
    direction                  = "Outbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "80"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }

  security_rule {
    name                       = "HTTPS"
    priority                   = 1021
    direction                  = "Outbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "443"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }

  security_rule {
    name                        = "ping"
    priority                    = 1050
    direction                   = "Inbound"
    access                      = "Allow"
    protocol                    = "Icmp"
    source_port_range           = "*"
    destination_port_range      = "*"
    source_address_prefix       = "*"
    destination_address_prefix  = "*"
  }

}

# Virtual Network
resource "azurerm_virtual_network" "vnet" {
  name                = "example-network"
  address_space       = ["10.0.0.0/16"]
  location            = example.location
  resource_group_name = example.resource_group
}

# Subnet
resource "azurerm_subnet" "subnet" {
  name                 = "example-subnet"
  resource_group_name  = example.resource_group
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = ["10.0.1.0/24"]
}

# Associate Network Security Group with Subnet
resource "azurerm_subnet_network_security_group_association" "nsg_association" {
  subnet_id                 = azurerm_subnet.subnet.id
  network_security_group_id = azurerm_network_security_group.nsg.id
}

resource "azurerm_public_ip" "public_ip" {
  name                = "example-pip"
  location            = example.location
  resource_group_name = example.resource_group
  allocation_method   = "Dynamic"
}

resource "azurerm_network_interface" "nic" {
  name                = "example-nic"
  location            = example.location
  resource_group_name = example.resource_group

  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.subnet.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.public_ip.id
  }
}