Skip to content

Commit 95906e5

Browse files
authored
Merge branch 'aliencube:main' into feature/22-request-payload-definition
2 parents ad5475f + 97a3b53 commit 95906e5

File tree

86 files changed

+4614
-1038
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+4614
-1038
lines changed

.gitattributes

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto
3+
4+
*.sln text eol=crlf
5+
*.csproj text eol=crlf
6+
*.props text eol=crlf
7+
*.sh text eol=lf

.github/workflows/azure-dev.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ jobs:
2525
AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
2626
AZURE_OPENAI_KEYS: ${{ secrets.AZURE_OPENAI_KEYS }}
2727
AZURE_KEYVAULT_URI: ${{ secrets.AZURE_KEYVAULT_URI }}
28-
AZURE_KEYVAULT_SECRET_NAME: ${{ vars.AZURE_KEYVAULT_SECRET_NAME }}
28+
AZURE_KEYVAULT_SECRET_NAME_OPENAI: ${{ vars.AZURE_KEYVAULT_SECRET_NAME_OPENAI }}
29+
AZURE_KEYVAULT_SECRET_NAME_STORAGE: ${{ vars.AZURE_KEYVAULT_SECRET_NAME_STORAGE }}
2930

3031
steps:
3132
- name: Checkout
@@ -54,7 +55,8 @@ jobs:
5455
$appsettings = Get-Content -Path "./src/AzureOpenAIProxy.ApiApp/appsettings.json" -Raw | ConvertFrom-Json
5556
$appsettings.Azure.OpenAI.Instances = @()
5657
$appsettings.Azure.KeyVault.VaultUri = "${{ env.AZURE_KEYVAULT_URI }}"
57-
$appsettings.Azure.KeyVault.SecretName = "${{ env.AZURE_KEYVAULT_SECRET_NAME }}"
58+
$appsettings.Azure.KeyVault.SecretNames.OpenAI = "${{ env.AZURE_KEYVAULT_SECRET_NAME_OPENAI }}"
59+
$appsettings.Azure.KeyVault.SecretNames.Storage = "${{ env.AZURE_KEYVAULT_SECRET_NAME_STORAGE }}"
5860
$appsettings | ConvertTo-Json -Depth 100 | Set-Content -Path "./src/AzureOpenAIProxy.ApiApp/appsettings.json" -Encoding UTF8 -Force
5961
6062
- name: Install Spectral Cli

.spectral.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,25 @@ rules:
8181
- field: 'content'
8282
function: truthy
8383
message: Content is required
84+
85+
# Ensure endpoints with path variables define a 404 response
86+
# path에 path variable이 있다면 404 응답 코드가 있어야 함
87+
path-variables-require-404:
88+
description: Path variables must include a 404 response
89+
severity: error
90+
given: $.paths[*][*].parameters[?(@.in == 'path')]^^
91+
then:
92+
- field: responses.404
93+
function: truthy
94+
message: Response 404 is required
95+
96+
# Ensure POST, PUT, PATCH methods define a 400 response
97+
# verb가 POST, PUT, PATCH일 경우 400 응답코드가 있어야 함
98+
post-put-patch-require-400:
99+
description: POST, PUT, PATCH methods must include a 400 response
100+
given: $.paths[*][?(@property == 'post' || @property == 'put' || @property == 'patch')]
101+
severity: error
102+
then:
103+
- field: responses.400
104+
function: truthy
105+
message: Response 400 is required

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<ImplicitUsings>enable</ImplicitUsings>
88
<Nullable>enable</Nullable>
99

10-
<AspireVersion>8.2.0</AspireVersion>
10+
<AspireVersion>8.2.1</AspireVersion>
1111
<AzureOpenAIVersion>2.*-*</AzureOpenAIVersion>
1212
<AspNetCoreVersion>8.*</AspNetCoreVersion>
1313
<MicrosoftExtensionsVersion>8.*</MicrosoftExtensionsVersion>

infra/aspire.bicep

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ param enabledForDeployment bool = true
1717
param enabledForTemplateDeployment bool = true
1818
param enableRbacAuthorization bool = true
1919

20+
//TODO: 배포 시점에 사용자 princpalId, apiapp principalId를 받는 방법 조사
21+
//param creatorAdminPrincipalId string = ''
22+
//param apiAppUserPrincipalId string = ''
23+
24+
// parameters for storage account
25+
param storageAccountName string = ''
26+
// tableNames passed as a comma separated string from command line
27+
param tableNames string = 'events'
28+
2029
var abbrs = loadJsonContent('./abbreviations.json')
2130

