azure-devops - 使用 AzureDevOps 构建代理使用托管标识从应用服务建立安全的 Azure SQL 数据库连接

标签 azure-devops azure-web-app-service azure-powershell azure-sql-server

我的努力特别是在默认配置中使用 AzureDevOps 构建代理实现完全自动化。

我正在尝试使用应用服务托管标识 (https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity) 访问 SQL 数据库。

整个资源组由 AzureDevOps 构建代理在单个部署期间创建。

我的部署的简化版本:


New-AzResourceGroup `
    -Name $Env:RESOURCEGROUP_NAME `
    -Location $Env:AZURE_REGION_COMMON `
    -Force

#Create the functionapp
New-AzResource `
    -ResourceGroupName $Env:RESOURCEGROUP_NAME `
    -location $Env:AZURE_REGION_COMMON `
    -ResourceName $Env:APPFUNCTIONS_NAME_SAFE `
    -Kind 'functionapp' `
    -ResourceType 'Microsoft.Web/Sites' `
    -Properties @{} `
    -Force

#Apply the Managed Service Identity
Set-AzWebApp `
    -ResourceGroupName $Env:RESOURCEGROUP_NAME `
    -Name $Env:APPFUNCTIONS_NAME_SAFE `
    -AssignIdentity $true

# Create Sql Server

New-AzSqlServer `
    -ResourceGroupName $Env:RESOURCEGROUP_NAME `
    -location $Env:AZURE_REGION_COMMON `
    -ServerName $Env:SQLSERVER_NAME_SAFE `
    -ServerVersion $Env:SQLSERVER_VERSION `
    -SqlAdministratorCredentials (New-Object `
        -TypeName System.Management.Automation.PSCredential `
        -ArgumentList $Env:SQLSERVER_ADMIN_USERNAME, (ConvertTo-SecureString -String $Env:SQLSERVER_ADMIN_PASSWORD -AsPlainText -Force)) `
    -AssignIdentity

#Update Sql Server Firewall Rules for Azure
New-AzSqlServerFirewallRule `
    -ResourceGroupName $Env:RESOURCEGROUP_NAME `
    -ServerName $Env:SQLSERVER_NAME_SAFE `
    -AllowAllAzureIPs

#Update Sql Server Firewall Rules for non-Azure build machine
$ip = Invoke-RestMethod http://ipinfo.io/json | Select -exp ip
New-AzSqlServerFirewallRule `
    -ResourceGroupName $Env:RESOURCEGROUP_NAME `
    -ServerName $Env:SQLSERVER_NAME_SAFE `
    -FirewallRuleName "BuildMachine" `
    -StartIpAddress $ip `
    -EndIpAddress $ip

#Create Sql Database
New-AzSqlDatabase `
    -ResourceGroupName $Env:RESOURCEGROUP_NAME `
    -ServerName $Env:SQLSERVER_NAME_SAFE `
    -DatabaseName $Env:SQLSERVER_DATABASE_NAME

此时;我没有找到构建代理可以运行以向身份授予数据库权限的任何 powershell。

我确实找到了建议在数据库上运行这样的东西的引用资料

CREATE USER [$Env:APPFUNCTIONS_NAME_SAFE] FROM EXTERNAL PROVIDER
ALTER ROLE db_datareader ADD MEMBER [$Env:APPFUNCTIONS_NAME_SAFE]
ALTER ROLE db_datawriter ADD MEMBER [$Env:APPFUNCTIONS_NAME_SAFE]

这一直是我集中精力的地方,但没有成功。

当我以数据库管理员身份登录数据库时(请参阅上面的 SqlAdministratorCredentials)然后我得到以下异常 Exception calling "ExecuteNonQuery" with "0" argument(s): "Principal '<value of Env:$APPFUNCTIONS_NAME_SAFE>' could not be created. Only connections established with Active Directory accounts can create other Active Directory users.

为了解决这个问题,我手动添加了一个 AAD 组,即与该组的 azure devops 服务连接。这使构建代理能够通过 AAD 向 Sql Server 进行身份验证。

再次部署我得到 System.Management.Automation.MethodInvocationException: Exception calling "Open" with "0" argument(s): "One or more errors occurred." ---> System.AggregateException: One or more errors occurred. ---> System.AggregateException: One or more errors occurred. ---> AdalException: No mapping between account names and security IDs was done.

这让我想到了 - 如何自动向 Sql 数据库验证 AppService Identity?

引用资料

下面是我作为构建代理执行 SQL 的方式

function Get-SqlServer{
    Get-AzSqlServer `
        -ResourceGroupName $Env:RESOURCEGROUP_NAME `
        -ServerName $Env:SQLSERVER_NAME_SAFE `
        -ErrorAction Ignore
}

function Add-User-Sql($database, $sql){

    $server = "tcp:$((Get-SqlServer).FullyQualifiedDomainName),1433"
    $adminName = $Env:SQLSERVER_ADMIN_USERNAME
    $adminPassword = $Env:SQLSERVER_ADMIN_PASSWORD

    $connectionString = "Server=$server;Database=$database;User ID=$adminName;Password=$adminPassword;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
    #$connectionString = "Data Source=$server; Authentication=Active Directory Integrated; Initial Catalog=$database;";
    $connection = New-Object -TypeName System.Data.SqlClient.SqlConnection($connectionString)

    $command = New-Object -TypeName System.Data.SqlClient.SqlCommand($sql, $connection)
    Write-Host "Add User [database=$database] on SqlServer [$Env:SQLSERVER_NAME_SAFE]"
    Write-Host $sql
    $connection.Open()
    $command.ExecuteNonQuery()
    $connection.Close()
}

清理脚本

Remove-AzResourceGroup `
    -Name $Env:RESOURCEGROUP_NAME `
    -Force

最佳答案

也许我遗漏了一些东西,但考虑到您的解释和 AFAIK,您所遵循的流程中的最新错误(“帐户名称和安全 ID 之间未完成映射”)可能是因为角色成员无效或过时某种方式。

关于您提出的将 AppService 身份自动验证到 Sql 数据库的方法的问题,请尝试 this 中提供的命令如果您还没有,请记录下来。

与此主题相关的其他引用资料:

Use Azure SQL Database from App Service with Managed Identity (Without Code Changes)/

Securing Azure SQL Databases with managed identities just got easier

希望这些信息对您有所帮助!!干杯!

关于azure-devops - 使用 AzureDevOps 构建代理使用托管标识从应用服务建立安全的 Azure SQL 数据库连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56500782/

相关文章:

azure - 如何识别两个不同的应用服务

Azure ARM 模板、站点的 VNET 集成

Azure Powershell : Az and AzureRM modules cannot be imported in the same session

azure - Powershell AzureADPreview cmdlet Set-AzureADApplication "PreAuthorizedApplications"参数的正确语法是什么?

azure - 映射 yarn 构建输出以暂存工件

azure-devops - 团队资源管理器中文件旁边的星号,更改面板

git - 如何通过 ssh 获取托管在 Azure DevOps Repo 中的 Terraform 模块

Azure ApplicationGateWay requestRoutingRules 在已定义时不会被引用

c# - Azure 应用服务出站请求超时

azure - 如何在 Azure 中自动部署机器人 channel 注册?