服务主体:Set-AzureRmKeyVaultAccessPolicy:没有足够的权限来完成操作

时间:2017-07-13 12:22:19

标签: azure azure-powershell azure-resource-manager

发布更新。问题已经解决。下面的脚本将创建资源组,创建服务主体,部署密钥保管库,配置权限以及向保管库写入密钥。希望对你有所帮助! :)

问题: 我作为服务主体登录到PowerShell,该服务主体具有资源组的所有者权限。 当我尝试创建保险库,设置保险库权限以及何时尝试写秘密时,我收到权限错误。

permission errors

解决方案: 第1步:创建资源组和服务主体。您必须以管理员身份登录才能执行此脚本

Clear-Host
Import-Module Azure
Import-Module AzureRM.Resources

Add-AzureRmAccount
Get-AzureRmSubscription
Set-AzureRmContext -SubscriptionId <Your subscription id goes here>

$ServicePrincipalDisplayName = "myServicePrincipalName"
$CertificateName = "CN=SomeCertName" 

$cert = New-SelfSignedCertificate -CertStoreLocation "cert:\CurrentUser\My" -Subject $CertificateName -KeySpec KeyExchange
$keyValue = [Convert]::ToBase64String($cert.GetRawCertData())

$ResouceGroupName = "myRessourceGroup"
$location = "North Central US"

# Create the resource group
New-AzureRmResourceGroup -Name $ResouceGroupName -Location $location

$ResouceGroupNameScope = (Get-AzureRmResourceGroup -Name $ResouceGroupName -ErrorAction Stop).ResourceId

# Create the Service Principal that logs in with a certificate
New-AzureRMADServicePrincipal -DisplayName $ServicePrincipalDisplayName -CertValue $keyValue -EndDate $cert.NotAfter -StartDate $cert.NotBefore

$myServicePrincipal = Get-AzureRmADServicePrincipal -SearchString $ServicePrincipalDisplayName
Write-Host "myServicePrincipal.ApplicationId " $myServicePrincipal.ApplicationId -ForegroundColor Green
Write-Host "myServicePrincipal.DisplayName " $myServicePrincipal.DisplayName

# Sleep here for a few seconds to allow the service principal application to become active (should only take a couple of seconds normally)
Write-Host "Waiting 10 seconds"
Start-Sleep -s 10

Write-Host "Make the Service Principal owner of the resource group " $ResouceGroupName

$NewRole = $null
$Retries = 0
 While ($NewRole -eq $null -and $Retries -le 6)
 {  
    New-AzureRMRoleAssignment -RoleDefinitionName Owner -ServicePrincipalName $myServicePrincipal.ApplicationId  -Scope $ResouceGroupNameScope -ErrorAction SilentlyContinue    
    $NewRole = Get-AzureRMRoleAssignment -ServicePrincipalName $myServicePrincipal.ApplicationId
    Write-Host "NewRole.DisplayName " $NewRole.DisplayName
    Write-Host "NewRole.Scope: " $NewRole.Scope
    $Retries++

    Start-Sleep -s 10
 }

Write-Host "Service principal created" -ForegroundColor Green