2231
// Tags that should be applied to all resources.
@@ -39,6 +48,9 @@ var resourceToken = uniqueString(resourceGroup().id)
3948
#disable-next-line no-unused-vars
4049
// var apiServiceName = 'python-api'
4150

51+
// tables for storage account seperated by comma
52+
var tables = split(tableNames, ',')
53+
4254
// Add resources to be provisioned below.
4355

4456
// Provision Key Vault
@@ -54,6 +66,35 @@ module keyVault './core/security/keyvault.bicep' = {
5466
}
5567
}
5668

69+
// Provision Storage Account
70+
module storageAccount './core/storage/storage-account.bicep' = {
71+
name: 'storageAccount'
72+
params: {
73+
name: !empty(storageAccountName) ? storageAccountName : '${abbrs.storageStorageAccounts}${resourceToken}'
74+
location: location
75+
tags: tags
76+
tables: tables
77+
keyVaultName: keyVault.outputs.name
78+
}
79+
}
80+
81+
// TODO: Key vault Secret 권한부여, 생성한 사람에게 관리자 권한을, 그 외에는 secret user 권한을 부여
82+
//resource keyVaultSecretRoleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = {
83+
// name: guid(resourceGroup().id, resolvedKeyVaultName, 'secret-role-assignment')
84+
// properties: {
85+
// principalId: creatorAdminPrincipalId
86+
// roleDefinitionId: '00482A5A-887F-4FB3-B363-3B7FE8E74483' // administrator role
87+
// }
88+
//}
89+
//
90+
//resource keyVaultSecretApiAppRoleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = {
91+
// name: guid(resourceGroup().id, resolvedKeyVaultName, 'secret-apiapp-role-assignment')
92+
// properties: {
93+
// principalId: apiAppUserPrincipalId
94+
// roleDefinitionId: '4633458B-17DE-408A-B874-0445C86B69E6' // secret user role
95+
// }
96+
//}
97+
5798
// Add outputs from the deployment here, if needed.
5899
//
59100
// This allows the outputs to be referenced by other bicep deployments in the deployment pipeline,
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
metadata description = 'Creates an Azure storage account.'
2+
param name string
3+
param location string = resourceGroup().location
4+
param tags object = {}
5+
6+
@allowed([
7+
'Cool'
8+
'Hot'
9+
'Premium' ])
10+
param accessTier string = 'Hot'
11+
param allowBlobPublicAccess bool = true
12+
param allowCrossTenantReplication bool = true
13+
param allowSharedKeyAccess bool = true
14+
param containers array = []
15+
param corsRules array = []
16+
param defaultToOAuthAuthentication bool = false
17+
param deleteRetentionPolicy object = {}
18+
@allowed([ 'AzureDnsZone', 'Standard' ])
19+
param dnsEndpointType string = 'Standard'
20+
param files array = []
21+
param kind string = 'StorageV2'
22+
param minimumTlsVersion string = 'TLS1_2'
23+
param queues array = []
24+
param shareDeleteRetentionPolicy object = {}
25+
param supportsHttpsTrafficOnly bool = true
26+
param tables array = []
27+
param networkAcls object = {
28+
bypass: 'AzureServices'
29+
defaultAction: 'Allow'
30+
}
31+
@allowed([ 'Enabled', 'Disabled' ])
32+
param publicNetworkAccess string = 'Enabled'
33+
param sku object = { name: 'Standard_LRS' }
34+
param keyVaultName string = ''
35+
36+
resource storage 'Microsoft.Storage/storageAccounts@2023-01-01' = {
37+
name: name
38+
location: location
39+
tags: tags
40+
kind: kind
41+
sku: sku
42+
properties: {
43+
accessTier: accessTier
44+
allowBlobPublicAccess: allowBlobPublicAccess
45+
allowCrossTenantReplication: allowCrossTenantReplication
46+
allowSharedKeyAccess: allowSharedKeyAccess
47+
defaultToOAuthAuthentication: defaultToOAuthAuthentication
48+
dnsEndpointType: dnsEndpointType
49+
minimumTlsVersion: minimumTlsVersion
50+
networkAcls: networkAcls
51+
publicNetworkAccess: publicNetworkAccess
52+
supportsHttpsTrafficOnly: supportsHttpsTrafficOnly
53+
}
54+
55+
resource blobServices 'blobServices' = if (!empty(containers)) {
56+
name: 'default'
57+
properties: {
58+
cors: {
59+
corsRules: corsRules
60+
}
61+
deleteRetentionPolicy: deleteRetentionPolicy
62+
}
63+
resource container 'containers' = [for container in containers: {
64+
name: container.name
65+
properties: {
66+
// todo: Warning use-safe-access: Use the safe access (.?) operator instead of checking object contents with the 'contains' function. [https://aka.ms/bicep/linter/use-safe-access]
67+
publicAccess: contains(container, 'publicAccess') ? container.publicAccess : 'None'
68+
}
69+
}]
70+
}
71+
72+
resource fileServices 'fileServices' = if (!empty(files)) {
73+
name: 'default'
74+
properties: {
75+
cors: {
76+
corsRules: corsRules
77+
}
78+
shareDeleteRetentionPolicy: shareDeleteRetentionPolicy
79+
}
80+
}
81+
82+
resource queueServices 'queueServices' = if (!empty(queues)) {
83+
name: 'default'
84+
properties: {
85+
86+
}
87+
resource queue 'queues' = [for queue in queues: {
88+
name: queue.name
89+
properties: {
90+
metadata: {}
91+
}
92+
}]
93+
}
94+
95+
resource tableServices 'tableServices' = if (!empty(tables)) {
96+
name: 'default'
97+
properties: {}
98+
// create tables pre-defined in aspire.bicep
99+
resource table 'tables' = [for table in tables: {
100+
name: table
101+
properties: {}
102+
}]
103+
}
104+
}
105+
106+
// Save Storage Account Connection String in Key Vault Secret
107+
module keyVaultSecrets '../../core/security/keyvault-secret.bicep' = {
108+
name: 'keyVaultSecrets'
109+
params: {
110+
name: 'storage-connection-string'
111+
secretValue:'DefaultEndpointsProtocol=https;EndpointSuffix=${environment().suffixes.storage};AccountName=${storage.name};AccountKey=${storage.listKeys().keys[0].value};BlobEndpoint=${storage.properties.primaryEndpoints.blob};FileEndpoint=${storage.properties.primaryEndpoints.file};QueueEndpoint=${storage.properties.primaryEndpoints.queue};TableEndpoint=${storage.properties.primaryEndpoints.table}'
112+
keyVaultName:keyVaultName
113+
}
114+
}
115+
116+
output id string = storage.id
117+
output name string = storage.name
118+
output primaryEndpoints object = storage.properties.primaryEndpoints

