Quantcast
Channel: Unleashed
Viewing all 71 articles
Browse latest View live

AZURE REST API & PowerShell: Retrieve Cloud Service Configuration

$
0
0

Recently I was working on an issue where we had to retrieve PaaS instance configuration details like the RDP, OS Family, Reserved IP etc. Typically this is present in the .cscfg file of a Cloud Service.

We had to retrieve these details via Azure Service Management REST API. Documentation on the Operations on Cloud Services can be found on MSDN.

The API of our interest is GET DEPLOYMENT. The documentation is available on MSDN: https://msdn.microsoft.com/en-us/library/azure/ee460804.aspx

In this post I will be using PowerShell scripts to invoke the GET DEPLOYMENT API.

Below is a snippet from MSDN:

The Get Deployment request can be used to retrieve deployment events for a single deployment slot (staging or production) or for a specific deployment name. If you want to retrieve information by deployment name, you must first get the unique name for the deployment. This unique name is part of the response when you make a request to get the deployment in a deployment slot.

From MSDN documentation there are two ways to invoke the API.

We already have a PowerShell commandlet for this functionality:
Get-AzureDeployment: https://msdn.microsoft.com/en-us/library/azure/dn495146.aspx

Requirements

In order to make an AZURE REST API call, you have to:

  1. Authenticate the request to Management Service. Refer this link: https://msdn.microsoft.com/en-in/library/azure/ee460782.aspx
  2. Some Azure Service Management REST API's require additional headers to be sent along with the request. Read the documentation for the API before proceeding further.
    1. The Get Deployment API requires the x-ms-version header in HTTP Request. Below is the snippet of the documentation for this API from MSDN.

Request Header

Description

x-ms-version

Required. Specifies the version of the operation to use for this request. This header should be set to 2009-10-01 or higher. For more information about versioning headers, see Service Management Versioning.

 

Generating the certificate

We will use MakeCert.exe. You may want to refer these articles:

Create & Upload a Management Certificate for Azure: https://msdn.microsoft.com/en-us/library/azure/gg551722.aspx
Makecert.exe (Certificate Creation Tool): https://msdn.microsoft.com/en-us/library/bfsktky3(v=vs.110).aspx

Open a Visual studio command prompt and execute the following command:

makecert -sky exchange -r -n "CN=<CertificateName>" -pe -a sha1 -len 2048 -ss My "<CertificateName>.cer"

Replace the highlighted section (in green) in the above command with your inputs

  • Browse to Visual Studio Tools folder.
  • Typically this is under: "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft Visual Studio 2012\Visual Studio Tools"
  • Double click and launch "VS2012 x86 Native Tools Command Prompt" in administrator mode
  • Execute the above command as shown below:
  • Go to run and type "mmc" and then click on OK.
  • Select FileàAdd/Remove Snap-in…
  • Select Certificates and click on Add > button
  • Under the Certificates snap-in select My user account and click on Finish.
  • Click on OK.
  • This view is the current user certificate store as shown below

  • Export the certificate without the private key and store it on your hard drive.
  • Now go to the Azure Management Portal
  • Scroll down to the SETTINGS section.

  • In the centre pane, click on MANAGEMENT CERTIFICATES& then click on UPLOAD.
  • Select the certificate we exported and upload it.
  • Make a note of the Certificate thumbprint.

     

Invoking the REST API

Once the certificate has been generated and uploaded. We can write a PowerShell script to retrieve the same certificate from the store and pass it along with the REST API request.

We will be using PowerShell to invoke the API and retrieve the details.

Below is the PowerShell script to retrieve the certificate from the user store and pass it on to the Azure Service Management for authentication.

#Request Headers required to invoke the GET DEPLOYMENT REST API
$method="GET"
$headerDate= '2009-10-01'
$headers= @{"x-ms-version"="$headerDate"}

#Retrieving the subscription ID
$subID= (Get-AzureSubscription-Current).SubscriptionId

$URI=https://management.core.windows.net/$subID/services/hostedservices/kaushalz/deployments/4f006bb7d2874dd4895f77a97b7938d0

#Retrieving the certificate from Local Store
$cert= (Get-ChildItemCert:\CurrentUser\My|?{$_.Thumbprint -eq"B4D460D985F1D07A6B9F8BFD67E36BC53A4490FC"}).GetRawCertData()

#converting the raw cert data to BASE64
body="<Binary>-----BEGIN CERTIFICATE-----`n$([convert]::ToBase64String($cert))`n-----END CERTIFICATE-----</Binary>"

#Retrieving the certificate ThumbPrint
$mgmtCertThumb= (Get-AzureSubscription-Current).Certificate.Thumbprint

#Passing all the above parameters to Invoke-RestMethod cmdlet
Invoke-RestMethod-Uri$URI-Method$method-Headers$headers-CertificateThumbprint" B4D460D985F1D07A6B9F8BFD67E36BC53A4490FC"-ContentType$ContentType

  • Launch Windows PowerShell ISE in administrator mode.
  • Copy the above sample script and paste it in the scripting window.

