How To Pass Arrays and Numbers As @secure() Parameters - Azure Bicep

In ARM templates and Azure Bicep, only two types can be secure: string and object, their respective ARM template types are secureString and secureObject. In most cases, it is enough, however, what if we need to pass a parameter of type array or number securely?

To pass an array or a number as a secure parameter into a Bicep file or an ARM template, the array or number should be wrapped into an object and passed as a parameter of type secureObject. An alternative solution is to pass the value as a string and parse it later in the template.

For example, this might come in handy if we want to pass an array of configuration objects with some secret values, and later use a looping construct to deploy resources based on these configs. Let’s see how to handle sensitive arrays and numbers using examples in the rest of this post.

Contents:

Overview

The ideas is this post are simple and the implementation is straightforward as well. We will cover two approaches how to pass arrays and numbers: using secureObject or secureString data types. Each case is illustrated with a small code sample to make it easy to understand.

Please note that since values of secure parameters are sensitive, in your production deployment you will probably pass them as parameter overrides (not through a parameter file) when using Azure CLI, Azure PowerShell, or ARM template deployment task. However, in this post’s examples we still use parameter files to make it simpler.

First, we discuss how to pass an array as a secure parameter by leveraging either secureObject or secureString and also look at examples how to implement it in Bicep.

Next, section Number (int) as “secure” Parameter covers how to do the same for integer data type using secureObject or secureString.

Array as “secure” Parameter

There is no dedicated data type for passing arrays securely, so we will leverage existing secureObject and secureString data types for this purpose. Even though we discuss two approaches, I personally prefer wrapping an array into an object since it is cleaner and doesn’t require deserialization.

Array as secureObject

The arrayAsObject is just a wrapper around our array value, and the array itself is stored in the myArray property. Often, the object can be called like somethingConfig or similar.

// ============ main.bicep ============

@secure()
param arrayAsObject object

var arr = arrayAsObject.myArray

Parameter file main.parameters.json:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "arrayAsObject": {
      "value": {
        "myArray": ["a", "b", "c"]
      }
    }
  }
}

Array as secureString

When passing an array as a string, we can use json function to deserialize a string into an array. This function can handle any string, and the data type will be inferred from the value.

// ============ main.bicep ============

@secure()
param arrayAsString string

var arr = json(arrayAsString)

Note that in the parameter file double quotes are escaped "\" to not break the json file structure:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "arrayAsString": {
      "value": "[\"a\", \"b\", \"c\"]"
    }
  }
}

Number (int) as “secure” Parameter

Approach to passing numbers as secure parameters into a Bicep file is identical to the way described for arrays in Array as “secure” Parameter. We are going to leverage secureObject and secureString to pass integer values.

As secureObject

Number is passed as a property myInt of the intAsObject secure object. To retrieve the value in the template, just use the property accessor . (dot) operator.

// ============ main.bicep ============

@secure()
param intAsObject object

var int = intAsObject.myInt

Parameter file looks like the following:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "intAsObject": {
      "value": {
        "myInt": 145
      }
    }
  }
}

As secureString

When passing an integer as a string, we need to deserialize it inside of our template into the int data type. This can be done with json function we used for arrays in the previous section, but also with int function which is specific to converting to integers.

@secure()
param intAsString string

var num = int(intAsString)
// var num = json(intAsString)

In the parameter file, the value is passed as a string.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "intAsString": {
      "value": "145"
    }
  }
}