Skip to content

Commit c55a81a

Browse files
authored
Merge pull request #15 from CUNYHackKnight2025/Feature/FinanceChat
Updated openapi for azure
2 parents fba84bf + 5f81d2c commit c55a81a

File tree

5 files changed

+1212
-0
lines changed

5 files changed

+1212
-0
lines changed

azure-apim-guide.md

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# Azure API Management Guide for FinBin Backend
2+
3+
## What is API Management?
4+
5+
Azure API Management (APIM) is a complete solution for publishing, securing, transforming, maintaining, and monitoring APIs. For your FinBin application, it sits as a façade between your backend services and API consumers.
6+
7+
## Getting Started with API Management
8+
9+
### 1. Create an API Management Service
10+
11+
1. In Azure Portal, go to **Create a resource** > **Integration** > **API Management**
12+
2. Fill in the basics:
13+
- **Name**: `finbin-apim` (must be unique)
14+
- **Subscription**: Your subscription
15+
- **Resource Group**: Use the same as your App Service (`rg-foundrysandbox`)
16+
- **Location**: Same region as your App Service
17+
- **Organization name**: Your organization
18+
- **Administrator email**: Your email
19+
- **Pricing tier**: Developer (for testing) or Basic/Standard (for production)
20+
21+
### 2. Import Your FinBin API
22+
23+
#### Option A: Import from OpenAPI (Swagger)
24+
25+
1. Go to your API Management service
26+
2. Select **APIs** > **+ Add API** > **OpenAPI**
27+
3. Enter the URL to your Swagger endpoint: `https://finbinbackend.azurewebsites.net/swagger/v1/swagger.json`
28+
- **Note**: This URL must be publicly accessible for API Management to import it
29+
4. Configure:
30+
- **Display name**: `FinBin API`
31+
- **Name**: `finbin-api`
32+
- **API URL suffix**: `finbin`
33+
- **Base URL**: Your backend URL
34+
- **Version**: `v1`
35+
36+
#### Option B: Import from App Service
37+
38+
1. Go to your API Management service
39+
2. Select **APIs** > **+ Add API** > **App Service**
40+
3. Select your App Service (`finbinbackend`)
41+
4. Configure similar settings as above
42+
43+
### 2.1 Configure API Definition (Swagger/OpenAPI)
44+
45+
For API Management to properly discover and import your API:
46+
47+
1. **Make sure your Swagger endpoint is publicly accessible**:
48+
- In App Service, ensure that the Swagger endpoint doesn't require authentication
49+
- Temporarily disable any IP restrictions that might block APIM from accessing it
50+
- Test the URL in an incognito browser to verify it's publicly accessible
51+
52+
2. **Set up CORS for your Swagger endpoint** (if needed):
53+
```csharp
54+
app.UseSwagger(c => {
55+
c.PreSerializeFilters.Add((swaggerDoc, httpReq) => {
56+
swaggerDoc.Servers = new List<OpenApiServer> {
57+
new OpenApiServer { Url = $"https://{httpReq.Host.Value}" }
58+
};
59+
});
60+
});
61+
```
62+
63+
3. **Configure API definition in APIM**:
64+
- Go to your API in APIM
65+
- Select **Settings** tab
66+
- Under **API definition**, choose "OpenAPI" format
67+
- Enter your Swagger URL or paste the JSON content directly
68+
- Click "Save" to update the definition
69+
70+
4. **Keep your Swagger documentation synchronized**:
71+
- Set up automatic import from your Swagger endpoint
72+
- In your API settings, enable "Always use latest API specification"
73+
- Configure a schedule for automatic updates
74+
75+
5. **Add API definition to Developer Portal**:
76+
- Enable the Developer Portal
77+
- Make sure API documentation is enabled
78+
- Customize the documentation appearance
79+
80+
### 3. Configure Security
81+
82+
#### Set Up JWT Validation
83+
84+
1. Go to your API > **Settings**
85+
2. In the **Security** tab, add a JWT validation policy:
86+
```xml
87+
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized">
88+
<openid-config url="your-auth-metadata-endpoint" />
89+
<audiences>
90+
<audience>same-as-your-JWT-audience</audience>
91+
</audiences>
92+
<issuers>
93+
<issuer>same-as-your-JWT-issuer</issuer>
94+
</issuers>
95+
</validate-jwt>
96+
```
97+
98+
### 4. Configure Policies
99+
100+
At the API level, add these important policies:
101+
102+
1. **CORS Policy** (if needed):
103+
```xml
104+
<cors allow-credentials="true">
105+
<allowed-origins>
106+
<origin>https://your-frontend-url.azurewebsites.net</origin>
107+
</allowed-origins>
108+
<allowed-methods preflight-result-max-age="300">
109+
<method>GET</method>
110+
<method>POST</method>
111+
<method>PUT</method>
112+
<method>DELETE</method>
113+
</allowed-methods>
114+
<allowed-headers>
115+
<header>*</header>
116+
</allowed-headers>
117+
</cors>
118+
```
119+
120+
2. **Rate Limiting**:
121+
```xml
122+
<rate-limit calls="20" renewal-period="60" />
123+
```
124+
125+
3. **Caching** (for appropriate endpoints):
126+
```xml
127+
<cache-lookup vary-by-developer="false" vary-by-developer-groups="false" downstream-caching-type="none" />
128+
<cache-store duration="60" />
129+
```
130+
131+
### 5. Set Up Products
132+
133+
1. Create a Product (e.g., "FinBin Standard")
134+
2. Add your API to the product
135+
3. Configure access control (subscription required or open)
136+
4. Publish the product
137+
138+
### 6. Configure Diagnostics and Monitoring
139+
140+
1. Go to **Diagnostics** in your API Management
141+
2. Create a new diagnostic setting
142+
3. Send logs to:
143+
- Application Insights (same one used by your App Service)
144+
- Log Analytics Workspace
145+
146+
### 7. Connect to Backend with Managed Identity
147+
148+
1. Enable System Assigned Managed Identity for your API Management
149+
2. Grant necessary permissions to access:
150+
- Azure SQL Database
151+
- Azure OpenAI service
152+
3. Configure backend with Managed Identity authentication:
153+
```xml
154+
<authentication-managed-identity resource="https://management.azure.com/" />
155+
```
156+
157+
### 8. Developer Portal (Optional)
158+
159+
1. Go to **Developer Portal** > **Portal Overview**
160+
2. Customize branding and content
161+
3. Publish the portal
162+
163+
## Testing Your API
164+
165+
1. Go to **APIs** > Your API > **Test** tab
166+
2. Select an operation
167+
3. Configure any parameters
168+
4. Add Authorization header if required
169+
5. Click **Send**
170+
171+
## Best Practices for FinBin
172+
173+
1. **Layer Security**:
174+
- Use API keys for frontend applications
175+
- Use OAuth/JWT for user authentication
176+
- Use Managed Identity for backend-to-backend communication
177+
178+
2. **Implement Versioning**:
179+
- Use URL path versioning (/v1/, /v2/)
180+
- Use API versioning in APIM
181+
182+
3. **Set Up Monitoring**:
183+
- Monitor API usage and performance
184+
- Set up alerts for error thresholds
185+
- Review logs regularly
186+
187+
4. **Deploy Changes Safely**:
188+
- Use separate instances for dev/test/prod
189+
- Use revisions for non-breaking changes
190+
- Use versions for breaking changes
191+
192+
## Next Steps
193+
194+
1. Set up a custom domain for your API Management
195+
2. Implement advanced policies (transformation, validation)
196+
3. Configure mutual TLS for backend communication
197+
4. Set up a CI/CD pipeline for API Management using Azure DevOps or GitHub Actions

