Azure ARM uniqueString 函数模拟

Azure ARM uniqueString function mimic

我需要使用以下方式将 Sql 数据库部署到 Azure Sql 服务器中:ARM 模板方式,以及使用 C# 代码的更自定义的方式。有一个名为 uniqueString(string) 的 ARM 模板函数可以生成给定字符串的伪随机散列。这是一个确定性的纯函数。

我需要找到一种方法来从我的 C# 代码中准确模拟此函数的行为。即我需要将此函数重现到我的 C# 代码中。

在哪里可以找到 ARM Api 使用的算法?

MSDN reference for uniqueString()

我终于找到了解决方法。我使用了一个非常简单的 ARM 模板,其目标是只输出 uniqueString 命令的结果。然后我在我的 C# 代码中获取这个输出。该解决方案并不是真正最快的解决方案 ;-),但它可以按预期工作。

我在这里找到了一些 PowerShell 代码来执行此操作:https://blogs.technet.microsoft.com/389thoughts/2017/12/23/get-uniquestring-generate-unique-id-for-azure-deployments/

我将此代码转换为 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;
}

我自己断断续续研究了 几年 现在,我 终于 成功了.. .

// "zcztcwvu6iyg6"
var unique = ArmUniqueString("tyeth");

我的 ArmUniqueString 函数是一些与 Azure Stack Hub Development Kit 一起分发的 dll 的包装器,它基本上是一个包含 Azure 服务器端平台的虚拟机映像,您可以 运行 本地...

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;

}

您需要下载 Azure Stack Hub 开发工具包并解压缩以获取 dll:

  • 下载 Azure Stack Hub Development Kit - 警告:大约 22Gb!
  • 运行 安装程序解压 55Gb *.vhdx
  • 挂载 *.vhdx,或在本地展开/解压它
  • 在 *.vhdx 中,找到此文件并将其解压缩到某处:
    • CloudBuilder\CloudDeployment\NuGetStore\Microsoft.AzureStack.Setup.Services.ResourceManager.5.20.1335.300.nupkg
  • *.nupkg 中的 content\Website\bin 文件夹包含必要的 dll

要使用它们,请添加对 Microsoft.WindowsAzure.ResourceStack.Frontdoor.Templates.dll 的程序集引用(它对 bin 文件夹中的其他文件有一些依赖性)并且包含 TemplateExpressionBuiltInFunctions class。上面的代码只是使用反射从该程序集调用私有 UniqueString 函数,并进行一些工作将参数编组为适当的 JToken 类型。

如果您想深入了解实现细节,您可能 运行 一个针对程序集的反编译器,以找出它在幕后做了什么...

注意 - 致谢这篇博客文章为我指明了正确的方向:

https://the.agilesql.club/2017/12/azure-arm-template-function-internals/

该函数在nuget中发布:https://www.nuget.org/packages/Azure.Deployments.Expression/ 实施: https://msazure.visualstudio.com/One/_git/AzureUX-Deployments?path=%2Fsrc%2FExpressions%2FExpressions%2FExpressionBuiltInFunctions.cs&version=GBmaster&_a=contents

示例:

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();

这是一个二头肌模板,它将为资源组输出一个 uniqueString:

output unique string = uniqueString(resourceGroup().id)