Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 53 additions & 2 deletions docs/user_guide/model_repository.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!--
# Copyright 2018-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# Copyright 2018-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
Expand Down Expand Up @@ -175,7 +175,9 @@ For a model repository residing in Azure Storage, the repository path must be pr
$ tritonserver --model-repository=as://account_name/container_name/path/to/model/repository ...
```

When using Azure Storage, you must set the `AZURE_STORAGE_ACCOUNT` and `AZURE_STORAGE_KEY` environment variables to an account that has access to the Azure Storage repository.
##### Shared Key Authentication (Default)

When using Azure Storage with shared key authentication, you must set the `AZURE_STORAGE_ACCOUNT` and `AZURE_STORAGE_KEY` environment variables to an account that has access to the Azure Storage repository.

If you don't know your `AZURE_STORAGE_KEY` and have your Azure CLI correctly configured, here's an example of how to find a key corresponding to your `AZURE_STORAGE_ACCOUNT`:

Expand All @@ -184,6 +186,50 @@ $ export AZURE_STORAGE_ACCOUNT="account_name"
$ export AZURE_STORAGE_KEY=$(az storage account keys list -n $AZURE_STORAGE_ACCOUNT --query "[0].value")
```

##### Azure Managed Identity Authentication

Triton supports Azure Managed Identity (MI) as an alternative to shared key
authentication. This eliminates the need to distribute or rotate storage account
keys and aligns with enterprise security best practices on Azure.

To enable Managed Identity authentication, set the `AZURE_STORAGE_AUTH_TYPE`
environment variable:

```bash
$ export AZURE_STORAGE_ACCOUNT="account_name"
$ export AZURE_STORAGE_AUTH_TYPE="managed_identity"
$ tritonserver --model-repository=as://account_name/container_name/path/to/model/repository ...
```

For **user-assigned Managed Identity**, additionally specify the client ID:

```bash
$ export AZURE_STORAGE_AUTH_TYPE="managed_identity"
$ export AZURE_STORAGE_CLIENT_ID="<your-managed-identity-client-id>"
```

You may also use `AZURE_STORAGE_AUTH_TYPE="default"` to activate the Azure
`DefaultAzureCredential` chain, which probes multiple credential sources in
order: environment variables, managed identity, Azure CLI, and others. This is
useful during local development but has slightly higher startup latency due to
the probing.

**Prerequisites:**

- The Managed Identity (system- or user-assigned) must be assigned the
**Storage Blob Data Reader** role (or broader) on the target storage
account or container.
- The Triton host (AKS pod, VM, VMSS, App Service, etc.) must have the
Managed Identity assigned.
- For AKS workloads, ensure that either pod identity or workload identity
federation is configured so that the pod can obtain AAD tokens.

**Sovereign clouds:** The Azure Identity SDK respects the `AZURE_AUTHORITY_HOST`
environment variable, so this authentication mode works for sovereign cloud
endpoints as well.

##### Local Model Directory

By default, Triton makes a local copy of a remote model repository in a temporary folder, which is deleted after Triton server is shut down.
If you would like to control where remote model repository is copied to, you may set the `TRITON_AZURE_MOUNT_DIRECTORY` environment variable to a path pointing to the existing folder on your local machine.

Expand Down Expand Up @@ -235,6 +281,11 @@ export TRITON_CLOUD_CREDENTIAL_PATH="cloud_credential.json"
"as://Account-002/Container": {
"account_str": "",
"account_key": ""
},
"as://Account-MI/Container": {
"account_str": "AZURE_STORAGE_ACCOUNT",
"auth_type": "managed_identity",
"client_id": ""
}
}
}
Expand Down
118 changes: 116 additions & 2 deletions qa/L0_storage_azure/test.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
# Copyright 2020-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# Copyright 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
Expand Down Expand Up @@ -137,7 +137,10 @@ sleep 10

# Test 1 Scenarios:
# 1. access blob using shared key in envs
# 2. adding more scenarios in future
# 2. access blob using system-assigned managed identity
# 3. access blob using user-assigned managed identity
# 4. access blob using DefaultAzureCredential
# 5. adding more scenarios in future
for ENV_VAR in "shared_key"; do
SERVER_LOG=$SERVER_LOG_BASE.$ENV_VAR.log
CLIENT_LOG=$CLIENT_LOG_BASE.$ENV_VAR.log
Expand Down Expand Up @@ -169,6 +172,117 @@ for ENV_VAR in "shared_key"; do
wait $SERVER_PID
done

