I need to deploy Sql Databases into an Azure Sql Server using to ways: the ARM template way, and a more custom way using C# code. There's a ARM template function called uniqueString(string)
that generate a pseudo random hash of a given string. It's a deterministic pure function.
I need to find a way to exactly mimic the behaviour of this function from my C# code. ie I need to reproduce this function into my C# code.
Where can i find the algorithm used by the ARM Api ?
MSDN reference for uniqueString()
I've been researching this myself on and off for a few years now, and I've finally hit paydirt...
// "zcztcwvu6iyg6"
var unique = ArmUniqueString("tyeth");
My ArmUniqueString
function is a wrapper around some dlls that are distributed with the Azure Stack Hub Development Kit which is basically a virtual machine image that contains the Azure server-side platform that you can run locally...
private static string ArmUniqueString(string originalString)
{
var assembly = Assembly.GetAssembly(
typeof(Microsoft.WindowsAzure.ResourceStack.Frontdoor.Templates.Engines.TemplateEngine)
);
var functions = assembly.GetType(
"Microsoft.WindowsAzure.ResourceStack.Frontdoor.Templates.Expressions.TemplateExpressionBuiltInFunctions"
);
var uniqueString = functions.GetMethod(
"UniqueString",
BindingFlags.Static | BindingFlags.NonPublic
);
var parameters = new object[] {
"uniqueString",
new JToken[] {
(JToken)originalString
}
};
var result = uniqueString.Invoke(null, parameters).ToString();
return result;
}
You'll need to download the Azure Stack Hub Development Kit and unpack it to get the dlls:
CloudBuilder\CloudDeployment\NuGetStore\Microsoft.AzureStack.Setup.Services.ResourceManager.5.20.1335.300.nupkg
content\Website\bin
folder inside the *.nupkg
contains the necessary dllsTo use them, add an assembly reference to Microsoft.WindowsAzure.ResourceStack.Frontdoor.Templates.dll
(it has some dependencies on other files in the bin folder) and that contains the TemplateExpressionBuiltInFunctions
class. The code above just uses reflection to invoke the private UniqueString
function from that assembly, with a little bit of work to marshal the parameters into appropriate JToken
types.
If you wanted to dig into the implementation details you could probably run a decompiler against the assembly to find out what it's doing under the covers...
Note - credits go to this blog article for pointing me in the right direction:
https://the.agilesql.club/2017/12/azure-arm-template-function-internals/
I found some PowerShell code to do this here: https://blogs.technet.microsoft.com/389thoughts/2017/12/23/get-uniquestring-generate-unique-id-for-azure-deployments/
I converted this code to C#:
public string GetUniqueString(string id, int length = 13)
{
string result = "";
var buffer = System.Text.Encoding.UTF8.GetBytes(id);
var hashArray = new System.Security.Cryptography.SHA512Managed().ComputeHash(buffer);
for(int i = 1; i <= length; i++)
{
var b = hashArray[i];
var c = Convert.ToChar((b % 26) + (byte)'a');
result = result + c;
}
return result;
}
This function is released in nuget: https://www.nuget.org/packages/Azure.Deployments.Expression/ The implementation: https://msazure.visualstudio.com/One/_git/AzureUX-Deployments?path=%2Fsrc%2FExpressions%2FExpressions%2FExpressionBuiltInFunctions.cs&version=GBmaster&_a=contents
Example:
using Azure.Deployments.Expression.Expressions;
using Newtonsoft.Json.Linq;
var funcs = ExpressionBuiltInFunctions.Functions;
var jt = new JTokenExpression("test");
var output = funcs.EvaluateFunction("uniqueString", new JToken[] { jt.Value }).ToString();
Sam Cogan wrote a blog post on how to do this in C# here: https://samcogan.com/using-bicep-functions-in-c-if-you-really-want-to/
Inspired by Sam, I wrote a PowerShell module (for PowerShell 7) that does the same. You can install the module by running Install-Module -Name AzExpression
which will give you command called New-AzUniqueString.
Here is an example on how to use it:New-AzUniqueString -InputStrings 'test', 'value'
Which will output: bhxq2thzm5dym
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With