Skip to main content

Configure File Upload Capture (Microsoft Azure)

File Upload Capture archives a copy of every file your employees upload through the browser. Each file is encrypted on the device with your public key before it leaves the browser, and written directly to a Blob Storage container in your own Azure subscription. Anzenna mediates the upload but never holds the private key and never sees the file contents.

On Azure, Anzenna authenticates to your storage through Entra workload identity federation: you consent a multi-tenant Anzenna app into your tenant and grant it narrowly-scoped RBAC on one container. No keys, secrets, or SAS tokens are ever exchanged, and you can revoke access at any time.

Prerequisites

  • File Upload Capture must be turned on for your tenant first — contact Anzenna support at support@anzenna.ai before you begin.

  • An active Microsoft Azure subscription — this is where the Blob Storage account you create below lives. Every Azure subscription comes with a Microsoft Entra ID tenant (your organization's directory), and that tenant is what the "Entra" steps below act on.

  • You'll consent the Anzenna Application (client) ID into your tenant in Part 2:

    245121cf-892e-4210-a296-88850ee586d3

    This is the same app for every customer — Anzenna authenticates into your tenant through it, and it requests no directory permissions.

  • You need an account with Application Administrator (or Global Administrator) in that Entra tenant to consent the app, and Owner or User Access Administrator on the subscription to create the role assignment.

Anzenna cannot recover your data

The private key never leaves your custody. If every copy is lost, every file encrypted to the matching public key is unrecoverable — there is no Anzenna-side backdoor. Store the private key in a vetted password manager or HSM before registering the public key in Anzenna.

Step-by-Step Instructions

Part 1: Generate a recipient keypair

The extension encrypts each captured upload — using the

age encryption format

— to one or more recipient public keys that you register with Anzenna. The matching private keys stay with you and are used to decrypt archived files during an investigation.

  1. Install the age CLI (Homebrew: brew install age; apt: apt install age).

  2. Generate the keypair to a protected file:

    age-keygen -o anzenna-upload-archive.identity

    The command prints the public key on stdout; the file contains the matching private key prefixed with AGE-SECRET-KEY-1….

  3. Move anzenna-upload-archive.identity into a password manager entry or vault. Do not check it into source control or share it over chat.

  4. Copy the public key (the age1… line printed during generation). That is what you will paste into Anzenna in Part 3.

Part 2: Provision the destination in Azure

You'll consent the Anzenna app into your tenant, provision a hardened storage account and a private container, and grant the app write access scoped to that one container.

Prefer infrastructure-as-code?

Rather provision with Terraform? Use the Provision with Terraform (Microsoft Azure) guide instead — it creates the same Key Vault key, storage account, container, and RBAC grant in one terraform apply. Then come back and continue at Part 3 below.

This creates a service principal — the local identity your RBAC grant in 2c will target. Run as an Application Administrator / Global Admin of your tenant:

az login --tenant <your-tenant-id>
az ad sp create --id 245121cf-892e-4210-a296-88850ee586d3

# verify the service principal now exists in your tenant
az ad sp show --id 245121cf-892e-4210-a296-88850ee586d3 --query "{name:displayName,id:id}" -o table
Do not use the browser "Grant admin consent" URL for this app

The /adminconsent endpoint returns AADSTS1003031: Misconfigured required resource access. That is expected, not a bug — the Anzenna app requests zero directory or API permissions, so the consent screen has nothing to approve and refuses. az ad sp create provisions the service principal directly, which is the correct path for a permission-less workload app. A side benefit: Anzenna gets no access to your directory — only the container-scoped storage RBAC you grant in 2c.

2b. Create the storage account and container

Create a storage account with this security posture, then a single private container for the archive. The portal path is Storage accounts > Create.

  • Require secure transfer (HTTPS only) and minimum TLS 1.2.

  • No anonymous / public blob access on the account and the container.

  • Disable shared-key access (set "Allow storage account key access" to Disabled). This forces Entra-only auth — no long-lived account keys exist to leak.

  • (Optional hardening) a customer-managed key (Key Vault) with infrastructure encryption. Not required for archiving to work — Azure already encrypts every blob at rest with Microsoft-managed keys by default; add a CMK only if your key-custody or data-residency policy calls for it.

  • Versioning and blob soft delete on; set a lifecycle expiry that matches your retention policy.

Azure storage account settings with Secure transfer required Enabled, Allow storage account key access Disabled, and Minimum TLS version 1.2 Azure storage account Encryption tab with Customer-managed keys selected and infrastructure encryption enabled

After the account is created, open it and go to Data storage > Containers > + Container. Name it uploads, set Public access level to Private, and create it.

Azure storage account Containers list showing the uploads container with Private access level

2c. Grant the Anzenna app write access (RBAC)

Assign Storage Blob Data Contributor to the consented Anzenna app, scoped to the container — not the account or subscription. This is least privilege: the app can write blobs to this one container and nothing else.

Open the container, go to Access Control (IAM) > Add > Add role assignment, pick Storage Blob Data Contributor, then on the Members tab click Select members and search for Anzenna File Archival (or paste the client ID 245121cf-892e-4210-a296-88850ee586d3). Select it and finish on Review + assign.

Azure Add role assignment on the uploads container, Members tab with the Anzenna File Archival app selected for the Storage Blob Data Contributor role
Or with the CLI:
# the app's service principal object ID in YOUR tenant
SP_OID=$(az ad sp show --id 245121cf-892e-4210-a296-88850ee586d3 --query id -o tsv)

az role assignment create \
--assignee-object-id "$SP_OID" \
--assignee-principal-type ServicePrincipal \
--role "Storage Blob Data Contributor" \
--scope "/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<account>/blobServices/default/containers/uploads"

Part 3: Register everything in Anzenna

  1. Log into

    Anzenna

    .

  2. Navigate to Settings > Preferences > Browser Extension.

  3. Find the File Upload Capture section.

3a. Add the recipient public key

  1. Click Add new public key.

  2. Acknowledge the private-key custody warning.

  3. Paste the public key from Part 1 (starts with age1…) and click Add key.

  4. Repeat for any additional recipients. Each archived file is a single blob — adding more recipients just means more private keys can decrypt that one blob, which is useful as a break-glass spare.

3b. Add the archive destination

  1. Click Add destination and choose Azure Blob Storage as the provider.

  2. Fill in the fields with the values from provisioning:

    • Storage account — your storage account name from 2b (e.g. anzupexample…), the name only, not a URL.

    • Container — the container you created in 2b, uploads.

    • Tenant ID — the Entra tenant that owns the storage account (a GUID). Get it with az account show --query tenantId -o tsv, or copy it from Microsoft Entra ID > Overview in the Azure portal.

    • Object key prefix — optional. Leave blank to write at the container root, or set a prefix (e.g. archive/) to nest archived blobs under it.

  3. Click Save destination.

  4. Click Test destination. Anzenna authenticates with its federated token and writes a small test blob to the container. A green Test upload succeeded confirms the consent and RBAC grant are wired correctly. If it fails, the error names the specific Azure denial to fix.

    Anzenna File Upload Capture settings showing the configured Azure Blob Storage archive destination
No credential is stored

Unlike a SAS token or account key, nothing secret is saved here. Anzenna writes through the federated app token — the only thing standing between Anzenna and your data is the container-scoped RBAC grant, which you control and can revoke at any time.

3c. Turn capture on

  1. Flip the File Upload Capture toggle at the top of the section to on.

  2. Save the Browser Extension settings.

Part 4: Verify capture end-to-end

  1. Pick a test device that has the Anzenna extension installed and is enrolled in the Anzenna agent.

  2. Confirm the device is currently considered managed. Upload credentials only mint for devices that have recently checked in with the agent. There is no self-serve way to check this today — contact Anzenna support at support@anzenna.ai and ask them to confirm the device shows a recent check-in before you test.

  3. On that device, upload a small test file to any web destination from the browser (e.g. attach a file to a Gmail draft).

  4. In the Azure portal, open the container and confirm a new blob appears within ~1 minute. Archived files use the .anzu extension.

    Azure container blob list showing a new .anzu archived upload object
  5. Download the blob and decrypt it (next section) to confirm the round trip works before relying on it during an investigation.

Part 5: Decrypt an archived file

Each archived .anzu blob is a small envelope: a 10-byte fixed header, a plaintext JSON manifest (filename, SHA-256, upload destination, timestamp, person ID, recipient list), then the age-encrypted file body. Decryption happens on your workstation with the matching private key — Anzenna is not in the path.

Anzenna ships a small Go CLI, anzenna-upload-decrypt, that reads the envelope, prints the manifest, and writes the decrypted file. Contact Anzenna support at support@anzenna.ai for the binary. The wire format is also documented (4-byte magic ANZU, 2-byte version, 4-byte big-endian manifest length, JSON manifest, then a standard age v1 ciphertext) so any age-compatible tool can decrypt the body once the header is stripped.

  1. Download the .anzu blob from the container to the workstation that holds the private key.

  2. Print the manifest to confirm what the file is and when it was captured:

    ./anzenna-upload-decrypt -i envelope.anzu --print-manifest
  3. Decrypt it:

    ./anzenna-upload-decrypt -i envelope.anzu -keyfile anzenna-upload-archive.identity

    The plaintext is written to ./<filename-from-manifest> by default; override with -o.

  4. Compare the SHA-256 of the decrypted output against the sha256 field in the manifest to confirm the file matches what was uploaded.


Need help? Contact Anzenna Support at support@anzenna.ai for assistance.