|
| 1 | +# Local Development Setup |
| 2 | + |
| 3 | +This document explains how local development authentication works for this Azure Functions project. |
| 4 | + |
| 5 | +## Authentication Approach |
| 6 | + |
| 7 | +This project uses **Azure Managed Identity** for authentication - both in production AND for local development. **No API keys are required!** |
| 8 | + |
| 9 | +### How It Works |
| 10 | + |
| 11 | +1. **In Azure (Production)**: The Function App uses its User-Assigned Managed Identity with the `Cognitive Services OpenAI User` role |
| 12 | +2. **Locally**: Developers use their own Azure credentials via `az login` with the same role |
| 13 | + |
| 14 | +## Setup Steps |
| 15 | + |
| 16 | +### 1. Run `azd up` or `azd provision` |
| 17 | + |
| 18 | +When you provision the infrastructure, the Bicep deployment automatically: |
| 19 | +- Creates the Azure OpenAI resource |
| 20 | +- Assigns the `Cognitive Services OpenAI User` role to the Function App's managed identity |
| 21 | +- **Assigns the same role to YOU** (the person running `azd provision`) |
| 22 | + |
| 23 | +This is done via the `principalId` parameter in `main.bicep`: |
| 24 | + |
| 25 | +```bicep |
| 26 | +// This assigns the role to the person running azd provision |
| 27 | +module openaiRoleAssignmentDeveloper 'app/rbac/openai-access.bicep' = if (!empty(principalId)) { |
| 28 | + name: 'openaiRoleAssignmentDeveloper' |
| 29 | + scope: rg |
| 30 | + params: { |
| 31 | + openAIAccountName: openai.outputs.aiServicesName |
| 32 | + roleDefinitionId: CognitiveServicesOpenAIUser |
| 33 | + principalId: principalId // Your user ID |
| 34 | + } |
| 35 | +} |
| 36 | +``` |
| 37 | + |
| 38 | +### 2. Make Sure You're Logged In |
| 39 | + |
| 40 | +```bash |
| 41 | +# Login to Azure |
| 42 | +az login |
| 43 | + |
| 44 | +# Verify you're using the correct subscription |
| 45 | +az account show |
| 46 | +``` |
| 47 | + |
| 48 | +### 3. Generate local.settings.json |
| 49 | + |
| 50 | +```bash |
| 51 | +# Run the postprovision script |
| 52 | +./scripts/generate-settings.sh |
| 53 | + |
| 54 | +# Verify it was created (notice: no API key!) |
| 55 | +cat src/local.settings.json |
| 56 | +``` |
| 57 | + |
| 58 | +### 4. Run the Function App Locally |
| 59 | + |
| 60 | +```bash |
| 61 | +cd src |
| 62 | +func start |
| 63 | +``` |
| 64 | + |
| 65 | +The Azure Functions runtime will automatically use your Azure credentials via `DefaultAzureCredential`. |
| 66 | + |
| 67 | +## Benefits of This Approach |
| 68 | + |
| 69 | +✅ **No secrets to manage** - No API keys in config files or environment variables |
| 70 | +✅ **More secure** - Credentials never leave Azure's identity system |
| 71 | +✅ **Production parity** - Local dev works exactly like production |
| 72 | +✅ **Automatic role assignment** - Developers get the right permissions when they provision |
| 73 | +✅ **Audit trail** - All API calls are tied to specific user identities |
| 74 | + |
| 75 | +## Troubleshooting |
| 76 | + |
| 77 | +### Error: "Access denied" or "Unauthorized" |
| 78 | + |
| 79 | +1. **Check your Azure login**: |
| 80 | + ```bash |
| 81 | + az login |
| 82 | + az account show |
| 83 | + ``` |
| 84 | + |
| 85 | +2. **Verify your role assignment**: |
| 86 | + ```bash |
| 87 | + # Get your user principal ID |
| 88 | + az ad signed-in-user show --query id -o tsv |
| 89 | + |
| 90 | + # List role assignments (replace <resource-group> and <openai-name>) |
| 91 | + az role assignment list --assignee <your-principal-id> \ |
| 92 | + --scope /subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.CognitiveServices/accounts/<openai-name> |
| 93 | + ``` |
| 94 | + |
| 95 | +3. **If role is missing**, run `azd provision` again or manually assign: |
| 96 | + ```bash |
| 97 | + az role assignment create \ |
| 98 | + --role "Cognitive Services OpenAI User" \ |
| 99 | + --assignee <your-email-or-principal-id> \ |
| 100 | + --scope /subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.CognitiveServices/accounts/<openai-name> |
| 101 | + ``` |
| 102 | + |
| 103 | +### For Additional Developers |
| 104 | + |
| 105 | +If other developers join the project: |
| 106 | + |
| 107 | +**Option 1: They run `azd provision`** (if they have subscription permissions) |
| 108 | +- This will automatically assign them the role |
| 109 | + |
| 110 | +**Option 2: Manually assign the role** (if you're the admin) |
| 111 | +```bash |
| 112 | +az role assignment create \ |
| 113 | + --role "Cognitive Services OpenAI User" \ |
| 114 | + --assignee <developer-email> \ |
| 115 | + --scope /subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.CognitiveServices/accounts/<openai-name> |
| 116 | +``` |
| 117 | + |
| 118 | +## FAQ |
| 119 | + |
| 120 | +**Q: Do I need an API key for local development?** |
| 121 | +A: No! Just make sure you're logged in with `az login`. |
| 122 | + |
| 123 | +**Q: What if I want to use an API key anyway?** |
| 124 | +A: You can manually add `AZURE_OPENAI_KEY` to your `local.settings.json`, but it's not recommended. The keyless approach is more secure. |
| 125 | + |
| 126 | +**Q: Does this work in CI/CD pipelines?** |
| 127 | +A: Yes! Use a service principal or managed identity for your CI/CD pipeline with the same role assignment. |
| 128 | + |
| 129 | +**Q: What about Cosmos DB access?** |
| 130 | +A: Same approach! Your user is assigned `DocumentDB Account Contributor` role during provisioning (see the `cosmosDb` module in `main.bicep`). |
0 commit comments