A few weeks ago, I was working with one of my customers in refining their public cloud governance model, in particular as it related to tag enforcement. While they had a mature resource deployment process that ensured the proper application of tags, they struggled with a single tag that could be set to alphanumeric values with assorted cases. There system of record for these values was ancient and despite my pleading to augment the data with a lower() or upper(), they asked me to come up with a solution.

With the requirement from the customer that I would not be able to augment their dataset, I had to find a way to perform an exact comparison of a value set for a tag against the dataset.

For a problem like this, I start by reviewing the publicy available documentation and this case was no exception. The Azure Policy definition documentation was comprehensive and specifically stated that outside of a dozen functions, all of the Azure Resource Manager template functions could be used within a policy definition. The template functions were nicely grouped by category and I reviewed them to see if there was one that would provide the comparison I needed. There were only two that raised my interest, contains and startsWith, both of which had inherant flaws in their implementation for what I needed them to do. contains was case-sensitive when comparing strings, but because of its lack of precision (by design), it could produce false positives (or negatives) during tag evaluation. startsWith had a similar flaw but was also case-insensitive. At first glance, none of the functions listed in the strings section would satisfy my requirement.

I spent time thinking about the problem over the next two days comparing this problem to ones I solved in the past. Years ago, when I was at RSA, spending time designing and implementing PKI for customers, I quickly learned the two most common formats for an X.509 certificate; DER, which was binary encoded ASN.1 and PEM, which was significantly more human readable. I lost count of how many times I sent a DER encoded certificate to output on the terminal and its bell ringing incessantly until it reached the end of the file. It was during this time that I learned the power of base64 encoding.

For those unfamiliar, “base64 is a group of binary-to-text encoding schemes that represent binary data (more specifically, a sequence of 8-bit bytes) in sequences of 24 bits that can be represented by four 6-bit Base64 digits1. In layman’s terms, providing a means to encode binary data in a human readable form. While our requirement for this use case is to compare string data, the nuance of character case needs to be maintained. In reviewing the the base64 alphabet, we observe that case can be preserved.

We can easily create a policy that would determine a precise match for a tag. Using the policy provided in the Microsoft example as reference, one could perform a comparison against a set of tags in the policy definition parameters using the base64 function.

1
2
3
4
5
6
7
8
9
10
11
12
      "if": {
        "allOf": [
          {
            "field": "type",
            "equals": "Microsoft.Resources/subscriptions/resourceGroups"
          },
          {
            "field": "[concat('tags[', parameters('tagName'), ']')]",
            "notEquals": "[base64(parameters('tagValue'))]"
          }
        ]
      },

Once the function was discovered, and we tested it successfully, we were quite pleased at how well it worked. The lesson learned here is that experiences from the past can be leveraged to solve problems in the present.

  1. https://en.wikipedia.org/wiki/Base64