Skip to main content

Azure reference

Facts to look up while deploying and running Polaris on Azure. For why Azure works the way it does, see Polaris on Azure.

What Polaris offers on Azure today​

CapabilityOn Azure
AMD SEV-SNP confidential VMs, DCas_v6 and ECas_v6 sizesAvailable
Intel TDX confidential VMs, DCes_v6 and ECes_v6 sizesAvailable. The Policy Manager records the TDX launch measurement without checking it
Confidential NVIDIA H100 on Standard_NCC40ads_H100_v5Only with --local-build and a VM image you bake, because the release manifest pins no GPU build of the proxy
Attestation of image, runtime and kernel, with the key's role assignment removed when a layer you enforce failsAvailable. The tooling deploys every layer in advise, and promote moves layers to enforce over SSH through the workload VM
Status routes and incident records readable through the endpointAvailable
Limiting inbound HTTPS to chosen address rangesAvailable, and on by default
Deployment from the Azure MarketplaceAvailable as a private plan
A route for the workload to use its attestation-gated keyNot yet available
Ending key access when the Policy Manager stops or hangsNot yet available
Keeping what the Policy Manager learned, and the promote settings, across a restart or replacementAvailable, on the Policy Manager's state disk, while the baseline is unchanged
Reading the Policy Manager's verdicts with statusAvailable, over SSH through the workload VM
Setting enforcement, or pinning the Policy Manager, from the deployment configNot yet available
More than one workload VMNot through the tooling. The Terraform module and the Marketplace offer accept more
Health telemetry from the Policy Manager over OpenTelemetryAvailable, with the --otel-* flags

Regions and VM sizes​

Polaris runs in any Azure region that offers the confidential VM size you choose. The tooling does not check the region itself. The default is eastus.

The CPU TEE is set by tee.cpu, and the Terraform module checks the size family against it before it creates anything.

tee.cpuSizes the module acceptsDefault for both VMs
sev-snpAMD sizes whose name has as_v or ads_v in it, such as Standard_DC2as_v6 or Standard_EC2as_v6Standard_DC2as_v6
tdxIntel sizes whose name has es_v or eds_v in it, such as Standard_DC2es_v6Standard_DC2es_v6

With tee.gpu: nvidia-h100, the workload VM must be Standard_NCC40ads_H100_v5, tee.cpu must be sev-snp, and compute.cvm_image_id must name a VM image that carries the NVIDIA driver. The Policy Manager stays on a CPU size.

Use the v6 sizes. The Policy Manager refuses AMD firmware below the levels in AMD bulletin AMD-SB-3020, and the module notes that Azure's Milan DCadsv5 fleet reports a lower level. The Terraform module can lower the floor, but the deployment config has no key for it.

VMConfig key
Workload VMcompute.cvm_machine_type
Policy Manager VMcompute.pm_machine_type

What a deployment creates​

Everything below is created in the resource group the deployment owns, <name>-rg by default, where <name> is the deployment name. destroy removes it, except where noted.

Network

  • A virtual network, <name>-vnet, 10.0.0.0/16, with a workload subnet <name>-sub-workload, 10.0.1.0/24, and a control subnet <name>-sub-control, 10.0.2.0/24, for the Policy Manager. Both subnets have a Microsoft.KeyVault service endpoint, so the VMs reach Key Vault through the virtual network.
  • A static public IP for the workload VM, <name>-cvm-0-pip.
  • A NAT gateway, <name>-nat, with its own public IP, <name>-nat-pip, for the Policy Manager's outbound traffic. The Policy Manager has no public IP.
  • Two network security groups, <name>-nsg-workload and <name>-nsg-control, attached to each VM's network interface. Their rules are in Where a deployment connects.
  • Two network interfaces, <name>-cvm-0-nic and <name>-pm-nic. Both take a dynamic private address. The Policy Manager's address is somewhere in 10.0.2.0/24.

Compute

  • Two confidential VMs, <name>-cvm-0 and <name>-pm, each with vTPM and Secure Boot on, a Premium_LRS OS disk with the VM guest state encrypted, boot diagnostics in managed storage, and a system-assigned managed identity. The admin user is azureuser, with SSH key login only.
  • Both boot Canonical's Ubuntu 22.04 confidential VM image, offer 0001-com-ubuntu-confidential-vm-jammy, SKU 22_04-lts-cvm. The workload VM boots the exact version latest names when deploy runs, so a new version replaces it on the next deploy. The Policy Manager boots latest as it is when the VM is created. With compute.cvm_image_id set, the workload VM boots that image instead.
  • A managed disk for the Policy Manager's state, <name>-pm-state, StandardSSD_LRS, 8 GB, attached to the Policy Manager VM at LUN 0. It is a disk of its own, so it outlives the VM, and a replacement Policy Manager attaches the same disk. It holds the Policy Manager's issuer keys, its record of the workload VMs, what it learned and the promote settings. destroy deletes it with the resource group.

