According to documentation in Azure API Management it is possible to create JWT token validation policy using certificate id of RSA certificate previously uploaded to APIM.
I am trying to build such policy as described in the docs, and it is saved without errors, but when I open the policy definition again, key element is always empty, without the certificate-id attribute I set earlier.
https://learn.microsoft.com/en-us/azure/api-management/api-management-access-restriction-policies#token-validation-with-rsa-certificate
I can also reproduce your issue on my side, after configuration and come back, the policy will be like below.
It looks should be a bug in UI, because if you get the policy with PowerShell Get-AzApiManagementPolicy or REST API - Api Policy - Get directly, we can get the value. So I think the policy should be applied, just ignore it and go on.
Powershell:
$ApiMgmtContext = New-AzApiManagementContext -ResourceGroupName "groupname" -ServiceName "joyapim"
Get-AzApiManagementPolicy -Context $ApiMgmtContext -ApiId 'echo-api'
REST API:
Related
I have generated a wildcard certificate using Azure's App Service Certificate.
After this Azure asks you to configure the certificate in a KeyVault, and this is where I am getting stuck.
I have a Keyvault which is in the same region, same subscription, same resource group.
I have the necessary permissions to the key vault. I am a User Admin, Cert officer, Secrets officer, contributor to the key vault .
This step is failing with an error
Failed to link certificate with the selected Key Vault. Check below errors for more detail.
The Activity Log under App Service Certificate shows :
Operation Name : Add or Update Certificate
Status : Failed
Summary :
Operation name : Add or Update Certificate
Time stamp : Tue Jan 19 2021 07:10:46 GMT+1100 (Australian Eastern Daylight Time)
Event initiated by: xxxx
Error code: BadRequest
Message : The parameter keyVaultCsmId has an invalid value.
The JSON has the following important information :
"authorization": {
"action": "Microsoft.CertificateRegistration/certificateOrders/certificates/write",
"scope": "/subscriptions/xxx/resourceGroups/yyyyyyy/providers/Microsoft.CertificateRegistration/certificateOrders/InternalWildCard/certificates/InternalWildCard"
}
"properties": {
"statusCode": "BadRequest",
"serviceRequestId": null,
"statusMessage": "{\"Code\":\"BadRequest\",\"Message\":\"The parameter keyVaultCsmId has an invalid value.\",\"Target\":null,\"Details\":[{\"Message\":\"The parameter keyVaultCsmId has an invalid value.\"},{\"Code\":\"BadRequest\"},{\"ErrorEntity\":{\"ExtendedCode\":\"51008\",\"MessageTemplate\":\"The parameter {0} has an invalid value.\",\"Parameters\":[\"keyVaultCsmId\"],\"Code\":\"BadRequest\",\"Message\":\"The parameter keyVaultCsmId has an invalid value.\"}}],\"Innererror\":null}",
"eventCategory": "Administrative",
"entity": "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.CertificateRegistration/certificateOrders/InternalWildCard/certificates/InternalWildCard",
"message": "Microsoft.CertificateRegistration/certificateOrders/certificates/write",
"hierarchy": "xxxx"
}
Any help on this or direction you can provide will be really appreciated :)
There should be a service principal in the Azure AD, if not you can create it.
Get-AzADServicePrincipal -DisplayName microsoft.azure.certificateregistration
You need to assign that permission to keyvault via either access policies OR RBAC.
In Azure Key Vault, supported certificate formats are PFX and PEM.
• .pem file format contains one or more X509 certificate files.
• .pfx file format is an archive file format for storing several cryptographic objects in a single file i.e. server certificate (issued for your domain), a matching private key, and may optionally include an intermediate CA.
Certificates used by App Service first needs to be converted to (and marked as) application/x-pkcs12. Re-importing the cert from a pfx file with the --password parameter (az keyvault certificate import), and after that import it from the key vault to the webapp might help. You may refer to this Blog might be helpful.
Also, look if Cert and the Key Vault are in their original resource group.
Additional details: https://learn.microsoft.com/en-us/azure/key-vault/certificates/tutorial-import-certificate
https://azure.github.io/AppService/2016/05/24/Deploying-Azure-Web-App-Certificate-through-Key-Vault.html
Stuff which I didn't mention in the original question..
The existing key vault Permission Model is using RBAC for policies which is in preview [ Azure role-based access control (preview) ].
It has "Selected Networks" open and allows Trusted MS Networks..
It already has another wildcard cert in it as a secret ( different name )
I temporarily switched the Key Vault Permission Model to Vault access policy, and tried linking - and it worked.
Looks like a bug with the Permission Model using Azure RBAC.
To fix the issue:
https://github.com/Azure/azure-quickstart-templates/tree/master/quickstarts/microsoft.web/app-service-certificate-standard
By default, 'Microsoft.CertificateRegistration' and 'Microsoft.Web' RPs don't have access to the Key Vault specified in the template hence you need to authorize these RPs by executing the following PowerShell commands before deploying the template:
Login-AzureRmAccount
Set-AzureRmContext -SubscriptionId AZURE_SUBSCRIPTION_ID
Set-AzureRmKeyVaultAccessPolicy -VaultName KEY_VAULT_NAME -ServicePrincipalName f3c21649-0979-4721-ac85-b0216b2cf413 -PermissionsToSecrets get,set,delete
Set-AzureRmKeyVaultAccessPolicy -VaultName KEY_VAULT_NAME -ServicePrincipalName abfa0a7c-a6b6-4736-8310-5855508787cd -PermissionsToSecrets get
ServicePrincipalName parameter represents these RPs in user tenant and will remain same for all Azure subscriptions. This is a onetime operation. Once you have a configured a Key Vault properly, you can use it to store as many App Service Certificates as you want without executing these PowerShell commands again.
I'm adding a new certificate to an existing App Registration in Azure AD using the following command:
New-AzureADApplicationKeyCredential -ObjectId $AppObjectId -CustomKeyIdentifier $base64Thumbprint -Type AsymmetricX509Cert -Usage Verify -Value $base64Value -StartDate $cer.GetEffectiveDateString() -EndDate $validTo
This works OK and I can see the cert added in the Portal.
Should this certificate not also be visible via https://login.microsoftonline.com/{tenant}/discovery/keys?appid={Application(client)ID}
I've also tried adding the certificate info via Set-AzureADApplication & directly via the Portal. Each time I can see the certificate under "Certificates and Secrets" as well as in the App Manifest. No matter what I do I can't see the public cert in the JWKS endpoint.
My assumption on this comes from the following:
https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens
"If your app has custom signing keys as a result of using the claims-mapping feature, you must append an appid query parameter containing the app ID to get a jwks_uri pointing to your app's signing key information, which should be used for validation. For example: https://login.microsoftonline.com/{tenant}/.well-known/openid-configuration?appid=6731de76-14a6-49ae-97bc-6eba6914391e contains a jwks_uri of https://login.microsoftonline.com/{tenant}/discovery/keys?appid=6731de76-14a6-49ae-97bc-6eba6914391e."
Any help would be much appreciated.
As far as I understand, the keys you add to the app are only used for authenticating your app to Azure AD.
Thus there is no need to advertise those keys in the public endpoint, as only Azure AD itself needs to use those public keys to verify assertions sent by your app.
Seems like you set the keyusage to Verify. If you want to use it for signing the token you need to set it to Sign and use a symmetric key:
New-AzureADApplicationKeyCredential -ObjectId $AppId -CustomKeyIdentifier "Test" -StartDate "11/7/2016" -Type "Symmetric" -Usage "Sign" -Value "123"
I have followed below article for configuring azure aad token lifetime to 10mins
How can I configure the expiration time of an Azure AD access token (using ADAL)?
I have used command below for assigning policy to app
Add-AzureADApplicationPolicy -Id <ObjectId of the AAD Application> -RefObjectId <ObjectId of the Policy>
Policy created but not reflected on new tokens created. Token expiry still showing as 1 hour for new tokens.
As AdminOfThings said, this policy is applied to the web API. When the native app requests the web API as a resource, this policy is applied.
And you could try to set -IsOrganizationDefault as true to create a strict policy for a web API.
New-AzureADPolicy -Definition #('{"TokenLifetimePolicy":{"Version":1,"AccessTokenLifetime":"00:10:00","MaxAgeSessionSingleFactor":"00:10:00"}}') -DisplayName "WebPolicyScenario" -IsOrganizationDefault $true -Type "TokenLifetimePolicy"
You should also check to see if a default policy exists too, as long as it is not overridden by a policy with a higher priority.
I am trying to add a Keyvault with PowerShell. I am always getting below two warnings while creating this. Though the vault is getting created successfully but, but want to understand how can I elminiate this warnings?
New-AzKeyVault -VaultName "kvxxxxxxxxxxx" `
-ResourceGroupName "RG-xxxx" -Location "South Central US"
WARNING: The provided information does not map to an AD object id.
WARNING: Access policy is not set. No user or application have access permission to use this vault. This can happen if the vault was created by a service principal. Please use Set-AzKeyVaultAccessPolicy to set access policies.
I can reproduce your issue on my side. The two WARNINGs were caused by your account is a Personal Account/Microsoft account(e.g. outlook, hotmail account) in your Azure AD tenant, your user type is Guest.
Actually you can just ignore them, or use the -WarningAction Ignore parameter as mentioned in the comment.
When using a work account/member user type to create a keyvault, it will add the account which used to create the keyvault to the access policy of the keyvault automatically. In your case, you could use the command Set-AzKeyVaultAccessPolicy to set the access policy after creating the keyvault.
Blogs like the following
https://blogs.technet.microsoft.com/neales/2017/06/26/getting-a-private-certificate-from-key-vault/
Seem to retrive the secret? Does it not matter if it's "stored" as a certificate or not?
It depends on what you are planning to do with the certificate. You could update your question with details about the expected workflow you want to support.
But basically a certificate can be stored as a file. You can see more details (C#) to get inspired on how to do that after the certificate is loaded into a variable.
Exporting a Certificate as BASE-64 encoded .cer
Update
Security considerations to take into account. If you see the certificate stored in the azure key vault as a secret and you want to limit the access to it, then you have to consider how your PowerShell scripts will store the needed credentials for authenticate against the KeyVault.
If you plan on running the script unattended / scheduled without user interaction, you will have to store some kind of credentials on the machine that needs to run the script. BetterCredentials is a great PowerShell native module for storing credentials on the local machine.
I would recommend that you create an Azure Service Principal (App Registration / Registered App), that will get only enough permissions to get the certificate from the KeyVault. The created Service Principal details should then be stored locally on the machine and you should load those credentials first and use them for connecting to the KeyVault.
Example code that should be capable of loading a Service Principal details from the BetterCredentials and sign into Azure:
BetterCredentials\Get-Credential -UserName <application ID> -Store
$azureTenantId = <tenant ID>
$Cred = BetterCredentials\Get-Credential -UserName <application ID>
Add-AzureRmAccount -Credential $Cred -TenantId $azureTenantId -ServicePrincipal