From b8da363d258fbb80319d58db609a29baaff87529 Mon Sep 17 00:00:00 2001 From: g2vinay Date: Mon, 9 Mar 2026 18:36:35 -0700 Subject: [PATCH] fix(docker): resolve permission denied and libsecret persistence failure Two issues affecting Docker users: 1. The azmcp binary in /mcp-server/ lacked execute permission because only the renamed server-binary was chmod'd. Any direct invocation of ./azmcp (custom entrypoints, workaround configs) hit 'permission denied'. Fix: chmod both server-binary and \. 2. InteractiveBrowserCredential's MSAL token-cache persistence requires libsecret, which was absent from the Alpine base image. This caused 'Persistence check failed / libsecret-1.so.0 not found' errors even when valid service-principal credentials were supplied via env vars, because the MsalCachePersistenceException propagated as an unhandled exception rather than CredentialUnavailableException, killing the chain. Fixes: - Install libsecret in the Dockerfile so persistence works when a keyring daemon is available. - Wrap CreateBrowserCredential in SafeTokenCredential so any remaining persistence failure gracefully falls through the credential chain instead of surfacing as an unhandled AuthenticationFailedException. Adds a Docker section to docs/Authentication.md explaining that AZURE_TOKEN_CREDENTIALS=prod must be set when running in a container to avoid interactive-credential fallback and the libsecret dependency. --- Dockerfile | 11 +++++-- .../Authentication/CustomChainedCredential.cs | 6 +++- docs/Authentication.md | 31 +++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2c57fdf516..c94883e0ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,11 @@ # Build the runtime image FROM mcr.microsoft.com/dotnet/runtime-deps:10.0-alpine AS runtime +# Install libsecret so MSAL token-cache persistence works on Alpine Linux. +# Without it, InteractiveBrowserCredential throws MsalCachePersistenceException +# in headless environments (Docker, WSL without a running keyring daemon). +RUN apk add --no-cache libsecret + # Add build argument for publish directory ARG PUBLISH_DIR @@ -30,8 +35,10 @@ RUN if [ ! -f $EXECUTABLE_NAME ]; then \ echo "ERROR: $EXECUTABLE_NAME executable does not exist" && exit 1; \ fi -# Copy the server binary to a known location and make it executable +# Copy the server binary to a known location and make it executable. +# Also chmod the original executable name so users can invoke it directly +# inside the container (e.g. via --entrypoint or exec). COPY ${PUBLISH_DIR}/${EXECUTABLE_NAME} server-binary -RUN chmod +x server-binary && test -x server-binary +RUN chmod +x server-binary ${EXECUTABLE_NAME} && test -x server-binary && test -x ${EXECUTABLE_NAME} ENTRYPOINT ["./server-binary", "server", "start"] diff --git a/core/Microsoft.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs b/core/Microsoft.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs index 2ef1c89ba2..b14565408f 100644 --- a/core/Microsoft.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs +++ b/core/Microsoft.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs @@ -175,7 +175,11 @@ private static TokenCredential CreateCredential(string? tenantId, ILogger +AZURE_CLIENT_ID= +AZURE_CLIENT_SECRET= +``` + +`AZURE_TOKEN_CREDENTIALS=prod` restricts the credential chain to `EnvironmentCredential`, `WorkloadIdentityCredential`, and `ManagedIdentityCredential`. This skips `InteractiveBrowserCredential` entirely, preventing errors caused by a missing GUI or keyring daemon inside the container. + +> [!IMPORTANT] +> Omitting `AZURE_TOKEN_CREDENTIALS=prod` in a Docker container causes the server to fall back to `InteractiveBrowserCredential`, which tries to initialize the MSAL token cache via `libsecret`. If no keyring daemon is running in the container, authentication fails with `Persistence check failed` / `libsecret-1.so.0` not found errors even though your service principal credentials are correct. + +**Alternative: Managed Identity (for Azure-hosted containers)** + +When running on Azure Container Instances, AKS, or App Service with a managed identity, set: + +```env +AZURE_TOKEN_CREDENTIALS=prod +# For user-assigned managed identity only: +AZURE_CLIENT_ID= +``` + ### CI/CD Pipelines For automated builds and deployments, set the following environment variables: @@ -93,6 +123,7 @@ For automated builds and deployments, set the following environment variables: export AZURE_CLIENT_ID="" export AZURE_CLIENT_SECRET="" export AZURE_TENANT_ID="" +export AZURE_TOKEN_CREDENTIALS=prod ``` ## Authentication Scenarios in Enterprise Environments