如何让Azure DSC配置读取含VM名称参数的自动化账户变量?
首先,针对你当前的DSC编译问题,核心原因是DSC配置在编译阶段会执行param块后的逻辑,而Get-AutomationVariable是运行时命令,编译阶段无法正确获取变量值,导致报错。不过其实我们可以换个思路,不用DSC也能实现你的需求,甚至更贴合你“尽量用模板/门户、少碰PowerShell”的目标。
方案一:用ARM模板的自定义脚本扩展(推荐,无需DSC)
这个方案完全可以通过ARM模板实现,同事不需要写PowerShell代码,只需要在模板里配置参数即可:
- 模板定义
membersOfLocalAdmins参数,类型为字符串(比如"mydomain\user1,mydomain\group1") - 添加
Microsoft.Compute/virtualMachines/extensions资源,使用自定义脚本扩展执行简单的PowerShell命令(脚本内嵌在模板里,不用单独维护)
示例模板片段:
{ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "vmName": { "type": "string" }, "membersOfLocalAdmins": { "type": "string", "metadata": { "description": "逗号分隔的域用户/组,格式:mydomain\\user1,mydomain\\group1" } }, "domainAdminUsername": { "type": "string" }, "domainAdminPassword": { "type": "securestring" } }, "resources": [ { "type": "Microsoft.Compute/virtualMachines/extensions", "name": "[concat(parameters('vmName'), '/AddLocalAdmins')]", "apiVersion": "2023-09-01", "location": "[resourceGroup().location]", "dependsOn": [ // 依赖你的VM资源 ], "properties": { "publisher": "Microsoft.Compute", "type": "CustomScriptExtension", "typeHandlerVersion": "1.10", "autoUpgradeMinorVersion": true, "settings": { "commandToExecute": "[concat('$members = \"', parameters('membersOfLocalAdmins'), '\" -split \",\"; $cred = New-Object System.Management.Automation.PSCredential(\"', parameters('domainAdminUsername'), '\", (ConvertTo-SecureString \"', parameters('domainAdminPassword'), '\" -AsPlainText -Force)); foreach($member in $members) { Add-LocalGroupMember -Group \"Administrators\" -Member $member -Credential $cred }')]" } } } ] }
这个脚本会把传入的字符串拆分成数组,逐个添加到本地管理员组,用域管理员权限执行(因为添加域用户/组到本地组需要域权限)。如果同事不会写模板,也可以在Azure门户里手动给VM添加自定义脚本扩展,直接在门户里输入命令即可:
- 进入VM的“扩展”页面,点击“添加”,选择“自定义脚本扩展”
- 在“命令”框里输入:
$members = "mydomain\user1,mydomain\group1" -split ","; $cred = New-Object System.Management.Automation.PSCredential("mydomain\admin", (ConvertTo-SecureString "yourPassword" -AsPlainText -Force)); foreach($member in $members) { Add-LocalGroupMember -Group "Administrators" -Member $member -Credential $cred }
替换对应的用户名、密码和要添加的成员即可。
方案二:修正你的DSC配置(如果必须用DSC)
如果你坚持要用DSC,需要调整配置逻辑,把Get-AutomationVariable的调用移到参数默认值中(编译时执行获取变量):
修正后的配置:
Configuration TestConfiguration1Win10 { param( [string[]]$ComputerName = "localhost", # 编译时从自动化变量读取默认值,自动拆分字符串为数组 [string[]]$membersOfLocalAdmins = $(Get-AutomationVariable -Name "membersOfLocalAdmins-$($ComputerName[0])").Split(',') ) $DomainUserName = Get-AutomationVariable -Name 'Internal_Domain_Username' $DomainUserPassword = Get-AutomationVariable -Name 'Internal_Domain_Password' $DomainCredential = New-Object -TypeName System.Management.Automation.PSCredential( $DomainUserName, (ConvertTo-SecureString $DomainUserPassword -AsPlainText -Force) ) Import-DscResource -ModuleName 'PSDesiredStateConfiguration' Import-DSCResource -Module xNetworking -Name xFirewallProfile Import-DSCResource -Module xSystemSecurity -Name xIEEsc Import-DscResource -ModuleName DeleteDscTmpFile Node $ComputerName { Group AddToLocalAdmins { GroupName ='Administrators' Ensure = 'Present' MembersToInclude = $membersOfLocalAdmins Credential = $DomainCredential } # 其他资源... } }
注意:编译配置时,需要确保自动化账户里已经存在membersOfLocalAdmins-<VM名称>这个变量,因为编译阶段会执行Get-AutomationVariable获取值。另外,门户编译表单只能传字符串,所以如果要手动传入,直接输入逗号分隔的字符串即可,配置会自动拆分。
为什么推荐方案一?
因为自定义脚本扩展完全可以通过ARM模板或门户操作,不需要维护DSC配置和自动化账户变量,同事不需要接触PowerShell代码(模板里的脚本是内嵌的,不需要他们修改),完全符合你“减少DSC/Cmdlet操作”的需求。
内容的提问来源于stack exchange,提问作者aberdeen angus