第2步:ARM部署保管库。创建filenamed keyvault2.parameters.json更新ID以反映您的安装(5479eaf6-31a3-4be3-9fb6-c2cdadc31735是访问Vault时azure Web应用程序使用的服务主体。)

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
  "parameters": {
    "vaultName": {
      "value": "valueFromParameterFile"
    },
    "vaultlocation": {
      "value": "valueFromParameterFile"
    },
    "skumode": {
      "value": "Standard"
    },
    "accessPolicyList": {
      "value": [
        {
          "objectId": "The object ID for your AAD user goes here so that you can read secrets etc",
          "tenantId": "Your Tenant Id goes here",
          "permissions": {
            "keys": [
              "Get",
              "List"
            ],
            "secrets": [
              "Get",
              "List"
            ],
            "certificates": [
              "Get",
              "List"
            ]
          }
        },
        {
          "objectId": "The object ID for the service principal goes here Get-AzureRmADServicePrincipal -ServicePrincipalName <Service Principal Application ID>",
          "tenantId": "Your Tenant Id goes here",
          "permissions": {
            "keys": [
              "Get",
              "List",
              "Update",
              "Create",
              "Import",
              "Delete",
              "Recover",
              "Backup",
              "Restore"
            ],
            "secrets": [
              "Get",
              "List",
              "Set",
              "Delete",
              "Recover",
              "Backup",
              "Restore"
            ],
            "certificates": [
              "Get",
              "List",
              "Update",
              "Create",
              "Import",
              "Delete",
              "ManageContacts",
              "ManageIssuers",
              "GetIssuers",
              "ListIssuers",
              "SetIssuers",
              "DeleteIssuers"
            ]
          },
          "applicationId": null
        },
        {
        "objectId": "5479eaf6-31a3-4be3-9fb6-c2cdadc31735",
        "tenantId": "Your Tenant Id goes here",
        "permissions": {
            "keys": [],
            "secrets": [
                "Get"
            ],
            "certificates": []
        },
        "applicationId": null
    }
      ]
    },
    "tenant": {
      "value": "Your Tenant Id goes here"
    },
    "isenabledForDeployment": {
      "value": true
    },
    "isenabledForTemplateDeployment": {
      "value": false
    },
    "isenabledForDiskEncryption": {
      "value": false
    }
  }
}

第3步:ARM部署保管库。创建filenamed keyvault2.template.json

{
    "$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
  "parameters": {
    "vaultName": {
      "type": "string"
    },
    "vaultlocation": {
      "type": "string"
    },
    "skumode": {
      "type": "string",
      "defaultValue": "Standard",
      "allowedValues": [
        "Standard",
        "standard",
        "Premium",
        "premium"
      ],
      "metadata": {
        "description": "SKU for the vault"
      }
    },
    "accessPolicyList": {
      "type": "array",
      "defaultValue": [],
      "metadata": {
        "description": "The access policies defined for this vault."
      }
    },
    "tenant": {
      "type": "string"
    },
    "isenabledForDeployment": {
      "type": "bool"
    },
    "isenabledForTemplateDeployment": {
      "type": "bool"
    },
    "isenabledForDiskEncryption": {
      "type": "bool"
    }
  },
    "resources": [
      {
        "apiVersion": "2015-06-01",
        "name": "[parameters('vaultName')]",
        "location": "[parameters('vaultlocation')]",
        "type": "Microsoft.KeyVault/vaults",
        "properties": {
          "enabledForDeployment": "[parameters('isenabledForDeployment')]",
          "enabledForTemplateDeployment": "[parameters('isenabledForTemplateDeployment')]",
          "enabledForDiskEncryption": "[parameters('isenabledForDiskEncryption')]",
          "accessPolicies": "[parameters('accessPolicyList')]",
          "tenantId": "[parameters('tenant')]",
          "sku": {
            "name": "[parameters('skumode')]",
            "family": "A"
          }
        }
      }
    ]
}

第4步:部署保管库。启动一个新的PowerShell窗口并执行此脚本。更新3 x id&#39; s

Clear-Host

Import-Module Azure
Import-Module AzureRM.Resources    

$ServicePrincipalApplicationId = "xxx"
$TenantId = "yyy"
$SubscriptionId = "zzz"
$CertificateName = "CN=SomeCertName"
$ResouceGroupName = "myRessourceGroup"
$location = "North Central US"
$VaultName = "MyVault" + (Get-Random -minimum 10000000 -maximum 1000000000)
$MySecret = ConvertTo-SecureString -String "MyValue" -AsPlainText -Force

$Cert = Get-ChildItem cert:\CurrentUser\My\ | Where-Object {$_.Subject -match $CertificateName }
Write-Host "cert.Thumbprint " $cert.Thumbprint
Write-Host "cert.Subject " $cert.Subject

Add-AzureRmAccount -ServicePrincipal -CertificateThumbprint $cert.Thumbprint -ApplicationId $ServicePrincipalApplicationId -TenantId $TenantId
Get-AzureRmSubscription
Set-AzureRmContext -SubscriptionId $SubscriptionId

