Skip to main content

Workload Contract

Polaris protects one customer workload per confidential VM. The deployment pipeline makes specific assumptions about that workload. Most are deliberate security posture; all of them are enforced whether or not your workload agrees. Read this before packaging an application for Polaris.

The contract in one paragraph

A Polaris workload is a single linux/amd64 Docker container, serving plain HTTP on one port behind the Polaris proxy, stateless, configured via environment variables, with no internet egress by default, no access to cloud instance credentials, and no persistent storage. If enforcement mode is the goal, it should also be exec-quiet: no shelling out, no cron, no self-modifying files, no per-request helper processes.

Packaging and deployment

  • One container. The pipeline runs exactly one workload container (client-workload). No sidecars, no compose files, no init containers. Bundle supporting processes into the image only if you accept the attestation consequences below.
  • linux/amd64. CVMs run AMD SEV-SNP or Intel TDX hardware; arm64-only images do not run.
  • Prebuilt image or local build. The deployment config takes either workload.image (a prebuilt reference, deployed as-is, digest pinned at deploy time) or workload.dir (a Dockerfile directory, built and pushed by the deploy pipeline). They are mutually exclusive.
  • Image immutability. The L2 attestation layer pins the exact image digest in the Golden Baseline. Re-pushing a tag or self-updating in place flips L2 to a hard fail. This is the tamper check working as designed: ship changes as a new deployment, not a mutated tag.

Network

  • Ingress is HTTPS through the proxy only. The workload publishes no ports. Clients reach it via the Polaris proxy on 443, which forwards to http://client-workload:<workload.port>. The workload serves plain HTTP on that one port; TLS termination, raw TCP/UDP, and multi-port layouts are not supported. WebSocket forwarding is available via configuration.
  • Egress is deny-by-default. The VPC allows only what Polaris itself needs (registry and cloud API endpoints). A workload that calls external APIs will see opaque timeouts unless those endpoints are explicitly allowed via network.allowed_egress_cidrs (HTTPS only, GCP only today).
  • No cloud instance credentials, ever. The metadata server is firewalled off for the workload on every deployment. Application Default Credentials and instance-identity tokens do not work from the workload container, by design: a compromised workload must not be able to steal the CVM's service-account identity and bypass attestation-gated KMS. If your application "just needs ADC", it needs redesigning for Polaris.

Configuration and secrets

  • Environment variables come from workload.env in the deployment config. Values are flags and non-secret configuration only: they pass through cloud-init user-data (readable by anyone with instance-read permission on the project) and live on the CVM disk. Multi-line values are not supported.
  • Secrets belong in the attestation-gated KMS path — that is the product. Do not put API keys in workload.env.

Runtime behavior and attestation

  • Stateless. No volumes are mounted; anything written inside the container is lost on redeploy. Databases and queues belong outside the TEE boundary or in a future persistent-storage design.
  • Start order. The workload starts before the Polaris proxy during boot. It must tolerate running while attestation is still coming up.
  • Crash loops are expensive. The container restarts forever (unless-stopped), and every restart feeds new process activity into the L3 behavioral layer, preventing IMA/eBPF autolearn from converging. The deploy pipeline checks workload health after deployment and warns if it is crash-looping.
  • Exec-quiet matters for enforcement. IMA measures every executable; eBPF profiles every process. Autolearn needs roughly 20 observed cycles plus 10 consecutive quiet ones (about 45–60 minutes at the default 60-second cadence) to converge. Workloads that spawn processes per request, run cron jobs, or JIT-write executables keep L2/L3 at flag/alert permanently and cannot survive reject_unknown/revoke enforcement policies.
  • Fresh deployments start at L2 flag / L3 alert. That is the expected advisory state until autolearn converges against a healthy, quiet workload — not a fault.