scenarios/apim-baseline/terraform/modules/gateway/certificate/certificate.tf (105 lines of code) (raw):
##################################################
# Tried creating the certificate using the #
# azurerm_key_vault_certificate resource, but it #
# doesn't work due to keyvault being private #
##################################################
# resource "azurerm_key_vault_certificate" "kv_domain_certs" {
# count = local.isLocalCertificate ? 1 : 0
# name = local.secretName
# key_vault_id = var.keyvaultId
# certificate {
# contents = filebase64(var.certificate_path)
# password = var.certificate_password
# }
# certificate_policy {
# issuer_parameters {
# name = "Self"
# }
# key_properties {
# exportable = true
# key_size = 256
# key_type = "EC"
# reuse_key = false
# curve = "P-256"
# }
# secret_properties {
# content_type = "application/x-pkcs12"
# }
# }
# lifecycle {
# prevent_destroy = true
# }
# }
# resource "azurerm_key_vault_certificate" "local_domain_certs" {
# count = !local.isLocalCertificate ? 1 : 0
# name = "generated-cert"
# key_vault_id = var.keyvaultId
# certificate_policy {
# issuer_parameters {
# name = "Self"
# }
# key_properties {
# exportable = true
# key_size = 2048
# key_type = "RSA"
# reuse_key = true
# }
# lifetime_action {
# action {
# action_type = "AutoRenew"
# }
# trigger {
# days_before_expiry = 30
# }
# }
# secret_properties {
# content_type = "application/x-pkcs12"
# }
# x509_certificate_properties {
# extended_key_usage = ["1.3.6.1.5.5.7.3.1"]
# key_usage = [
# "digitalSignature",
# "keyEncipherment"
# ]
# subject = "CN=${var.appGatewayFqdn}"
# validity_in_months = 12
# }
# }
# lifecycle {
# prevent_destroy = true
# }
# }
#########################################################
# Tried creating the certificate using the #
# azurerm_resource_deployment_script_azure_power_shell #
# resource, but it doesn't work due to keyvault being #
# private. Main issue compared to bicep is the resource #
# doesn't have the option to run from a subnet #
#########################################################
# resource "azurerm_resource_deployment_script_azure_power_shell" "appGatewayCertificate" {
# name = "${local.secretName}-certificate"
# resource_group_name = var.sharedResourceGroupName
# location = var.location
# version = "6.6"
# retention_interval = "P1D"
# command_line = " -vaultName ${var.keyVaultName} -certificateName ${local.secretName} -subjectName ${local.subjectName} -certPwd ${local.certPwd} -certDataString ${local.certDataString} -certType ${var.appGatewayCertType}"
# cleanup_preference = "OnSuccess"
# force_update_tag = "1"
# timeout = "PT30M"
# # container -> doesn't have the property to tell it from which subnet to run
# script_content = <<EOF
# param(
# [string] [Parameter(Mandatory=$true)] $vaultName,
# [string] [Parameter(Mandatory=$true)] $certificateName,
# [string] [Parameter(Mandatory=$true)] $subjectName,
# [string] [Parameter(Mandatory=$true)] $certPwd,
# [string] [Parameter(Mandatory=$true)] $certDataString,
# [string] [Parameter(Mandatory=$true)] $certType
# )
# $ErrorActionPreference = 'Stop'
# $DeploymentScriptOutputs = @{}
# if ($certType -eq 'selfsigned') {
# $policy = New-AzKeyVaultCertificatePolicy -SubjectName $subjectName -IssuerName Self -ValidityInMonths 12 -Verbose
# # private key is added as a secret that can be retrieved in the ARM template
# Add-AzKeyVaultCertificate -VaultName $vaultName -Name $certificateName -CertificatePolicy $policy -Verbose
# $newCert = Get-AzKeyVaultCertificate -VaultName $vaultName -Name $certificateName
# # it takes a few seconds for KeyVault to finish
# $tries = 0
# do {
# Write-Host 'Waiting for certificate creation completion...'
# Start-Sleep -Seconds 10
# $operation = Get-AzKeyVaultCertificateOperation -VaultName $vaultName -Name $certificateName
# $tries++
# if ($operation.Status -eq 'failed')
# {
# throw 'Creating certificate $certificateName in vault $vaultName failed with error $($operation.ErrorMessage)'
# }
# if ($tries -gt 120)
# {
# throw 'Timed out waiting for creation of certificate $certificateName in vault $vaultName'
# }
# } while ($operation.Status -ne 'completed')
# }
# else {
# $ss = Convertto-SecureString -String $certPwd -AsPlainText -Force;
# Import-AzKeyVaultCertificate -Name $certificateName -VaultName $vaultName -CertificateString $certDataString -Password $ss
# }
# EOF
# identity {
# type = "UserAssigned"
# identity_ids = [
# data.azurerm_user_assigned_identity.deploymentIdentity.id
# ]
# }
# depends_on = [
# azurerm_key_vault_access_policy.user_assigned_deployment_keyvault_permissions
# ]
# }
#########################
# Trying azapi approach #
#########################
# locals
locals {
secretName = replace(var.appGatewayFqdn, ".", "-")
subjectName = "CN=${var.appGatewayFqdn}"
certPwd = var.appGatewayCertType == "selfsigned" ? "null" : var.certificate_password
certDataString = var.appGatewayCertType == "selfsigned" ? "null" : var.certificate_path
}
# data userasignedidentity for deployment
data "azurerm_user_assigned_identity" "deploymentIdentity" {
resource_group_name = var.sharedResourceGroupName
name = var.deploymentIdentityName
}
resource "azurerm_key_vault_access_policy" "user_assigned_deployment_keyvault_permissions" {
key_vault_id = var.keyvaultId
tenant_id = data.azurerm_user_assigned_identity.deploymentIdentity.tenant_id
object_id = data.azurerm_user_assigned_identity.deploymentIdentity.principal_id
certificate_permissions = [
"Import",
"Get",
"List",
"Update",
"Create"
]
secret_permissions = [
"Get",
"List",
]
lifecycle {
prevent_destroy = true
}
}
# get the ide of the resource group
data "azurerm_resource_group" "sharedResourceGroup" {
name = var.sharedResourceGroupName
}
resource "azapi_resource" "appGatewayCertificate" {
type = "Microsoft.Resources/deploymentScripts@2023-08-01"
name = "${local.secretName}-certificate"
depends_on = [azurerm_key_vault_access_policy.user_assigned_deployment_keyvault_permissions]
parent_id = data.azurerm_resource_group.sharedResourceGroup.id
identity {
type = "UserAssigned"
identity_ids = [data.azurerm_user_assigned_identity.deploymentIdentity.id]
}
body = jsonencode({
kind = "AzurePowerShell"
location = var.location
properties = {
storageAccountSettings = {
storageAccountName = var.deploymentStorageName
}
azPowerShellVersion = "6.6"
containerSettings = {
subnetIds = [
{
id = var.deploymentSubnetId
}
]
}
arguments = " -vaultName ${var.keyVaultName} -certificateName ${local.secretName} -subjectName ${local.subjectName} -certPwd ${local.certPwd} -certDataString ${local.certDataString} -certType ${var.appGatewayCertType}"
scriptContent = <<-EOT
param(
[string] [Parameter(Mandatory=$true)] $vaultName,
[string] [Parameter(Mandatory=$true)] $certificateName,
[string] [Parameter(Mandatory=$true)] $subjectName,
[string] [Parameter(Mandatory=$true)] $certPwd,
[string] [Parameter(Mandatory=$true)] $certDataString,
[string] [Parameter(Mandatory=$true)] $certType
)
$ErrorActionPreference = 'Stop'
$DeploymentScriptOutputs = @{}
if ($certType -eq 'selfsigned') {
$policy = New-AzKeyVaultCertificatePolicy -SubjectName $subjectName -IssuerName Self -ValidityInMonths 12 -Verbose
# private key is added as a secret that can be retrieved in the ARM template
Add-AzKeyVaultCertificate -VaultName $vaultName -Name $certificateName -CertificatePolicy $policy -Verbose
$newCert = Get-AzKeyVaultCertificate -VaultName $vaultName -Name $certificateName
# it takes a few seconds for KeyVault to finish
$tries = 0
do {
Write-Host 'Waiting for certificate creation completion...'
Start-Sleep -Seconds 10
$operation = Get-AzKeyVaultCertificateOperation -VaultName $vaultName -Name $certificateName
$tries++
if ($operation.Status -eq 'failed')
{
throw 'Creating certificate $certificateName in vault $vaultName failed with error $($operation.ErrorMessage)'
}
if ($tries -gt 120)
{
throw 'Timed out waiting for creation of certificate $certificateName in vault $vaultName'
}
} while ($operation.Status -ne 'completed')
}
else {
$ss = Convertto-SecureString -String $certPwd -AsPlainText -Force;
Import-AzKeyVaultCertificate -Name $certificateName -VaultName $vaultName -CertificateString $certDataString -Password $ss
}
$certificateIdOutput = $(Get-AzKeyVaultCertificate -VaultName $vaultName -Name $certificateName).id
Write-Output "certificateId: $certificateIdOutput"
$DeploymentScriptOutputs = @{}
$DeploymentScriptOutputs['certificateId'] = $certificateIdOutput
EOT
retentionInterval = "P1D"
}
})
response_export_values = ["*"]
}
output "secret_id" {
value = jsondecode(azapi_resource.appGatewayCertificate.output).properties.outputs.certificateId
}