Dommicentl
Dommicentl

Reputation: 751

Dynamic appsettings array content in ARM

I have the following simplified ARM template (I left out certain parts to make it more readable). I have a parameter called PrivateKeyCertificateThumbprint. If this parameter is filled in, I want to set the appsetting WEBSITE_LOAD_CERTIFICATES to a certain value. If the parameter is empty, I do not want to set the value. So the elements in the appSettings array are sort of dynamic based on the content of the PrivateKeyCertificateThumbprint parameter.

I do not seem to find a solution for this in ARM. The usecase seems so simple. First I tried to add an additional Microsoft.Web/sites/config/appsettings resource with only the WEBSITE_LOAD_CERTIFICATES key. But doing that removes all the already existing appsettings from the application.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    ...
    "PrivateKeyCertificateThumbprint": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "The thumbprint of the client certificate used by the application"
      }
    }
  },
  "resources": [
    {
      "type": "Microsoft.Web/sites",
      "apiVersion": "2018-11-01",
      "name": "[parameters('AppResourcename')]",
      "identity": {
        "type": "SystemAssigned"
      },
      "Location": "[parameters('Location')]",
      "kind": "[parameters('SitesKind')]",
      "properties": {
        "siteConfig": {
          "appSettings": [
              {
                "name": "APPINSIGHTS_INSTRUMENTATIONKEY",
                "value": "[if(empty(parameters('AppinsResourceName')), '', reference(resourceId('microsoft.insights/components/', parameters('AppinsResourceName')), '2015-05-01').InstrumentationKey)]"
              },
              {
                "name": "ApplicationInsightsAgent_EXTENSION_VERSION",
                "value": "~2"
              },
              {
                "name": "WEBSITE_HEALTHCHECK_MAXPINGFAILURES",
                "value": "5"
              },
              {
                "name": "WEBSITE_LOAD_CERTIFICATES",
                "value": "[parameters('PrivateKeyCertificateThumbprint')]"
              }
          ],
          "healthCheckPath": "[parameters('HealthCheckPath')]"
        }
        ...
    }
  ]
}

Upvotes: 0

Views: 1089

Answers (2)

Dommicentl
Dommicentl

Reputation: 751

I finally managed to get it to work in ARM by using functions. I created 3 functions that created 3 sub arrays with as parameters, values I could only get in the resource itself. I then used a concat in combination with an if, to conditionally add parts to the settings array in the resource.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": 
    // ...
    "PrivateKeyCertificateThumbprint": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "The thumbprint of the client certificate used by the application"
      }
    }
  },
  "variables": {
    // ...
  },
  "functions": [
    {
      "namespace": "test",
      "members": {
        "createAppSettings": {
          "parameters": [],
          "output": {
            "value": [
              {
                "name": "ApplicationInsightsAgent_EXTENSION_VERSION",
                "value": "~2"
              },
              {
                "name": "WEBSITE_HEALTHCHECK_MAXPINGFAILURES",
                "value": "5"
              }
            ],
            "type": "array"
          }
        },
        "createAppInsightSettings": {
          "parameters": [
            {
              "name": "instrumentationkey",
              "type": "string"
            }
          ],
          "output": {
            "value": [
              {
                "name": "APPINSIGHTS_INSTRUMENTATIONKEY",
                "value": "[parameters('instrumentationkey')]"
              }
            ],
            "type": "array"
          }
        },
        "createCertificateAppSettings": {
          "parameters": [
            {
              "name": "certthumbprint",
              "type": "string"
            }
          ],
          "output": {
            "value": [
              {
                "name": "WEBSITE_LOAD_CERTIFICATES",
                "value": "[parameters('certthumbprint')]"
              }
            ],
            "type": "array"
          }
        }
      }
    }
  ],
  "resources": [
    {
      "type": "Microsoft.Web/sites",
      "apiVersion": "2018-11-01",
      "name": "[parameters('AppResourcename')]",
      "identity": {
        "type": "SystemAssigned"
      },
      "Location": "[parameters('Location')]",
      "kind": "[parameters('SitesKind')]",
      "properties": {
        "siteConfig": {
          "appSettings": "[concat(
            test.createAppSettings(),
            if(empty(parameters('AppinsResourceName')), createArray(), test.createAppInsightSettings(reference(resourceId('microsoft.insights/components/',parameters('AppinsResourceName')), '2015-05-01').InstrumentationKey)),
            if(empty(parameters('PrivateKeyCertificateThumbprint')), createArray(), test.createCertificateAppSettings(parameters('PrivateKeyCertificateThumbprint')))
          )]",
          "healthCheckPath": "[parameters('HealthCheckPath')]"
        }
        // ...
      }
    }
  ]
}