Key Vault

  • A Key Vault named <name>-kv-<6 random characters>, on the premium SKU, with Azure RBAC authorization, purge protection on and a 90-day soft-delete retention. Its firewall denies by default and admits the two subnets and the public address of the machine that runs deploy.
  • The workload key, <name>-workload-key, an RSA-HSM key of 3072 bits, allowed to encrypt, decrypt, sign, verify, wrapKey and unwrapKey.
  • Secrets that the VMs read at boot: polaris-management-token, polaris-readonly-token, polaris-workload-token, polaris-sentinel-auth-token and polaris-registry-password.

destroy deletes the vault, and Azure keeps it and the key soft-deleted for the 90-day retention window. Purge protection stops anyone purging them sooner.

Identity

  • A custom role, <name>-pm-vm-reader, that allows only Microsoft.Compute/virtualMachines/read, assignable within the resource group.
  • The role assignments in Identities and role assignments.

Created, and kept by destroy

  • An Azure Container Registry on the Basic SKU, in a resource group of its own, <registry>-rg. Its name is cloud.azure.acr_name, or polaris followed by the first 10 hex characters of the SHA-256 of the subscription ID, so every deployment in a subscription shares it unless you name another. The tooling turns on the registry's admin user and uses its password both to push images and for the VMs to pull them.

Identities and role assignments​

WhoRoleScopeMade by
The identity that runs deployKey Vault Crypto OfficerThe vaultTerraform, so it can create the key
The identity that runs deployKey Vault Secrets OfficerThe vaultTerraform, so it can write the secrets
Workload VM identityKey Vault Secrets UserThe vaultTerraform, so the VM can read its tokens at boot
Policy Manager identityKey Vault Secrets UserThe vaultTerraform, for the same reason
Policy Manager identityRole Based Access Control Administrator, with a conditionThe workload key onlyTerraform
Policy Manager identity<name>-pm-vm-readerThe resource groupTerraform
Workload VM identityKey Vault Crypto UserThe workload key onlyThe Policy Manager, while the VM passes

The two assignments to the deploying identity stay in place for the life of the deployment. Key Vault Crypto Officer lets that identity use the workload key directly.

The Policy Manager's access to the key​

The Policy Manager holds Role Based Access Control Administrator on the workload key alone, not on the vault. A condition on that assignment lets it create and delete only assignments of one role, Key Vault Crypto User (role definition 12338af0-0e69-4776-bea7-57ae8d297424). A create must also name one of this deployment's workload VM identities, the same list the Policy Manager is started with in PM_AZURE_ALLOWED_PRINCIPAL_IDS. A delete is limited by role only, so when it starts the Policy Manager can delete a stray Polaris assignment whatever principal it names.

When a workload VM passes, the Policy Manager assigns Key Vault Crypto User on the key to that VM's managed identity. The assignment's name is derived from the VM's cvm_id, and its description is polaris:cvm=<cvm_id>. The Policy Manager deletes the assignment when a layer you enforce fails, or when the VM has not passed within the grant lifetime, attestation.grant_ttl. Azure gives a role assignment no expiry of its own, so the lifetime is kept by the Policy Manager. When it starts, the Policy Manager deletes Polaris assignments on the key that it is not tracking.

The Policy Manager's other roles​

  • Key Vault Secrets User on the vault, to read its tokens at boot. The workload key is a key, not a secret, so this role does not reach it.
  • <name>-pm-vm-reader on the resource group. The Policy Manager looks up which managed identities Azure assigned to the VM named in the hardware evidence, through Azure Resource Graph, and requires the identity token the VM presented to be one of them.

Where a deployment connects​

