Skip to content

Commit

Permalink
feat(avm/app/managed-environment): add certificate key vault properti…
Browse files Browse the repository at this point in the history
…es - `avm/res/app/managed-environment` (#2719)

## Description

<!--
>Thank you for your contribution !
> Please include a summary of the change and which issue is fixed.
> Please also include the context.
> List any dependencies that are required for this change.

Fixes #123
Fixes #456
Closes #123
Closes #456
-->

## Pipeline Reference

<!-- Insert your Pipeline Status Badge below -->

| Pipeline |
| -------- |
|
[![avm.res.app.managed-environment](https://github.com/robvangeloven/bicep-registry-modules/actions/workflows/avm.res.app.managed-environment.yml/badge.svg?branch=feature%2F2642-add-certificate-key-vault-properties)](https://github.com/robvangeloven/bicep-registry-modules/actions/workflows/avm.res.app.managed-environment.yml)
|

## Type of Change

<!-- Use the checkboxes [x] on the options that are relevant. -->

- [ ] Update to CI Environment or utilities (Non-module affecting
changes)
- [X] Azure Verified Module updates:
- [ ] Bugfix containing backwards-compatible bug fixes, and I have NOT
bumped the MAJOR or MINOR version in `version.json`:
- [ ] Someone has opened a bug report issue, and I have included "Closes
#{bug_report_issue_number}" in the PR description.
- [ ] The bug was found by the module author, and no one has opened an
issue to report it yet.
- [X] Feature update backwards compatible feature updates, and I have
bumped the MINOR version in `version.json`.
- [ ] Breaking changes and I have bumped the MAJOR version in
`version.json`.
  - [ ] Update to documentation

## Checklist

- [X] I'm sure there are no other open Pull Requests for the same
update/change
- [X] I have run `Set-AVMModule` locally to generate the supporting
module files.
- [ ] My corresponding pipelines / checks run clean and green without
any errors or warnings

<!-- Please keep up to date with the contribution guide at
https://aka.ms/avm/contribute/bicep -->

---------

Co-authored-by: Matthew Schmitt <[email protected]>
Co-authored-by: Matthew Schmitt <[email protected]>
Co-authored-by: Máté Barabás <[email protected]>
Co-authored-by: Rainer Halanek <[email protected]>
Co-authored-by: JFolberth <[email protected]>
Co-authored-by: Rob van Geloven <[email protected]>
Co-authored-by: Alexander Sehr <[email protected]>
  • Loading branch information
8 people authored Oct 29, 2024
1 parent c5c2a03 commit e4d6d46
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 3 deletions.
48 changes: 48 additions & 0 deletions avm/res/app/managed-environment/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,11 @@ module managedEnvironment 'br/public:avm/res/app/managed-environment:<version>'
name: 'amemax001'
// Non-required parameters
appInsightsConnectionString: '<appInsightsConnectionString>'
certificateKeyVaultProperties: {
identityResourceId: '<identityResourceId>'
keyVaultUrl: '<keyVaultUrl>'
}
dnsSuffix: 'contoso.com'
dockerBridgeCidr: '172.16.0.1/28'
infrastructureResourceGroupName: '<infrastructureResourceGroupName>'
infrastructureSubnetId: '<infrastructureSubnetId>'
Expand Down Expand Up @@ -276,6 +281,15 @@ module managedEnvironment 'br/public:avm/res/app/managed-environment:<version>'
"appInsightsConnectionString": {
"value": "<appInsightsConnectionString>"
},
"certificateKeyVaultProperties": {
"value": {
"identityResourceId": "<identityResourceId>",
"keyVaultUrl": "<keyVaultUrl>"
}
},
"dnsSuffix": {
"value": "contoso.com"
},
"dockerBridgeCidr": {
"value": "172.16.0.1/28"
},
Expand Down Expand Up @@ -400,6 +414,11 @@ param logAnalyticsWorkspaceResourceId = '<logAnalyticsWorkspaceResourceId>'
param name = 'amemax001'
// Non-required parameters
param appInsightsConnectionString = '<appInsightsConnectionString>'
param certificateKeyVaultProperties = {
identityResourceId: '<identityResourceId>'
keyVaultUrl: '<keyVaultUrl>'
}
param dnsSuffix = 'contoso.com'
param dockerBridgeCidr = '172.16.0.1/28'
param infrastructureResourceGroupName = '<infrastructureResourceGroupName>'
param infrastructureSubnetId = '<infrastructureSubnetId>'
Expand Down Expand Up @@ -712,6 +731,7 @@ param workloadProfiles = [
| Parameter | Type | Description |
| :-- | :-- | :-- |
| [`appInsightsConnectionString`](#parameter-appinsightsconnectionstring) | securestring | Application Insights connection string. |
| [`certificateKeyVaultProperties`](#parameter-certificatekeyvaultproperties) | object | A key vault reference to the certificate to use for the custom domain. |
| [`certificatePassword`](#parameter-certificatepassword) | securestring | Password of the certificate used by the custom domain. |
| [`certificateValue`](#parameter-certificatevalue) | securestring | Certificate to use for the custom domain. PFX or PEM. |
| [`daprAIConnectionString`](#parameter-dapraiconnectionstring) | securestring | Application Insights connection string used by Dapr to export Service to Service communication telemetry. |
Expand Down Expand Up @@ -807,6 +827,34 @@ Application Insights connection string.
- Type: securestring
- Default: `''`

### Parameter: `certificateKeyVaultProperties`

A key vault reference to the certificate to use for the custom domain.

- Required: No
- Type: object

**Required parameters**

| Parameter | Type | Description |
| :-- | :-- | :-- |
| [`identityResourceId`](#parameter-certificatekeyvaultpropertiesidentityresourceid) | string | The resource ID of the identity. This is the identity that will be used to access the key vault. |
| [`keyVaultUrl`](#parameter-certificatekeyvaultpropertieskeyvaulturl) | string | A key vault URL referencing the wildcard certificate that will be used for the custom domain. |

### Parameter: `certificateKeyVaultProperties.identityResourceId`

The resource ID of the identity. This is the identity that will be used to access the key vault.

- Required: Yes
- Type: string

### Parameter: `certificateKeyVaultProperties.keyVaultUrl`

A key vault URL referencing the wildcard certificate that will be used for the custom domain.

- Required: Yes
- Type: string

### Parameter: `certificatePassword`

Password of the certificate used by the custom domain.
Expand Down
17 changes: 17 additions & 0 deletions avm/res/app/managed-environment/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ param certificatePassword string = ''
@secure()
param certificateValue string = ''

@description('Optional. A key vault reference to the certificate to use for the custom domain.')
param certificateKeyVaultProperties certificateKeyVaultPropertiesType

@description('Optional. DNS suffix for the environment domain.')
param dnsSuffix string = ''

Expand Down Expand Up @@ -171,6 +174,12 @@ resource managedEnvironment 'Microsoft.App/managedEnvironments@2024-02-02-previe
certificatePassword: certificatePassword
certificateValue: !empty(certificateValue) ? certificateValue : null
dnsSuffix: dnsSuffix
certificateKeyVaultProperties: !empty(certificateKeyVaultProperties)
? {
identity: certificateKeyVaultProperties!.identityResourceId
keyVaultUrl: certificateKeyVaultProperties!.keyVaultUrl
}
: null
}
openTelemetryConfiguration: !empty(openTelemetryConfiguration) ? openTelemetryConfiguration : null
peerTrafficConfiguration: {
Expand Down Expand Up @@ -315,6 +324,14 @@ type roleAssignmentType = {
delegatedManagedIdentityResourceId: string?
}[]?

type certificateKeyVaultPropertiesType = {
@description('Required. The resource ID of the identity. This is the identity that will be used to access the key vault.')
identityResourceId: string

@description('Required. A key vault URL referencing the wildcard certificate that will be used for the custom domain.')
keyVaultUrl: string
}?

type storageType = {
@description('Required. Access mode for storage: "ReadOnly" or "ReadWrite".')
accessMode: ('ReadOnly' | 'ReadWrite')
Expand Down
31 changes: 28 additions & 3 deletions avm/res/app/managed-environment/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.29.47.4906",
"templateHash": "5062482221653261403"
"version": "0.30.23.60470",
"templateHash": "2437611645646369754"
},
"name": "App ManagedEnvironments",
"description": "This module deploys an App Managed Environment (also known as a Container App Environment).",
Expand Down Expand Up @@ -134,6 +134,24 @@
},
"nullable": true
},
"certificateKeyVaultPropertiesType": {
"type": "object",
"properties": {
"identityResourceId": {
"type": "string",
"metadata": {
"description": "Required. The resource ID of the identity. This is the identity that will be used to access the key vault."
}
},
"keyVaultUrl": {
"type": "string",
"metadata": {
"description": "Required. A key vault URL referencing the wildcard certificate that will be used for the custom domain."
}
}
},
"nullable": true
},
"storageType": {
"type": "array",
"items": {
Expand Down Expand Up @@ -313,6 +331,12 @@
"description": "Optional. Certificate to use for the custom domain. PFX or PEM."
}
},
"certificateKeyVaultProperties": {
"$ref": "#/definitions/certificateKeyVaultPropertiesType",
"metadata": {
"description": "Optional. A key vault reference to the certificate to use for the custom domain."
}
},
"dnsSuffix": {
"type": "string",
"defaultValue": "",
Expand Down Expand Up @@ -441,7 +465,8 @@
"customDomainConfiguration": {
"certificatePassword": "[parameters('certificatePassword')]",
"certificateValue": "[if(not(empty(parameters('certificateValue'))), parameters('certificateValue'), null())]",
"dnsSuffix": "[parameters('dnsSuffix')]"
"dnsSuffix": "[parameters('dnsSuffix')]",
"certificateKeyVaultProperties": "[if(not(empty(parameters('certificateKeyVaultProperties'))), createObject('identity', parameters('certificateKeyVaultProperties').identityResourceId, 'keyVaultUrl', parameters('certificateKeyVaultProperties').keyVaultUrl), null())]"
},
"openTelemetryConfiguration": "[if(not(empty(parameters('openTelemetryConfiguration'))), parameters('openTelemetryConfiguration'), null())]",
"peerTrafficConfiguration": {
Expand Down
77 changes: 77 additions & 0 deletions avm/res/app/managed-environment/tests/e2e/max/dependencies.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ param virtualNetworkName string
@description('Required. The name of the Managed Identity to create.')
param managedIdentityName string

@description('Required. The name of the Key Vault to create.')
param keyVaultName string

@description('Required. The name of the Deployment Script to create for the Certificate generation.')
param certDeploymentScriptName string

@secure()
@description('Required. The name for the SSL certificate.')
param certname string

var certPWSecretName = 'pfxCertificatePassword'
var certSecretName = 'pfxBase64Certificate'

@description('Required. The name of the Storage Account to create.')
param storageAccountName string

Expand Down Expand Up @@ -80,6 +93,55 @@ resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-
location: location
}

resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = {
name: keyVaultName
location: location
properties: {
sku: {
family: 'A'
name: 'standard'
}
tenantId: tenant().tenantId
enablePurgeProtection: null
enabledForTemplateDeployment: true
enabledForDiskEncryption: true
enabledForDeployment: true
enableRbacAuthorization: true
accessPolicies: []
}
}

resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid('msi-${managedIdentity.name}-KeyVault-Admin-RoleAssignment')
scope: keyVault
properties: {
principalId: managedIdentity.properties.principalId
roleDefinitionId: subscriptionResourceId(
'Microsoft.Authorization/roleDefinitions',
'00482a5a-887f-4fb3-b363-3b7fe8e74483'
) // Key Vault Administrator
principalType: 'ServicePrincipal'
}
}

resource certDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = {
name: certDeploymentScriptName
location: location
kind: 'AzurePowerShell'
identity: {
type: 'UserAssigned'
userAssignedIdentities: {
'${managedIdentity.id}': {}
}
}
properties: {
azPowerShellVersion: '8.0'
retentionInterval: 'P1D'
arguments: '-KeyVaultName "${keyVault.name}" -CertName "${certname}" -CertSubjectName "CN=*.contoso.com"'
scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Set-CertificateInKeyVault.ps1')
}
}

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: storageAccountName
location: location
Expand Down Expand Up @@ -134,6 +196,21 @@ output managedIdentityPrincipalId string = managedIdentity.properties.principalI
@description('The resource ID of the created Managed Identity.')
output managedIdentityResourceId string = managedIdentity.id

@description('The resource ID of the created Key Vault.')
output keyVaultResourceId string = keyVault.id

@description('The URI of the created Key Vault.')
output keyVaultUri string = keyVault.properties.vaultUri

@description('The URL of the created certificate.')
output certificateSecretUrl string = certDeploymentScript.properties.outputs.secretUrl

@description('The name of the certification password secret.')
output certPWSecretName string = certPWSecretName

@description('The name of the certification secret.')
output certSecretName string = certSecretName

@description('The Connection String of the created Application Insights Component.')
output appInsightsConnectionString string = appInsightsComponent.properties.ConnectionString

Expand Down
8 changes: 8 additions & 0 deletions avm/res/app/managed-environment/tests/e2e/max/main.test.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ module nestedDependencies 'dependencies.bicep' = {
virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}'
location: resourceLocation
managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}'
keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}'
certname: 'dep-${namePrefix}-cert-${serviceShort}'
certDeploymentScriptName: 'dep-${namePrefix}-ds-${serviceShort}'
appInsightsComponentName: 'dep-${namePrefix}-appinsights-${serviceShort}'
storageAccountName: 'dep${namePrefix}sa${serviceShort}'
}
Expand Down Expand Up @@ -66,6 +69,11 @@ module testDeployment '../../../main.bicep' = [
}
]
internal: true
dnsSuffix: 'contoso.com'
certificateKeyVaultProperties: {
identityResourceId: nestedDependencies.outputs.managedIdentityResourceId
keyVaultUrl: '${nestedDependencies.outputs.keyVaultUri}secrets/${split(nestedDependencies.outputs.certificateSecretUrl, '/')[4]}'
}
dockerBridgeCidr: '172.16.0.1/28'
peerTrafficEncryption: true
platformReservedCidr: '172.17.17.0/24'
Expand Down

0 comments on commit e4d6d46

Please sign in to comment.