azure-apim-import-guide.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Importing OpenAPI Specification into Azure API Management
2+
3+
## Preparing Your OpenAPI Specification
4+
5+
1. **Validate your specification**:
6+
- Use the Swagger Editor (https://editor.swagger.io/) to validate your YAML
7+
- Fix any errors or warnings before importing
8+
9+
2. **Make sure your specification includes**:
10+
- Proper server URLs that match your backend endpoints
11+
- Security definitions (in our case, JWT Bearer authentication)
12+
- Complete schema definitions for requests and responses
13+
14+
## Import Methods
15+
16+
### Method 1: Import via Azure Portal
17+
18+
1. Go to your Azure API Management service
19+
2. Select **APIs** from the menu
20+
3. Click **+ Add API**
21+
4. Select **OpenAPI** from the available options
22+
5. Choose one of the following:
23+
- **OpenAPI specification** - Upload or paste your YAML/JSON specification
24+
- **OpenAPI link** - Provide a URL to your specification file
25+
- *(Note: If using URL, it must be publicly accessible)*
26+
6. Configure these settings:
27+
- **Display name**: FinBin API
28+
- **Name**: finbin-api
29+
- **API URL suffix**: finbin
30+
- **Products**: Associate with your products (optional)
31+
- **Tags**: Add relevant tags (optional)
32+
- **Gateway URL**: Will be auto-generated
33+
7. Click **Create**
34+
35+
### Method 2: Import via Azure CLI
36+
37+
```bash
38+
# Upload API definition from local file
39+
az apim api import --resource-group rg-foundrysandbox \
40+
--service-name finbin-apim \
41+
--path "finbin" \
42+
--display-name "FinBin API" \
43+
--api-id finbin-api \
44+
--specification-format OpenApi \
45+
--specification-path "c:\Users\Brandon\finbinBackend\finbin-openapi.yaml"
46+
```
47+
48+
### Method 3: Import via PowerShell
49+
50+
```powershell
51+
$context = New-AzApiManagementContext -ResourceGroupName "rg-foundrysandbox" -ServiceName "finbin-apim"
52+
$openApiSpec = Get-Content -Path "c:\Users\Brandon\finbinBackend\finbin-openapi.yaml" -Raw
53+
Import-AzApiManagementApi -Context $context -SpecificationFormat "OpenApi" -SpecificationPath $openApiSpec -Path "finbin" -ApiId "finbin-api"
54+
```
55+
56+
## After Importing
57+
58+
1. **Test your API operations**:
59+
- Use the built-in test console in API Management
60+
- Verify request/response formats match your expectations
61+
62+
2. **Configure policies** (if not defined in OpenAPI):
63+
- Add JWT validation
64+
- Set rate limiting
65+
- Configure caching for appropriate endpoints
66+
67+
3. **Set up backend service URL**:
68+
- Verify the backend service URL points to your App Service
69+
- Configure backend authentication (Managed Identity if applicable)
70+
71+
4. **Create products and subscriptions**:
72+
- Add your API to appropriate products
73+
- Generate subscription keys for consumers
74+
75+
5. **Enable CORS** (if needed):
76+
- Add CORS policy at API or operation level
77+
- Configure allowed origins for your frontend
78+
79+
## Versioning and Revisions
80+
81+
- Use **revisions** for non-breaking changes to your API
82+
- Use **versions** when introducing breaking changes
83+
- Configure **API versioning scheme** (path, header, or query parameter)
84+
85+
## Troubleshooting Common Import Issues
86+
87+
- **Schema validation errors**: Ensure your OpenAPI spec conforms to the OpenAPI 3.0 specification
88+
- **Server URL issues**: Make sure server URLs are properly defined and accessible
89+
- **Authentication problems**: Verify security definitions match your backend configuration
90+
- **Operation conflicts**: Check for duplicate operation IDs or paths

azure-rbac-fix.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Fixing "Role Assignment Already Exists" Error in Azure
2+
3+
## Error Explanation
4+
5+
The error message "The role assignment already exists. (Code: RoleAssignmentExists)" occurs when:
6+
7+
1. You're trying to assign an Azure role to a principal (user, service principal, or managed identity) that already has this role assignment
8+
2. The same role is being assigned to the same principal on the same scope multiple times
9+
10+
This commonly happens during:
11+
- Deployment script execution
12+
- Infrastructure as Code deployments (ARM, Bicep, Terraform)
13+
- GitHub Actions workflows with Azure login actions
14+
- Service principal setup for CI/CD pipelines
15+
16+
## Solutions
17+
18+
### Option 1: Use Deterministic GUIDs in Bicep (Recommended)
19+
20+
When defining role assignments in Bicep, use the `guid()` function to create a deterministic GUID that ensures uniqueness:
21+
22+
```bicep
23+
resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-10-01-preview' = {
24+
name: guid(resourceGroup().id, principalId, roleDefinitionId)
25+
properties: {
26+
roleDefinitionId: roleDefinitionId
27+
principalId: principalId
28+
principalType: principalType
29+
}
30+
}
31+
```
32+
33+
This approach:
34+
- Creates a unique but deterministic GUID based on the combination of inputs
35+
- Ensures the same role assignment always gets the same GUID
36+
- Prevents the "RoleAssignmentExists" error on subsequent deployments
37+
- Works for both new and existing role assignments
38+
39+
### Option 2: Check Existing Role Assignments Before Creating New Ones
40+
41+
If you're using Azure CLI in scripts:
42+
43+
```bash
44+
# Check if role exists before assigning
45+
role_exists=$(az role assignment list --assignee "your-principal-id" --role "your-role" --scope "your-scope" --query "[].id" -o tsv)
46+
47+
if [ -z "$role_exists" ]; then
48+
# Role doesn't exist, create it
49+
az role assignment create --assignee "your-principal-id" --role "your-role" --scope "your-scope"
50+
else
51+
echo "Role assignment already exists"
52+
fi
53+
```
54+
55+
### Option 3: For GitHub Actions Workflows
56+
57+
If you're experiencing this in GitHub Actions with the `azure/login` action:
58+
59+
```yaml
60+
- name: Azure Login
61+
uses: azure/login@v1
62+
with:
63+
creds: ${{ secrets.AZURE_CREDENTIALS }}
64+
allow-no-subscriptions: true # Add this if you don't need subscription access
65+
```
66+
67+
### Option 4: For Azure Portal Deployments
68+
69+
If you're deploying through the Azure Portal:
70+
71+
1. Check existing role assignments:
72+
- Navigate to your resource
73+
- Select "Access control (IAM)"
74+
- Check if the role assignment already exists
75+
76+
2. Consider using "Access control (IAM)" → "Check access" to verify existing permissions before adding new ones
77+
78+
## For Your FinBin App Service Deployment
79+
80+
Since you're deploying an App Service with connections to Azure SQL and Azure OpenAI:
81+
82+
1. Instead of repeatedly assigning roles, configure a **Managed Identity** for your App Service
83+
2. If using Bicep for deployment:
84+
```bicep
85+
// Define the role assignment with a deterministic GUID
86+
resource appServiceRoleAssignment 'Microsoft.Authorization/roleAssignments@2020-10-01-preview' = {
87+
name: guid(resourceGroup().id, appService.id, roleDefinitionId)
88+
scope: sqlServer.id // For example, to grant access to SQL Server
89+
properties: {
90+
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'role-guid-here')
91+
principalId: appService.identity.principalId
92+
principalType: 'ServicePrincipal'
93+
}
94+
}
95+
```
96+
3. Use Key Vault references in your App Service configuration to securely store and access credentials
97+
98+
If you're continuing to encounter this error despite these measures, try:
99+
- Deleting the existing role assignment first, then creating it again
100+
- Using a different deployment principal
101+
- Using a different scope for the assignment (resource-specific vs. resource group level)

0 commit comments

Comments
 (0)