如何利用PowerShell与Azure Function创建虚拟机并配置MSI及HTTP API
实现Azure Function通过MSI认证创建VM并提供带认证的HTTP触发API
没问题,我来带你一步步实现这个需求:用Azure Function托管PowerShell脚本,通过MSI创建虚拟机,同时对外提供带认证的HTTP触发API。下面是详细的步骤和代码实现:
1. 创建Azure Function并启用系统托管标识(MSI)
- 在Azure门户创建一个Function App,运行时选择PowerShell,其他配置按需选择(比如托管计划选消耗计划即可)
- 进入Function App的标识选项卡,切换到「系统分配」页签,点击「启用」并保存——这样就给Function App分配了一个自动管理的MSI身份,后续创建VM时就用这个身份认证
2. 为MSI分配创建VM的权限
- 找到你要创建VM的目标资源组(如果需要订阅级别的权限,就选择订阅),进入访问控制(IAM)
- 点击「添加角色分配」,角色选择虚拟机参与者(如果需要更细粒度的权限,可以自定义角色,但这个角色足够覆盖VM创建的核心操作)
- 成员类型选择「托管标识」,然后搜索并选择刚才创建的Function App的标识,完成角色分配
3. 编写PowerShell Function代码
创建一个HTTP触发的Function,替换默认代码为以下内容:
using namespace System.Net param($Request, $TriggerMetadata) Write-Host "开始处理创建VM的HTTP请求..." # 从请求参数中获取VM配置信息 $vmName = $Request.Query.VMName $resourceGroupName = $Request.Query.ResourceGroupName $location = $Request.Query.Location ?? "eastus" # 默认使用eastus区域 # 参数校验 if (-not $vmName -or -not $resourceGroupName) { Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::BadRequest Body = "请传入必填参数:VMName(虚拟机名称)和ResourceGroupName(资源组名称)" }) return } try { # 用MSI身份自动登录Azure,无需手动提供凭据 Connect-AzAccount -Identity # 准备VM基础配置(这里简化了网络配置,你可以根据需求添加创建VNet、子网、网卡的逻辑) $vmConfig = New-AzVMConfig -VMName $vmName -VMSize "Standard_D2s_v3" # 建议从Key Vault获取管理员凭据,避免硬编码(需给MSI分配Key Vault的访问权限) # $credSecret = Get-AzKeyVaultSecret -VaultName "your-vault-name" -Name "vm-admin-cred" # $credential = [System.Management.Automation.PSCredential]::new("adminuser", $credSecret.SecretValue) $credential = Get-AzCredential -UserName "adminuser" # 临时用交互式方式获取,生产环境替换为Key Vault $vmConfig = Set-AzVMOperatingSystem -VM $vmConfig -Windows -ComputerName $vmName -Credential $credential -ProvisionVMAgent -EnableAutoUpdate $vmConfig = Set-AzVMSourceImage -VM $vmConfig -PublisherName "MicrosoftWindowsServer" -Offer "WindowsServer" -Skus "2022-Datacenter" -Version "latest" # 绑定已存在的网卡(如果需要自动创建网卡,可添加New-AzNetworkInterface的逻辑) $nic = Get-AzNetworkInterface -ResourceGroupName $resourceGroupName -Name "$vmName-nic" $vmConfig = Add-AzVMNetworkInterface -VM $vmConfig -Id $nic.Id # 执行VM创建 New-AzVM -ResourceGroupName $resourceGroupName -Location $location -VM $vmConfig Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = "虚拟机 $vmName 已在资源组 $resourceGroupName 中成功创建!" }) } catch { Write-Error "创建VM失败:$_" Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::InternalServerError Body = "创建VM失败:$($_.Exception.Message)" }) }
提示:生产环境中,管理员密码不要硬编码,建议存储在Azure Key Vault中,给MSI分配Key Vault的「密钥/机密用户」权限,然后用
Get-AzKeyVaultSecret获取凭据。另外,网络相关资源(VNet、子网、网卡)也可以在脚本中自动创建,让整个流程完全自动化。
4. 配置HTTP触发的认证保护
为了防止API被未授权调用,我们可以选择两种认证方式:
方式一:Azure AD身份认证(企业级推荐)
- 进入Function App的身份验证选项卡,点击「添加身份验证提供程序」
- 选择「Microsoft」作为身份提供程序,配置允许的租户(比如你的组织租户),设置未授权请求的处理方式为「HTTP 401 未授权」
- 保存后,只有经过Azure AD认证的用户/应用才能调用该API
方式二:API密钥认证(快速简单)
- 在Function的集成选项卡,找到HTTP触发的「授权级别」,设置为「函数」(使用函数级密钥)或「管理员」(使用主密钥)
- 调用时需要在请求头中添加:
x-functions-key: <你的API密钥>
5. 测试API调用
如果使用API密钥认证,你可以用curl或者Postman测试:
curl "https://<你的FunctionApp名称>.azurewebsites.net/api/<Function名称>?VMName=test-vm&ResourceGroupName=test-rg&Location=eastus" -H "x-functions-key: <你的API密钥>"
如果使用Azure AD认证,需要先获取Azure AD访问令牌,然后在请求头中添加:Authorization: Bearer <你的访问令牌>
内容的提问来源于stack exchange,提问作者Ashutosh Jha
相关产品推荐
相关产品推荐

