pi-foundry-auth
v0.1.1
Published
Security-first Microsoft Entra ID provider extension for pi and Azure AI Foundry.
Downloads
109
Maintainers
Readme
pi Foundry Auth
Security-first pi provider plugin for Azure AI Foundry model deployments. It uses Microsoft Entra ID for authentication, routes requests through the OpenAI-compatible API, and never stores Azure API keys or access tokens in pi's auth storage.
The public npm package is pi-foundry-auth. Publishing is intentionally a manual step so a maintainer can review the exact version and tarball first.
This package adds an azure-foundry provider that uses the Azure OpenAI-compatible /openai/v1/ route and Microsoft Entra ID. It is intended for Foundry model deployments that are usable through that route. It does not implement Foundry Agent Service, evaluations, or mutating management APIs.
Security model
- Microsoft Entra ID only; this extension does not accept or persist Azure API keys.
- Access tokens are acquired through
@azure/identity, used in memory for requests, and never written to pi'sauth.json, printed, or included in diagnostics by this plugin. Any persistence belongs to the selected credential provider (for example, Azure CLI), not this plugin. /login azure-foundrystores only a non-secret marker so pi can manage the provider./logout azure-foundryremoves that marker.- The default credential chain is used: environment/workload identity, managed identity, Azure CLI, Azure Developer CLI, and other supported local developer credentials.
- The Pi device-code flow uses
@azure/identitydirectly; it never starts Azure CLI or parses terminal output. - Endpoint validation requires HTTPS and an Azure Foundry/Azure OpenAI hostname by default. Arbitrary endpoints require an explicit opt-in.
Requirements
- Node.js 22+
- pi 0.84 or later (
@earendil-works/pi-coding-agent) - An Azure AI Foundry resource with a model deployment
- An Entra identity with permission to use the resource (for example, the appropriate Cognitive Services/Foundry user role)
Install from a local checkout
From this repository:
cd /path/to/pi-foundry-auth
pnpm install
pi -e ./extensionsTo make it available globally while developing, add the extension directory to pi's settings or copy the package into ~/.pi/agent/extensions/.
Configure a resource and model
The plugin never needs a secret in its configuration. Configure the endpoint and deployment names with environment variables:
export AZURE_FOUNDRY_RESOURCE="my-foundry-resource"
export AZURE_FOUNDRY_MODELS="my-gpt-deployment,my-reasoning-deployment"Deployment IDs are the names you assigned in Azure; they are not necessarily the public model names.
You can also use a metadata-only config file at ~/.pi/agent/azure-foundry.json:
{
"resource": "my-foundry-resource",
"tenantId": "00000000-0000-0000-0000-000000000000",
"clientId": "00000000-0000-4000-8000-000000000000",
"subscriptionId": "00000000-0000-4000-8000-000000000000",
"resourceGroup": "my-foundry-rg",
"models": [
{
"id": "my-gpt-deployment",
"name": "My GPT deployment",
"reasoning": false,
"input": ["text", "image"],
"contextWindow": 128000,
"maxTokens": 16384
}
]
}If this machine already uses Atlas, the plugin also reads only the non-secret [foundry] resource, endpoint, tenant_id, client_id, subscription_id, and resource_group fields from Atlas's config.toml as a fallback. Plugin environment variables and ~/.pi/agent/azure-foundry.json always take precedence. It never reads Atlas's token or keychain files.
Project-local .pi/azure-foundry.json overrides the global file. The following environment variables override file values:
| Variable | Purpose |
| --- | --- |
| AZURE_FOUNDRY_RESOURCE | Azure resource name; used to build the standard endpoint |
| AZURE_FOUNDRY_ENDPOINT | Full https://.../openai/v1/ endpoint |
| AZURE_FOUNDRY_MODELS | Optional comma-separated deployment IDs; discovered models are added automatically |
| AZURE_FOUNDRY_TENANT_ID | Optional tenant restriction |
| AZURE_FOUNDRY_CLIENT_ID | Optional Entra App Registration client ID for direct device-code login |
| AZURE_FOUNDRY_SUBSCRIPTION_ID | Azure subscription ID for authoritative ARM deployment discovery |
| AZURE_FOUNDRY_RESOURCE_GROUP | Azure resource group for authoritative ARM deployment discovery |
| AZURE_FOUNDRY_SCOPE | Token scope; defaults to https://ai.azure.com/.default |
| AZURE_FOUNDRY_CONFIG | Explicit metadata config path |
The only accepted scopes are https://ai.azure.com/.default and https://cognitiveservices.azure.com/.default.
Sign in
Start pi with the extension, then use:
/login azure-foundryChoose “Use an existing Azure credential” if you have already authenticated with Azure CLI, Azure Developer CLI, VS Code, environment credentials, or managed identity. Choose “Sign in with Microsoft Entra device code” to run Azure Identity's direct device-code flow inside Pi. This flow displays the verification URL and user code through Pi's login dialog; it does not start az or parse CLI output.
For enterprise or production use, set AZURE_FOUNDRY_CLIENT_ID to an App Registration that your organization controls. The optional AZURE_FOUNDRY_TENANT_ID restricts the sign-in authority to the selected tenant. The client ID is an application identifier, not a secret; no client secret is accepted by this plugin. If no client ID is configured, Azure Identity uses its developer sign-on application for convenience, which is not the recommended production setup.
If you prefer Azure CLI's own credential cache, run az login --use-device-code in a separate terminal first, then choose “Use an existing Azure credential”. This is the same external-credential pattern used by other Azure Foundry Pi extensions.
The plugin verifies that it can request the configured Entra scope. The access token itself remains owned by the Azure identity library and is not copied into pi storage.
After a successful login, the plugin discovers models and registers them in Pi. When subscriptionId, resourceGroup, and either resource or a standard Azure Foundry endpoint are configured, it uses the read-only Azure Resource Manager deployments list and includes only deployments whose provisioning state is Succeeded. This authoritative path does not invoke model inference. Without those management coordinates, it falls back to the data-plane /openai/v1/models catalog, which can include models that are not deployed to this resource.
If discovery was unavailable during login, retry it with:
/azure-foundry-modelsThen use /model to select one. ARM discovery requests a separate https://management.azure.com/.default access token and sends it only to management.azure.com; catalog discovery uses the data-plane token only at the configured endpoint.
You can check readiness without displaying a token:
/azure-foundry-statusEndpoint safety
By default, the full endpoint must use HTTPS, have no credentials/port/query/fragment, end in /openai/v1, and use one of these host suffixes:
.openai.azure.com.services.ai.azure.com
For an enterprise gateway or private proxy, you may explicitly opt in with AZURE_FOUNDRY_ALLOW_CUSTOM_ENDPOINT=true. The endpoint still must use HTTPS and the exact /openai/v1 path. Review this setting carefully because it allows the bearer token to be sent to the configured host.
Development
pnpm install
pnpm check
pnpm pack:check
pnpm publish:checkThe test suite uses fake credentials and local/mocked streams; it does not contact Azure and does not require an Azure account.
Issues and feedback
Issues, bug reports, documentation fixes, and feature proposals are welcome. Before opening one, please search existing issues and include the pi/package versions, Node.js version, operating system, the smallest reproducible configuration, and sanitized error output. Never include access tokens, refresh tokens, API keys, client secrets, or private endpoint details.
Open a GitHub issue or browse existing issues. Please use the private reporting route described in SECURITY.md for suspected vulnerabilities rather than a public issue.
Publish to npm
The package uses pnpm for installation, testing, auditing, and package preparation. The final repository-based registry publish uses npm's Trusted Publishing and GitHub OIDC; it is not run automatically on every push.
For the initial bootstrap release, authenticate with npm and verify the account:
npm login
npm whoamiReview the package contents and then publish the current version:
pnpm check
pnpm audit --prod --audit-level high
pnpm publish:check
npm publish --access publicThe package version must be incremented before each subsequent release. All preparation uses pnpm; the final npm publish command is intentional because npm Trusted Publishing authenticates the npm CLI with GitHub OIDC. No npm token is stored in the repository or workflow. npm requires this initial package to exist before a Trusted Publisher can be configured.
Then configure npm Trusted Publishing for GitHub Actions with:
- Owner:
WGB5445 - Repository:
pi-foundry-auth - Workflow filename:
publish.yml - Environment:
npm-publish - Allowed action:
npm publish
The recommended path is the npm web UI: open the package's Settings → Trusted publishing page and create a GitHub Actions publisher with the fields above. The package is already present on npm, so this configuration is now available.
The CLI alternative requires npm CLI 11.15.0 or newer. If npm trust prints Unknown command: "trust", your npm CLI is too old; upgrade npm or use the web UI:
npm --version
npm install --global npm@^11.15.0
npm trust github pi-foundry-auth --repo WGB5445/pi-foundry-auth --file publish.yml --allow-publishAfter that bootstrap release, manually run the Publish Package workflow from the Actions tab. It requests only the GitHub OIDC id-token: write permission and has no NPM_TOKEN secret. npm generates provenance automatically for trusted publishes.
The workflow only publishes from main, verifies that the package version is not already on npm, and reruns the full test/audit/package checks before publishing.
References
- pi custom providers
- Microsoft Foundry Entra ID authentication
- Microsoft Foundry application integration and endpoint guidance
- Azure AI Services deployments list API
Current limitations
- Model discovery prefers the read-only ARM deployment list when subscription/resource-group coordinates are configured; otherwise it uses the Azure AI Foundry data-plane
/openai/v1/modelscatalog. Manual model metadata remains supported for custom names, capabilities, context windows, and costs. - The plugin targets Foundry's OpenAI v1-compatible model route, not the Foundry Agent Service project API.
- Direct device-code login keeps the Azure Identity credential in memory for the current Pi process; Pi auth storage contains only the non-secret login marker. Existing Azure CLI credentials are read through
DefaultAzureCredential. - For direct device-code login, configure an organization-owned
AZURE_FOUNDRY_CLIENT_IDand, when appropriate,AZURE_FOUNDRY_TENANT_ID; the plugin does not persist refresh tokens or enable a persistent token cache.
License
MIT. See LICENSE.