NOTE: replace the thumbprint in the above script with the thumbprint of your certificate. You can retrieve this from the MMC windows we accessed earlier. I'm passing the Deployment Name (or Deployment ID) in the above URL.

  • Run the script to get the output as shown below:

If you read the documentation, the response body is in XML format and it is displaying only the parent node (DEPLOYMENT).

We can read the response into a XML object and then display it. Here is sample snippet:

#Getting the response from the REST API and saving it as a XML object
[xml]$url =Invoke-RestMethod-Uri$URI-Method$method-Headers$headers-CertificateThumbprint"B4D460D985F1D07A6B9F8BFD67E36BC53A4490FC"-ContentType$ContentType

#Printing the XML
write$url.ChildNodes

Below is a screenshot of the output after adding the above two lines in the earlier script:

NOTE: The Configuration section in the above output is a Base-64 encoded string. You would have to add the following snippet to parse this further:

$base64encodedconfiguration=$url.Deployment.Configuration
$d=[System.Convert]::FromBase64String($base64encodedconfiguration)
[xml]$decodedxml =[System.Text.Encoding]::UTF8.GetString($d)
write$decodedxml.ChildNodes

You can use the same approach to call any other Azure Service Management REST API. Ensure you read the documentation carefully and then proceed further.

HTH J


Azure Web Apps: How to retrieve user email in the claim when using Microsoft Account as a provider in Easy Auth

$
0
0

App Service Authentication/Authorization also known as Easy Auth is one of the widely used feature in Azure App Service. It reduces the burden on the developers and provides a way for the application to sign in users without changing code. It is implemented as a module and is injected at runtime within the app. It automates a lot of configuration which usually is a tedious task. It is a one time process where the users have to configure the web app to use one or more of the identity providers. Following is a list of providers currently supported with this module:

  • Azure Active Directory (AAD)
  • Facebook
  • Google
  • Twitter
  • Microsoft Account (microsoftaccount)

Refer the following article to configure your web application to use Microsoft account as the auth provider.

How to configure your App Service application to use Microsoft Account login 

Multiple providers can be configured for a single web app. For this, in portal set the

Action to take when request is not authenticated = “Allow request (no action)”.

This is also known as deferred authentication. In this case the providers from the app have to be called explicitly and the application will consume it based on the obtained claim. The following table illustrates the api endpoint which is used to invoke certain calls. 

 Login End Point   /.auth/login/<provider> 
  /.auth/login/<provider>?post_login_redirect_uri=<url-path> 
 Logout End point   /.auth/logout 
  /.auth/logout?post_logout_redirect_uri=<url-path> 
 Token Access   /.auth/me 

<providers> can be set to aad, facebook, google, twitter & microsoftaccount. Here is an example:

https://easyauth.kaushalz.com/.auth/login/microsoftaccount?post_login_redirect_url=/

NOTE: The query string parameter post_login_redirect_uri redirects the user request to the value specified in url path. In the above example url, post successful authentication, the users will be redirected to the root of the application.

Adding users email address to the Claim

By default, the claim which is obtained from Microsoft Account provider doesn’t contain the users email address. Here is a how the default user claims obtained from MSA looks like

image

To add the email address as part of the claim the following scopes have to be enabled:

  • wl.basic
  • wl.emails 
NOTE: The token can be obtain by calling the following endpoint /.auth/me

