Azure CLI (az) Deployment

Details how to deploy a Trustgrid appliance and related resources using the Azure CLI (az) commands.

Deploying the Trustgrid appliance requires certain resources to be created in Azure before the appliance VM can be deployed. This guide will walk through deploying those prerequisite resources using the Azure CLI (az) commands and then deploying the Trustgrid appliance VM itself.

See AZ CLI Example Walkthrough to see the output of running the below commands, and see how you could create the Azure Appliance Requirements with the az cli in advance if they do not exist.

Prerequisites

In addition to the Azure Appliance Requirements you will need:

Deploy Azure VM as Trustgrid Appliance

First, Ensure you are authenticated to Azure and have selected the desired subscript using az account set --subscription "MySubscription" and ensure all the Azure Appliance Requirements exist before proceeding.

Declare Required Variables

VariableExample Bash CommandDescription
locationexport location="centralus"
  • Change centralus to the desired Azure region for deploying resources
  • See the table of supported regions for locations with the required Trustgrid image published
resourceGroupexport resourceGroup="myResourceGroup"Change myResourceGroup to the name of your target resource group
vNetNameexport vNetName="myVnet"Change myVnet to the name of your target virtual network where the Trustgrid appliance will be connected
outsideSubnetexport outsideSubnet="outside"Change outside to the name of your target WAN subnet. This must exist in the virtual network defined by myVnetName
insideSubnetexport insideSubnet="inside"Change inside to the name of your target LAN subnet. This must exist in the virtual network defined by myVnetName
nameexport name="myNode"Change myNode to the desired name of your Trustgrid appliance virtual machine being created
sizeexport size="Standard_B2s"Change Standard_B2s to the desired VM size. See Instance sizes for supported options and sizing recommendation.
osDiskSizeexport osDiskSize=30Change 30 to the desired size in GB for the OS disk. Minimum recommended is 30GB.

Here are all the commands together without values so that you can copy (a button will appear if you hover in the top right), edit and paste into your terminal.

export location=""
export resourceGroup=""
export vNetName=""
export outsideSubnet=""
export insideSubnet=""
export name=""
export size="Standard_B2s"
export osDiskSize=30

Capture Latest Trustgrid Image ID

export imageID=$(az sig image-version list-community \
  --public-gallery-name trustgrid-45680719-9aa7-43b9-a376-dc03bcfdb0ac \
  --gallery-image-definition trustgrid-node-2204-prod \
  --location $location \
  --output json 2>/dev/null | jq -r 'sort_by(.name)| reverse | .[0].uniqueId')

The above command sets imageID to the latest Trustgrid image ID from the Trustgrid image gallery in the Azure region specified by location.

You can use the command echo $imageID to see the result. it should look something like the below:

sales@Azure:~$ echo $imageID
/CommunityGalleries/trustgrid-45680719-9aa7-43b9-a376-dc03bcfdb0ac/Images/trustgrid-node-2204-prod/Versions/2.17.1

Prepare SSH Key in Azure

After registration, SSH is only accessible via the Trustgrid portal, but Azure requires an SSH key to be associated with the VM to allow SSH access on creation.

There are a few ways to handle this in Azure, but it is important you end up with a variable sshKeyName containing the name of an existing SSH key resource in Azure.

Reference an Existing Azure SSH key resource

If you have an existing SSH key resource in Azure you can export its name as a variable:

export sshKeyName="MyKeyName"

Create new key and Azure SSH key resource

The below example creates a new SSH key pair and uses that to create a new Azure SSH key resource associated with the resource group:

sales@Azure:~$ export sshKeyName="myNewSSHKey"
az sshkey create --name $sshKeyName --resource-group $resourceGroup --location $location
No public key is provided. A key pair is being generated for you.
Private key is saved to "/home/sales/.ssh/1698355223_61326".
Public key is saved to "/home/sales/.ssh/1698355223_61326.pub".
{
 "id": "/subscriptions/#######-####-####-####-#########/resourceGroups/DOCSEXAMPLE/providers/Microsoft.Compute/sshPublicKeys/myNewSSHKey",
 "location": "eastus",
 "name": "myNewSSHKey",
 "publicKey": "ssh-rsa ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6fak3eFAKEKEY8uRMxw+GfkT4xFGkUlFakeyDTNeM59C3z7g1cTtABCDEF12345678910ABCDksVaNfFakeKeyInHere+UoXUQtDZghF38I6t7S58xvZX7Gdr+W4qvlhLP7YYQXdMwFakEyXoS+ZrmdFakeyZZFakeKeyi2V8U1tzlvF5M= generated-by-azure",
 "resourceGroup": "DOCSEXAMPLE",
 "tags": null,
 "type": null
}

Here is the command without output or values

az sshkey create --name $sshKeyName --resource-group $resourceGroup --location $location

Create new Azure SSH Key resource with existing public key

If you have an existing SSH key pair already, you can import the public key to create a new Azure SSH key resource:

sales@Azure:~$ az sshkey create --name $sshKeyName --resource-group $resourceGroup --location $location --public-key "ssh-rsa ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6fak3eFAKEKEY8uRMxw+GfkT4xFGkUlFakeyDTNeM59C3z7g1cTtABCDEF12345678910ABCDksVaNfFakeKeyInHere+UoXUQtDZghF38I6t7S58xvZX7Gdr+W4qvlhLP7YYQXdMwFakEyXoS+ZrmdFakeyZZFakeKeyi2V8U1tzlvF5M= existing-key"
{
  "id": "/subscriptions/#######-####-####-####-#########/resourceGroups/DOCSEXAMPLE/providers/Microsoft.Compute/sshPublicKeys/myNewSSHKey",
  "location": "eastus",
  "name": "myNewSSHKey",
  "publicKey": "ssh-rsa ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6fak3eFAKEKEY8uRMxw+GfkT4xFGkUlFakeyDTNeM59C3z7g1cTtABCDEF12345678910ABCDksVaNfFakeKeyInHere+UoXUQtDZghF38I6t7S58xvZX7Gdr+W4qvlhLP7YYQXdMwFakEyXoS+ZrmdFakeyZZFakeKeyi2V8U1tzlvF5M= existing-key",
  "resourceGroup": "DOCSEXAMPLE",
  "tags": null,
  "type": null
}

Here is the command without output or values

az sshkey create --name $sshKeyName --resource-group $resourceGroup --location $location --public-key ""

Create Network Interfaces

This step will create the network interfaces for the Trustgrid appliance VM to connect to the subnets. As part of this process, we will create these additional resources:

  • Public IP for the outside interface.
  • Network Security Group for the outside interface and an explicit Outbound rule for the required connectivity to the Trustgrid Control Plane. Additional rules will need to be added to allow the node to connect to:
    • Outbound rules for data plane gateway IPs and ports if the appliance is acting as an edge/client device
    • Inbound rules if the appliance will be acting as a data plane or ZTNA gateway
  • Network Security Group for the inside interface with no additional rules. After deployment, this security group could be extended to allow for required communication to internal resources.

Here are the commands without output

az network public-ip create --name $name-pubIP \
  --resource-group $resourceGroup --location $location \
  --sku "Standard" --allocation-method "Static"

az network nsg create --name $name-outside \
  --resource-group $resourceGroup --location $location

az network nsg rule create --name "TGControlPlaneTCP" \
  --nsg-name $name-outside \
  --resource-group $resourceGroup \
  --priority 1000 \
  --access 'Allow' \
  --description 'TCP ports required Trustgrid Control Plane networks' \
  --destination-address-prefixes '35.171.100.16/28' '34.223.12.192/28' \
  --destination-port-ranges 443 8443 \
  --direction 'Outbound' \
  --protocol 'Tcp' 

az network nsg create --name $name-inside \
  --resource-group $resourceGroup --location $location

az network nic create --resource-group $resourceGroup \
 --location $location --name $name-outside \
  --vnet-name $vNetName --subnet $outsideSubnet \
  --accelerated-networking false --public-ip-address $name-pubIP \
  --network-security-group $name-outside
  
az network nic create --resource-group $resourceGroup \
  --location $location --name $name-inside \
  --vnet-name $vNetName --subnet $insideSubnet \
  --accelerated-networking false --ip-forwarding true \
  --network-security-group $name-inside

See the example output for all of the above commands in the AZ CLI Example Walkthrough

Create Trustgrid Appliance VM

Finally, we can deploy the actual VM with the two below commands

This command creates the VM:

az vm create \
  --resource-group $resourceGroup \
  --name $name \
  --image $imageID \
  --accept-term \
  --admin-user 'ubuntu' \
  --assign-identity '[system]' \
  --authentication-type 'ssh' \
  --nics $name-outside $name-inside \
  --nic-delete-option 'Delete' \
  --os-disk-size-gb $osDiskSize \
  --os-disk-delete-option 'Delete' \
  --size $size \
  --ssh-key-name $sshKeyName

This command enables boot diagnostics so that the serial console can be accessed.

az vm boot-diagnostics enable --name $name --resource-group $resourceGroup 

See the example output in the AZ CLI Example Walkthrough

Get MAC Address

To make Console login easier run the below command to get the outside interface’s MAC address:

az network nic show --name $name-outside \
  --resource-group $resourceGroup | jq '.macAddress' | \
   sed 's/-/:/g' | tr 'A-F' 'a-f'

Example output:

sales@Azure:~$ az network nic show --name $name-outside \
  --resource-group $resourceGroup | jq '.macAddress' | \
   sed 's/-/:/g' | tr 'A-F' 'a-f'
"00:0d:3a:9d:a3:2d"

Register the VM

You can now start the console registration process and if you have portal access complete the activation process.

Additional Steps for HA Clusters

If deploying an HA cluster there are additional steps required:

Create Additional VM Appliance

Repeat the steps above to deploy a second VM appliance using different names but in the same resource group and vNet. This will be the secondary node in the HA cluster.

Assuming you still have the same variables declared from the above deployment you will just need to update the $name variable to a new value like shown in the example below.

export name="newName"

Then you can proceed with creating the network interface resources and then create the vm appliance.

Create Role for Route Management

The steps below create a custom role that has permission to manipulate route tables:

First, download the template JSON file to your environment.

curl -o tg-route-role.json https://raw.githubusercontent.com/trustgrid/trustgrid-infra-as-code/main/azure/resources/cluster-role-template/tg-route-role.json

Use the command below to get your subscription ID:

az account show --query id -o tsv

Use an editor such as vi or nano to modify the template and replace the placeholders REPLACE in the template with your subscription ID.

Or, you can perform both the above steps in a single command:

sed -i "s/REPLACE/$(az account show --query id -o tsv)/g" tg-route-role.json

Optionally, you can edit the Name and Description fields as well.

Then create the role using:

az role definition create --role-definition @tg-route-role.json

See AZ CLI Example Walkthrough for output.

Assign Role for Route Management

Finally, we need to assign this role. Below are the commands to perform this process without values for the names of the two VMs (vm1 and vm2) for the resource group.

export vm1=""
export vm2=""
export resourceGroup=""
export roleName="Trustgrid HA Route Role"
export subscription=$(az account show --query id -o tsv)
export vm1ID=$(az vm show --name $vm1 --resource-group $resourceGroup --query 'identity.principalId' -o tsv)
export vm2ID=$(az vm show --name $vm2 --resource-group $resourceGroup --query 'identity.principalId' -o tsv)
export roleID=$(az role definition list --query "[?roleName=='$roleName'].name | [0]" -o tsv)
az role assignment create --role "Trustgrid HA Route Role" --assignee $vm1ID --scope "/subscriptions/$subscription/resourceGroups/$resourceGroup"
az role assignment create --role "Trustgrid HA Route Role" --assignee $vm2ID --scope "/subscriptions/$subscription/resourceGroups/$resourceGroup"

See AZ CLI Example Walkthrough for output.


Example Walkthrough of Azure CLI (az) Deployment

Shows how to create all prerequisite resources and the output of running the deployment commands