# Test 2: Managed Identity authentication
# Requires the test host (VM/AKS) to have a system-assigned managed identity
# with Storage Blob Data Reader on the test storage account.
# Skip if not running in an MI-capable environment.
if [ ! -z "$TEST_AZURE_MANAGED_IDENTITY" ]; then
echo -e "\n***\n*** Testing system-assigned Managed Identity\n***"

# Save original key and clear it so it won't be used
SAVED_AZURE_STORAGE_KEY=$AZURE_STORAGE_KEY
unset AZURE_STORAGE_KEY
export AZURE_STORAGE_AUTH_TYPE="managed_identity"

SERVER_LOG=$SERVER_LOG_BASE.managed_identity_system.log
CLIENT_LOG=$CLIENT_LOG_BASE.managed_identity_system.log
MODEL_REPO="${AS_URL}/models"
SERVER_ARGS="--model-repository=$MODEL_REPO --exit-timeout-secs=120"

run_server
if [ "$SERVER_PID" == "0" ]; then
echo -e "\n***\n*** Failed to start $SERVER with system-assigned MI\n***"
cat $SERVER_LOG
RET=1
else
set +e
run_unit_tests
set -e

kill $SERVER_PID
wait $SERVER_PID
fi

# Test 3: User-assigned Managed Identity (if client ID is provided)
if [ ! -z "$AZURE_STORAGE_CLIENT_ID" ]; then
echo -e "\n***\n*** Testing user-assigned Managed Identity\n***"

SERVER_LOG=$SERVER_LOG_BASE.managed_identity_user.log
CLIENT_LOG=$CLIENT_LOG_BASE.managed_identity_user.log
SERVER_ARGS="--model-repository=$MODEL_REPO --exit-timeout-secs=120"

run_server
if [ "$SERVER_PID" == "0" ]; then
echo -e "\n***\n*** Failed to start $SERVER with user-assigned MI\n***"
cat $SERVER_LOG
RET=1
else
set +e
run_unit_tests
set -e

kill $SERVER_PID
wait $SERVER_PID
fi
else
echo -e "\n***\n*** Skipping user-assigned MI test (AZURE_STORAGE_CLIENT_ID not set)\n***"
fi

# Test 4: DefaultAzureCredential chain
echo -e "\n***\n*** Testing DefaultAzureCredential\n***"
export AZURE_STORAGE_AUTH_TYPE="default"
unset AZURE_STORAGE_CLIENT_ID

SERVER_LOG=$SERVER_LOG_BASE.default_credential.log
CLIENT_LOG=$CLIENT_LOG_BASE.default_credential.log
SERVER_ARGS="--model-repository=$MODEL_REPO --exit-timeout-secs=120"

run_server
if [ "$SERVER_PID" == "0" ]; then
echo -e "\n***\n*** Failed to start $SERVER with DefaultAzureCredential\n***"
cat $SERVER_LOG
RET=1
else
set +e
run_unit_tests
set -e

kill $SERVER_PID
wait $SERVER_PID
fi

# Test: invalid auth_type should fail gracefully
echo -e "\n***\n*** Testing invalid auth_type (expect failure)\n***"
export AZURE_STORAGE_AUTH_TYPE="invalid_type"

SERVER_LOG=$SERVER_LOG_BASE.invalid_auth_type.log
SERVER_ARGS="--model-repository=$MODEL_REPO --exit-timeout-secs=120 --exit-on-error=false"

run_server
if [ "$SERVER_PID" != "0" ]; then
# Server started — but model load should have failed. Verify the log
# contains an authentication error rather than a successful load.
if grep -q "Unable to create Azure filesystem client" $SERVER_LOG; then
echo -e "*** invalid auth_type correctly rejected ***"
else
echo -e "\n***\n*** Expected auth failure with invalid auth_type\n***"
cat $SERVER_LOG
RET=1
fi
kill $SERVER_PID
wait $SERVER_PID
else
echo -e "*** Server correctly refused to start with invalid auth_type ***"
fi

# Restore environment for remaining tests
unset AZURE_STORAGE_AUTH_TYPE
unset AZURE_STORAGE_CLIENT_ID
export AZURE_STORAGE_KEY=$SAVED_AZURE_STORAGE_KEY
else
echo -e "\n***\n*** Skipping Managed Identity tests (TEST_AZURE_MANAGED_IDENTITY not set)\n***"
fi

# Test localization to a specified location
export TRITON_AZURE_MOUNT_DIRECTORY=`pwd`/azure_localization_test

Expand Down
Loading