Upvotes: 1

Thomas
Thomas

Reputation: 29522

For clarity, I used a bicep template.
Here I've defined a variable with default appsettings. Then if the cert thumbprint is not empty, I'm adding the extra app setting:

param PrivateKeyCertificateThumbprint string = ''
param AppResourcename string
param Location string
param SitesKind string
param AppinsResourceName string

// Common app settings
var defaultAppSettings = [
  {
    name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
    value: (empty(AppinsResourceName) ? '' : reference(resourceId('microsoft.insights/components/', AppinsResourceName), '2015-05-01').InstrumentationKey)
  }
  {
    name: 'ApplicationInsightsAgent_EXTENSION_VERSION'
    value: '~2'
  }
  {
    name: 'WEBSITE_HEALTHCHECK_MAXPINGFAILURES'
    value: '5'
  }
]

// if the cert thumbprint is not empty, we add it.
var appSettings = concat(defaultAppSettings, empty(PrivateKeyCertificateThumbprint) ? [] : [
  {
    name: 'WEBSITE_LOAD_CERTIFICATES'
    value: PrivateKeyCertificateThumbprint
  }
])

// create the webapp
resource webApp 'Microsoft.Web/sites@2018-11-01' = {
  name: AppResourcename
  identity: {
    type: 'SystemAssigned'
  }
  location: Location
  kind: SitesKind
  properties: {
    siteConfig: {
      appSettings: appSettings
    }
  }
}

Using Az CLI, you can then generate the ARM temnplate:

az bicep build --file .\main.bicep

the generated ARM template looks like that:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "PrivateKeyCertificateThumbprint": {
      "type": "string",
      "defaultValue": ""
    },
    "AppResourcename": {
      "type": "string"
    },
    "Location": {
      "type": "string"
    },
    "SitesKind": {
      "type": "string"
    },
    "AppinsResourceName": {
      "type": "string"
    }
  },
  "resources": [
    {
      "type": "Microsoft.Web/sites",
      "apiVersion": "2018-11-01",
      "name": "[parameters('AppResourcename')]",
      "identity": {
        "type": "SystemAssigned"
      },
      "location": "[parameters('Location')]",
      "kind": "[parameters('SitesKind')]",
      "properties": {
        "siteConfig": {
          "appSettings": "[concat(createArray(createObject('name', 'APPINSIGHTS_INSTRUMENTATIONKEY', 'value', if(empty(parameters('AppinsResourceName')), '', reference(resourceId('microsoft.insights/components/', parameters('AppinsResourceName')), '2015-05-01').InstrumentationKey)), createObject('name', 'ApplicationInsightsAgent_EXTENSION_VERSION', 'value', '~2'), createObject('name', 'WEBSITE_HEALTHCHECK_MAXPINGFAILURES', 'value', '5')), if(empty(parameters('PrivateKeyCertificateThumbprint')), createArray(), createArray(createObject('name', 'WEBSITE_LOAD_CERTIFICATES', 'value', parameters('PrivateKeyCertificateThumbprint')))))]"
        }
      }
    }
  ]
}

Upvotes: 2

Related Questions