Connecting to Azure Databricks with user assigned managed identity - azure

TL;DR: Authentication to Databricks using managed identity fails due to wrong audience claim in the token.
Technical details: When acquiring token to access databricks using managed identity (with http://169.254.169.254/metadata/identity/oauth2/token API), the returned token audience is 'spn:2ff814a6-3304-4ab8-85cb-cd0e6f879c1d' instead of '2ff814a6-3304-4ab8-85cb-cd0e6f879c1d'.
When trying to use the acquired token, I get the following error:
Error 400 io.jsonwebtoken.IncorrectClaimException: Expected aud claim to be: 2ff814a6-3304-4ab8-85cb-cd0e6f879c1d, but was: spn:2ff814a6-3304-4ab8-85cb-cd0e6f879c1d.
It seems that the audience is always prefixed with 'spn:' in case of the resource being a guid and not a url.
I also tried to use the databricks app url ('https://azuredatabricks.net/') as the resource, but the token was not accepted here also.
Is this a known issue? Are there any workarounds (other than using the service principal method)?
Thanks!

I can also reproduce your issue, it looks like a bug, using managed identity with Azure Container Instance is still a preview feature.
I also test the same user-assigned managed identity with a Linux VM with the same curl command, it works fine.

Related

Get Azure Webjob History - 403 Token invalid

I am trying to retrieve the web job history of an Azure web job via REST using a .NET backend and the OAuth2 credentials flow (as described here
https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/get-triggered-web-job-history-slot)
How do I need to authenticate correctly?
I retrieve the token as follows:
POST https://login.microsoftonline.com/{MySubscription}/oauth2/v2.0/token
client_id={MyApp}
&grant_type=client_credentials
&scope=https://management.azure.com/.default
&client_secret={myclient_secret}
I get a token back, however I get a 403 error message when I try to retrieve the resource:
GET https://management.azure.com/subscriptions/{MySubscription}/resourceGroups/{MyResource}/providers/Microsoft.Web/sites/{MyApp}/slots/{MySlot}/triggeredwebjobs/{MyWebjob}/history?api-version=2021-02-01
Authorization: Bearer {MyToken}
Client '{MyApp}' with object ID '{MyApp}' is not
authorized to perform the action
'Microsoft.Web/sites/slots/triggeredwebjobs/history/read' using the
scope
'/subscriptions/{MySubscription}/resourceGroups/{MyResource}/providers/Microsoft.Web/sites/{MyApp}/slots/{MySlot}/triggeredwebjobs/{MyWebjob}'
or the scope is invalid. If access was granted recently, please update
your credentials.
What am I doing wrong?
I already added the API-Permission
The "403 Token invalid" error usually occurs if you missed giving permissions to particular scope (Azure Service Management).
By giving this scope it enables you to access https://management.azure.com
To resolve this error, please follow below steps:
Go to Azure Ad ->your application -> API permissions -> Add permission -> Azure Service Management -> delegated permissions ->User impersonation -> Add
After giving these permissions try to retrieve the resource again, there won't be any error.
Since I didn't find a solution that worked with OAuth2 and the Credentials flow, I got it working with Basic Authentication. The username (userName) and password (userPWD) can be taken from the publishing profile of the respective app service.
GET https://{appservicename}.scm.azurewebsites.net/api/triggeredwebjobs/{jobName}/history
Authorization Basic ....

Using Quarkus OpenId Connect and Azure b2c

I'm building a backend-service that provides an API using Quarkus and I need to validate the incoming requests.
By default, quarkus uses keycload, but I want to validate with azure b2c.
At the moment I have the following configs:
quarkus.oidc.auth-server-url=https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/oauth2/v2.0/authorize?p={policy}
quarkus.oidc.application.application-type=service
quarkus.http.auth.permission.authenticated.paths=/hello/*
quarkus.http.auth.permission.authenticated.policy=authenticated
quarkus.log.category."io.quarkus.oidc".level= DEBUG
And as an example:
#Path("/hello")
public class GreetingResource {
#GET
#Produces(MediaType.TEXT_PLAIN)
#RolesAllowed("test")
public String hello() {
return "Hello RESTEasy";
}
But Quarkus keeps throwing the same error:
OIDC server is not available at the 'https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/oauth2/v2.0/authorize?p={policy}'
Am I doing something wrong?
Thanks in advance!
Policy name for Azure AD B2C, format is like
quarkus.oidc.auth-server-url=https://<tenant-name>.b2clogin.com/<tenant-name>.onmicrosoft.com/<policy-name>/oauth2/v2.0/authorize
(or)
quarkus.oidc.auth-server-url=https://<tenant-name>.b2clogin.com/<tenant-id> /<policy-name>/oauth2/v2.0/authorize
The code in your Azure AD B2C-enabled applications and APIs may refer
to login.microsoftonline.com in several places. For example, your code
might have references to user flows and token endpoints. Update the
following to instead reference your-tenant-name.b2clogin.com:
Authorization endpoint
Token endpoint
Token issuer
Please do check this MS docs for more information on the same.
2.
OIDC service application needs to know OpenId Connect provider’s token,
By default they are discovered by adding a /.well-known/openid-configuration path to the configured quarkus.oidc.auth-server-url.
Ex: https://{tenant-name}.b2clogin.com/{tenant-id}/.well-known/openid-configuration?p={policy-name}
By default, the iss claim value is compared to the issuer property which may have been discovered in the well-known provider configuration. But if quarkus.oidc.token.issuer property is set then the iss claim value is compared to it instead.
References:
quarkus/issues
security-openid-connect

How to Fetch Token to access APIM from Function App with Managed identity

I am trying to access APIM from Azure Function and want APIM to authenticate through Managed Identity Token. I have assigned system assigned identity to the function app.I am following this (sample)[https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=dotnet#asal] to generate token. In the below line if I give "https://vault.azure.net" to GetAccessTokenAsync method I am getting the token. but I want the audience to be APIM so I provided https://azure-api.net like mentioned in the last line. but I am getting exception. how can I provide the APIM Url to fetch the access token?
using Microsoft.Azure.Services.AppAuthentication;
var azureServiceTokenProvider = new AzureServiceTokenProvider();
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://vault.azure.net");
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://azure-api.net");
An Update. I think something wrong with listing the resources. because when I give the proper resource name it says resource doesnt exist in the tenant though I can see the subscription is under the same tenant when I run through az cli.
As I mentioned in the comment, you need to Register an application in Azure AD to represent the API, then you can get the token for it(i.e. with the Application ID URI in the previous link).
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("<Application ID URI>");
Something you need to know:
You can use azureServiceTokenProvider to get the token for https://vault.azure.net, https://managment.azure.com, because they are all the APIs exposed by Microsoft, i.e. azure keyvault rest api and azure management rest api, essentially they are all AD App registered by Microsoft, so if you want to get the token for your own API, you need to register the AD App first to represent the API first.
Also, when you use managed identity to get the token, essentially it uses the client credential flow to get the token, actually the managed identity is a service principal(i.e. enterprise application) managed by azure. Remember to leverage the app role if you need to validate the roles claim when you get the access token.

Login into Azure cli for a service principal

I'm trying to get my ansible script to get logged into azure via azure cli. For some reasons, I'm not allowed to use the ansible azure package. I have to use the shell and call directly the commands from there.
I'm fairly new with azure in general, so all this tenants, service principals and such are still concepts that I don't fully grasp.
I've been checking official the documentation. I've created an app registration for it (Named ansible_test). I get all I need, including the secret. and then I call the the commands as this:
az login --service-principal -u $AZURE_SERVICE_PRINCIPAL_NAME -p $AZURE_SECRET --tenant $AZURE_TENANT
where:
$AZURE_SERVICE_PRINCIPAL_NAME = ansible_test
$AZURE_SECRET = ${The one that I've defined via Certificates & secrets section in the app registration}
$AZURE_TENANT = ${The azure tenant that I find in the app registration}
I'm getting the error:
Get Token request returned http error: 400 and server response: {"error":"unauthorized_client","error_description":"AADSTS700016: Application with identifier 'ansible_test' was not found in the directory '${AZURE_TENANT}(Blurred because I'm not sure this is something secret or not)'. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You may have sent your authentication request to the wrong tenant.
As I understand, I got the wrong tenant. But I'm getting the exact one that I'm getting from the app registration. I've been hitting my head against this wall for some time. I've tried many other things, but it doesn't seem to work.
In this image, I'm trying to show that I've indeed created the app registration (What I'm understanding that it's a service principal). I've blurred the ids just out of ignorance whether they are private or not.
What is that I'm doing wrong? I can't really understand the origin of the error...
The username for a service principal is its Application (client) ID, so you need to use that instead of the app name.
It uses client credentials flow under the covers to get tokens which requires the client id, tenant id + client secret/client certificate to authenticate.
Use the following command, before running this command, make sure to define variables.
az login --service-principal -u ${app_id} -p ${password} --tenant ${tenant_id}

Error getting SAML Metadata for Azure AD B2C Policy - AADB2C90022

Setting up a custom policy in Azure AD B2C to connect to an ADFS Identity Provider. This requires a SAML metadata endpoint as specified in the documentation at the link below.
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-custom-setup-adfs2016-idp#configure-an-adfs-relying-party-trust
The error being encountered is:
AADB2C90022: Unable to return metadata for the policy [my-policy] in tenant [my-tenant].onmicrosoft.com.
and is being encountered when I go to the endpoint:
https://login.microsoftonline.com/te/[my-tenant].onmicrosoft.com/[my-policy]/samlp/metadata?idptp=[my-technical-profile]
I have tried making the request from the b2clogin.com endpoint with the same result as above.
E.g. https://[my-tenant].b2clogin.com/te/[my-tenant].onmicrosoft.com/[my-policy]/samlp/metadata?idptp=[my-technical-profile]
I have also tried using my tenantId GUID in place of [my-tenant].onmicrosoft.com which resulted in the exact same result.
E.g. https://login.microsoftonline.com/te/[my-tenant-id]/[my-policy]/samlp/metadata?idptp=[my-technical-profile]
Re-visit the process by which you created the certificate, uploaded it to your 'Policy Keys' and referenced it in your custom policy files.
My scenario was similar, I had the same error and no output via Application Insights / Journey Recorder.
I had tried to avoid using 'makecert.exe' and instead used another SSC generation tool. This simply did not work, I think because the private key was not being incorporated in the certificate file.
This guide has been invaluable, see also this test facility

Resources