FromToFor
The machine that runs deployAzure APIs in your subscriptionCreating and checking the deployment
The machine that runs deployapi.ipify.orgFinding its own public address, which the Key Vault firewall and, by default, the workload endpoint admit
The machine that runs deployThe Key Vault data planeCreating the key and writing the secrets
The machine that runs deployghcr.io, Fr0ntierX's container registryCopying the Polaris images into your registry, pinned by digest
Workload VMAny address on the internet, on ports 443 and 80Pulling images, package installs at first boot, and your workload's outbound traffic
Workload VMThe ranges in network.allowed_egress_cidrs, on any portYour workload's other outbound traffic
Workload VMThe control subnet, on 443 and on 8443Reports to the Policy Manager, and the operator tunnel to it
Policy ManagerAny address on the internet, on ports 443 and 80, through the NAT gatewayAzure APIs, AMD's Key Distribution Service, Microsoft's token signing keys and the registry

Inbound, the workload VM accepts HTTPS on port 443 from the ranges in network.workload_ingress_cidrs, or from the public address of the machine that ran deploy when that list is empty. It accepts SSH on port 22 from cloud.azure.operator_ssh_cidrs, and from nowhere while that list is empty. The Policy Manager accepts ports 443 and 8443 from the workload subnet and refuses them from the rest of the virtual network. SSH to it from inside the virtual network goes through Azure's default rule, which is how the tooling reaches it through the workload VM.

Every other destination on the internet is denied in both directions. Traffic inside the virtual network, Azure DNS and the instance metadata service are outside the rule that denies the internet.

Neither VM sends telemetry. The deployment creates no role assignment for anyone outside your tenant.

Permissions​

The identity that deploys​

The identity that runs deploy and destroy needs to create and delete, in your subscription:

AreaWhat it createsUsed for
Resource groupsThe deployment's resource group and the registry'sHolding everything else
ComputeVirtual machines and their disks, and reading their boot diagnosticsThe two VMs, and reading each VM's SSH host keys from its console
NetworkVirtual networks, subnets with service endpoints, network security groups and rules, public IPs, NAT gateways and network interfacesThe network
Key VaultVaults, and through the role assignments below, keys and secretsThe vault, the workload key and the tokens
AuthorizationRole definitions and role assignments, so Microsoft.Authorization/roleDefinitions/write and Microsoft.Authorization/roleAssignments/write, and the matching deletesThe custom role and the six assignments in Identities and role assignments
Container RegistryRegistries, turning on the admin user, reading its credentials, and pushing imagesCopying the Polaris images in, and the VMs' pulls

The deployment's resource group does not exist until deploy creates it, so the role assignments have to be allowed at the subscription. The module's notes call for Owner or User Access Administrator at subscription scope, and say that Contributor is not enough, because the deployment creates a role definition and role assignments.

An identity that can create role assignments can give any identity any role, so treat the deploying identity as an administrator of the subscription.

What the deployment does not need​

The deployment creates its own Key Vault and key, so there is no existing key to grant access to, and no key policy to edit.

Deployment config keys​

The keys specific to Azure, under cloud.azure:

KeyRequiredDefaultMeaning
subscription_idYesThe subscription to deploy into. The tooling switches the Azure CLI to it
tenant_idNofrom az account showThe Microsoft Entra tenant. The Policy Manager checks it in every identity token
resource_groupNo<name>-rgThe resource group the deployment creates and owns
locationNoeastusThe Azure region
ssh_public_key_fileNo~/.ssh/id_rsa.pubThe public key installed for azureuser on both VMs
ssh_private_keyNossh_public_key_file without .pubThe private half, used to reach the Policy Manager through the workload VM
operator_ssh_cidrsNoemptyAddress ranges allowed to SSH to the workload VM. While it is empty, SSH opens to nobody, deploy skips pinning the SSH host keys and capturing the Policy Manager's identity record, and status and promote cannot reach the Policy Manager
acr_nameNoderived from the subscription IDThe container registry to create or reuse
id_key_digestsNothe one Microsoft digest the tooling knowsThe paravisor launch authorities the Policy Manager accepts on SEV-SNP, as 96 hex characters each. Append a new one rather than replacing the list

The module rejects, in operator_ssh_cidrs, network.workload_ingress_cidrs and network.allowed_egress_cidrs, any entry that is not an address range with a prefix, and any /0 or /1 range.

Keys shared with the other clouds that apply on Azure:

KeyDefaultMeaning on Azure
metadata.nameThe deployment name. On Azure, a lowercase letter, then lowercase letters, digits or hyphens, 12 characters at most, because the Key Vault name is built from it
tee.cpusev-snp or tdx
tee.gpunonenone or nvidia-h100
compute.cvm_machine_typeStandard_DC2as_v6, or Standard_DC2es_v6 for tdxWorkload VM size. See Regions and VM sizes
compute.pm_machine_typeStandard_DC2as_v6, or Standard_DC2es_v6 for tdxPolicy Manager VM size
compute.cvm_image_idA Compute Gallery image or image version for the workload VM. Required with tee.gpu: nvidia-h100
network.workload_ingress_cidrsthe deploying machine's public addressRanges allowed to reach the endpoint on port 443
network.allowed_egress_cidrsemptyExtra ranges both VMs may reach, on any port and protocol
features.ebpffalseRuns the Sentinel agent on the workload VM, which collects runtime and kernel evidence. Set it to true for runtime and kernel attestation
features.imafalseHas no effect on Azure. The Sentinel collects the kernel's measurements of every executable whenever it runs
features.attestation_modefullHas no effect on the Terraform the Azure deploy writes, which always deploys full. Leave it at full
workload.imageA prebuilt workload image. The VMs log in to the deployment's container registry, so an image there needs nothing else. An image elsewhere has to be public
workload.dirIn place of workload.image, a folder with a Dockerfile, relative to the top folder of the tooling. deploy builds it for linux/amd64 and pushes it to the deployment's registry
workload.port3000The port your workload listens on, over plain HTTP
workload.envemptyEnvironment variables for the workload. They are written into the VM's custom data, so keep secrets out
workload.resources.cpus, workload.resources.memory_mbno limitHard limits for the workload container
workload.security.read_onlyfalseRuns the workload with a read-only filesystem and a small /tmp
workload.security.capabilitiesemptyLinux capabilities to add back to the workload, which otherwise runs with none
license.fileA license file for a direct contract. See Licensing
polaris.docker_repopolaris-dockerThe path the Polaris images are copied to inside the registry
attestation.report_interval30Seconds between evidence reports, 5 to 300
attestation.deadman_interval240Seconds without a fresh report before the Policy Manager deletes a VM's role assignment, 30 or more
attestation.grant_ttl300Lifetime of a role assignment in seconds, 60 or more, renewed by each passing report. The module sets 300 because a new assignment can take up to about five minutes to take effect on the Key Vault data plane
attestation.autolearn_window10mHow long the learners must watch before they can finish
attestation.promotion_window1dHow long a layer must be clean under advise before the Policy Manager lets it enforce
attestation.trust_domainpolaris.<name>The name the Policy Manager writes into every certificate it issues. It is stored on the Policy Manager's state disk, so set it before the first deploy, if at all, and never change it afterwards
attestation.deployment_idderived from the trust domainA UUID naming the deployment in the Policy Manager's record of its workload VMs. The Policy Manager refuses to start when its state disk holds a record under another ID, so never change it, or the trust domain it is derived from, once the deployment exists

compute.cvm_count and kms.azure are accepted by the config schema and not read on Azure. A deployment has one workload VM, and the vault and key names come from the deployment name.

Commands​

All but watch and set-workload take --config <file>.

CommandWhat it does on Azure
deployCreates the deployment, or updates it. A VM is replaced when its rendered boot configuration changes. A new workload VM has a new managed identity, which the Policy Manager's boot configuration names, so it replaces the Policy Manager too. A new version of Canonical's image replaces the workload VM, and so the Policy Manager, on a plain run. --force-replace recreates both VMs even when nothing changed
statusLists the VMs in the deployment's resource group whose names start with <name>-, with size, power state and addresses, then reads each workload VM's verdict, the license state and how far learning has got from the Policy Manager, over SSH through the workload VM. Without cloud.azure.operator_ssh_cidrs and the pinned host keys, it says why it did not read the Policy Manager
promoteMoves enforcement layers between advise, enforce and off, in place, over SSH through the workload VM. Needs cloud.azure.operator_ssh_cidrs with your address and the pinned host keys. --layers takes a comma-separated list of l2, l3, l31, ima_boot, l3_syscalls, l3_binaries and l3_network, and defaults to l31. --mode defaults to enforce. It refuses to enforce a layer whose allowlist is still empty, and only warns for l3_binaries, unless you pass --force. The Policy Manager also refuses enforce for a layer that has not been clean under advise for the promotion window. promote reads the settings back to confirm them
watchShows each layer's status and how far learning has got, through the endpoint. Takes --endpoint https://<address> and --token <token>, and works with the read-only token
set-workloadPoints the running deployment at a new workload image, pinned by digest, through the endpoint. Takes --endpoint, --token and --image
destroyRuns terraform destroy, which removes the resource group and everything in it