Write-Host ""
Write-Host "Creating vault" -ForegroundColor Yellow

New-AzureRmResourceGroupDeployment -ResourceGroupName $ResouceGroupName -vaultName $vaultName -vaultlocation $location -isenabledForDeployment $true -TemplateFile ".\keyvault2.template.json"  -TemplateParameterFile ".\keyvault2.parameters.json"

Write-Host ""
Write-Host "Key Vault " $vaultName " deployed" -ForegroundColor green

Write-Host "Wait 5 seconds"
Start-Sleep -Seconds 5

Write-Host "Write Secret" -ForegroundColor Yellow    
Set-AzureKeyVaultSecret -VaultName $VaultName -Name "MyKey" -SecretValue $MySecret

Write-Host "Wait 10 seconds"
Start-Sleep -Seconds 10

Write-Host "Read secret"
Get-AzureKeyVaultSecret -VaultName $VaultName -Name "MyKey"

4 个答案:

答案 0 :(得分:5)

Set-AzureRmKeyVaultAccessPolicy -VaultName $name -ObjectId $oId -PermissionsToSecrets get
返回错误
Set-AzureRmKeyVaultAccessPolicy : Insufficient privileges to complete the operation.

解决方案是添加其他参数-BypassObjectIdValidation

Set-AzureRmKeyVaultAccessPolicy -BypassObjectIdValidation -VaultName $name -ObjectId $oId -PermissionsToSecrets get

解决方案看起来像黑客,但它适用于我。在此之后,具有$ oId的对象可以访问keyVault。 (对于检查访问策略使用Get-AzureRmKeyVault -VaultName $vaultName

答案 1 :(得分:2)

解决方案是将权限配置移动到ARM模板,而不是尝试使用PowerShell执行此操作。我一做到这一切,所有的许可问题都得到了解决。

在ARM模板中,我为服务主体指定的对象ID是错误的。它认为它是您可以在应用程序注册下的门户网站中找到的对象ID,但不是,它实际上是它想要的Azure AD应用程序的服务主体的对象ID。

即使您使用了错误的ID以及类似的配置,也可以很好地部署ARM模板,直到您开始想知道为什么服务主体与其他用户相比图标看起来不同。这当然,如果你喜欢我只有一个用户,你将不会注意到......

错误的ID(此图标不同): wrong id

正确的身份证明: enter image description here

这篇文章给了我最后的解决方案。

How do I fix an "Operation 'set' not allowed" error when creating an Azure KeyVault secret programmatically?

答案 2 :(得分:0)

根据您的描述,我在我的实验室测试,我也使用我的服务主管登录我的Azure订阅。你的cmdlet适合我。

enter image description here

您是否检查了我的服务主管角色?您可以在Azure门户上查看它。

enter image description here

请确保您的服务主管具有ContributorOwner权限。有关这方面的更多信息,请参阅此link

更新

我在我的实验室测试,您的PowerShell脚本适合您。我建议您可以使用Power Shell创建密钥保管库并授予权限。

答案 3 :(得分:0)

本周我在这个问题上苦苦挣扎,因为我的AAD中没有权限为服务主体添加API权限。我找到了一个使用ARM Output市场项目的解决方案。使用ARM输出任务,我可以从ARM模板中检索对象的主体ID,并将它们转换为管道变量,Azure PowerShell脚本可以使用这些变量来成功更新密钥库访问策略。

在ARM模板中,我添加了此输出变量,以返回网站主体ID-这是我无法查询AD的信息。

"outputs": {
  "websitePrincipalId": {
    "type": "string",
    "value": "[reference(concat(resourceId('Microsoft.Web/sites', variables('webSiteName')), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2015-08-31-PREVIEW').principalId]"
  }
}

然后,我使用ARM Output任务将输出作为管道变量返回,这在Azure PowerShell脚本中非常有用,在该脚本中,我可以使用它来使用正确的访问策略填充密钥库:

Set-AzKeyVaultAccessPolicy -VaultName "$(KeyVaultName)" -ObjectId "$(servicePrincipalId)" -PermissionsToSecrets list,get -PassThru -BypassObjectIdValidation