Refer the following steps on how to configure this via the Azure portal

  • Log-in to Azure portal: https://portal.azure.com 
  • Click on App Service & select the web app
  • Under Settings blade, click on Authentication/Authorization (This will launch another blade for this feature
  • In here, configure the following
    1. Set App Service Authentication to On
    2. Under Authentication providers, click on Microsoft Account.
    3. Click on wl.basic & wl.emails to enable them (Refer the following screenshot)

image

  • Click on OK and then click on Save.

When the users try to login again, the application will notify the user that it needs permissions so that the application can retrieve users email address. This happens for the first time.

image

Upon giving permissions to the application, the users email address becomes part of the user_claims. Below is a screenshot for reference:

image

NOTE: I used Chrome browser with the JSON Formatter extension installed to see the claim

 

MORE INFORMATION:

In case the application is not hosted on Azure App Service, please refer the following thread on Stackoverflow on how to do this for your application.

http://stackoverflow.com/questions/17168353/getting-email-from-oauth-authentication-microsoft?lq=1

 

Azure App Service: How to connect to the Kudu site of a specific instance

$
0
0

Every Azure Web App has an associated ‘scm’ service site, which runs Kudu and other Site Extensions.

OVERVIEW:
  • Kudu site can be accessed using either of these credentials
    • Single Sign-on
    • User-level credentials (aka Deployment Credentials)
    • Site-level credentials  (aka Publish Profile Credentials)
  • Kudu site always connect to a single instance. E.g. If the site is hosted in an App Service plan which is scaled out to 3 instances, then at any time the KUDU will always connect to one instance only.

Here is a simple request flow of an Azure Web App

image

The front-end uses ARRAffinity cookie to affinitize the request to specific instances. This cookie can be disabled if needed. Refer this on how disable ARR Affinity.

The ARRAffinity cookie is unique and corresponds to an instance. If there are multiple instances, then there will be ARRAffinity cookie corresponding to those many instances. So we can modify the ARRAffinity cookie in the HTTP response and force KUDU to connect to a specific instance.
 
PRE-REQUISITES:

DETERMINE THE ARRAFFINITY COOKIE OF AN INSTANCE

  • Browse to https://resources.azure.com/ (Azure Resource Explorer)
  • In the search window enter the name of the web app. See the following screenshot for reference:

image

  • If there are other Azure resources with similar names, select the resource of type “Microsoft.Web/sites
  • In the left side panel, expand “instances” and this would load all the instances on which the web app is hosted. The instance name displayed is also the value of the ARRAffinity cookie.

image

In the above image the site kaushalp is scaled out to 2 instances. So we have 2 instance id’s which are beginning with:

  1. bac64d
  2. c2a879

CONNECT TO THE KUDU CONSOLE OF A SPECIFIC INSTANCE

  • For this we need to have a tool which allows us to modify the cookies
  • There are multiple ways to do this.
  • I am using EditThisCookie extension in chrome browser. Here is the link to install this: Install EditThisCookie
  • Now, browse to the KUDU site of your web app: https://<sitename>.scm.azurewebsites.net (replace <sitename> with name of the web app)
  • Click on Environment.
  • Under System info, the “instance id” value determines the instance to which the KUDU is connected. In the screenshot below, the kudu site is connected to the instance whose short instance id is bac64d.

image

  • We can use one of the instances value we obtained via ARM explorer to force KUDU to connect to a specific site.
    (Here we are connecting to the instance with the id beginning with “bac64d” )
  • In the browser window click on EditThisCookie clip_image005  icon (next to the Address bar).

clip_image006

  • In the pop-up, click on ARRAffinity

clip_image007

  • Replace the value with the instance id that you need to connect to

image

  • Click on the tick mark to save the cookie and then refresh the page.

It should have connected to other instance. To confirm, browse to Environment and under System Info the value of Instance id should match the value that was entered earlier.

Azure App Service: Using cURL for deployment

$
0
0

cURL is a command line tool that can be used to send or receive files. cURL.exe supports numerous protocols like HTTP, HTTPS, FTP, FTPS, SFTP, LDAP, TELNET, SMTP, POP3 etc. For more information please refer the below links:

https://en.wikipedia.org/wiki/CURL
https://curl.haxx.se/docs/

Syntax

curl.exe -T <path-to-file-that-needs-to-be-deployed> -u “username:password” “FTP URL”

From curl documentation

T, —upload-file FILE Transfer FILE to destination
url URL URL to work with -u, –user USER[:PASSWORD] Server user and password
tlsuser USER TLS username
tlspassword STRING TLS password
tlsauthtype STRING TLS authentication type (default SRP)

Pre-Requisites:

  • Deployment over FTPS will work only if the version of the curl is SSL aware. Download it from here:

https://curl.haxx.se/download.html

  • FTP endpoint of the web app. You can get this from portal or from the publish profile of the web app (under FTP section search for publishURL)
  • Username and password for authentication (Either deployment or publish profile credentials. See this)
    • With user-level credentials (User specific): sitename\username
    • With site-level credentials (Site specific/publish profile) : sitename\$sitename

For FTPS

Deploying via FTP

  • Launch command prompt
  • Browse to the folder location where curl was downloaded and execute the following command:
C:\>curl -T C:\sample.war -u “kaushalp\$kaushalp:<password>” ftp://waws-prod-sg1-005.ftp.azurewebsites.windows.net/site/wwwroot/

image

Deploying via FTPS

While using cURL via FTPS (FTP over SSL), the following error may be encountered when trying to connect over HTTP.

image

The following error is seen because curl will try to verify the certificate received in the Server Hello and it fails as it couldn’t verify the CA who issued the certificate.

This problem can be addressed by using an additional parameter either –cacert or -k can be specified.

C:\>curl -T C:\sample.war -u “kaushalp\$kaushalp:<password>” ftps://waws-prod-sg1-005.ftp.azurewebsites.windows.net/site/wwwroot/ -k

-k, –insecure Allow connections to SSL sites without certs (H)

C:\>curl -T C:\sample.war -u “kaushalp\$kaushalp:<password>” ftps://waws-prod-sg1-005.ftp.azurewebsites.windows.net/site/wwwroot/ –cacert e:\tools\kaushal-bundle.crt

–cacert FILE CA certificate to verify peer against (SSL)

TROUBLESHOOTING

Error: “curl: (25) Failed FTP upload: 550
image
This error is seen when the FTP URL does not contain a trailing slash “/”.

More Information:

Here is the default list of CA’s that are supported by curl: https://curl.haxx.se/ca/cacert.pem (This was the file that was downloaded under pre-requisites)

Users can generate their own crt file and pass it to CURL.

Azure App Service: How to read & parse connection strings via PHP

$
0
0

On Azure App Service, developers have the ability configure the connection strings as key-value pair under App Settings section as shown below:

image

At runtime, Azure App Service retrieves this key-value pair for you and makes them available to your hosted application. These are provided to the web app as Environment Variables.

Here is a good article on how to these work internally: How Application Strings and Connection Strings Work 

Here is a sample code on how to read the app settings in PHP

Summary

The sample code is a way to get started on how to retrieve the connection strings at runtime in PHP. I have used the above sample to read from a database and display it on a page. The project is hosted on GitHub. See here: https://github.com/kaushalp/Problematique/edit/master/ProblematicMvc/client.php

Azure App Service: Manually collect memory dumps

$
0
0

While troubleshooting web application performance issues we are sometimes required to gather memory dumps during the time of the issue.

In Azure App Service, we do not have RDP access to the machines. However, this doesn’t restrict us from gathering logs & data for troubleshooting. I am listing out few methods using which we can generate memory dumps of the process during the time of the issue.

Method 1: Using ProcDump.exe

Pre-Requisite: For this we need the sysinternals utility: ProcDump.exe

Azure App Service instances include the sysinternals suite in the default image. They can be located here via the KUDU console: D:\devtools\sysinternals

The users may also download ProcDump from here and upload it a specific location such as D:\home\LogFiles\Dumps and use it.

  • Browse to the KUDU console
  • Click on Process Explorer menu.
  • There will be 2 w3wp.exe processes, one for SCM (KUDU) and another for the application.

image

  • Note the PID (Process ID) of the w3wp.exe corresponding to the application (see the image above)
  • Browse to Debug Console –> CMD
  • In the command window, navigate to the dumps folder.
  • Execute the following command to generate a full memory dump of the process
procdump.exe -accepteula –ma <PID of the process>
where,
        -ma               Write a dump file with all process memory. The default dump format only includes
                             thread and handle information
        -accepteula    Use this switch to automatically accept the Sysinternals license agreement.

image

Method 2: Using Diagnostics as a Service (DaaS)

Via Portal:

  • Login to Azure portal. (https://portal.azure.com)
  • Select the Azure Web App that you intend to troubleshoot
  • Click on Diagnose and solve problems.

image

  • In the new blade click on Diagnostics as a Service. (Bottom right side of the blade.)

image

  • In the new blade, set the following:
    • Application Type – Depending on the type of application set the value to ASP.NET or PHP or Node.js.
    • Diagnosers – Since this post is about collecting memory dumps, ensure that the check box against Memory Dump is selected. If you need Event Viewer Logs & Http Logs then you can enable them too.
    • Instances – If the App Service Plan is configured to use more than one instance, then you can configure this to collect the logs on either multiple instance or specific instances.

image

  • Click on Run to collect the logs. The blade will indicate the status of the operation and will also run analysis on the collected data.
  • This puts the data under D:\home\data\DaaS\Logs folder.

Via KUDU:

In scenarios, where the user may not have access to the portal, they can use Kudu to access DaaS. The option to select instances is not available here as KUDU by default connects to a specific instance. You can refer my previous post on this: How to connect to the Kudu site of a specific instance

image

  • This will initiate logs collect.
  • You can click on Schedule Analysis to select the logs that will be collected and whether you want to run an analysis on that.

More Information:

DaaS – Diagnostics as a Service for Azure Web Sites

New Updates to DaaS – Diagnostics as a Service for Azure Websites 

https://sunithamk.wordpress.com/2015/11/04/diagnose-and-mitigate-issues-with-azure-web-apps-support-portal/ 

Method 3: Using Process Explorer (KUDU) (least favorable)

This method is the least favorable as it generates the memory dump and the prompts the user to download it. If the download is interrupted due to some reason then the data is lost.

  • Login to the KUDU console. (http://<yoursitename>.scm.azurewebsites.net)
  • Click on Process Explorer menu
  • There will be 2 w3wp.exe processes, one for SCM (KUDU) and another for the application.
  • Reproduce the issue
  • Right click the w3wp process (without the scm tag) and select Download memory dump –> Full Dump as shown below:

clip_image001

  • Depending on the size of the process it will take couple of seconds or few minutes to generate the dump on the VM and prompt you to download the file

****IMPORTANT****

  • Using Daas via portal is the preferable method. When the web app is scaled out to run on more than one instance, then you can use DaaS to collect the memory dump from a specific instance. Method 2 & 3 will generate memory dump on a specific instance and is not fool proof as the issue may or may not be occurring on the connected instance. You can however connect to the KUDU of a specific instance using my previous post here: How to connect to the Kudu site of a specific instance
  • The downloading of the memory dump will contribute towards the outbound bandwidth of the App service plan. For more details refer: http://azure.microsoft.com/en-us/pricing/details/data-transfers/
  • When the memory dump is being written, the process remains in a frozen state for the entire duration of operation. So this impacts the application’s availability.
  • You can compress the memory dump via 7zip which is availably by default on Azure App Service instances. You can run the following command:

D:\home\Logfiles\Dumps>D:\7zip\7za.exe a MemoryDumps.zip *.dmp

NOTE: Compression consumes CPU cycles, so you may want to re-consider when running this on a Small sized instance

image

Azure App Service: Generating memory dumps on first chance exception using Procdump

$
0
0

In one of my older posts, I have explained on how we can generate memory dumps on first chance exceptions using Debug Diag. In certain scenarios where the users do not have permissions to install tools, users have to look for alternate options. For example, in Azure App Service, the users do not have permissions to install anything on the VM.

However, Azure App Service provides the KUDU console, using which the users can use a command line utility like procdump.exe to generate memory dumps. We can also use procdump to generate memory dumps on first chance exception using the below command:

procdump.exe -accepteula -ma -e 1 -f “<Exception Name>” <Process ID>

where,
        -ma               Write a dump file with all process memory. The default dump format only includes
                             thread and handle information
        -accepteula   Use this switch to automatically accept the Sysinternals license agreement.

        -e                  Write a dump when the process encounters an unhandled exception. Include the 
                             1 to create dump on first chance exceptions.

       -f                  Filter the first chance exceptions. Wildcards (*) are supported. To just display
                             the names without dumping, use a blank (“”) filter

Azure App Service instances include the sysinternals suite in the default image. They can be located here via the KUDU console: D:\devtools\sysinternals

The users may also download ProcDump from here and upload it a specific location such as D:\home\Dumps and use it.

You would need to determine the process ID of the process against which procdump would be executed. You can determine that by navigating to the Process explorer in the KUDU console as shown below: (Note the PID of the w3wp process without the SCM tag)

image

Here is an example:

D:\home\Dumps>procdump.exe -accepteula -ma -e 1 -f “System.UnauthorizedAccessException” 7808

ProcDump v8.2 – Sysinternals process dump utility
Copyright (C) 2009-2016 Mark Russinovich and Andrew Richards
Sysinternals –
www.sysinternals.com

Process:               w3wp.exe (7808)
Process image:         D:\Windows\SysWOW64\inetsrv\w3wp.exe
CPU threshold:         n/a
Performance counter:   n/a
Commit threshold:      n/a
Threshold seconds:     n/a
Hung window check:     Disabled
Log debug strings:     Disabled
Exception monitor:     First Chance+Unhandled
Exception filter:      [Includes]
                       *System.UnauthorizedAccessException*
                       [Excludes]
Terminate monitor:     Disabled
Cloning type:          Disabled
Concurrent limit:      n/a
Avoid outage:          n/a
Number of dumps:       1
Dump folder:           D:\home\Dumps\
Dump filename/mask:    PROCESSNAME_YYMMDD_HHMMSS
Queue to WER:          Disabled
Kill after dump:       Disabled

Press Ctrl-C to end monitoring without terminating the process.
CLR Version: v4.0.30319
[10:02:46] Exception: E0434F4D.System.Exception (“There was a problem processing this request”)
[10:02:47] Exception: E0434F4D.System.UnauthorizedAccessException (“Access is denied.”)
[10:02:47] Dump 1 initiated: D:\home\Dumps\w3wp.exe_170426_100247.dmp
[10:02:52] Dump 1 writing: Estimated dump file size is 306 MB.
[10:03:16] Dump 1 complete: 306 MB written in 29.8 seconds
[10:03:17] Dump count reached

HTH! Smile

Azure App Service: Using Easy Auth to query Facebook information via Graph API

$
0
0

On 8th August 2016, Facebook ended support FQL (Facebook Query Language). Here is a screenshot of the messaging from their site Facebook Query Language (FQL) Reference

image

So they are encouraging the developers to use the GraphAPI to query the information. In this post we will cover on how to do this.

Pre-Requisites

  • Create an Azure Web App and configure Facebook Authentication. This will require creating a “App ID” & “App Secret”. Refer this link on on how to do this.
  • In the Azure Portal, under Facebook Authentication Settings select the scopes (or permissions) to access the required data.
  • I created a ASP.NET MVC 5 application with default authentication set to Individual User Accounts.

Determining the scopes required to query the facebook data

Facebook provides Graph API Explorer, which allows the users to test, create and debug their graph API calls. Using this the users can generate a accesstoken with specific scope. Using this token, the users can call the Facebook GraphApi and review the results right there.

Here is a screenshot of the UI:

image

Once you have understood, the scopes and parameters you need to pass when calling the Facebook graph Api, we can start working on building the web application.

Create a Function to call an external Endpoint

The below RequestResponse() method takes an URL as input. Using the HttpWebRequest method, we call the URL and return the response.

Calling the Facebook Graph Api

The below CallFacebookGraphApi() method code takes 3 inputs, all of which are of type string.

  1. id – This is the path that will be called. For example “me/feed”
  2. fields – this is the query string parameters that needs to be provided with the id above.
  3. accesstoken – this is the value of the “X-MS-TOKEN-FACEBOOK-ACCESS-TOKEN” header, that gets generated upon successful user login. This is used to authorize the GraphAPI call.

using the above 3 parameters we create a URL and call the RequestResponse() method we created earlier.

Fetching results from Facebook

Here we have a ActionResult Facebook, where we pass the parameters to the CallFacebookGraphApi() method we created above.

I have deployed a working version of the code on one of my web apps (Azure App Service). You can see the it working here: https://easyauthkaushal-staging.azurewebsites.net

This code is published on Github. You may fork it here: https://github.com/kaushalp/Facebook-GraphApi-with-EasyAuth

HTH,
Kaushal


Client Certificate Authentication (Part 2)

$
0
0

This is a continuation of my earlier post on Client Certificate Authentication (Part 1) aka TLS Mutual Authentication. Earlier, I had discussed on what Client Certificates are and how they work in SSL/TLS Handshake.

In this post, I will explain how to review SSL/TLS handshake with help of tools like WireShark & Curl.

Before proceeding further, lets review the SERVER HELLO definition in RFC 5246.  As per the RFC, the server will request the certificate from the client in the Server hello by including certificate_request message, which has the decimal code of 13 (0d in Hex). This will help us in determining the Certificate Request in Server Hello.

enum {
    hello_request(0), client_hello(1), server_hello(2),
    certificate(11), server_key_exchange (12),
    certificate_request(13), server_hello_done(14),
    certificate_verify(15), client_key_exchange(16),
    finished(20), (255)
} HandshakeType;
struct {
    HandshakeType msg_type;    /* handshake type */
    uint24 length;             /* bytes in message */
    select (HandshakeType) {
        case hello_request:       HelloRequest;
        case client_hello:        ClientHello;
        case server_hello:        ServerHello;
        case certificate:         Certificate;
        case server_key_exchange: ServerKeyExchange;
        case certificate_request: CertificateRequest;
        case server_hello_done:   ServerHelloDone;
        case certificate_verify:  CertificateVerify;
        case client_key_exchange: ClientKeyExchange;
        case finished:            Finished;
    } body;
} Handshake;

Once the client sees the certificate_request message it will provide the certificate to the server.

Real world example:

Setup: Hosted a site on IIS inside an Azure VM. This requires a client certificate for authentication. Here is the endpoint https://azurevm.kaushal.co.in

I have added the SSL binding via netsh using the following command:

netsh http add sslcert ipport=0.0.0.0:443 certhash=<certificate thumbprint goes here> appid={4dc3e181-e14b-4a21-b022-59fc669b0914} certstorename=My clientcertnegotiation=enable

 

Analyzing the TLS/SSL handshake in WireShark

As shown below, the server has sent a certificate request message to the client and the client has then responded with the certificate in the next communication.

image

In WireShark you can set the filter to “ssl.handshake.type == 13” to specifically look for certificate_request message in Server Hello.

image

NOTE: Some SSL/TLS servers support only Secure negotiation. Therefore you may not see the Certificate Request message explicitly in the Server Hello. In this case, the server will send the Certificate Request message as a part of the Encrypted Handshake Message.

Analyzing the TLS/SSL handshake in cURL

By far, cURL has made it easier to determine if the server is sending the Certificate Request in Server Hello. You will have to download the version of curl that includes support SSL Protocol. This works in scenarios where the server supports only Secure Negotiation. I

You can find various builds of cURL available for download here: https://curl.haxx.se/dlwiz/?type=bin&os=Win64&flav=-&ver=*&cpu=x86_64 

I am using the following

curl version: 7.54.0 – SSL enabled SSH enabled
URL:
https://bintray.com/artifact/download/vszakats/generic/curl-7.54.0-win64-mingw.7z 

Execute the following from command prompt

curl –v https://<hostname> –k –cert clientcert.pem:<password>

Where,
     -v, –verbose       Make the operation more talkative
     -k, –insecure      Allow connections to SSL sites without certs (H)
     -E, –cert CERT[:PASSWD] Client certificate file and password (SSL)

Once the request has been issued via cURL. In the verbose output, search for TLS handshake message “Request CERT (13)” as highlighted in the below example.

C:\>curl -v https://azurevm.kaushal.co.in -k –cert ClientCert.pem:Password

* Rebuilt URL to: https://azurevm.kaushal.co.in/
* Adding handle: conn: 0x34a6540
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* – Conn 0 (0x34a6540) send_pipe: 1, recv_pipe: 0
* About to connect() to azurevm.kaushal.co.in port 443 (#0)
*   Trying 13.71.126.36…
* Connected to azurevm.kaushal.co.in (13.71.126.36) port 443 (#0)
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Request CERT (13):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS handshake, CERT verify (15):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using AES256-SHA
* Server certificate:
*        subject: OU=Domain Control Validated; CN=*.kaushal.co.in
*        start date: 2017-05-10 09:05:00 GMT
*        expire date: 2018-05-10 09:05:00 GMT
*        issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=
http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority – G2
*        SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
> GET / HTTP/1.1
> User-Agent: curl/7.33.0
> Host: azurevm.kaushal.co.in
> Accept: */*
>
< HTTP/1.1 200 OK
< Cache-Control: private
< Content-Type: text/html; charset=utf-8
* Server Microsoft-IIS/8.5 is not blacklisted
< Server: Microsoft-IIS/8.5
< X-AspNetMvc-Version: 5.2
< X-AspNet-Version: 4.0.30319
< X-Powered-By: ASP.NET
< Date: Fri, 09 Jun 2017 16:51:13 GMT
< Content-Length: 5767

. . .

<continued/>

On Windows, in order to pass the client certificate via cURL, you will have to extract the .pem file out of the .pfx. Use the following command:

openssl pkcs12 -in clientcertificate.pfx -out clientcertificate.pem –clcerts
Enter Import Password:
MAC verified OK
Enter PEM pass phrase:
Verifying – Enter PEM pass phrase:

 

HTH,

Kaushal

Azure App Service: Understanding TLS Mutual Authentication with Web App

$
0
0

I have published 2 posts in the past on Client Certificate authentication.

  • Client Certificate Authentication (Part 1)
  • Client Certificate Authentication (Part 2)

    In order to enable Client Certificate authentication on azure web app, we need to flip the clientCertEnabled property to true. Please refer the following article on how to enable TLS mutual auth for an Azure Web App:

    How To Configure TLS Mutual Authentication for Web App 

    HOW IT WORKS

    The best way to understand this is to capture a network trace by issuing a HTTPS request to the Azure Web app. You will notice that the certificate request is not part of the Server Hello. This is because the server supports Secure Renegotiation and it tends to send this as a part of the Encrypted Handshake Message to the client. Refer my earlier post here.
    To demonstrate this, I have enabled client certificate Authentication on one of the staging slots of my web app. Here is the link:
    https://clientcertauth-demo.azurewebsites.net
    I have written a sample code, which accepts any certificate that is provided to it. It reads the client certificate and displays the results in a tabular format.
    I browsed this web app and captured a network trace using WireShark. Here is a screenshot of this trace:

    image

  • So, how do we confirm if the server is requesting for client certificate. You can use one of the following methods:

    1. Enable SSL traffic decryption in WireShark.
      I found a blog post on how to do this and tested it myself. Here is the link: https://jimshaver.net/2015/02/11/decrypting-tls-browser-traffic-with-wireshark-the-easy-way/ 
      Here is a screenshot of the Decrypted message: The server is sending another Server Hello which contains the Certificate Request message.
      image
    2. Using cURL.exe
      You can refer to my previous post on client cert here to use curl. FYI, cURL is included by default on all the Azure App Service instances. Path is D:\Program Files (x86)\Git\usr\bin. This means you can do run cURL inside the command prompt window in the Kudu console.
      • Open the following URL in a browser: https://<sitename>.scm.azurewebsites.net/DebugConsole (replace <sitename> with the name of the web app)
      • Execute the following command:
        curl -v https://<hostname>
      • Review the verbose output and search for “Request CERT (13)”.
      • Following is a brief output of the command from the Kudu console of the web app. The Server is requesting for the client certificate in the second Server Hello message. See the text highlighted in yellow.

        D:\home>curl -v https://clientcertauth-demo.azurewebsites.net
        * STATE: INIT => CONNECT handle 0x80073200; line 1103 (connection #-5000)
        * Rebuilt URL to:
        https://clientcertauth-demo.azurewebsites.net/
        * Added connection 0. The cache now contains 1 members
        *   Trying 111.221.95.27…
        * STATE: CONNECT => WAITCONNECT handle 0x80073200; line 1156 (connection #0)
          % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                         Dload  Upload   Total   Spent    Left  Speed
          0     0    0     0    0     0      0      0 –:–:– –:–:– –:–:–     0* Connected to clientcertauth-demo.azurewebsites.net (111.221.95.27) port 443 (#0)
        * STATE: WAITCONNECT => SENDPROTOCONNECT handle 0x80073200; line 1253 (connection #0)
        * ALPN, offering http/1.1
        * Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
        * successfully set certificate verify locations:
        *   CAfile: /usr/ssl/certs/ca-bundle.crt
          CApath: none
        * TLSv1.2 (OUT), TLS header, Certificate Status (22):
        } [5 bytes data]
        * TLSv1.2 (OUT), TLS handshake, Client hello (1):
        } [512 bytes data]
        * STATE: SENDPROTOCONNECT => PROTOCONNECT handle 0x80073200; line 1267 (connection #0)
        <!DOCTYPE html>
        <html>

        <————————–Trimmed HTML Response ————————–>

        </html>
        { [5 bytes data]
        * TLSv1.2 (IN), TLS handshake, Server hello (2):
        { [81 bytes data]
        * TLSv1.2 (IN), TLS handshake, Certificate (11):
        { [3245 bytes data]
        * TLSv1.2 (IN), TLS handshake, Server key exchange (12):
        { [333 bytes data]
        * TLSv1.2 (IN), TLS handshake, Server finished (14):
        { [4 bytes data]
        * TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
        } [70 bytes data]
        * TLSv1.2 (OUT), TLS change cipher, Client hello (1):
        } [1 bytes data]
        * TLSv1.2 (OUT), TLS handshake, Finished (20):
        } [16 bytes data]
        * TLSv1.2 (IN), TLS change cipher, Client hello (1):
        { [1 bytes data]
        * TLSv1.2 (IN), TLS handshake, Finished (20):

        { [16 bytes data]
        * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-SHA384
        * ALPN, server did not agree to a protocol
        * Server certificate:
        *      subject: CN=*.azurewebsites.net
        *      start date: Sep 28 21:45:23 2016 GMT
        *      expire date: May  7 17:03:30 2018 GMT
        *      subjectAltName: clientcertauth-demo.azurewebsites.net matched
        *      issuer: C=US; ST=Washington; L=Redmond; O=Microsoft Corporation; OU=Microsoft IT; CN=Microsoft IT SSL SHA2
        *      SSL certificate verify ok.
        * STATE: PROTOCONNECT => DO handle 0x80073200; line 1288 (connection #0)
        } [5 bytes data]

        > GET / HTTP/1.1
        > Host: clientcertauth-demo.azurewebsites.net
        > User-Agent: curl/7.47.1
        > Accept: */*
        >
        * STATE: DO => DO_DONE handle 0x80073200; line 1350 (connection #0)
        * STATE: DO_DONE => WAITPERFORM handle 0x80073200; line 1477 (connection #0)
        * STATE: WAITPERFORM => PERFORM handle 0x80073200; line 1487 (connection #0)
        { [5 bytes data]

        * TLSv1.2 (IN), TLS handshake, Hello request (0):
        { [4 bytes data]
        * TLSv1.2 (OUT), TLS handshake, Client hello (1):
        } [512 bytes data]
        * TLSv1.2 (IN), TLS handshake, Server hello (2):
        { [105 bytes data]
        * TLSv1.2 (IN), TLS handshake, Certificate (11):
        { [3245 bytes data]
        * TLSv1.2 (IN), TLS handshake, Server key exchange (12):
        { [333 bytes data]
        * TLSv1.2 (IN), TLS handshake, Request CERT (13):
        { [30 bytes data]
        * TLSv1.2 (IN), TLS handshake, Server finished (14):
        { [4 bytes data]
        * TLSv1.2 (OUT), TLS handshake, Certificate (11):
        } [7 bytes data]
        * TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
        } [70 bytes data]
        * TLSv1.2 (OUT), TLS change cipher, Client hello (1):
        } [1 bytes data]
        * TLSv1.2 (OUT), TLS handshake, Finished (20):
        } [16 bytes data]
        * TLSv1.2 (IN), TLS change cipher, Client hello (1):
        { [1 bytes data]
        * TLSv1.2 (IN), TLS handshake, Finished (20):
        { [16 bytes data]
        * HTTP 1.1 or later with persistent connection, pipelining supported
        < HTTP/1.1 403 Forbidden
        < Content-Type: text/html
        * Server Microsoft-IIS/8.0 is not blacklisted
        < Server: Microsoft-IIS/8.0
        < Date: Fri, 09 Jun 2017 19:19:37 GMT
        < Connection: close
        < Content-Length: 2399

        <————————–Trimmed ————————–>

        Hope this clarifies few doubts on how TLS Mutual Auth works on Azure App Service.

        RESTRICTIONS

      • Currently, TLS Mutual Authentication is supported for web apps running in Basic or higher pricing tiers only. You will receive the following error if you try to enable it for a web app running in FREE/SHARED tier.
        Cannot enable client certificate for a site ‘{0}’ because current site mode does not allow it.
      • When the clientCertEnabled property is set to true the web app mandates the client to provide a client certificate. If the client fails to provide a client certificate they will receive a 403 error. Those familiar with IIS, this is equivalent to setting the sslFlags property (inside <access> tags) in IIS to include “SslRequireCert”.

        <location path=”Kaushal”>
            <system.webServer>
                <security>
                    <access sslFlags=”Ssl, SslNegotiateCert, SslRequireCert” />
                </security>
            </system.webServer>
        </location>

      • As of now, Azure App Service supports Secure Renegotiation and doesn’t entertain ReNego. If there are TLS clients, that are not compliant as per the RFC 5746 and depend on Re-Negotiation, then they cannot connect to Azure App Service.

    HTML Table with horizontal & vertical scrolling

    $
    0
    0

    I blog very frequently and sometimes the posts contain code snippets. The site template sometimes limits the available real-estate and this can cause certain issues. If there is long text in one line, then they are stripped and will not be visible.

    The solution to this is to:

    • Use a template which provides more real-estate.
      OR
    • Use a scrollable HTML table.

    If you chose the second option of a scrollable HTML table, below is a sample code-snippet that you can use to achieve this. The below snippet provides horizontal scrolling only. You can modify the same to achieve vertical scrolling

     

    This is how it looks in different browsers:

    image

     

    Viewing all 71 articles
    Browse latest View live


    Latest Images

    <script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>