Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added UDT for Managed identity and Deployment Scripts #1224

Merged
merged 14 commits into from
Mar 11, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ runs:
# Load used functions
. (Join-Path $env:GITHUB_WORKSPACE 'avm' 'utilities' 'pipelines' 'e2eValidation' 'regionSelector' 'Get-AzAvailableResourceLocation.ps1')

# Set fucntion input parameters
# Set function input parameters
$functionInput = @{
ModuleRoot = '${{ inputs.modulePath }}'
GlobalResourceGroupLocation = '${{ inputs.deploymentMetadataLocation }}'
Expand All @@ -86,7 +86,6 @@ runs:

$resourceLocation = Get-AzAvailableResourceLocation @functionInput -Verbose

$deploymentLocation = @{}
Write-Verbose ('{0}-{1}' -f 'resourceLocation', $resourceLocation) -Verbose
Write-Output ('{0}={1}' -f 'resourceLocation', $resourceLocation) >> $env:GITHUB_OUTPUT

Expand Down
38 changes: 37 additions & 1 deletion avm/res/managed-identity/user-assigned-identity/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,43 @@ The federated identity credentials list to indicate which token from the externa

- Required: No
- Type: array
- Default: `[]`

**Required parameters**

| Parameter | Type | Description |
| :-- | :-- | :-- |
| [`audiences`](#parameter-federatedidentitycredentialsaudiences) | array | The list of audiences that can appear in the issued token. |
| [`issuer`](#parameter-federatedidentitycredentialsissuer) | string | The URL of the issuer to be trusted. |
| [`name`](#parameter-federatedidentitycredentialsname) | string | The name of the federated identity credential. |
| [`subject`](#parameter-federatedidentitycredentialssubject) | string | The identifier of the external identity. |

### Parameter: `federatedIdentityCredentials.audiences`

The list of audiences that can appear in the issued token.

- Required: Yes
- Type: array

### Parameter: `federatedIdentityCredentials.issuer`

The URL of the issuer to be trusted.

- Required: Yes
- Type: string

### Parameter: `federatedIdentityCredentials.name`

The name of the federated identity credential.

- Required: Yes
- Type: string

### Parameter: `federatedIdentityCredentials.subject`

The identifier of the external identity.

- Required: Yes
- Type: string

### Parameter: `location`

Expand Down
18 changes: 16 additions & 2 deletions avm/res/managed-identity/user-assigned-identity/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ param name string
param location string = resourceGroup().location

@description('Optional. The federated identity credentials list to indicate which token from the external IdP should be trusted by your application. Federated identity credentials are supported on applications only. A maximum of 20 federated identity credentials can be added per application object.')
param federatedIdentityCredentials array = []
param federatedIdentityCredentials federatedIdentityCredentialsType

@description('Optional. The lock settings of the service.')
param lock lockType
Expand Down Expand Up @@ -66,7 +66,7 @@ resource userAssignedIdentity_lock 'Microsoft.Authorization/locks@2020-05-01' =
scope: userAssignedIdentity
}

module userAssignedIdentity_federatedIdentityCredentials 'federated-identity-credential/main.bicep' = [for (federatedIdentityCredential, index) in federatedIdentityCredentials: {
module userAssignedIdentity_federatedIdentityCredentials 'federated-identity-credential/main.bicep' = [for (federatedIdentityCredential, index) in (federatedIdentityCredentials ?? []): {
name: '${uniqueString(deployment().name, location)}-UserMSI-FederatedIdentityCredential-${index}'
params: {
name: federatedIdentityCredential.name
Expand Down Expand Up @@ -143,3 +143,17 @@ type roleAssignmentType = {
@description('Optional. The Resource Id of the delegated managed identity resource.')
delegatedManagedIdentityResourceId: string?
}[]?

type federatedIdentityCredentialsType = {
@description('Required. The name of the federated identity credential.')
name: string

@description('Required. The list of audiences that can appear in the issued token.')
audiences: string[]

@description('Required. The URL of the issuer to be trusted.')
issuer: string

@description('Required. The identifier of the external identity.')
subject: string
}[]?
51 changes: 43 additions & 8 deletions avm/res/managed-identity/user-assigned-identity/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"_generator": {
"name": "bicep",
"version": "0.25.53.49325",
"templateHash": "14161959215427804200"
"templateHash": "11532993654681133775"
},
"name": "User Assigned Identities",
"description": "This module deploys a User Assigned Identity.",
Expand Down Expand Up @@ -103,6 +103,42 @@
}
},
"nullable": true
},
"federatedIdentityCredentialsType": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"metadata": {
"description": "Required. The name of the federated identity credential."
}
},
"audiences": {
"type": "array",
"items": {
"type": "string"
},
"metadata": {
"description": "Required. The list of audiences that can appear in the issued token."
}
},
"issuer": {
"type": "string",
"metadata": {
"description": "Required. The URL of the issuer to be trusted."
}
},
"subject": {
"type": "string",
"metadata": {
"description": "Required. The identifier of the external identity."
}
}
}
},
"nullable": true
}
},
"parameters": {
Expand All @@ -120,8 +156,7 @@
}
},
"federatedIdentityCredentials": {
"type": "array",
"defaultValue": [],
"$ref": "#/definitions/federatedIdentityCredentialsType",
"metadata": {
"description": "Optional. The federated identity credentials list to indicate which token from the external IdP should be trusted by your application. Federated identity credentials are supported on applications only. A maximum of 20 federated identity credentials can be added per application object."
}
Expand Down Expand Up @@ -231,7 +266,7 @@
"userAssignedIdentity_federatedIdentityCredentials": {
"copy": {
"name": "userAssignedIdentity_federatedIdentityCredentials",
"count": "[length(parameters('federatedIdentityCredentials'))]"
"count": "[length(coalesce(parameters('federatedIdentityCredentials'), createArray()))]"
},
"type": "Microsoft.Resources/deployments",
"apiVersion": "2022-09-01",
Expand All @@ -243,19 +278,19 @@
"mode": "Incremental",
"parameters": {
"name": {
"value": "[parameters('federatedIdentityCredentials')[copyIndex()].name]"
"value": "[coalesce(parameters('federatedIdentityCredentials'), createArray())[copyIndex()].name]"
},
"userAssignedIdentityName": {
"value": "[parameters('name')]"
},
"audiences": {
"value": "[parameters('federatedIdentityCredentials')[copyIndex()].audiences]"
"value": "[coalesce(parameters('federatedIdentityCredentials'), createArray())[copyIndex()].audiences]"
},
"issuer": {
"value": "[parameters('federatedIdentityCredentials')[copyIndex()].issuer]"
"value": "[coalesce(parameters('federatedIdentityCredentials'), createArray())[copyIndex()].issuer]"
},
"subject": {
"value": "[parameters('federatedIdentityCredentials')[copyIndex()].subject]"
"value": "[coalesce(parameters('federatedIdentityCredentials'), createArray())[copyIndex()].subject]"
}
},
"template": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ param serviceShort string = 'miuaimax'
@description('Optional. A token to inject into the name of each resource.')
param namePrefix string = '#_namePrefix_#'

// Set to fixed location as the RP function returns unsupported locations
// Right now (2024/03) the following locations are NOT supported: East Asia, Qatar Central, Malaysia South, Italy North, Israel Central
param enforcedLocation string = 'westeurope'

// ============ //
// Dependencies //
// ============ //
Expand All @@ -36,7 +40,7 @@ module nestedDependencies 'dependencies.bicep' = {
name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies'
params: {
managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}'
location: resourceLocation
location: enforcedLocation
}
}

Expand All @@ -50,7 +54,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem'
name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}'
params: {
name: '${namePrefix}${serviceShort}001'
location: resourceLocation
location: enforcedLocation
lock: {
kind: 'CanNotDelete'
name: 'myCustomLockName'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ param serviceShort string = 'miuaiwaf'
@description('Optional. A token to inject into the name of each resource.')
param namePrefix string = '#_namePrefix_#'

// Set to fixed location as the RP function returns unsupported locations
// Right now (2024/03) the following locations are NOT supported for federated identity credentials: East Asia, Qatar Central, Malaysia South, Italy North, Israel Central
param enforcedLocation string = 'westeurope'

// ============ //
// Dependencies //
// ============ //
Expand All @@ -41,7 +45,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem'
name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}'
params: {
name: '${namePrefix}${serviceShort}001'
location: resourceLocation
location: enforcedLocation
lock: {
kind: 'CanNotDelete'
name: 'myCustomLockName'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://aka.ms/bicep-registry-module-version-file-schema#",
"version": "0.1",
"version": "0.2",
"pathFilters": [
"./main.json"
]
Expand Down
1 change: 0 additions & 1 deletion avm/res/resources/deployment-script/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,6 @@ The environment variables to pass over to the script. The list is passed as an o

- Required: No
- Type: secureObject
- Default: `{}`

### Parameter: `location`

Expand Down
26 changes: 12 additions & 14 deletions avm/res/resources/deployment-script/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,8 @@ param scriptContent string?
@description('Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent parameter instead.')
param primaryScriptUri string?

@metadata({
example: '''
secureList: [
{
name: 'string'
secureValue: 'string'
value: 'string'
}
]
'''
})
@description('Optional. The environment variables to pass over to the script. The list is passed as an object with a key name "secureList" and the value is the list of environment variables (array). The list must have a \'name\' and a \'value\' or a \'secretValue\' property for each object.')
@secure()
param environmentVariables object = {}
param environmentVariables environmentVariableType

@description('Optional. List of supporting files for the external script (defined in primaryScriptUri). Does not work with internal scripts (code defined in scriptContent).')
param supportingScriptUris array?
Expand Down Expand Up @@ -195,7 +183,7 @@ resource deploymentScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = {
containerSettings: !empty(containerSettings) ? containerSettings : null
storageAccountSettings: !empty(storageAccountResourceId) ? storageAccountSettings : null
arguments: arguments
environmentVariables: !empty(environmentVariables) ? environmentVariables.secureList : []
environmentVariables: environmentVariables != null ? environmentVariables!.secureList : []
AlexanderSehr marked this conversation as resolved.
Show resolved Hide resolved
scriptContent: !empty(scriptContent) ? scriptContent : null
primaryScriptUri: !empty(primaryScriptUri) ? primaryScriptUri : null
supportingScriptUris: !empty(supportingScriptUris) ? supportingScriptUris : null
Expand Down Expand Up @@ -264,3 +252,13 @@ type roleAssignmentType = {
@description('Optional. The Resource Id of the delegated managed identity resource.')
delegatedManagedIdentityResourceId: string?
}[]?

@secure()
type environmentVariableType = {
@description('Optional. The list of environment variables to pass over to the deployment script.')
secureList: {
name: string
secureValue: string?
value: string?
}[]
}?
36 changes: 31 additions & 5 deletions avm/res/resources/deployment-script/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"_generator": {
"name": "bicep",
"version": "0.25.53.49325",
"templateHash": "6812401706170828518"
"templateHash": "11832942286479289748"
},
"name": "Deployment Scripts",
"description": "This module deploys Deployment Scripts.",
Expand Down Expand Up @@ -118,6 +118,34 @@
}
},
"nullable": true
},
"environmentVariableType": {
"type": "secureObject",
"properties": {
"secureList": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"secureValue": {
"type": "string",
"nullable": true
},
"value": {
"type": "string",
"nullable": true
}
}
},
"metadata": {
"description": "Optional. The list of environment variables to pass over to the deployment script."
}
}
},
"nullable": true
}
},
"parameters": {
Expand Down Expand Up @@ -187,10 +215,8 @@
}
},
"environmentVariables": {
"type": "secureObject",
"defaultValue": {},
"$ref": "#/definitions/environmentVariableType",
"metadata": {
"example": "secureList: [\n {\n name: 'string'\n secureValue: 'string'\n value: 'string'\n }\n]\n",
"description": "Optional. The environment variables to pass over to the script. The list is passed as an object with a key name \"secureList\" and the value is the list of environment variables (array). The list must have a 'name' and a 'value' or a 'secretValue' property for each object."
}
},
Expand Down Expand Up @@ -396,7 +422,7 @@
"containerSettings": "[if(not(empty(variables('containerSettings'))), variables('containerSettings'), null())]",
"storageAccountSettings": "[if(not(empty(parameters('storageAccountResourceId'))), if(not(empty(parameters('storageAccountResourceId'))), createObject('storageAccountKey', if(empty(parameters('subnetResourceIds')), listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(if(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountResourceId'), '//'), '/')[2], split(if(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountResourceId'), '////'), '/')[4]), 'Microsoft.Storage/storageAccounts', last(split(if(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountResourceId'), 'dummyAccount'), '/'))), '2023-01-01').keys[0].value, null()), 'storageAccountName', last(split(parameters('storageAccountResourceId'), '/'))), null()), null())]",
"arguments": "[parameters('arguments')]",
"environmentVariables": "[if(not(empty(parameters('environmentVariables'))), parameters('environmentVariables').secureList, createArray())]",
"environmentVariables": "[if(not(equals(parameters('environmentVariables'), null())), parameters('environmentVariables').secureList, createArray())]",
"scriptContent": "[if(not(empty(parameters('scriptContent'))), parameters('scriptContent'), null())]",
"primaryScriptUri": "[if(not(empty(parameters('primaryScriptUri'))), parameters('primaryScriptUri'), null())]",
"supportingScriptUris": "[if(not(empty(parameters('supportingScriptUris'))), parameters('supportingScriptUris'), null())]",
Expand Down
4 changes: 2 additions & 2 deletions avm/res/resources/deployment-script/version.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://aka.ms/bicep-registry-module-version-file-schema#",
"version": "0.1",
"version": "0.2",
"pathFilters": [
"./main.json"
]
}
}
Loading