使用 Azure Powershell Runbook 将 AzureAD 用户作为 db_owner 添加到 Azure SQL 数据库
Use Azure Powershell Runbook to add AzureAD user as db_owner to an Azure SQL database
我有一个 Powershell Runbook,我正在尝试将 AzureAD 用户添加为 Azure SQL 数据库上的数据库所有者。
## Connect
$servicePrincipalConnection = Get-AutomationConnection -Name "AzureRunAsConnection"
Connect-AzureAD `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
## Generate new access token
$cert = Get-AutomationCertificate -Name 'AzureRunAsCertificate'
# Set Resource URI to Azure Database
$resourceAppIdURI = 'https://database.windows.net/'
# Set Authority to Azure AD Tenant
$authority = 'https://login.windows.net/' + $servicePrincipalConnection.TenantId
$ClientCred = [Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate]::new($servicePrincipalConnection.ApplicationId, $cert)
$authContext = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext]::new($authority)
$authResult = $authContext.AcquireTokenAsync($resourceAppIdURI, $ClientCred)
$AccessToken = $authResult.Result.AccessToken
## Execute sql
$AccessToken
$connectionString = "Data Source=MYCOOLSQLSERVER.database.windows.net;Initial Catalog=MYCOOLDATABASE;Connect Timeout=30"
$connection = New-Object -TypeName System.Data.SqlClient.SqlConnection($connectionString)
$query = "Create User [abc@xyz.com] From EXTERNAL PROVIDER;"
$command = New-Object -TypeName System.Data.SqlClient.SqlCommand($query, $connection)
$connection.AccessToken = $AccessToken
$connection.Open()
$command.ExecuteNonQuery()
$connection.Close()
我最终收到下面的错误,其中 abc@xyz.com
是 AzureAD 用户。
Principal 'abc@xyz.com' could not be resolved.
有什么我遗漏的吗?
创建用户后,我打算使用 Alter role
使他成为 db_owner
。
对于这种情况,我们应该使用用户密码流来使这个命令起作用。请尝试下面的 PS:
$tenant='<your tenant name/id>'
$username='<SQL admin account>'
$password='<SQL admin password>'
$appid='<app id>'
$appsec='<app secret>'
$SQLServerName = '<azure sql servername>'
$DatabaseName='<db name>'
$body=@{
"grant_type"="password";
"resource"="https://database.windows.net/";
"client_id"=$appid;
"client_secret"=$appsec;
"username"=$username;
"password" = $password;
}
$result=Invoke-RestMethod -Uri "https://login.windows.net/$tenant/oauth2/token" -Method POST -Body $body
$conn = New-Object System.Data.SqlClient.SQLConnection
$conn.ConnectionString = "Data Source=$SQLServerName.database.windows.net;Initial Catalog=$DatabaseName;Connect Timeout=30"
$conn.AccessToken = $result.access_token
Write-Verbose "Connect to database and execute SQL script"
$conn.Open()
$query = 'CREATE USER [Account] FROM EXTERNAL PROVIDER;'
$command = New-Object -TypeName System.Data.SqlClient.SqlCommand($query, $conn)
$Result = $command.ExecuteScalar()
$Result
$conn.Close()
在您 运行 是脚本之前,您应该在此处为您在 Azure AD 中的 SPN 授予 user_impersonation Azure SQL API 访问权限:
添加后授予权限:
顺便说一句,请确保 SQL 管理员帐户和 SPN 都是 Active Directory 管理员组的成员:
它在我这边有效,并且已成功添加一条记录:
如果有任何不清楚的地方,请随时告诉我:)
原来有一种未记录的方法可以做到这一点。在 Azure 支持团队的帮助下发现它。
要使用的SQL查询实际上是:
CREATE USER [abc@xyz.com] WITH SID = $hexSid, Type E;
这里$hexSid
可以通过下面SQL查询得到
- 获取 AzureAD 用户的 ObjectId
$objectId = (Get-AzureADUser -ObjectId "abc@xyz.com").ObjectId
- 使用下面的SQL得到
sid
DECLARE @sid = uniqueidentifier = cast('$objectId' as
uniqueidentifier) select cast(@sid as varbinary(max))
- 现在理想情况下,有效查询会直接使用
@sid
但这是不可能的,因为 With SID
需要硬编码值。所以我不得不像下面这样单独处理 sid 查询的输出:
$result = $command.ExecuteScalar() # result is byte array
$hexSid = ($result | ForEach-Object ToString X2) -Join '' # convert to hex format
$hexSid = "0x$hexSid"
有了这些更改,问题中的代码就可以正常工作了!
实际上,我们只在创建用户查询中传递 AzureAD 用户的 objectId。
我有一个 Powershell Runbook,我正在尝试将 AzureAD 用户添加为 Azure SQL 数据库上的数据库所有者。
## Connect
$servicePrincipalConnection = Get-AutomationConnection -Name "AzureRunAsConnection"
Connect-AzureAD `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
## Generate new access token
$cert = Get-AutomationCertificate -Name 'AzureRunAsCertificate'
# Set Resource URI to Azure Database
$resourceAppIdURI = 'https://database.windows.net/'
# Set Authority to Azure AD Tenant
$authority = 'https://login.windows.net/' + $servicePrincipalConnection.TenantId
$ClientCred = [Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate]::new($servicePrincipalConnection.ApplicationId, $cert)
$authContext = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext]::new($authority)
$authResult = $authContext.AcquireTokenAsync($resourceAppIdURI, $ClientCred)
$AccessToken = $authResult.Result.AccessToken
## Execute sql
$AccessToken
$connectionString = "Data Source=MYCOOLSQLSERVER.database.windows.net;Initial Catalog=MYCOOLDATABASE;Connect Timeout=30"
$connection = New-Object -TypeName System.Data.SqlClient.SqlConnection($connectionString)
$query = "Create User [abc@xyz.com] From EXTERNAL PROVIDER;"
$command = New-Object -TypeName System.Data.SqlClient.SqlCommand($query, $connection)
$connection.AccessToken = $AccessToken
$connection.Open()
$command.ExecuteNonQuery()
$connection.Close()
我最终收到下面的错误,其中 abc@xyz.com
是 AzureAD 用户。
Principal 'abc@xyz.com' could not be resolved.
有什么我遗漏的吗?
创建用户后,我打算使用 Alter role
使他成为 db_owner
。
对于这种情况,我们应该使用用户密码流来使这个命令起作用。请尝试下面的 PS:
$tenant='<your tenant name/id>'
$username='<SQL admin account>'
$password='<SQL admin password>'
$appid='<app id>'
$appsec='<app secret>'
$SQLServerName = '<azure sql servername>'
$DatabaseName='<db name>'
$body=@{
"grant_type"="password";
"resource"="https://database.windows.net/";
"client_id"=$appid;
"client_secret"=$appsec;
"username"=$username;
"password" = $password;
}
$result=Invoke-RestMethod -Uri "https://login.windows.net/$tenant/oauth2/token" -Method POST -Body $body
$conn = New-Object System.Data.SqlClient.SQLConnection
$conn.ConnectionString = "Data Source=$SQLServerName.database.windows.net;Initial Catalog=$DatabaseName;Connect Timeout=30"
$conn.AccessToken = $result.access_token
Write-Verbose "Connect to database and execute SQL script"
$conn.Open()
$query = 'CREATE USER [Account] FROM EXTERNAL PROVIDER;'
$command = New-Object -TypeName System.Data.SqlClient.SqlCommand($query, $conn)
$Result = $command.ExecuteScalar()
$Result
$conn.Close()
在您 运行 是脚本之前,您应该在此处为您在 Azure AD 中的 SPN 授予 user_impersonation Azure SQL API 访问权限:
顺便说一句,请确保 SQL 管理员帐户和 SPN 都是 Active Directory 管理员组的成员:
它在我这边有效,并且已成功添加一条记录:
如果有任何不清楚的地方,请随时告诉我:)
原来有一种未记录的方法可以做到这一点。在 Azure 支持团队的帮助下发现它。
要使用的SQL查询实际上是:
CREATE USER [abc@xyz.com] WITH SID = $hexSid, Type E;
这里$hexSid
可以通过下面SQL查询得到
- 获取 AzureAD 用户的 ObjectId
$objectId = (Get-AzureADUser -ObjectId "abc@xyz.com").ObjectId
- 使用下面的SQL得到
sid
DECLARE @sid = uniqueidentifier = cast('$objectId' as uniqueidentifier) select cast(@sid as varbinary(max))
- 现在理想情况下,有效查询会直接使用
@sid
但这是不可能的,因为With SID
需要硬编码值。所以我不得不像下面这样单独处理 sid 查询的输出:
$result = $command.ExecuteScalar() # result is byte array $hexSid = ($result | ForEach-Object ToString X2) -Join '' # convert to hex format $hexSid = "0x$hexSid"
有了这些更改,问题中的代码就可以正常工作了!
实际上,我们只在创建用户查询中传递 AzureAD 用户的 objectId。