@gradientedge/cdk-utils-azure 2.18.0 → 2.20.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.
@@ -116,10 +116,10 @@ export class CommonAzureStack extends ComponentResource {
116
116
  createConstruct() { }
117
117
  registerOutputs() {
118
118
  if (this.construct && this.construct.resourceGroup) {
119
- this.outputs = {
119
+ this.outputs = _.merge(this.outputs, {
120
120
  resourceGroupId: this.construct.resourceGroup.id,
121
121
  resourceGroupName: this.construct.resourceGroup.name,
122
- };
122
+ });
123
123
  super.registerOutputs(this.outputs);
124
124
  }
125
125
  }
@@ -14,6 +14,9 @@ export function isTaggableResource(resourceType) {
14
14
  return false;
15
15
  if (resourceType.startsWith('pulumi:'))
16
16
  return false;
17
+ if (resourceType.startsWith('azure-native:apimanagement:') &&
18
+ resourceType !== 'azure-native:apimanagement:ApiManagementService')
19
+ return false;
17
20
  // Extract the resource name from the type (e.g., 'ResourceGroup' from 'azure-native:resources:ResourceGroup')
18
21
  const resourceName = resourceType.split(':').pop() || '';
19
22
  // Check if this resource is in the exclusion list
@@ -3,6 +3,7 @@ import * as path from 'path';
3
3
  import * as archive from '@pulumi/archive';
4
4
  import { getConfigurationStoreOutput, } from '@pulumi/azure-native/appconfiguration/index.js';
5
5
  import { getComponentOutput } from '@pulumi/azure-native/applicationinsights/index.js';
6
+ import { PrincipalType } from '@pulumi/azure-native/authorization/index.js';
6
7
  import { SkuFamily, SkuName } from '@pulumi/azure-native/keyvault/index.js';
7
8
  import { listStorageAccountKeysOutput } from '@pulumi/azure-native/storage/index.js';
8
9
  import { AuthenticationType, FunctionsDeploymentStorageType, } from '@pulumi/azure-native/web/index.js';
@@ -321,11 +322,11 @@ export class AzureFunctionApp extends CommonAzureConstruct {
321
322
  */
322
323
  createRoleAssignments() {
323
324
  if (this.props.dataStorageAccount) {
324
- this.authorisationManager.grantRoleAssignmentToStorageAccount(`${this.id}-data`, this, this.dataStorageAccount.id, this.getFunctionAppPrincipalId(), RoleDefinitionId.STORAGE_BLOB_DATA_CONTRIBUTOR);
325
+ this.authorisationManager.grantRoleAssignmentToStorageAccount(`${this.id}-data`, this, this.dataStorageAccount.id, this.getFunctionAppPrincipalId(), this.authorisationManager.resolveRoleDefinitionId(this, RoleDefinitionId.STORAGE_BLOB_DATA_CONTRIBUTOR));
325
326
  }
326
- this.authorisationManager.grantRoleAssignmentToStorageAccount(this.id, this, this.appStorageAccount.id, this.getFunctionAppPrincipalId(), RoleDefinitionId.STORAGE_BLOB_DATA_CONTRIBUTOR);
327
+ this.authorisationManager.grantRoleAssignmentToStorageAccount(this.id, this, this.appStorageAccount.id, this.getFunctionAppPrincipalId(), this.authorisationManager.resolveRoleDefinitionId(this, RoleDefinitionId.STORAGE_BLOB_DATA_CONTRIBUTOR));
327
328
  if (!this.props.useConfigOverride) {
328
- this.authorisationManager.grantRoleAssignmentToApplicationConfiguration(this.id, this, this.appConfig.id, this.getFunctionAppPrincipalId(), RoleDefinitionId.APP_CONFIGURATION_DATA_READER);
329
+ this.authorisationManager.grantRoleAssignmentToApplicationConfiguration(this.id, this, this.appConfig.id, this.getFunctionAppPrincipalId(), PrincipalType.ServicePrincipal, this.authorisationManager.resolveRoleDefinitionId(this, RoleDefinitionId.APP_CONFIGURATION_DATA_READER));
329
330
  }
330
331
  if (this.appConfigurationsParsedConfig &&
331
332
  AzureAppConfigurationManager.hasCosmosDependencies(this.appConfigurationsParsedConfig)) {
@@ -334,12 +335,12 @@ export class AzureFunctionApp extends CommonAzureConstruct {
334
335
  if (this.appKeyVaultsByResourceGroup && this.appKeyVaultsByResourceGroup.size > 0) {
335
336
  this.appKeyVaultsByResourceGroup.forEach((keyVaultNames, resourceGroup) => {
336
337
  keyVaultNames.forEach(keyVaultName => {
337
- this.authorisationManager.grantRoleAssignmentToKeyVault(this.id, this, keyVaultName, resourceGroup, this.getFunctionAppPrincipalId(), RoleDefinitionId.KEY_VAULT_SECRETS_USER);
338
+ this.authorisationManager.grantRoleAssignmentToKeyVault(this.id, this, keyVaultName, resourceGroup, this.getFunctionAppPrincipalId(), this.authorisationManager.resolveRoleDefinitionId(this, RoleDefinitionId.KEY_VAULT_SECRETS_USER));
338
339
  });
339
340
  });
340
341
  }
341
342
  if (AzureAppConfigurationManager.hasEventGridTargets(this.appConfigurationsParsedConfig)) {
342
- this.authorisationManager.grantRoleAssignmentToEventgridTopic(this.id, this, this.props.existingTopicName, this.props.existingTopicResourceGroupName, this.getFunctionAppPrincipalId(), RoleDefinitionId.EVENTGRID_DATA_SENDER);
343
+ this.authorisationManager.grantRoleAssignmentToEventgridTopic(this.id, this, this.props.existingTopicName, this.props.existingTopicResourceGroupName, this.getFunctionAppPrincipalId(), this.authorisationManager.resolveRoleDefinitionId(this, RoleDefinitionId.EVENTGRID_DATA_SENDER));
343
344
  }
344
345
  }
345
346
  /**
@@ -1,5 +1,6 @@
1
- import { HostnameType, LoggerType } from '@pulumi/azure-native/apimanagement/index.js';
1
+ import { getApiManagementServiceOutput, HostnameType, LoggerType } from '@pulumi/azure-native/apimanagement/index.js';
2
2
  import { getComponentOutput } from '@pulumi/azure-native/applicationinsights/index.js';
3
+ import { PrincipalType } from '@pulumi/azure-native/authorization/index.js';
3
4
  import { getVaultOutput } from '@pulumi/azure-native/keyvault/index.js';
4
5
  import * as pulumi from '@pulumi/pulumi';
5
6
  import { CommonAzureConstruct } from '../../common/index.js';
@@ -83,7 +84,7 @@ export class AzureRestApi extends CommonAzureConstruct {
83
84
  {
84
85
  hostName: `api-${this.props.locationConfig?.[this.props.location].name}.${this.props.domainName}`,
85
86
  keyVaultId: this.props.apiManagement.certificateKeyVaultId,
86
- type: HostnameType.Management,
87
+ type: HostnameType.Proxy,
87
88
  },
88
89
  ];
89
90
  }
@@ -97,10 +98,15 @@ export class AzureRestApi extends CommonAzureConstruct {
97
98
  this.api.id = this.api.apim.id;
98
99
  this.api.name = this.api.apim.name;
99
100
  this.api.resourceGroupName = this.resourceGroup.name;
100
- if (this.props.apiManagement.certificateKeyVaultId) {
101
+ const apimIdentity = getApiManagementServiceOutput({
102
+ serviceName: this.api.apim.name,
103
+ resourceGroupName: this.resourceGroup.name,
104
+ }).identity;
105
+ if (this.props.apiManagement.certificateKeyVaultId && apimIdentity) {
101
106
  this.authorisationManager.createRoleAssignment(`${this.id}-kv-role`, this, {
102
- principalId: this.api.apim.identity.apply(identity => identity?.principalId ?? ''),
103
- roleDefinitionId: RoleDefinitionId.KEY_VAULT_CERTIFICATE_USER,
107
+ principalId: apimIdentity.apply(id => id?.principalId ?? ''),
108
+ roleDefinitionId: this.authorisationManager.resolveRoleDefinitionId(this, RoleDefinitionId.KEY_VAULT_CERTIFICATE_USER),
109
+ principalType: PrincipalType.ServicePrincipal,
104
110
  scope: this.props.apiManagement.certificateKeyVaultId,
105
111
  });
106
112
  }
@@ -117,11 +123,18 @@ export class AzureRestApi extends CommonAzureConstruct {
117
123
  createNamespaceSecretRole() {
118
124
  if (this.props.apiManagement.useExistingApiManagement)
119
125
  return;
120
- this.api.namedValueRoleAssignment = this.authorisationManager.createRoleAssignment(`${this.id}-key-vault-role-api-namespace`, this, {
121
- principalId: this.api.apim.identity.apply(identity => identity?.principalId ?? ''),
122
- roleDefinitionId: `/subscriptions/${this.props.subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6`,
123
- scope: this.api.authKeyVault.id,
124
- });
126
+ const apimIdentity = getApiManagementServiceOutput({
127
+ serviceName: this.api.apim.name,
128
+ resourceGroupName: this.resourceGroup.name,
129
+ }).identity;
130
+ if (apimIdentity) {
131
+ this.api.namedValueRoleAssignment = this.authorisationManager.createRoleAssignment(`${this.id}-key-vault-role-api-namespace`, this, {
132
+ principalId: apimIdentity.apply(id => id?.principalId ?? ''),
133
+ principalType: PrincipalType.ServicePrincipal,
134
+ roleDefinitionId: this.authorisationManager.resolveRoleDefinitionId(this, RoleDefinitionId.KEY_VAULT_SECRETS_USER),
135
+ scope: this.api.authKeyVault.id,
136
+ });
137
+ }
125
138
  }
126
139
  /**
127
140
  * @summary Method to create the namespace secret in Key Vault for Application Insights
@@ -131,8 +144,8 @@ export class AzureRestApi extends CommonAzureConstruct {
131
144
  return;
132
145
  this.api.namedValueSecret = this.keyVaultManager.createKeyVaultSecret(`${this.id}-key-vault-api-namespace-secret`, this, {
133
146
  vaultName: this.api.authKeyVault.name,
134
- secretName: `${this.applicationInsights.name}-${this.id}-key`,
135
- resourceGroupName: this.resourceGroup.name,
147
+ secretName: pulumi.interpolate `${this.applicationInsights.name}-${this.id}-key`,
148
+ resourceGroupName: this.props.apiAuthKeyVault.resourceGroupName,
136
149
  properties: {
137
150
  value: this.applicationInsights.instrumentationKey,
138
151
  },
@@ -150,12 +163,12 @@ export class AzureRestApi extends CommonAzureConstruct {
150
163
  displayName: 'all-apis',
151
164
  state: 'active',
152
165
  allowTracing: false,
153
- scope: '', // todo
166
+ scope: '/apis',
154
167
  });
155
168
  this.keyVaultManager.createKeyVaultSecret(`${this.id}-key-vault-api-subscription-key-secret`, this, {
156
169
  vaultName: this.api.authKeyVault.name,
157
170
  secretName: `${this.id}-subscription-key`,
158
- resourceGroupName: this.resourceGroup.name,
171
+ resourceGroupName: this.props.apiAuthKeyVault.resourceGroupName,
159
172
  properties: {
160
173
  value: apiManagementSubscription.primaryKey.apply(key => key ?? ''),
161
174
  },
@@ -171,21 +184,22 @@ export class AzureRestApi extends CommonAzureConstruct {
171
184
  displayName: this.applicationInsights.name,
172
185
  resourceGroupName: this.resourceGroup.name,
173
186
  serviceName: this.api.apim.name,
174
- namedValueId: `${this.applicationInsights.name}-key`,
187
+ namedValueId: pulumi.interpolate `${this.applicationInsights.name}-key`,
175
188
  secret: true,
176
189
  keyVault: {
177
- secretIdentifier: this.api.namedValueSecret.id,
190
+ secretIdentifier: this.api.namedValueSecret.properties.apply(p => p.secretUri),
178
191
  },
179
192
  });
180
193
  this.api.logger = this.apiManagementManager.createLogger(`${this.id}-am-logger`, this, {
194
+ loggerId: this.applicationInsights.name,
181
195
  resourceGroupName: this.resourceGroup.name,
182
196
  serviceName: this.api.apim.name,
183
197
  resourceId: this.applicationInsights.id,
184
198
  loggerType: LoggerType.ApplicationInsights,
185
199
  credentials: {
186
- instrumentationKey: `{{${apiAppNamedValue.displayName}}}`,
200
+ instrumentationKey: pulumi.interpolate `{{${apiAppNamedValue.displayName}}}`,
187
201
  },
188
- });
202
+ }, { dependsOn: [apiAppNamedValue] });
189
203
  }
190
204
  /**
191
205
  * @summary Method to create the API diagnostic settings for API Management
@@ -123,7 +123,7 @@ export class AzureRestApiFunction extends AzureFunctionApp {
123
123
  if (this.props.apiManagement.certificateKeyVaultId) {
124
124
  this.authorisationManager.createRoleAssignment(`${this.id}-kv-role`, this, {
125
125
  principalId: this.api.apim.identity.apply(identity => identity?.principalId ?? ''),
126
- roleDefinitionId: RoleDefinitionId.KEY_VAULT_CERTIFICATE_USER,
126
+ roleDefinitionId: this.authorisationManager.resolveRoleDefinitionId(this, RoleDefinitionId.KEY_VAULT_CERTIFICATE_USER),
127
127
  scope: this.props.apiManagement.certificateKeyVaultId,
128
128
  });
129
129
  }
@@ -64,8 +64,8 @@ export class AzureRestApiWithCache extends AzureRestApi {
64
64
  }).apply(keys => `${hostName}:10000,password=${keys.primaryKey},ssl=True,abortConnect=False`));
65
65
  this.api.redisNamedValueSecret = this.keyVaultManager.createKeyVaultSecret(`${this.id}-key-vault-redis-namespace-secret`, this, {
66
66
  vaultName: this.api.authKeyVault.name,
67
- secretName: `${this.api.redisCluster.name}key`,
68
- resourceGroupName: this.resourceGroup.name,
67
+ secretName: pulumi.interpolate `${this.api.redisCluster.name}key`,
68
+ resourceGroupName: this.props.apiAuthKeyVault.resourceGroupName,
69
69
  properties: {
70
70
  value: connectionString,
71
71
  },
@@ -76,13 +76,13 @@ export class AzureRestApiWithCache extends AzureRestApi {
76
76
  */
77
77
  createRedisCacheNamespace() {
78
78
  this.api.redisNamedValue = this.apiManagementManager.createNamedValue(`${this.id}-redis-nv`, this, {
79
- displayName: `${this.api.redisCluster.name}key`,
79
+ displayName: pulumi.interpolate `${this.api.redisCluster.name}key`,
80
80
  resourceGroupName: this.resourceGroup.name,
81
81
  serviceName: this.api.apim.name,
82
- namedValueId: `${this.api.redisCluster.name}key`,
82
+ namedValueId: pulumi.interpolate `${this.api.redisCluster.name}key`,
83
83
  secret: true,
84
84
  keyVault: {
85
- secretIdentifier: this.api.redisNamedValueSecret.id,
85
+ secretIdentifier: this.api.redisNamedValueSecret.properties.apply(p => p.secretUri),
86
86
  },
87
87
  });
88
88
  }
@@ -92,11 +92,11 @@ export class AzureRestApiWithCache extends AzureRestApi {
92
92
  createRedisCacheApiManagement() {
93
93
  this.apiManagementManager.createCache(`${this.id}-am-redis-cache`, this, {
94
94
  serviceName: this.api.apim.name,
95
- connectionString: `{{${this.api.redisNamedValue.name}}}`,
96
- cacheId: this.api.redisCluster.id,
95
+ connectionString: pulumi.interpolate `{{${this.api.redisNamedValue.name}}}`,
96
+ cacheId: this.api.redisCluster.name,
97
97
  resourceGroupName: this.resourceGroup.name,
98
98
  useFromLocation: this.api.redisCluster.location,
99
- description: `Redis cache for ${this.api.apim.name}`,
99
+ description: pulumi.interpolate `Redis cache for ${this.api.apim.name}`,
100
100
  });
101
101
  }
102
102
  }
@@ -71,7 +71,7 @@ export declare class AzureApiManagementManager {
71
71
  * @param resourceOptions Optional settings to control resource behaviour
72
72
  * @see [Pulumi Azure Native API Management Diagnostic]{@link https://www.pulumi.com/registry/packages/azure-native/api-docs/apimanagement/apidiagnostic/}
73
73
  */
74
- createApiDiagnostic(id: string, scope: CommonAzureConstruct, props: ApiDiagnosticProps, resourceOptions?: ResourceOptions): import("@pulumi/azure-native/apimanagement/apiDiagnostic.js").ApiDiagnostic;
74
+ createApiDiagnostic(id: string, scope: CommonAzureConstruct, props: ApiDiagnosticProps, resourceOptions?: ResourceOptions): import("@pulumi/azure-native/apimanagement/diagnostic.js").Diagnostic;
75
75
  /**
76
76
  * @summary Method to create a new API Logger
77
77
  * @param id scoped id of the resource
@@ -1,4 +1,4 @@
1
- import { Api, ApiDiagnostic, ApiManagementService, ApiOperation, ApiOperationPolicy, ApiPolicy, Backend, BackendProtocol, Cache, getApiManagementServiceOutput, Logger, LoggerType, NamedValue, Protocol, Subscription, } from '@pulumi/azure-native/apimanagement/index.js';
1
+ import { Api, ApiManagementService, ApiOperation, ApiOperationPolicy, ApiPolicy, Backend, BackendProtocol, Cache, Diagnostic, getApiManagementServiceOutput, Logger, LoggerType, NamedValue, Protocol, Subscription, } from '@pulumi/azure-native/apimanagement/index.js';
2
2
  import { listDatabaseKeysOutput } from '@pulumi/azure-native/redisenterprise/index.js';
3
3
  import * as pulumi from '@pulumi/pulumi';
4
4
  /**
@@ -148,7 +148,7 @@ export class AzureApiManagementManager {
148
148
  createApiDiagnostic(id, scope, props, resourceOptions) {
149
149
  if (!props)
150
150
  throw new Error(`Props undefined for ${id}`);
151
- return new ApiDiagnostic(`${id}`, props, { parent: scope, ...resourceOptions });
151
+ return new Diagnostic(`${id}`, props, { parent: scope, ...resourceOptions });
152
152
  }
153
153
  /**
154
154
  * @summary Method to create a new API Logger
@@ -30,14 +30,13 @@ export class AzureApplicationInsightsManager {
30
30
  if (!props)
31
31
  throw new Error(`Props undefined for ${id}`);
32
32
  // Get resource group name
33
- const resourceGroupName = (props.resourceGroupName ?? scope.props.resourceGroupName)
34
- ? `${scope.props.resourceGroupName}-${scope.props.stage}`
35
- : props.resourceGroupName;
33
+ const resourceGroupName = props.resourceGroupName ?? scope.resourceNameFormatter.format(scope.props.resourceGroupName);
36
34
  if (!resourceGroupName)
37
35
  throw new Error(`Resource group name undefined for ${id}`);
38
- const component = new Component(`${id}-ai`, {
36
+ const resourceName = scope.resourceNameFormatter.format(props.resourceName?.toString(), scope.props.resourceNameOptions?.applicationInsights);
37
+ const component = new Component(`${id}`, {
39
38
  ...props,
40
- resourceName: scope.resourceNameFormatter.format(props.resourceName?.toString(), scope.props.resourceNameOptions?.applicationInsights),
39
+ resourceName,
41
40
  resourceGroupName,
42
41
  applicationType: props.applicationType ?? ApplicationType.Web,
43
42
  kind: props.kind ?? 'web',
@@ -48,7 +47,12 @@ export class AzureApplicationInsightsManager {
48
47
  },
49
48
  }, { parent: scope, ...resourceOptions });
50
49
  if (props.billingFeatures) {
51
- this.createComponentCurrentBillingFeature(`${id}-billing`, scope, props.billingFeatures, {
50
+ this.createComponentCurrentBillingFeature(`${id}-billing`, scope, {
51
+ ...props.billingFeatures,
52
+ currentBillingFeatures: props.billingFeatures?.currentBillingFeatures ?? ['Basic'],
53
+ resourceName,
54
+ resourceGroupName,
55
+ }, {
52
56
  parent: scope,
53
57
  ...resourceOptions,
54
58
  });
@@ -1,3 +1,4 @@
1
+ import { PrincipalType } from '@pulumi/azure-native/authorization/index.js';
1
2
  import { Input, ResourceOptions } from '@pulumi/pulumi';
2
3
  import { CommonAzureConstruct } from '../../common/index.js';
3
4
  import { RoleDefinitionId } from './constants.js';
@@ -40,7 +41,7 @@ export declare class AzureAuthorisationManager {
40
41
  * @param roleDefinitionId the role definition id
41
42
  * @param resourceOptions Optional settings to control resource behaviour
42
43
  */
43
- grantRoleAssignmentToKeyVault(id: string, scope: CommonAzureConstruct, vaultName: string, resourceGroupName: Input<string>, principalId: Input<string>, roleDefinitionId: RoleDefinitionId, resourceOptions?: ResourceOptions): import("@pulumi/azure-native/authorization/roleAssignment.js").RoleAssignment;
44
+ grantRoleAssignmentToKeyVault(id: string, scope: CommonAzureConstruct, vaultName: string, resourceGroupName: Input<string>, principalId: Input<string>, roleDefinitionId: string, resourceOptions?: ResourceOptions): import("@pulumi/azure-native/authorization/roleAssignment.js").RoleAssignment;
44
45
  /**
45
46
  * @summary Method to grant a role assignment to event grid topic
46
47
  * @param id scoped id of the resource
@@ -51,7 +52,7 @@ export declare class AzureAuthorisationManager {
51
52
  * @param roleDefinitionId the role definition id
52
53
  * @param resourceOptions Optional settings to control resource behaviour
53
54
  */
54
- grantRoleAssignmentToEventgridTopic(id: string, scope: CommonAzureConstruct, topicName: Input<string>, resourceGroupName: Input<string>, principalId: Input<string>, roleDefinitionId: RoleDefinitionId, resourceOptions?: ResourceOptions): import("@pulumi/azure-native/authorization/roleAssignment.js").RoleAssignment;
55
+ grantRoleAssignmentToEventgridTopic(id: string, scope: CommonAzureConstruct, topicName: Input<string>, resourceGroupName: Input<string>, principalId: Input<string>, roleDefinitionId: string, resourceOptions?: ResourceOptions): import("@pulumi/azure-native/authorization/roleAssignment.js").RoleAssignment;
55
56
  /**
56
57
  * @summary Method to grant a role assignment to application configuration
57
58
  * @param id scoped id of the resource
@@ -61,7 +62,7 @@ export declare class AzureAuthorisationManager {
61
62
  * @param roleDefinitionId the role definition id
62
63
  * @param resourceOptions Optional settings to control resource behaviour
63
64
  */
64
- grantRoleAssignmentToApplicationConfiguration(id: string, scope: CommonAzureConstruct, appConfigId: Input<string>, principalId: Input<string>, roleDefinitionId: RoleDefinitionId, resourceOptions?: ResourceOptions): import("@pulumi/azure-native/authorization/roleAssignment.js").RoleAssignment;
65
+ grantRoleAssignmentToApplicationConfiguration(id: string, scope: CommonAzureConstruct, appConfigId: Input<string>, principalId: Input<string>, principalType: Input<PrincipalType>, roleDefinitionId: string, resourceOptions?: ResourceOptions): import("@pulumi/azure-native/authorization/roleAssignment.js").RoleAssignment;
65
66
  /**
66
67
  * @summary Method to grant a role assignment to storage account
67
68
  * @param id scoped id of the resource
@@ -71,7 +72,7 @@ export declare class AzureAuthorisationManager {
71
72
  * @param roleDefinitionId the role definition id
72
73
  * @param resourceOptions Optional settings to control resource behaviour
73
74
  */
74
- grantRoleAssignmentToStorageAccount(id: string, scope: CommonAzureConstruct, accountId: Input<string>, principalId: Input<string>, roleDefinitionId: RoleDefinitionId, resourceOptions?: ResourceOptions): import("@pulumi/azure-native/authorization/roleAssignment.js").RoleAssignment;
75
+ grantRoleAssignmentToStorageAccount(id: string, scope: CommonAzureConstruct, accountId: Input<string>, principalId: Input<string>, roleDefinitionId: string, resourceOptions?: ResourceOptions): import("@pulumi/azure-native/authorization/roleAssignment.js").RoleAssignment;
75
76
  /**
76
77
  * @summary Method to grant a role assignment to storage table
77
78
  * @param id scoped id of the resource
@@ -81,5 +82,6 @@ export declare class AzureAuthorisationManager {
81
82
  * @param roleDefinitionId the role definition id
82
83
  * @param resourceOptions Optional settings to control resource behaviour
83
84
  */
84
- grantRoleAssignmentToStorageTable(id: string, scope: CommonAzureConstruct, tableId: Input<string>, principalId: Input<string>, roleDefinitionId: RoleDefinitionId, resourceOptions?: ResourceOptions): import("@pulumi/azure-native/authorization/roleAssignment.js").RoleAssignment;
85
+ grantRoleAssignmentToStorageTable(id: string, scope: CommonAzureConstruct, tableId: Input<string>, principalId: Input<string>, roleDefinitionId: string, resourceOptions?: ResourceOptions): import("@pulumi/azure-native/authorization/roleAssignment.js").RoleAssignment;
86
+ resolveRoleDefinitionId(scope: CommonAzureConstruct, roleDefinitionId: RoleDefinitionId): string;
85
87
  }
@@ -29,7 +29,7 @@ export class AzureAuthorisationManager {
29
29
  createRoleAssignment(id, scope, props, resourceOptions) {
30
30
  if (!props)
31
31
  throw new Error(`Props undefined for ${id}`);
32
- return new RoleAssignment(`${id}`, props, { parent: scope, ...resourceOptions });
32
+ return new RoleAssignment(`${id}`, props, { parent: scope, ignoreChanges: ['scope'], ...resourceOptions });
33
33
  }
34
34
  /**
35
35
  * @summary Method to grant a role assignment to key vault
@@ -79,9 +79,10 @@ export class AzureAuthorisationManager {
79
79
  * @param roleDefinitionId the role definition id
80
80
  * @param resourceOptions Optional settings to control resource behaviour
81
81
  */
82
- grantRoleAssignmentToApplicationConfiguration(id, scope, appConfigId, principalId, roleDefinitionId, resourceOptions) {
82
+ grantRoleAssignmentToApplicationConfiguration(id, scope, appConfigId, principalId, principalType, roleDefinitionId, resourceOptions) {
83
83
  return this.createRoleAssignment(`${id}-ac-role`, scope, {
84
84
  principalId,
85
+ principalType,
85
86
  roleDefinitionId,
86
87
  scope: appConfigId,
87
88
  }, resourceOptions);
@@ -118,4 +119,9 @@ export class AzureAuthorisationManager {
118
119
  scope: tableId,
119
120
  }, resourceOptions);
120
121
  }
122
+ resolveRoleDefinitionId(scope, roleDefinitionId) {
123
+ if (!scope.props.subscriptionId)
124
+ throw Error('Subscription id undefined');
125
+ return `/subscriptions/${scope.props.subscriptionId}${roleDefinitionId}`;
126
+ }
121
127
  }
@@ -1,4 +1,5 @@
1
1
  import { DatabaseAccount, getDatabaseAccountOutput, getSqlResourceSqlRoleDefinitionOutput, ResourceIdentityType, SqlResourceSqlContainer, SqlResourceSqlDatabase, SqlResourceSqlRoleAssignment, } from '@pulumi/azure-native/cosmosdb/index.js';
2
+ import { v5 as uuidv5 } from 'uuid';
2
3
  import { CosmosRoleDefinition, CosmosRoleDefinitionId } from './constants.js';
3
4
  /**
4
5
  * Provides operations on Azure CosmosDB using Pulumi
@@ -78,14 +79,14 @@ export class AzureCosmosDbManager {
78
79
  if (!props)
79
80
  throw new Error(`Props undefined for ${id}`);
80
81
  // Get resource group name
81
- const resourceGroupName = (props.resourceGroupName ?? scope.props.resourceGroupName)
82
- ? `${scope.props.resourceGroupName}-${scope.props.stage}`
83
- : props.resourceGroupName;
82
+ const resourceGroupName = props.resourceGroupName ?? scope.resourceNameFormatter.format(scope.props.resourceGroupName);
84
83
  if (!resourceGroupName)
85
84
  throw new Error(`Resource group name undefined for ${id}`);
86
85
  return new SqlResourceSqlContainer(`${id}-cc`, {
87
86
  ...props,
88
- containerName: scope.resourceNameFormatter.format(props.containerName?.toString(), scope.props.resourceNameOptions?.cosmosDbSqlContainer),
87
+ ...(props.containerName && {
88
+ containerName: scope.resourceNameFormatter.format(props.containerName.toString(), scope.props.resourceNameOptions?.cosmosDbSqlContainer),
89
+ }),
89
90
  resourceGroupName,
90
91
  }, { parent: scope, ...resourceOptions });
91
92
  }
@@ -98,7 +99,11 @@ export class AzureCosmosDbManager {
98
99
  * @see [Pulumi Azure Native CosmosDB SQL Role Assignment]{@link https://www.pulumi.com/registry/packages/azure-native/api-docs/documentdb/sqlresourcesqlroleassignment/}
99
100
  */
100
101
  createSqlResourceSqlRoleAssignment(id, scope, props, resourceOptions) {
101
- return new SqlResourceSqlRoleAssignment(`${id}`, props, { parent: scope, ...resourceOptions });
102
+ const namespace = uuidv5(`${scope.id}-${id}`, uuidv5.URL);
103
+ return new SqlResourceSqlRoleAssignment(`${id}`, {
104
+ ...props,
105
+ roleAssignmentId: props.roleAssignmentId ?? uuidv5(id, namespace),
106
+ }, { parent: scope, ...resourceOptions });
102
107
  }
103
108
  /**
104
109
  * @summary Method to resolve an existing cosmosdb account
@@ -1,4 +1,4 @@
1
- import { EventDeliverySchema, EventSubscription, getTopicOutput, SystemTopic, SystemTopicEventSubscription, Topic, } from '@pulumi/azure-native/eventgrid/index.js';
1
+ import { DataResidencyBoundary, EventDeliverySchema, EventSubscription, getTopicOutput, SystemTopic, SystemTopicEventSubscription, TlsVersion, Topic, } from '@pulumi/azure-native/eventgrid/index.js';
2
2
  /**
3
3
  * Provides operations on Azure Event Grid using Pulumi
4
4
  * - A new instance of this class is injected into {@link CommonAzureConstruct} constructor.
@@ -36,6 +36,8 @@ export class AzureEventgridManager {
36
36
  topicName: scope.resourceNameFormatter.format(props.topicName?.toString(), scope.props.resourceNameOptions?.eventGridTopic),
37
37
  location: props.location ?? scope.props.location,
38
38
  resourceGroupName,
39
+ dataResidencyBoundary: props.dataResidencyBoundary ?? DataResidencyBoundary.WithinGeopair,
40
+ minimumTlsVersionAllowed: props.minimumTlsVersionAllowed ?? TlsVersion.TlsVersion_1_2,
39
41
  tags: {
40
42
  environment: scope.props.stage,
41
43
  ...scope.props.defaultTags,
@@ -32,6 +32,6 @@ export class AzureMonitorManager {
32
32
  return new DiagnosticSetting(`${id}-ds`, {
33
33
  ...props,
34
34
  name: scope.resourceNameFormatter.format(props.name?.toString(), scope.props.resourceNameOptions?.monitorDiagnosticSetting),
35
- }, { parent: scope, ...resourceOptions });
35
+ }, { parent: scope, ignoreChanges: ['resourceUri'], ...resourceOptions });
36
36
  }
37
37
  }
@@ -1,4 +1,4 @@
1
- import { Table, Workspace, WorkspaceSkuNameEnum } from '@pulumi/azure-native/operationalinsights/index.js';
1
+ import { Table, TablePlanEnum, Workspace, WorkspaceSkuNameEnum, } from '@pulumi/azure-native/operationalinsights/index.js';
2
2
  /**
3
3
  * Provides operations on Azure Log Analytics Workspace using Pulumi
4
4
  * - A new instance of this class is injected into {@link CommonAzureConstruct} constructor.
@@ -58,6 +58,11 @@ export class AzureOperationalInsightsManager {
58
58
  createTable(id, scope, props, resourceOptions) {
59
59
  if (!props)
60
60
  throw new Error(`Props undefined for ${id}`);
61
- return new Table(`${id}`, props, { parent: scope, ...resourceOptions });
61
+ return new Table(`${id}`, {
62
+ ...props,
63
+ plan: props.plan ?? TablePlanEnum.Analytics,
64
+ retentionInDays: props.retentionInDays ?? 30,
65
+ totalRetentionInDays: props.totalRetentionInDays ?? 30,
66
+ }, { parent: scope, ...resourceOptions });
62
67
  }
63
68
  }
@@ -1,5 +1,6 @@
1
1
  import fs from 'fs';
2
2
  import { Dashboard } from '@pulumi/azure-native/portal/index.js';
3
+ import * as pulumi from '@pulumi/pulumi';
3
4
  import { AzureDashboardRenderer } from './renderer.js';
4
5
  /**
5
6
  * Provides operations on Azure Portal Dashboards using Pulumi
@@ -32,21 +33,27 @@ export class AzurePortalManager {
32
33
  createDashBoard(id, scope, props, renderer, resourceOptions) {
33
34
  if (!props)
34
35
  throw new Error(`Props undefined for ${id}`);
35
- const resourceGroup = scope.resourceGroupManager.resolveResourceGroup(scope, props.resourceGroupName.toString() ?? scope.props.resourceGroupName, resourceOptions);
36
+ const resourceGroup = scope.resourceGroup ??
37
+ scope.resourceGroupManager.resolveResourceGroup(scope, props.resourceGroupName.toString() ?? scope.props.resourceGroupName, resourceOptions);
36
38
  const dashboardName = scope.resourceNameFormatter.format(props.dashboardName?.toString(), scope.props.resourceNameOptions?.portalDashboard);
37
39
  const dashboardRenderer = renderer ?? new AzureDashboardRenderer();
38
40
  const templateFile = dashboardRenderer.renderToFile(dashboardName, props);
39
41
  const template = fs.readFileSync(templateFile, 'utf-8');
40
- const content = Object.entries(props.variables).reduce((result, [key, value]) => result.replaceAll(`\${${key}}`, JSON.stringify(String(value)).slice(1, -1)), template);
42
+ const keys = Object.keys(props.variables);
43
+ const values = Object.values(props.variables);
44
+ const properties = pulumi.all(values).apply(resolved => {
45
+ const content = keys.reduce((result, key, i) => result.replaceAll(`\${${key}}`, JSON.stringify(String(resolved[i])).slice(1, -1)), template);
46
+ return JSON.parse(content);
47
+ });
41
48
  return new Dashboard(`${id}-dashboard`, {
42
49
  ...props,
43
50
  dashboardName: scope.resourceNameFormatter.format(props.dashboardName?.toString(), scope.props.resourceNameOptions?.portalDashboard),
44
51
  resourceGroupName: resourceGroup.name,
45
52
  location: props.location ?? resourceGroup.location,
46
- properties: JSON.parse(content),
53
+ properties,
47
54
  tags: {
48
55
  'hidden-title': `${props.location} - ${props.displayName}`,
49
56
  },
50
- }, { ...resourceOptions, ignoreChanges: ['location'] });
57
+ }, { parent: scope, ...resourceOptions, ignoreChanges: ['location'] });
51
58
  }
52
59
  }
@@ -35,9 +35,8 @@ export class AzureDashboardRenderer {
35
35
  render(params) {
36
36
  _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
37
37
  // if client is used instead of hosts
38
- let partsIndex = 0;
39
38
  let yIndex = 0;
40
- const parts = {};
39
+ const parts = [];
41
40
  for (const pane of params.panes) {
42
41
  try {
43
42
  const paneTemplate = this.getPaneId(pane.id);
@@ -91,8 +90,7 @@ export class AzureDashboardRenderer {
91
90
  const paneJSON = JSON.parse(paneContent);
92
91
  const templateParts = paneJSON.parts;
93
92
  for (const part of templateParts) {
94
- parts[`${partsIndex}`] = part;
95
- partsIndex++;
93
+ parts.push(part);
96
94
  }
97
95
  yIndex += paneTemplate.dimensions.height;
98
96
  }
@@ -104,12 +102,12 @@ export class AzureDashboardRenderer {
104
102
  }
105
103
  }
106
104
  const dashboard = {
107
- lenses: {
108
- '0': {
105
+ lenses: [
106
+ {
109
107
  order: 0,
110
108
  parts,
111
109
  },
112
- },
110
+ ],
113
111
  metadata: {
114
112
  model: {
115
113
  timeRange: {
@@ -1,4 +1,4 @@
1
- import { Database, RedisEnterprise, SkuName } from '@pulumi/azure-native/redisenterprise/index.js';
1
+ import { AccessKeysAuthentication, ClusteringPolicy, Database, DeferUpgradeSetting, EvictionPolicy, Protocol, RedisEnterprise, SkuName, } from '@pulumi/azure-native/redisenterprise/index.js';
2
2
  /**
3
3
  * Provides operations on Azure Managed Redis (Enterprise) using Pulumi
4
4
  * - A new instance of this class is injected into {@link CommonAzureConstruct} constructor.
@@ -49,6 +49,13 @@ export class AzureRedisManager {
49
49
  clusterName: cluster.name,
50
50
  resourceGroupName,
51
51
  databaseName: databaseProps?.databaseName ?? 'default',
52
+ accessKeysAuthentication: databaseProps?.accessKeysAuthentication ?? AccessKeysAuthentication.Enabled,
53
+ clientProtocol: databaseProps?.clientProtocol ?? Protocol.Encrypted,
54
+ clusteringPolicy: databaseProps?.clusteringPolicy ?? ClusteringPolicy.OSSCluster,
55
+ evictionPolicy: databaseProps?.evictionPolicy ?? EvictionPolicy.VolatileLRU,
56
+ port: databaseProps?.port ?? 10000,
57
+ persistence: databaseProps?.persistence ?? { aofEnabled: false, rdbEnabled: false },
58
+ deferUpgrade: databaseProps?.deferUpgrade ?? DeferUpgradeSetting.NotDeferred,
52
59
  }, { parent: scope, dependsOn: [cluster], ...resourceOptions });
53
60
  return { cluster, database };
54
61
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gradientedge/cdk-utils-azure",
3
- "version": "2.18.0",
3
+ "version": "2.20.0",
4
4
  "description": "Azure Pulumi utilities for @gradientedge/cdk-utils",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -17,10 +17,11 @@
17
17
  "@pulumi/archive": "0.3.7",
18
18
  "@pulumi/azure-native": "3.16.0",
19
19
  "@pulumi/azuread": "6.9.0",
20
- "@pulumi/pulumi": "3.230.0",
20
+ "@pulumi/pulumi": "3.231.0",
21
21
  "@types/lodash": "4.17.24",
22
22
  "app-root-path": "3.1.0",
23
23
  "lodash": "4.18.1",
24
+ "uuid": "13.0.0",
24
25
  "yaml": "2.8.3",
25
26
  "@gradientedge/cdk-utils-common": "2.1.0"
26
27
  },