src/AzureOpenAIProxy.ApiApp/AzureOpenAIProxy.ApiApp.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
<ItemGroup>
99
<PackageReference Include="Azure.AI.OpenAI" Version="$(AzureOpenAIVersion)" />
10+
<PackageReference Include="Azure.Data.Tables" Version="12.9.0" />
1011
<PackageReference Include="Azure.Identity" Version="1.12.0" />
1112
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.6.0" />
1213
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="$(AspNetCoreVersion)" />

src/AzureOpenAIProxy.ApiApp/Configurations/KeyVaultSettings.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class KeyVaultSettings
1616
public string? VaultUri { get; set; }
1717

1818
/// <summary>
19-
/// Gets or sets the secret name.
19+
/// Gets or sets the secret names.
2020
/// </summary>
21-
public string? SecretName { get; set; }
21+
public Dictionary<string, string> SecretNames { get; set; } = [];
2222
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace AzureOpenAIProxy.ApiApp.Configurations;
2+
3+
/// <summary>
4+
/// This represents the settings entity for storage account.
5+
/// </summary>
6+
public class StorageAccountSettings
7+
{
8+
/// <summary>
9+
/// Gets the name of the configuration settings.
10+
/// </summary>
11+
public const string Name = "StorageAccount";
12+
13+
/// <summary>
14+
/// Gets or sets the <see cref="TableStorageSettings"/> instance.
15+
/// </summary>
16+
public TableStorageSettings TableStorage { get; set; } = new();
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace AzureOpenAIProxy.ApiApp.Configurations;
2+
3+
/// <summary>
4+
/// This represents the settings entity for Azure Table Stroage.
5+
/// </summary>
6+
public class TableStorageSettings
7+
{
8+
/// <summary>
9+
/// Gets the name of the configuration settings.
10+
/// </summary>
11+
public const string Name = "TableStorage";
12+
13+
/// <summary>
14+
/// Gets or sets the table name.
15+
/// </summary>
16+
public string? TableName { get; set; }
17+
}

0 commit comments

Comments
 (0)