这样做可能很邪恶,但是为了在我们的Azure数据库中设置托管身份,我们使用null_resource像这样:
# https://www.terraform.io/docs/providers/null/resource.html
# This technique was stolen from https://stackoverflow.com/a/54523391/442773
resource "null_resource" "create-sql-user" {
triggers = {
db = azurerm_sql_database.x.id
}
# https://www.terraform.io/docs/provisioners/local-exec.html
provisioner "local-exec" {
# https://docs.microsoft.com/en-us/powershell/module/sqlserver/Invoke-Sqlcmd?view=sqlserver-ps
# Adding the Managed Identity to the database as a user and assign it the roles of db_datareader and db_datawriter
# NOTE: This is using the executing users credentials to connect to the db, this may not work if this is executed from a service principal within a devops pipeline
# NOTE: this requires powershell to have the SqlServer module installed. We tried a bunch of things to make it so it'd auto install the module but couldn't get it to work
command = <<EOF
Invoke-Sqlcmd `
-Query "CREATE USER [${azurerm_app_service.x.name}] FROM EXTERNAL PROVIDER; ALTER ROLE db_datareader ADD MEMBER [${azurerm_app_service.x.name}]; ALTER ROLE db_datawriter ADD MEMBER [${azurerm_app_service.x.name}];" `
-ConnectionString "Server=tcp:${azurerm_sql_server.x.fully_qualified_domain_name},1433;Initial Catalog=${azurerm_sql_database.x.name};Persist Security Info=False;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Authentication=Active Directory Integrated;" `
EOF
interpreter = ["PowerShell", "-Command"]
}
}
问题是必须具有可用的Invoke-Sqlcmd,但这仅由带terraform的Install-Module SqlServer提供。我在命令中尝试了一些其他操作以实现此目的。喜欢:
# https://www.terraform.io/docs/provisioners/local-exec.html
provisioner "local-exec" {
# https://docs.microsoft.com/en-us/powershell/module/sqlserver/Invoke-Sqlcmd?view=sqlserver-ps
# Adding the Managed Identity to the database as a user and assign it the roles of db_datareader and db_datawriter
command = "Install-Module -Name SqlServer -AcceptLicense -SkipPublisherCheck -Force -AllowClobber -Scope CurrentUser;"
interpreter = ["PowerShell", "-ExecutionPolicy", "Bypass", "-Command"]
}
错误:运行命令“ Install-Module -Name SqlServer -AcceptLicense -SkipPublisherCheck -Force -AllowClobber -Scope CurrentUser;”时出错:退出状态1.输出:Install-Module:在“安装模块”中找到了“ Install-Module”命令模块'PowerShellGet',但无法加载该模块。有关更多信息,请运行“导入模块PowerShellGet”。
因此将命令切换到
command = "Import-Module PowerShellGet; Install-Module -Name SqlServer -AcceptLicense -SkipPublisherCheck -Force -AllowClobber -Scope CurrentUser;"
但这会导致此输出
Error: Error running command 'Import-Module PowerShellGet; Install-Module -Name SqlServer -AcceptLicense -SkipPublisherCheck -Force -AllowClobber -Scope CurrentUser;': exit status 1. Output: Import-Module : The specified module 'C:\program
files\powershell\6\Modules\PackageManagement\fullclr\Microsoft.PackageManagement.dll' was not loaded because no valid
module file was found in any module directory.
At line:1 char:1
+ Import-Module PowerShellGet; Install-Module -Name SqlServer -AcceptLi ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (C:\program file...eManagement.dll:String) [Import-Module], FileNot
FoundException
+ FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand
PackageManagement\Get-PackageProvider : The term 'PackageManagement\Get-PackageProvider' is not recognized as the name
of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included,
verify that the path is correct and try again.
At C:\program files\powershell\6\Modules\PowerShellGet\PSModule.psm1:2926 char:26
+ ... $nugetProvider = PackageManagement\Get-PackageProvider -ErrorA ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (PackageManagement\Get-PackageProvider:String) [], CommandNotFoundExcept
ion
+ FullyQualifiedErrorId : CommandNotFoundException
PackageManagement\Get-PackageProvider : The term 'PackageManagement\Get-PackageProvider' is not recognized as the name
of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included,
verify that the path is correct and try again.
At C:\program files\powershell\6\Modules\PowerShellGet\PSModule.psm1:2940 char:40
+ ... ailableNugetProviders = PackageManagement\Get-PackageProvider -Name $ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (PackageManagement\Get-PackageProvider:String) [], CommandNotFoundExcept
ion
+ FullyQualifiedErrorId : CommandNotFoundException
Exception calling "ShouldContinue" with "2" argument(s): "Object reference not set to an instance of an object."
At C:\program files\powershell\6\Modules\PowerShellGet\PSModule.psm1:3115 char:8
+ if($Force -or $psCmdlet.ShouldContinue($shouldContinueQueryMessag ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : NullReferenceException
Install-Module : NuGet provider is required to interact with NuGet-based repositories. Please ensure that '2.8.5.201'
or newer version of NuGet provider is installed.
At line:1 char:30
+ ... erShellGet; Install-Module -Name SqlServer -AcceptLicense -SkipPublis ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Install-Module], InvalidOperationException
+ FullyQualifiedErrorId : CouldNotInstallNuGetProvider,Install-Module
我想知道的一件事是Powershell版本6和5是否以某种方式进入这里...
答案 0 :(得分:2)
编辑: 我相信您使用的解释器错误,请尝试将Powershell切换为pwsh以将Powershell 6用作解释器。
provisioner "local-exec" {
...
interpreter = ["pwsh", "-Command"]
...
}
我不确定您需要Powershell才能运行的基础架构。似乎您正在使用Powershell 6。
我还使用null提供程序资源,调用脚本,传递参数,然后创建用户。这样做的一个好处是,我知道我正在运行哪个Powershell Verson(核心)作为触发命令,它是pwsh
。
我将向您展示如何创建空资源和脚本片段,希望对您有所帮助。
用于调用负责创建用户的脚本的空资源
resource "null_resource" "create_sql_user" {
provisioner "local-exec" {
command = ".'${path.module}\\scripts\\create-sql-user.ps1' -password \"${random_password.sql_password.result}\" -username \"${var.sql_username}\" -sqlSaConnectionString \"${var.sql_server_connectionstring}\" -databaseName \"${azurerm_sql_database.db.name}\" "
interpreter = ["pwsh", "-Command"]
}
depends_on = [azurerm_sql_database.db]
}
create-sql-user.ps1
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]
$password,
[Parameter(Mandatory = $true)]
[string]
$username,
[Parameter(Mandatory = $true)]
[string]
$sqlSaConnectionString
)
Install-Module -Name SqlServer -Force
$sqlCmd = "CREATE LOGIN $username WITH PASSWORD = '$password'; ALTER LOGIN $username enable"
Invoke-Sqlcmd -ConnectionString $sqlSaConnectionString -Query $sqlCmd
...
其他:
在这种情况下,我正在使用随机资源生成sql密码。可以对用户名使用类似的方法:
resource "random_password" "sql_password" {
length = 54
special = true
override_special = "$%@&*()"
}