Showing posts with label Web App. Show all posts
Showing posts with label Web App. Show all posts

Sunday, April 5, 2020

Azure Application Gateway: HTTP headers rewrite rules for App Service with AAD authentication

As you probably already know, you can use Azure App Service as backend pool for Application Gateway. The general configuration procedure can be found in the Microsoft documentation. This configuration works fine for simple sites, but in case you App Service uses Azure Active Directory (AAD) for authentication and authorization extra steps required to deal with HTTP redirections related to the AAD authentication flow.

The problem

Azure App Services configured with AAD authentication like this
two HTTP redirects happen during login process.

The first redirect happens when App Service sends un-authenticated user to AAD authorize endpoint  to allow user to login and obtain the ID token from AAD. The redirect URL will be like this one:

https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id={clieent_id}
&response_type=id_token
&redirect_uri=https%3A%2F%2Fsomeapp.azurewebsites.net%2F.auth%2Flogin%2Faad%2Fcallback
&response_mode=form_post
&scope=openid
&state=12345
&nonce=678910



This URL (also known as callback URL) contains the address where Azure AD will direct user's browser to POST authentication response after successful login. You can find more details about this process here

The second redirect happens as response from the HTTP POST to the authentication callback URL when App Service redirects authenticated user to the initially requested app URL.

Below are examples of these redirects extracted from the browser's development tools.
First redirect (browser accesses address waf.dg20.net that resolves into the Application Gateway frontend IP):

Second redirect:

As you can see, even if the browser tried to access our app using an address assigned to the Application Gateway, after login we will end-up sending HTTP requests directly to App Service by-passing Application Gateway. This would defeat the whole purpose of putting the app behind the Application Gateway. In the case when App Service is properly locked down and have enabled static IP restrictions to enforce access only through Application Gateway, user potentially will see 403 HTTP error after logon:

The solution

The Azure documentation describes this issue here and offers solution (HTTP headers rewrite) here. Unfortunately, the prescribed procedure doesn't account for Azure AD authentication process and only offers a method to 'fix' the second redirect. Honestly speaking, this could be considered a "good enough" solution, but it still exposes App Service native address to the client and will work only if client can hit this address directly after AAD logon process.
The solution below will hide backend address from client and will work with locked down App Service. It will rewrite "Location" header in the both redirection 302 responses using two rules in the single Rewrite Set on the Application Gateway. Both rules check and rewrite 'Location' header in the HTTP response.

1. First redirect rewrite - login redirect to AAD
Condition (If): header "Pattern to match"
(.*)(redirect_uri=https%3A%2F%2F).*\.azurewebsites\.net(.*)$

Action (then): set header value
{http_resp_Location_1}{http_resp_Location_2}{var_host}{http_resp_Location_3}

2. Second redirect rewrite - callback from AAD
Condition (If): header "Pattern to match"
(https:\/\/).*\.azurewebsites\.net(.*)$

Action (then): set header value
https://{var_host}{http_resp_Location_2}
This Rewrite Set must be associated with Application Gateway routing rule to be effective. The set can be used with any routing rule that uses Azure App Service with AAD authentication as a backend and it can significantly simplify gateway configuration, especially in the scenario where multiple sites are hosted.

Thursday, October 24, 2019

How to use Azure Web App MSI to verify Data Lake access

Sometimes you need to verify that your Azure web (or function) app can access its data using MSI in Azure Data Lake.

  1. Open web app debug console at https://your-az-weapp.scm.azurewebsites.net/DebugConsole/?shell=powershell
  2. Run next PS script (replace data lake name and path to the target file)
$progressPreference = "silentlyContinue"
$req=Invoke-WebRequest -UseBasicParsing -Uri "$($env:MSI_ENDPOINT)?resource=https://datalake.azure.net/&api-version=2017-09-01" -Headers @{"Secret"="$env:MSI_SECRET"} |ConvertFrom-JSON

$headers = @{}
$headers.Add('x-ms-version','2018-03-28')
$headers.Add('x-ms-client-request-id',[guid]::NewGuid())
$headers.Add('x-ms-date',(Get-Date).AddHours(1).ToString('ddd, dd MMM yyyy HH:MM:ss G\MT'))
$headers.Add('Authorization',"Bearer $($req.access_token)")


$resp=Invoke-WebRequest -UseBasicParsing -Uri "https://somelake.azuredatalakestore.net/webhdfs/v1/Folder/SubFolder/somefile.json?op=GETFILESTATUS&tooid=True&api-version=2018-09-01" -Method GET -Headers $headers
$resp.StatusCode


If it works (and the app has access), you will see "200" HTTP response code:


PS D:\home> $resp.StatusCode
200
PS D:\home>


Otherwise, it would be an error like this one:


Invoke-WebRequest : {"RemoteException":{"exception":"AccessControlException","message":"GETFILESTATUS failed with error 0x83090aa2 (Forbidden. ACL verification failed. Either the resource does not exist or the user is not authorized to perform the requested operation.). [af00739c-f9fb-4bfc-8dfd-655169970161] failed with error 0x83090aa2 (Forbidden. ACL verification failed. Either the resource does not exist or the user is not authorized to perform the requested operation.). [af00739c-f9fb-4bf c-8dfd-655169970161][2019-10-24T08:44:20.5577411-07:00]","javaClassName":"org.a pache.hadoop.security.AccessControlException"}}

How to backup Azure DevOps code repositories

Under " shared responsibility in the cloud " model, the client is always responsible for its own data. Azure DevOps, as a SaaS off...