@gradientedge/cdk-utils-azure 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/src/common/constants.d.ts +83 -0
- package/dist/src/common/constants.js +87 -0
- package/dist/src/common/construct.d.ts +80 -0
- package/dist/src/common/construct.js +128 -0
- package/dist/src/common/index.d.ts +6 -0
- package/dist/src/common/index.js +6 -0
- package/dist/src/common/resource-name-formatter.d.ts +18 -0
- package/dist/src/common/resource-name-formatter.js +34 -0
- package/dist/src/common/stack.d.ts +46 -0
- package/dist/src/common/stack.js +120 -0
- package/dist/src/common/tagging.d.ts +29 -0
- package/dist/src/common/tagging.js +78 -0
- package/dist/src/common/types.d.ts +57 -0
- package/dist/src/common/types.js +1 -0
- package/dist/src/construct/event-handler/index.d.ts +2 -0
- package/dist/src/construct/event-handler/index.js +2 -0
- package/dist/src/construct/event-handler/main.d.ts +61 -0
- package/dist/src/construct/event-handler/main.js +180 -0
- package/dist/src/construct/event-handler/types.d.ts +35 -0
- package/dist/src/construct/event-handler/types.js +1 -0
- package/dist/src/construct/function-app/index.d.ts +2 -0
- package/dist/src/construct/function-app/index.js +2 -0
- package/dist/src/construct/function-app/main.d.ts +128 -0
- package/dist/src/construct/function-app/main.js +374 -0
- package/dist/src/construct/function-app/types.d.ts +33 -0
- package/dist/src/construct/function-app/types.js +1 -0
- package/dist/src/construct/index.d.ts +6 -0
- package/dist/src/construct/index.js +6 -0
- package/dist/src/construct/rest-api/index.d.ts +2 -0
- package/dist/src/construct/rest-api/index.js +2 -0
- package/dist/src/construct/rest-api/main.d.ts +64 -0
- package/dist/src/construct/rest-api/main.js +216 -0
- package/dist/src/construct/rest-api/types.d.ts +25 -0
- package/dist/src/construct/rest-api/types.js +1 -0
- package/dist/src/construct/rest-api-function/index.d.ts +2 -0
- package/dist/src/construct/rest-api-function/index.js +2 -0
- package/dist/src/construct/rest-api-function/main.d.ts +66 -0
- package/dist/src/construct/rest-api-function/main.js +302 -0
- package/dist/src/construct/rest-api-function/types.d.ts +29 -0
- package/dist/src/construct/rest-api-function/types.js +1 -0
- package/dist/src/construct/rest-api-with-cache/index.d.ts +2 -0
- package/dist/src/construct/rest-api-with-cache/index.js +2 -0
- package/dist/src/construct/rest-api-with-cache/main.d.ts +41 -0
- package/dist/src/construct/rest-api-with-cache/main.js +85 -0
- package/dist/src/construct/rest-api-with-cache/types.d.ts +13 -0
- package/dist/src/construct/rest-api-with-cache/types.js +1 -0
- package/dist/src/construct/site-with-webapp/index.d.ts +2 -0
- package/dist/src/construct/site-with-webapp/index.js +2 -0
- package/dist/src/construct/site-with-webapp/main.d.ts +60 -0
- package/dist/src/construct/site-with-webapp/main.js +176 -0
- package/dist/src/construct/site-with-webapp/types.d.ts +30 -0
- package/dist/src/construct/site-with-webapp/types.js +1 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.js +4 -0
- package/dist/src/services/api-management/index.d.ts +2 -0
- package/dist/src/services/api-management/index.js +2 -0
- package/dist/src/services/api-management/main.d.ts +143 -0
- package/dist/src/services/api-management/main.js +244 -0
- package/dist/src/services/api-management/types.d.ts +72 -0
- package/dist/src/services/api-management/types.js +1 -0
- package/dist/src/services/app-configuration/index.d.ts +2 -0
- package/dist/src/services/app-configuration/index.js +2 -0
- package/dist/src/services/app-configuration/main.d.ts +41 -0
- package/dist/src/services/app-configuration/main.js +71 -0
- package/dist/src/services/app-configuration/types.d.ts +3 -0
- package/dist/src/services/app-configuration/types.js +1 -0
- package/dist/src/services/app-service/index.d.ts +2 -0
- package/dist/src/services/app-service/index.js +2 -0
- package/dist/src/services/app-service/main.d.ts +40 -0
- package/dist/src/services/app-service/main.js +90 -0
- package/dist/src/services/app-service/types.d.ts +6 -0
- package/dist/src/services/app-service/types.js +1 -0
- package/dist/src/services/application-insights/index.d.ts +2 -0
- package/dist/src/services/application-insights/index.js +2 -0
- package/dist/src/services/application-insights/main.d.ts +40 -0
- package/dist/src/services/application-insights/main.js +68 -0
- package/dist/src/services/application-insights/types.d.ts +6 -0
- package/dist/src/services/application-insights/types.js +1 -0
- package/dist/src/services/authorisation/constants.d.ts +13 -0
- package/dist/src/services/authorisation/constants.js +14 -0
- package/dist/src/services/authorisation/index.d.ts +3 -0
- package/dist/src/services/authorisation/index.js +3 -0
- package/dist/src/services/authorisation/main.d.ts +84 -0
- package/dist/src/services/authorisation/main.js +120 -0
- package/dist/src/services/authorisation/types.d.ts +3 -0
- package/dist/src/services/authorisation/types.js +1 -0
- package/dist/src/services/cosmosdb/constants.d.ts +8 -0
- package/dist/src/services/cosmosdb/constants.js +10 -0
- package/dist/src/services/cosmosdb/index.d.ts +3 -0
- package/dist/src/services/cosmosdb/index.js +3 -0
- package/dist/src/services/cosmosdb/main.d.ts +87 -0
- package/dist/src/services/cosmosdb/main.js +162 -0
- package/dist/src/services/cosmosdb/types.d.ts +9 -0
- package/dist/src/services/cosmosdb/types.js +1 -0
- package/dist/src/services/dns/index.d.ts +2 -0
- package/dist/src/services/dns/index.js +2 -0
- package/dist/src/services/dns/main.d.ts +58 -0
- package/dist/src/services/dns/main.js +107 -0
- package/dist/src/services/dns/types.d.ts +9 -0
- package/dist/src/services/dns/types.js +1 -0
- package/dist/src/services/eventgrid/index.d.ts +2 -0
- package/dist/src/services/eventgrid/index.js +2 -0
- package/dist/src/services/eventgrid/main.d.ts +69 -0
- package/dist/src/services/eventgrid/main.js +136 -0
- package/dist/src/services/eventgrid/types.d.ts +11 -0
- package/dist/src/services/eventgrid/types.js +1 -0
- package/dist/src/services/function/index.d.ts +2 -0
- package/dist/src/services/function/index.js +2 -0
- package/dist/src/services/function/main.d.ts +60 -0
- package/dist/src/services/function/main.js +223 -0
- package/dist/src/services/function/types.d.ts +20 -0
- package/dist/src/services/function/types.js +1 -0
- package/dist/src/services/index.d.ts +18 -0
- package/dist/src/services/index.js +18 -0
- package/dist/src/services/key-vault/index.d.ts +2 -0
- package/dist/src/services/key-vault/index.js +2 -0
- package/dist/src/services/key-vault/main.d.ts +49 -0
- package/dist/src/services/key-vault/main.js +83 -0
- package/dist/src/services/key-vault/types.d.ts +5 -0
- package/dist/src/services/key-vault/types.js +1 -0
- package/dist/src/services/monitor/index.d.ts +2 -0
- package/dist/src/services/monitor/index.js +2 -0
- package/dist/src/services/monitor/main.d.ts +31 -0
- package/dist/src/services/monitor/main.js +36 -0
- package/dist/src/services/monitor/types.d.ts +3 -0
- package/dist/src/services/monitor/types.js +1 -0
- package/dist/src/services/operational-insights/index.d.ts +2 -0
- package/dist/src/services/operational-insights/index.js +2 -0
- package/dist/src/services/operational-insights/main.d.ts +40 -0
- package/dist/src/services/operational-insights/main.js +64 -0
- package/dist/src/services/operational-insights/types.d.ts +5 -0
- package/dist/src/services/operational-insights/types.js +1 -0
- package/dist/src/services/portal/error.d.ts +5 -0
- package/dist/src/services/portal/error.js +10 -0
- package/dist/src/services/portal/index.d.ts +4 -0
- package/dist/src/services/portal/index.js +4 -0
- package/dist/src/services/portal/main.d.ts +33 -0
- package/dist/src/services/portal/main.js +51 -0
- package/dist/src/services/portal/renderer.d.ts +11 -0
- package/dist/src/services/portal/renderer.js +156 -0
- package/dist/src/services/portal/types.d.ts +40 -0
- package/dist/src/services/portal/types.js +1 -0
- package/dist/src/services/redis/index.d.ts +2 -0
- package/dist/src/services/redis/index.js +2 -0
- package/dist/src/services/redis/main.d.ts +31 -0
- package/dist/src/services/redis/main.js +52 -0
- package/dist/src/services/redis/types.d.ts +3 -0
- package/dist/src/services/redis/types.js +1 -0
- package/dist/src/services/resource-group/index.d.ts +2 -0
- package/dist/src/services/resource-group/index.js +2 -0
- package/dist/src/services/resource-group/main.d.ts +38 -0
- package/dist/src/services/resource-group/main.js +53 -0
- package/dist/src/services/resource-group/types.d.ts +3 -0
- package/dist/src/services/resource-group/types.js +1 -0
- package/dist/src/services/security-center/index.d.ts +2 -0
- package/dist/src/services/security-center/index.js +2 -0
- package/dist/src/services/security-center/main.d.ts +31 -0
- package/dist/src/services/security-center/main.js +33 -0
- package/dist/src/services/security-center/types.d.ts +3 -0
- package/dist/src/services/security-center/types.js +1 -0
- package/dist/src/services/servicebus/index.d.ts +2 -0
- package/dist/src/services/servicebus/index.js +2 -0
- package/dist/src/services/servicebus/main.d.ts +67 -0
- package/dist/src/services/servicebus/main.js +127 -0
- package/dist/src/services/servicebus/types.d.ts +11 -0
- package/dist/src/services/servicebus/types.js +1 -0
- package/dist/src/services/storage/index.d.ts +2 -0
- package/dist/src/services/storage/index.js +2 -0
- package/dist/src/services/storage/main.d.ts +88 -0
- package/dist/src/services/storage/main.js +173 -0
- package/dist/src/services/storage/types.d.ts +20 -0
- package/dist/src/services/storage/types.js +1 -0
- package/dist/src/types/index.d.ts +4 -0
- package/dist/src/types/index.js +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import * as archive from '@pulumi/archive';
|
|
2
|
+
import { getConfigurationStoreOutput, } from '@pulumi/azure-native/appconfiguration/index.js';
|
|
3
|
+
import { getComponentOutput } from '@pulumi/azure-native/applicationinsights/index.js';
|
|
4
|
+
import { SkuFamily, SkuName } from '@pulumi/azure-native/keyvault/index.js';
|
|
5
|
+
import { listStorageAccountKeysOutput } from '@pulumi/azure-native/storage/index.js';
|
|
6
|
+
import { AuthenticationType, FunctionsDeploymentStorageType, } from '@pulumi/azure-native/web/index.js';
|
|
7
|
+
import * as pulumi from '@pulumi/pulumi';
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import _ from 'lodash';
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
import { CommonAzureConstruct } from '../../common/index.js';
|
|
12
|
+
import { CosmosRoleDefinition } from '../../services/cosmosdb/constants.js';
|
|
13
|
+
import { AzureAppConfigurationManager, RoleDefinitionId } from '../../services/index.js';
|
|
14
|
+
/**
|
|
15
|
+
* @classdesc Provides a construct to create and deploy an Azure Function App with Flex Consumption hosting
|
|
16
|
+
* @example
|
|
17
|
+
* import { AzureFunctionApp, AzureFunctionAppProps } from '@gradientedge/cdk-utils'
|
|
18
|
+
*
|
|
19
|
+
* class CustomConstruct extends AzureFunctionApp {
|
|
20
|
+
* constructor(id: string, props: AzureFunctionAppProps) {
|
|
21
|
+
* super(id, props)
|
|
22
|
+
* this.props = props
|
|
23
|
+
* this.id = id
|
|
24
|
+
* this.initResources()
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
*/
|
|
28
|
+
export class AzureFunctionApp extends CommonAzureConstruct {
|
|
29
|
+
props;
|
|
30
|
+
app;
|
|
31
|
+
appServicePlan;
|
|
32
|
+
appEnvironmentVariables = {};
|
|
33
|
+
appStorageAccount;
|
|
34
|
+
appDeploymentStorageContainer;
|
|
35
|
+
appStorageContainer;
|
|
36
|
+
appConfig;
|
|
37
|
+
appCodeArchiveFile;
|
|
38
|
+
appConfigHash;
|
|
39
|
+
appKeyVaultsByResourceGroup;
|
|
40
|
+
appConnectionStrings;
|
|
41
|
+
appConfigPrefix;
|
|
42
|
+
appConfigurationsParsedConfig;
|
|
43
|
+
appConfigurationsOriginalParsedConfig;
|
|
44
|
+
dataStorageAccount;
|
|
45
|
+
dataStorageContainer;
|
|
46
|
+
applicationInsights;
|
|
47
|
+
functionDashboard;
|
|
48
|
+
constructor(id, props) {
|
|
49
|
+
super(id, props);
|
|
50
|
+
this.props = props;
|
|
51
|
+
this.id = id;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* @summary Initialise and provision resources
|
|
55
|
+
*/
|
|
56
|
+
initResources() {
|
|
57
|
+
this.createResourceGroup();
|
|
58
|
+
this.resolveCommonLogAnalyticsWorkspace();
|
|
59
|
+
this.resolveApplicationInsights();
|
|
60
|
+
this.createAppServicePlan();
|
|
61
|
+
this.createdParsedAppConfigurations();
|
|
62
|
+
this.createAppConfiguration();
|
|
63
|
+
this.createAppConfigurations();
|
|
64
|
+
this.createStorageAccount();
|
|
65
|
+
this.createStorageDeploymentContainer();
|
|
66
|
+
this.createStorageContainer();
|
|
67
|
+
this.createDataStorageAccount();
|
|
68
|
+
this.createDataStorageContainer();
|
|
69
|
+
this.generateStorageContainerSas();
|
|
70
|
+
this.createFunctionHosts();
|
|
71
|
+
this.createCodePackage();
|
|
72
|
+
this.createFunctionAppSiteConfig();
|
|
73
|
+
this.createFunctionApp();
|
|
74
|
+
this.createRoleAssignments();
|
|
75
|
+
this.createFunctionDashboard();
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* @summary Method to resolve the Application Insights instance
|
|
79
|
+
*/
|
|
80
|
+
resolveApplicationInsights() {
|
|
81
|
+
if (!this.props.commonApplicationInsights || !this.props.commonApplicationInsights.resourceName)
|
|
82
|
+
return;
|
|
83
|
+
this.applicationInsights = getComponentOutput({
|
|
84
|
+
resourceName: this.props.commonApplicationInsights.resourceName,
|
|
85
|
+
resourceGroupName: this.props.commonApplicationInsights.resourceGroupName,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* @summary Method to create the App Service Plan for the function app
|
|
90
|
+
*/
|
|
91
|
+
createAppServicePlan() {
|
|
92
|
+
this.appServicePlan = this.appServiceManager.createAppServicePlan(`${this.id}-app-service-plan`, this, {
|
|
93
|
+
...this.props.functionApp.servicePlan,
|
|
94
|
+
name: this.id,
|
|
95
|
+
resourceGroupName: this.resourceGroup.name,
|
|
96
|
+
location: this.resourceGroup.location,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* @summary Method to create parsed app configurations
|
|
101
|
+
* - To be implemented in the overriding method in the implementation class
|
|
102
|
+
*/
|
|
103
|
+
createdParsedAppConfigurations() { }
|
|
104
|
+
/**
|
|
105
|
+
* @summary Method to create or resolve the App Configuration store
|
|
106
|
+
*/
|
|
107
|
+
createAppConfiguration() {
|
|
108
|
+
if (this.props.functionApp.appConfiguration) {
|
|
109
|
+
this.appConfig = this.appConfigurationManager.createConfigurationStore(`${this.id}-app-configuration`, this, {
|
|
110
|
+
...this.props.functionApp.appConfiguration,
|
|
111
|
+
resourceGroupName: this.resourceGroup.name,
|
|
112
|
+
location: this.resourceGroup.location,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
else if (!this.props.useConfigOverride) {
|
|
116
|
+
this.appConfig = getConfigurationStoreOutput({
|
|
117
|
+
configStoreName: this.props.existingConfigStoreName,
|
|
118
|
+
resourceGroupName: this.props.existingConfigStoreResourceGroupName,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
this.appConfigPrefix = _.camelCase(this.id);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* @summary Method to create app configurations
|
|
125
|
+
* - To be implemented in the overriding method in the implementation class
|
|
126
|
+
*/
|
|
127
|
+
createAppConfigurations() { }
|
|
128
|
+
/**
|
|
129
|
+
* @summary Method to create the storage account for the function app
|
|
130
|
+
*/
|
|
131
|
+
createStorageAccount() {
|
|
132
|
+
this.appStorageAccount = this.storageManager.createStorageAccount(`${this.id}-storage-account`, this, {
|
|
133
|
+
...this.props.functionApp.storageAccount,
|
|
134
|
+
location: this.resourceGroup.location,
|
|
135
|
+
resourceGroupName: this.resourceGroup.name,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* @summary Method to create the storage deployment container for the function app
|
|
140
|
+
*/
|
|
141
|
+
createStorageDeploymentContainer() {
|
|
142
|
+
this.appDeploymentStorageContainer = this.storageManager.createStorageContainer(`${this.id}-storage-deployment-container`, this, {
|
|
143
|
+
...this.props.functionApp.deploymentStorageContainer,
|
|
144
|
+
accountName: this.appStorageAccount.name,
|
|
145
|
+
resourceGroupName: this.resourceGroup.name,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* @summary Method to create the storage container for the function app
|
|
150
|
+
*/
|
|
151
|
+
createStorageContainer() {
|
|
152
|
+
if (!this.props.functionApp.storageContainer)
|
|
153
|
+
return;
|
|
154
|
+
this.appStorageContainer = this.storageManager.createStorageContainer(`${this.id}-storage-container`, this, {
|
|
155
|
+
...this.props.functionApp.storageContainer,
|
|
156
|
+
accountName: this.appStorageAccount.name,
|
|
157
|
+
resourceGroupName: this.resourceGroup.name,
|
|
158
|
+
});
|
|
159
|
+
this.appEnvironmentVariables = {
|
|
160
|
+
...this.appEnvironmentVariables,
|
|
161
|
+
AZURE_STORAGE_ACCOUNT_NAME: this.appStorageAccount.name,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* @summary Method to create the data storage account
|
|
166
|
+
*/
|
|
167
|
+
createDataStorageAccount() {
|
|
168
|
+
if (!this.props.dataStorageAccount)
|
|
169
|
+
return;
|
|
170
|
+
this.dataStorageAccount = this.storageManager.createStorageAccount(`${this.id}-data-storage-account`, this, {
|
|
171
|
+
...this.props.dataStorageAccount,
|
|
172
|
+
resourceGroupName: this.resourceGroup.name,
|
|
173
|
+
location: this.resourceGroup.location,
|
|
174
|
+
});
|
|
175
|
+
this.appEnvironmentVariables = {
|
|
176
|
+
...this.appEnvironmentVariables,
|
|
177
|
+
AZURE_STORAGE_ACCOUNT_NAME: this.dataStorageAccount.name,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* @summary Method to create the data storage container
|
|
182
|
+
*/
|
|
183
|
+
createDataStorageContainer() {
|
|
184
|
+
if (!this.props.dataStorageContainer)
|
|
185
|
+
return;
|
|
186
|
+
this.dataStorageContainer = this.storageManager.createStorageContainer(`${this.id}-data-storage-container`, this, {
|
|
187
|
+
...this.props.dataStorageContainer,
|
|
188
|
+
accountName: this.dataStorageAccount.name,
|
|
189
|
+
resourceGroupName: this.resourceGroup.name,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* @summary Method to generate a SAS token for the storage container and store it in Key Vault
|
|
194
|
+
*/
|
|
195
|
+
generateStorageContainerSas() {
|
|
196
|
+
if (!this.props.dataStorageContainerSas)
|
|
197
|
+
return;
|
|
198
|
+
const sasToken = this.storageManager.generateContainerSasToken(`${this.id}-storage-container`, this, this.props.dataStorageContainerSas, this.dataStorageAccount);
|
|
199
|
+
const keyVault = this.keyVaultManager.createKeyVault(`${this.id}`, this, {
|
|
200
|
+
vaultName: this.props.dataKeyVaultName,
|
|
201
|
+
location: this.resourceGroup.location,
|
|
202
|
+
resourceGroupName: this.resourceGroup.name,
|
|
203
|
+
properties: {
|
|
204
|
+
sku: {
|
|
205
|
+
name: SkuName.Standard,
|
|
206
|
+
family: SkuFamily.A,
|
|
207
|
+
},
|
|
208
|
+
tenantId: this.props.tenantId ?? '',
|
|
209
|
+
},
|
|
210
|
+
}, { ignoreChanges: ['location'] });
|
|
211
|
+
this.monitorManager.createMonitorDiagnosticSettings(`${this.id}-${this.props.dataKeyVaultName}`, this, {
|
|
212
|
+
name: `${this.props.dataKeyVaultName}-keyvault`,
|
|
213
|
+
resourceUri: keyVault.id,
|
|
214
|
+
workspaceId: this.commonLogAnalyticsWorkspace.id,
|
|
215
|
+
logAnalyticsDestinationType: 'Dedicated',
|
|
216
|
+
logs: [
|
|
217
|
+
{
|
|
218
|
+
categoryGroup: 'allLogs',
|
|
219
|
+
enabled: true,
|
|
220
|
+
},
|
|
221
|
+
],
|
|
222
|
+
metrics: [
|
|
223
|
+
{
|
|
224
|
+
category: 'AllMetrics',
|
|
225
|
+
enabled: true,
|
|
226
|
+
},
|
|
227
|
+
],
|
|
228
|
+
});
|
|
229
|
+
this.keyVaultManager.createKeyVaultSecret(`${this.id}-sas-token-secret`, this, {
|
|
230
|
+
vaultName: keyVault.name,
|
|
231
|
+
secretName: this.props.dataKeyVaultSecretName,
|
|
232
|
+
resourceGroupName: this.resourceGroup.name,
|
|
233
|
+
properties: {
|
|
234
|
+
value: sasToken,
|
|
235
|
+
},
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* @summary Method to create and configure the function host.json
|
|
240
|
+
*/
|
|
241
|
+
createFunctionHosts() {
|
|
242
|
+
const currentDirectory = path.resolve();
|
|
243
|
+
const hostsJsonFile = `${currentDirectory}/${this.props.functionApp.deploySource}/host.json`;
|
|
244
|
+
if (!fs.existsSync(hostsJsonFile))
|
|
245
|
+
return;
|
|
246
|
+
const sourceHostsConfig = JSON.parse(fs.readFileSync(hostsJsonFile).toString('utf-8'));
|
|
247
|
+
const hostsConfig = _.merge(sourceHostsConfig, this.props.hostsConfiguration, this.props.functionApp.hostsConfiguration);
|
|
248
|
+
fs.writeFileSync(hostsJsonFile, JSON.stringify(hostsConfig, null, 2));
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* @summary Method to create the code package archive for deployment
|
|
252
|
+
*/
|
|
253
|
+
createCodePackage() {
|
|
254
|
+
const currentDirectory = path.resolve();
|
|
255
|
+
this.appCodeArchiveFile = archive.getFileOutput({
|
|
256
|
+
type: 'zip',
|
|
257
|
+
sourceDir: `${currentDirectory}/${this.props.functionApp.deploySource}`,
|
|
258
|
+
outputPath: `${currentDirectory}/${this.props.functionApp.deploySource}/${this.props.functionApp.packageName}`,
|
|
259
|
+
excludes: ['*.zip'],
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* @summary Method to create the function app site configuration
|
|
264
|
+
* - To be implemented in the overriding method in the implementation class
|
|
265
|
+
*/
|
|
266
|
+
createFunctionAppSiteConfig() { }
|
|
267
|
+
/**
|
|
268
|
+
* @summary Method to create the Azure Function App with Flex Consumption hosting
|
|
269
|
+
*/
|
|
270
|
+
createFunctionApp(resourceOptions) {
|
|
271
|
+
this.app = this.functionManager.createFunctionAppFlexConsumption(`${this.id}-function-app-flex`, this, {
|
|
272
|
+
...this.props.functionApp,
|
|
273
|
+
name: this.props.functionApp.app.name ?? this.id,
|
|
274
|
+
serverFarmId: this.appServicePlan.id,
|
|
275
|
+
resourceGroupName: this.resourceGroup.name,
|
|
276
|
+
functionAppConfig: {
|
|
277
|
+
deployment: {
|
|
278
|
+
storage: {
|
|
279
|
+
type: FunctionsDeploymentStorageType.BlobContainer,
|
|
280
|
+
value: pulumi.interpolate `${this.appStorageAccount.primaryEndpoints.apply(e => e?.blob)}${this.appDeploymentStorageContainer.name}`,
|
|
281
|
+
authentication: {
|
|
282
|
+
type: AuthenticationType.StorageAccountConnectionString,
|
|
283
|
+
storageAccountConnectionStringName: 'AzureWebJobsStorage',
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
siteConfig: {
|
|
289
|
+
appSettings: [
|
|
290
|
+
..._.map(this.appEnvironmentVariables, (value, name) => ({ name, value })),
|
|
291
|
+
{
|
|
292
|
+
name: 'APPLICATIONINSIGHTS_CONNECTION_STRING',
|
|
293
|
+
value: this.applicationInsights.connectionString,
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
name: 'APPINSIGHTS_INSTRUMENTATIONKEY',
|
|
297
|
+
value: this.applicationInsights.instrumentationKey,
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
name: 'AzureWebJobsStorage',
|
|
301
|
+
value: pulumi.interpolate `DefaultEndpointsProtocol=https;AccountName=${this.appStorageAccount.name};AccountKey=${listStorageAccountKeysOutput({
|
|
302
|
+
resourceGroupName: this.resourceGroup.name,
|
|
303
|
+
accountName: this.appStorageAccount.name,
|
|
304
|
+
}).keys[0].value};EndpointSuffix=core.windows.net`,
|
|
305
|
+
},
|
|
306
|
+
],
|
|
307
|
+
connectionStrings: Object.fromEntries(this.appConnectionStrings.map(cs => [cs.name, { type: cs.type, value: cs.value }])),
|
|
308
|
+
},
|
|
309
|
+
httpsOnly: this.props.functionApp.app.httpsOnly ?? true,
|
|
310
|
+
}, { ...resourceOptions });
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* @summary Method to get the function app managed identity principal ID
|
|
314
|
+
*/
|
|
315
|
+
getFunctionAppPrincipalId() {
|
|
316
|
+
return this.app.identity.apply(identity => (identity?.principalId ? identity.principalId : ''));
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* @summary Method to create role assignments for the function app identity
|
|
320
|
+
*/
|
|
321
|
+
createRoleAssignments() {
|
|
322
|
+
if (this.props.dataStorageAccount) {
|
|
323
|
+
this.authorisationManager.grantRoleAssignmentToStorageAccount(`${this.id}-data`, this, this.dataStorageAccount.id, this.getFunctionAppPrincipalId(), RoleDefinitionId.STORAGE_BLOB_DATA_CONTRIBUTOR);
|
|
324
|
+
}
|
|
325
|
+
this.authorisationManager.grantRoleAssignmentToStorageAccount(this.id, this, this.appStorageAccount.id, this.getFunctionAppPrincipalId(), RoleDefinitionId.STORAGE_BLOB_DATA_CONTRIBUTOR);
|
|
326
|
+
if (!this.props.useConfigOverride) {
|
|
327
|
+
this.authorisationManager.grantRoleAssignmentToApplicationConfiguration(this.id, this, this.appConfig.id, this.getFunctionAppPrincipalId(), RoleDefinitionId.APP_CONFIGURATION_DATA_READER);
|
|
328
|
+
}
|
|
329
|
+
if (this.appConfigurationsParsedConfig &&
|
|
330
|
+
AzureAppConfigurationManager.hasCosmosDependencies(this.appConfigurationsParsedConfig)) {
|
|
331
|
+
this.cosmosDbManager.grantSqlRoleDefinitionToAccount(this.id, this, this.props.existingCosmosAccountName, this.props.existingCosmosAccountResourceGroupName, this.getFunctionAppPrincipalId(), [CosmosRoleDefinition.CONTRIBUTOR, CosmosRoleDefinition.READER]);
|
|
332
|
+
}
|
|
333
|
+
if (this.appKeyVaultsByResourceGroup && this.appKeyVaultsByResourceGroup.size > 0) {
|
|
334
|
+
this.appKeyVaultsByResourceGroup.forEach((keyVaultNames, resourceGroup) => {
|
|
335
|
+
keyVaultNames.forEach(keyVaultName => {
|
|
336
|
+
this.authorisationManager.grantRoleAssignmentToKeyVault(this.id, this, keyVaultName, resourceGroup, this.getFunctionAppPrincipalId(), RoleDefinitionId.KEY_VAULT_SECRETS_USER);
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
if (AzureAppConfigurationManager.hasEventGridTargets(this.appConfigurationsParsedConfig)) {
|
|
341
|
+
this.authorisationManager.grantRoleAssignmentToEventgridTopic(this.id, this, this.props.existingTopicName, this.props.existingTopicResourceGroupName, this.getFunctionAppPrincipalId(), RoleDefinitionId.EVENTGRID_DATA_SENDER);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* @summary Method to get the dashboard template variables
|
|
346
|
+
*/
|
|
347
|
+
dashboardVariables() {
|
|
348
|
+
return {
|
|
349
|
+
displayName: this.props.functionApp.dashboard.displayName,
|
|
350
|
+
name: this.id,
|
|
351
|
+
subscriptionId: this.props.subscriptionId,
|
|
352
|
+
functionAppName: this.app.name,
|
|
353
|
+
functionAppResourceGroupName: this.resourceGroup.name,
|
|
354
|
+
insightsAppName: this.applicationInsights.name,
|
|
355
|
+
insightsAppResourceGroupName: this.props.commonLogAnalyticsWorkspace?.resourceGroupName,
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* @summary Method to create the Azure Portal dashboard for the function app
|
|
360
|
+
*/
|
|
361
|
+
createFunctionDashboard() {
|
|
362
|
+
if (!this.props.functionApp.dashboard?.enabled)
|
|
363
|
+
return;
|
|
364
|
+
this.functionDashboard = this.portalManager.createDashBoard(`${this.id}-dsh`, this, {
|
|
365
|
+
displayName: this.props.functionApp.dashboard.displayName,
|
|
366
|
+
location: this.props.locationConfig?.[this.props.location].name,
|
|
367
|
+
dashboardName: this.id,
|
|
368
|
+
resourceGroupName: this.resourceGroup.name,
|
|
369
|
+
variables: this.dashboardVariables(),
|
|
370
|
+
panes: this.props.functionApp.dashboard.panes,
|
|
371
|
+
properties: this.appConfigurationsOriginalParsedConfig.appConfig,
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AppConfigurationProps, CommonAzureStackProps, ContainerSasTokenProps, FunctionAppFlexConsumptionProps, PortalDashboardProps, ServicePlanProps, StorageAccountProps, StorageContainerProps } from '../../index.js';
|
|
2
|
+
export interface OtelProps {
|
|
3
|
+
otelTracesSamplerArg: string;
|
|
4
|
+
}
|
|
5
|
+
export interface FunctionAppProperties {
|
|
6
|
+
app: FunctionAppFlexConsumptionProps;
|
|
7
|
+
appConfiguration: AppConfigurationProps;
|
|
8
|
+
dashboard: PortalDashboardProps;
|
|
9
|
+
deploymentStorageContainer: StorageContainerProps;
|
|
10
|
+
deploySource: string;
|
|
11
|
+
hostsConfiguration?: string;
|
|
12
|
+
packageName: string;
|
|
13
|
+
servicePlan: ServicePlanProps;
|
|
14
|
+
storageAccount: StorageAccountProps;
|
|
15
|
+
storageContainer: StorageContainerProps;
|
|
16
|
+
timerTriggerCronExpression: string;
|
|
17
|
+
}
|
|
18
|
+
export interface AzureFunctionAppProps extends CommonAzureStackProps {
|
|
19
|
+
existingTopicName: string;
|
|
20
|
+
existingTopicResourceGroupName: string;
|
|
21
|
+
existingCosmosAccountResourceGroupName: string;
|
|
22
|
+
existingCosmosAccountName: string;
|
|
23
|
+
hostsConfiguration: any;
|
|
24
|
+
existingConfigStoreResourceGroupName: string;
|
|
25
|
+
existingConfigStoreName: string;
|
|
26
|
+
functionApp: FunctionAppProperties;
|
|
27
|
+
useConfigOverride?: boolean;
|
|
28
|
+
dataStorageContainer: StorageContainerProps;
|
|
29
|
+
dataStorageAccount: StorageAccountProps;
|
|
30
|
+
dataStorageContainerSas: ContainerSasTokenProps;
|
|
31
|
+
dataKeyVaultName: string;
|
|
32
|
+
dataKeyVaultSecretName: string;
|
|
33
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { GetComponentResult } from '@pulumi/azure-native/applicationinsights/index.js';
|
|
2
|
+
import { Output } from '@pulumi/pulumi';
|
|
3
|
+
import { CommonAzureConstruct } from '../../common/index.js';
|
|
4
|
+
import { AzureApi, AzureRestApiProps } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* @classdesc Provides a construct to create and deploy an Azure API Management service with diagnostics and logging
|
|
7
|
+
* @example
|
|
8
|
+
* import { AzureRestApi, AzureRestApiProps } from '@gradientedge/cdk-utils'
|
|
9
|
+
*
|
|
10
|
+
* class CustomConstruct extends AzureRestApi {
|
|
11
|
+
* constructor(id: string, props: AzureRestApiProps) {
|
|
12
|
+
* super(id, props)
|
|
13
|
+
* this.props = props
|
|
14
|
+
* this.id = id
|
|
15
|
+
* this.initResources()
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
*/
|
|
19
|
+
export declare class AzureRestApi extends CommonAzureConstruct {
|
|
20
|
+
props: AzureRestApiProps;
|
|
21
|
+
api: AzureApi;
|
|
22
|
+
applicationInsights: Output<GetComponentResult>;
|
|
23
|
+
constructor(id: string, props: AzureRestApiProps);
|
|
24
|
+
/**
|
|
25
|
+
* @summary Initialise and provision resources
|
|
26
|
+
*/
|
|
27
|
+
initResources(): void;
|
|
28
|
+
/**
|
|
29
|
+
* @summary Method to resolve the API authentication Key Vault
|
|
30
|
+
*/
|
|
31
|
+
protected resolveApiKeyVault(): void;
|
|
32
|
+
/**
|
|
33
|
+
* @summary Method to resolve the Application Insights instance
|
|
34
|
+
*/
|
|
35
|
+
protected resolveApplicationInsights(): void;
|
|
36
|
+
/**
|
|
37
|
+
* @summary Method to create or resolve an existing API Management service
|
|
38
|
+
*/
|
|
39
|
+
protected createApiManagement(): void;
|
|
40
|
+
/**
|
|
41
|
+
* @summary Method to create the Key Vault role assignment for the API Management identity
|
|
42
|
+
*/
|
|
43
|
+
protected createNamespaceSecretRole(): void;
|
|
44
|
+
/**
|
|
45
|
+
* @summary Method to create the namespace secret in Key Vault for Application Insights
|
|
46
|
+
*/
|
|
47
|
+
protected createNamespaceSecret(): void;
|
|
48
|
+
/**
|
|
49
|
+
* @summary Method to create the API Management subscription and store the key in Key Vault
|
|
50
|
+
*/
|
|
51
|
+
protected createSubscriptionKeySecret(): void;
|
|
52
|
+
/**
|
|
53
|
+
* @summary Method to create the API Management logger with Application Insights integration
|
|
54
|
+
*/
|
|
55
|
+
protected createApiManagementLogger(): void;
|
|
56
|
+
/**
|
|
57
|
+
* @summary Method to create the API diagnostic settings for API Management
|
|
58
|
+
*/
|
|
59
|
+
protected createApiDiagnostic(): void;
|
|
60
|
+
/**
|
|
61
|
+
* @summary Method to create the Monitor diagnostic log settings for API Management
|
|
62
|
+
*/
|
|
63
|
+
protected createDiagnosticLog(): void;
|
|
64
|
+
}
|