我在尝试从 Azure Automation Runbook 中的 Azure Key Vault 检索证书时遇到问题。尽管验证了证书是否存在,但我在运行脚本时遇到了错误。自动化帐户已分配 Key Vault 证书用户和 Key Vault 机密用户角色,并且我已确保 API 权限正确 (Microsoft Graph Sites.FullControl.All、Microsoft Graph User.Read、SharePoint Sites.FullControl.All )。我还检查了 Entra ID,并确认启用了基于证书的身份验证。
错误输出:
Completed
Environments Context
------------ -------
{[AzureChinaCloud, AzureChinaCloud], [AzureCloud, AzureCloud], [AzureUSGovernment, AzureUSGovernment]} Microsoft.Azure.…
Exception calling ".ctor" with "3" argument(s): "Array may not be empty or null. (Parameter 'rawData')"
System.Management.Automation.ParameterBindingValidationException: Cannot bind argument to parameter 'ClientCertificate' because it is null.
at System.Management.Automation.ParameterBinderBase.ValidateNullOrEmptyArgument(CommandParameterInternal parameter, CompiledCommandParameter parameterMetadata, Type argumentType, Object parameterValue, Boolean recurseIntoCollections)
at System.Management.Automation.ParameterBinderBase.BindParameter(CommandParameterInternal parameter, CompiledCommandParameter parameterMetadata, ParameterBindingFlags flags)
at System.Management.Automation.CmdletParameterBinderController.BindParameter(CommandParameterInternal argument, MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
at System.Management.Automation.CmdletParameterBinderController.BindParameter(UInt32 parameterSets, CommandParameterInternal argument, MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
at System.Management.Automation.CmdletParameterBinderController.BindNamedParameter(UInt32 parameterSets, CommandParameterInternal argument, MergedCompiledCommandParameter parameter)
at System.Management.Automation.ParameterBinderController.BindNamedParameters(UInt32 parameterSets, Collection`1 arguments)
at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParametersNoValidation(Collection`1 arguments)
at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection`1 arguments)
at System.Management.Automation.CommandProcessor.BindCommandLineParameters()
at System.Management.Automation.CommandProcessor.Prepare(IDictionary psDefaultParameterValues)
at System.Management.Automation.CommandProcessorBase.DoPrepare(IDictionary psDefaultParameterValues)
at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream)
at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
--- End of stack trace from previous location ---
at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext funcContext)
at System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
我并不完全有信心以最好的方式完成这件事,因为我依赖 ChatGPT 的指导。
PS脚本:
# Login with Managed Identity (for Azure Automation Account)
Write-Host "Logging in with Automation Account Managed Identity..."
Connect-AzAccount -Identity
Write-Host "Logged in with Managed Identity."
# Set API Key
$APIKey = Get-AutomationVariable -Name '...'
Write-Host "API Key retrieved: $APIKey"
# Set SharePoint Site URL and Folder
$SharePointSiteUrl = "..."
$SharePointFolder = "..."
# Set Azure App Registration credentials
$tenantId = "..."
$clientId = "..."
# Retrieve the certificate from Azure Key Vault
Write-Host "Retrieving certificate from Azure Key Vault..."
$certificate = Get-AzKeyVaultCertificate -VaultName '...' -Name '...'
# Check if certificate retrieval was successful
if ($certificate -eq $null) {
Write-Host "Error: Certificate not found in Key Vault!"
exit
}
# Convert from Base64 to Byte Array and create the certificate object
$pfxBytes = [Convert]::FromBase64String($certificate.SecretValueText)
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($pfxBytes, $null, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
Write-Host "Certificate retrieved successfully."
# Use the certificate to authenticate with Azure AD and get an access token
Write-Host "Authenticating with Azure AD using the certificate..."
$GraphConnection = Get-MsalToken -ClientCertificate $cert -ClientId $clientId -TenantId $tenantId
# Get the access token from the authentication response
$Token = $GraphConnection.AccessToken
# Check if the token was retrieved
if (-not $Token) {
Write-Host "Error: Failed to retrieve access token!"
exit
}
Write-Host "Access token retrieved successfully."
所有占位符均已替换为脚本中的实际详细信息,而不是保留为“...”
要从 Azure Key Vault 检索证书并生成访问令牌,请使用
Get-AzKeyVaultSecret
命令而不是 Get-AzKeyVaultCertificate
命令。
# Parameters
$tenantID = 'TenantID'
$clientID = 'ClientID'
$keyVaultName = 'autokvruk'
$certName = 'rukcerttdyypfx'
$scope = 'https://graph.microsoft.com/.default'
Connect-AzAccount -Identity
# Retrieve the certificate from Azure Key Vault as a Base64-encoded string
$pfxSecret = Get-AzKeyVaultSecret -VaultName $keyVaultName -Name $certName -AsPlainText
# Convert the Base64-encoded string to bytes
$secretByte = [Convert]::FromBase64String($pfxSecret)
# Load the certificate using the X509Certificate2 class
$x509Cert = New-Object Security.Cryptography.X509Certificates.X509Certificate2($secretByte, $null, [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
# Get the MSAL token using the certificate
try {
$token = Get-MsalToken -ClientId $clientID -TenantId $tenantID -ClientCertificate $x509Cert -Scope $scope
Write-Host "Successfully retrieved the token."
Write-Host "Access Token: $($token.AccessToken)"
} catch {
Write-Host "Error getting the token: $_"
}
访问令牌生成成功:
已在 Azure Key Vault 中上传
.pfx
证书:
并将
.cer
证书上传到Microsoft Entra ID应用程序:
参考: