Cosmos DB Integration (Managed Identity)¶
Use this recipe to connect a Java Container App to Azure Cosmos DB for NoSQL with managed identity first and a connection string fallback only when you cannot use RBAC yet.
Architecture¶
flowchart TD
C[Client] --> I[Container Apps Ingress]
I --> APP[Java Container App]
APP --> COSMOS[Azure Cosmos DB]
APP -.-> MI[Managed Identity]
MI -.-> ENTRA[Microsoft Entra ID]
MI -.-> COSMOS Solid arrows show runtime data flow. Dashed arrows show identity and authentication.
Prerequisites¶
- Existing Container App:
$APP_NAMEin resource group$RG - Existing Azure Cosmos DB account, SQL database, and container
- Azure CLI with Container Apps and Cosmos extensions
Step 1: Enable managed identity on the Container App¶
az containerapp identity assign \
--name "$APP_NAME" \
--resource-group "$RG" \
--system-assigned
export PRINCIPAL_ID=$(az containerapp show \
--name "$APP_NAME" \
--resource-group "$RG" \
--query "identity.principalId" \
--output tsv)
Step 2: Grant Cosmos DB data-plane access¶
export COSMOS_ACCOUNT_ID=$(az cosmosdb show \
--name "$COSMOS_ACCOUNT" \
--resource-group "$RG" \
--query "id" \
--output tsv)
az role assignment create \
--assignee-object-id "$PRINCIPAL_ID" \
--assignee-principal-type ServicePrincipal \
--role "Cosmos DB Built-in Data Contributor" \
--scope "$COSMOS_ACCOUNT_ID"
Step 3: Configure non-secret settings in Container Apps¶
Azure Container Apps does not inject Cosmos DB connection settings automatically. Store non-secret values as environment variables, and store fallback secrets in secrets[] with secretref:.
az containerapp update \
--name "$APP_NAME" \
--resource-group "$RG" \
--set-env-vars COSMOS_ENDPOINT="https://$COSMOS_ACCOUNT.documents.azure.com:443/" COSMOS_DATABASE="$COSMOS_DATABASE" COSMOS_CONTAINER="$COSMOS_CONTAINER"
Step 4: Java code (managed identity)¶
Add dependencies:
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-cosmos</artifactId>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
Use DefaultAzureCredentialBuilder when COSMOS_CONNECTION_STRING is not present:
import com.azure.cosmos.CosmosClient;
import com.azure.cosmos.CosmosClientBuilder;
import com.azure.cosmos.CosmosContainer;
import com.azure.cosmos.CosmosDatabase;
import com.azure.cosmos.models.CosmosItemResponse;
import com.azure.cosmos.models.PartitionKey;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
public class CosmosRecipe {
private static CosmosClient createClient() {
String connectionString = System.getenv("COSMOS_CONNECTION_STRING");
CosmosClientBuilder builder = new CosmosClientBuilder();
if (connectionString != null && !connectionString.isBlank()) {
return builder.connectionString(connectionString).buildClient();
}
return builder
.endpoint(System.getenv("COSMOS_ENDPOINT"))
.credential(new DefaultAzureCredentialBuilder().build())
.buildClient();
}
public static void main(String[] args) {
try (CosmosClient client = createClient()) {
CosmosDatabase database = client.getDatabase(System.getenv("COSMOS_DATABASE"));
CosmosContainer container = database.getContainer(System.getenv("COSMOS_CONTAINER"));
ObjectNode item = JsonNodeFactory.instance.objectNode();
item.put("id", "order-1001");
item.put("partitionKey", "order-1001");
item.put("type", "order");
item.put("status", "created");
container.upsertItem(item, new PartitionKey(item.get("partitionKey").asText()), null);
CosmosItemResponse<ObjectNode> response = container.readItem(
"order-1001",
new PartitionKey("order-1001"),
ObjectNode.class
);
System.out.println(response.getItem().toPrettyString());
}
}
}
Step 5: Connection string fallback¶
Only use this pattern when you cannot enable RBAC yet.
az containerapp secret set \
--name "$APP_NAME" \
--resource-group "$RG" \
--secrets cosmos-connection-string="AccountEndpoint=https://$COSMOS_ACCOUNT.documents.azure.com:443/;AccountKey=<cosmos-account-key>;"
az containerapp update \
--name "$APP_NAME" \
--resource-group "$RG" \
--set-env-vars COSMOS_CONNECTION_STRING=secretref:cosmos-connection-string COSMOS_DATABASE="$COSMOS_DATABASE" COSMOS_CONTAINER="$COSMOS_CONTAINER"
Verification¶
- Confirm identity assignment:
az containerapp show \
--name "$APP_NAME" \
--resource-group "$RG" \
--query "identity" \
--output json
- Confirm role assignment exists:
az role assignment list \
--assignee "$PRINCIPAL_ID" \
--scope "$COSMOS_ACCOUNT_ID" \
--output table
- Check app logs for successful upsert and read operations.