src/backends/azure.rs
audience: ai
Azure Virtual Machines backend via ARM. Operator
supplies a service principal
(tenant_id + client_id + client_secret) scoped to a
specific resource group the bridge is permitted to
mutate.
Reports tdx_capable = true when
[azure.tdx_vm_sizes] is non-empty. Azure’s
Confidential Computing v3 family
(Standard_DC*ds_v3, Standard_EC*ds_v3) exposes
Intel TDX; grants with manifest.tdx = Required
provision into those SKUs with
security_profile.security_type = ConfidentialVM.
Other grants use the broader vm_sizes list.
//! Azure Virtual Machines backend.
//!
//! Uses the Azure Resource Manager SDK via
//! `azure_mgmt_compute`. Operator supplies a service
//! principal (tenant id + client id + client secret) or
//! a managed identity, scoped to a resource group the
//! bridge is permitted to mutate.
//!
//! Azure's Confidential Computing v3 instance family
//! (`Standard_DCdsv3_*`, `Standard_ECdsv3_*`) exposes
//! Intel TDX. Operators list TDX-enabled SKUs in
//! `[azure.tdx_vm_sizes]` to mark this backend as
//! `tdx_capable`.
use anyhow::{anyhow, Context};
use async_trait::async_trait;
use coalition_compute::{AlmanacTick, ComputeGrant, UsageMetrics};
use crate::backends::{Backend, Capabilities, ProvisionedInstance};
use crate::config::AzureBootConfig;
use crate::zipnet_io::Envelope;
pub struct AzureBackend {
cfg: AzureBootConfig,
// TODO: cache azure_mgmt_compute Client, resolved per
// subscription + resource group.
}
impl AzureBackend {
pub async fn new(cfg: &AzureBootConfig) -> anyhow::Result<Self> {
Ok(Self { cfg: cfg.clone() })
}
}
#[async_trait]
impl Backend for AzureBackend {
fn name(&self) -> &'static str { "azure" }
async fn capabilities(&self) -> anyhow::Result<Capabilities> {
Ok(Capabilities {
regions: self.cfg.regions.clone(),
tdx_capable: !self.cfg.tdx_vm_sizes.is_empty(),
max_cpu_millicores: u32::MAX,
max_ram_mib: u32::MAX,
})
}
fn can_satisfy(&self, grant: &ComputeGrant<'_>) -> bool {
let _ = grant;
true
}
async fn provision(
&self,
grant: &ComputeGrant<'_>,
envelope: &Envelope,
) -> anyhow::Result<ProvisionedInstance> {
// Real flow (ARM API):
// 1. Resolve target region.
// 2. Pick VM SKU. TDX grants → tdx_vm_sizes.
// 3. Create a per-grant ssh public key resource.
// 4. virtual_machines.create_or_update({
// location, hardware_profile: {vm_size},
// storage_profile: {image_reference, os_disk},
// os_profile: {admin_username, linux_configuration.ssh.public_keys},
// network_profile,
// security_profile: {security_type: ConfidentialVM, ...} if TDX,
// })
// 5. Poll provisioning_state == Succeeded.
// 6. Read the allocated public IP, return ProvisionedInstance.
let _ = (grant, envelope);
Err(anyhow!(
"AzureBackend::provision is a prototype stub; implement via \
azure_mgmt_compute::virtual_machines::Client"
))
}
async fn watch_until_exit(
&self,
instance: &ProvisionedInstance,
valid_to: AlmanacTick,
) -> anyhow::Result<UsageMetrics> {
let _ = (instance, valid_to);
Err(anyhow!(
"AzureBackend::watch_until_exit is a prototype stub"
))
}
async fn terminate(&self, instance: &ProvisionedInstance) -> anyhow::Result<()> {
let _ = instance;
Ok(())
}
}
Up: compute-bridge → backends.