deploy also takes --otel-endpoint, --otel-protocol, --otel-headers, --otel-temporality and --otel-egress-cidrs on Azure, which send the Policy Manager's health metrics to an OpenTelemetry collector. They are off by default, and nothing exports from the workload VM.

The Azure deployment leaves ima_boot unset, so it follows l2. The Policy Manager keeps the settings promote makes, and everything it learned, on its state disk while the baseline file stays the same. A deploy that changes the baseline, such as a new workload image digest, a new workload port or a new VM image, returns every layer to the settings in the baseline file and starts learning again.

Routes on the endpoint​

The proxy on the workload VM serves these on port 443.

RouteTokenReturns
/polaris-container/healthnone{"status":"ok"} while the proxy runs
/polaris-container/readynoneWhether the proxy is serving workload traffic, as ready and gate
/polaris-container/attestationnoneThe hardware evidence, for a client to check
/polaris-container/tls-infononeThe hash of the proxy's TLS public key
/polaris-container/attestation-statusnoneThe latest verdict, with a status for each layer and checked_at
/polaris-container/attestation-statusread-onlyThe same, with the reason for a failure and the alerts
/management/statusread-onlyThe Policy Manager's status for each workload VM, including its cvm_id
/management/profiles/learn, /management/ima/learn and /management/kernel/learnread-onlyEach learner's progress
/management/incidents/<cvm_id> and /management/incidents/<cvm_id>/reportread-onlyThe VM's recent incidents, as JSON or as a plain-text report
/management/checks/<cvm_id>read-onlyThe latest checks, one by one
/management/history/<cvm_id>read-onlyRecent verdicts
/management/workloadworkload or managementThe workload image the deployment should run. set-workload posts to it

The read-only token answers GET requests only. The management token answers every method on /management/.

The workload has no key routes on Azure. See Use the gated key from your workload.

Files the tooling keeps​

Run every command from the copy of the tooling that deployed, since it holds these files. The state, the tfvars file and the token files carry the deployment's tokens in plain text, and the tfvars file also carries the registry's admin password, so keep the folder encrypted and access-controlled.

FileHoldsRemoved by destroy
terraform/deploy/azure/terraform-<name>.tfstateThe Terraform state, including every tokenNo
terraform/deploy/azure/terraform-<name>.tfvarsThe deployment's resolved configuration, including the management and read-only tokens and the registry passwordNo
terraform/modules/azure/terraform-<name>.tokenThe management tokenYes
terraform/modules/azure/terraform-<name>.readonly.tokenThe read-only token, used by watch and the management routesYes
terraform/deploy/azure/terraform-<name>.known_hostsThe pinned SSH host keys of both VMs, filed under each VM's vmUniqueIdNo
terraform/deploy/azure/pm-identity-<name>.jsonThe record Polaris Desktop checks the Policy Manager againstNo

The workload-swap token is generated by Terraform and is not written to a file. Read it from the state, or use the management token in its place:

cd terraform/deploy/azure
terraform output -state=terraform-<name>.tfstate -raw workload_token

The Azure Marketplace offer​

Polaris is listed on the Azure Marketplace as an Azure Application, a solution template, on a private plan. Only the tenants and subscriptions Fr0ntierX adds to the plan's audience can deploy it, and the offer is not shown publicly. Billing is under your contract, not through the Marketplace.

The template creates the same resources as the Terraform module, into a resource group you choose, with these differences:

  • It creates no resource group of its own.
  • It creates the key and secrets through Azure Resource Manager, so the deploying identity gets no Key Vault Crypto Officer or Secrets Officer assignment, and the vault firewall admits only the two subnets and any addresses you list.
  • The Policy Manager has a fixed private address, 10.0.2.4.
  • The VMs boot a Polaris image with the proxy, Policy Manager and Sentinel built in, so only your workload image is pulled at boot.
  • The image carries no license. Paste the license file Fr0ntierX sent you into the form's License step. See Licensing.
  • The form asks for the number of workload VMs, the CPU TEE and sizes, the client ranges allowed on 443, the SSH ranges, whether to run the Sentinel, an enforcement mode of alert or enforce, and an optional registry for a private workload image.

The identity that deploys needs to create a role definition and role assignments in the resource group, so Owner or User Access Administrator there.

After a deployment, the template's outputs include the endpoint and the az keyvault secret show commands for the tokens. To run them from outside the virtual network, your address has to be in the template's keyVaultAllowedIps, since the vault firewall refuses any other, and your identity needs a Key Vault role that can read secrets, since the template assigns none to you.