在Azure数据工厂中参数化连接(ARM模板)

在Azure数据工厂中参数化连接(ARM模板),azure,azure-resource-manager,azure-data-factory,Azure,Azure Resource Manager,Azure Data Factory,我正在尝试在CI/CD设置中设置Azure数据工厂。我遵循了微软的最佳实践() 我有4个环境(开发、测试、UAT、PRD) 简言之,我所做的是: 创建Azure数据工厂并将其链接到开发环境上的my Azure DevOps repo 在其他环境(测试、UAT和PRD)上创建Azure数据工厂,但不要将其链接到DevOps。相反,使用ARM模板在这些数据工厂上发布管道,并在Azure DevOps中发布管道 我已经参数化了所有必要的部分,以便能够覆盖我的每个环境中的设置 目前,我能够成功地部署

我正在尝试在CI/CD设置中设置Azure数据工厂。我遵循了微软的最佳实践()

我有4个环境(开发、测试、UAT、PRD)

简言之,我所做的是:

  • 创建Azure数据工厂并将其链接到开发环境上的my Azure DevOps repo

  • 在其他环境(测试、UAT和PRD)上创建Azure数据工厂,但不要将其链接到DevOps。相反,使用ARM模板在这些数据工厂上发布管道,并在Azure DevOps中发布管道

  • 我已经参数化了所有必要的部分,以便能够覆盖我的每个环境中的设置

目前,我能够成功地部署到我的其他环境,但是,azure上我的数据库的linkedservice不起作用。我已经参数化了一切,就像微软建议的那样,但当我将linkedservice导出到ARM模板时,它使用连接字符串而不是参数化设置

下面是我在Azure Data Factory门户中的设置图片:

当我尝试将其导出到ARM模板时,会得到以下结果:

{
            "name": "[concat(parameters('factoryName'), '/database')]",
            "type": "Microsoft.DataFactory/factories/linkedServices",
            "apiVersion": "2018-06-01",
            "properties": {
                "parameters": {
                    "sqlServerUrl": {
                        "type": "string"
                    },
                    "databaseName": {
                        "type": "string"
                    },
                    "sqlPwd": {
                        "type": "string"
                    },
                    "sqlAdminUsername": {
                        "type": "string"
                    }
                },
                "annotations": [],
                "type": "AzureSqlDatabase",
                "typeProperties": {
                    "connectionString": {
                        "type": "SecureString",
                        "value": "[parameters('database_connectionString')]"
                    }
                }
            },
            "dependsOn": []
        },
此ARM模板的问题在于,它不使用参数来创建连接字符串,而是使用连接字符串参数database_connectionString(默认情况下,连接字符串始终由Azure参数化,因此我无法删除此参数)

当发布管道使用此模板时,不会填充connectionstring(只填充参数),因此与数据库的连接失败。如何设置连接,以便只需更改参数即可自动(无需人工交互)部署到所有环境


我不想更改来自Azure Data Factory的ARM模板,因为这需要人工交互

我通过使用版本中的
Azure资源组部署
任务来做到这一点。其中一个选项是覆盖模板参数,这将允许您准确地执行所需操作。可以创建以空格分隔的参数列表,以替代手臂模板并传入变量

在你的情况下是这样的

-database_connectionstring $(VariableHere)
我会将连接字符串存储在Azure KeyVault中,并将其链接到安全变量组。您也可以点击标准变量上的挂锁来保护它

然后将自定义变量绑定到发行版中的每个阶段

任务

覆盖

提供的另一个答案是使用覆盖参数的有效方法。此答案将提供一个不同的答案,并提供更多关于如何定义SQL连接以及如何利用和实施关键Vault和Data Factory集成的一些更新的上下文

如果使用on-prem连接到SQL,则连接字符串如下所示:

"Server={serverName};Database={databaseName};User ID={domain}\{userName};Password={password};Integrated Security=True;" 
引号是必需的,可以作为覆盖参数传入

如果使用Azure数据库,甚至使用Key Vault,请通过在ARM模板中包含此项来添加

 "identity": {
        "type": "SystemAssigned"
    }
添加后,Azure SQL数据库将需要具有。这可以通过可重用的SQL脚本完成,如:

    DECLARE @rolename AS NVARCHAR(100) = 'DataFactory_User'
    DECLARE @username AS NVARCHAR(100) -- This will be the DataFactory name
    SET @username = 'DataFacotryName'

if exists(select * from sys.database_principals where name = @username and Type = 'X' or Type='E')
    BEGIN
        DECLARE @dropUserSql varchar(1000)
        SET @dropUserSql='DROP USER [' + @username + ']'
        PRINT 'Executing ' + @dropUserSql
        EXEC (@dropUserSql)
        PRINT 'Completed ' + @dropUserSql
    END

DECLARE @createUserSql varchar(1000)
SET @createUserSql='CREATE USER [' + @username + '] FROM EXTERNAL PROVIDER'
PRINT 'Executing ' + @createUserSql
EXEC (@createUserSql)
PRINT 'Completed ' + @createUserSql
我建议删除并重新创建此用户。SQL识别托管标识的指纹,每次删除并重新创建数据工厂时,都会创建一个新的指纹

就利用密钥保险库而言,有一个依赖于上述托管身份来检索机密的数据库

如果通过ARM部署密钥库,则需要将访问策略更新为类似以下内容:

"accessPolicies": [
          {
            "tenantID": "[subscription().tenantId]",
            "objectId": "[reference(resourceId('Microsoft.DataFactory/factories/', parameters('DataFactoryName')), '2018-02-01', 'Full').identity.principalId]",
            "permissions": {
              "secrets": [
                "get"
              ],
              "keys": [
                "get"
              ],
              "certificates": [
                "import"
              ]
            },
            "dependsOn": [
              "[resourceId('Microsoft.DataFactory/factories/', parameters('DataFactoryName'))]"
            ]
          }
        ]

此代码段假定密钥Vault和数据工厂位于同一ARM模板中。如果不是,访问策略仍然可以通过ARM完成,方法是将其作为ObjectId传入并删除dependsOn语句。

以防您没有找到答案或解决此问题:

我的情况非常相似,我有几个参数化的Azure SQL数据库(数据库名称),需要在我的ADF Azure发布管道中更改SQL server名称以在环境之间交换

我发现,通过检查链接服务({}旁边)的代码定义,可以得到一个连接字符串,其中包含您定义的任何参数:

我复制了“connectionString”的值,修改了我需要的内容(服务器地址),并保留了参数,并将其添加到Azure发布管道中的“connectionString”覆盖参数中,结果成功了!(包括引号!)


我希望这能帮助您或将来遭受同样挫折/困惑的任何人。

请注意,如果您的
VariableHere
中有空格,请执行此
“$(VariableHere)”