Skip to main content

PowerShell + AzureRM : Using Certificate based automated login

This is a long overdue post (previous one here) on how to use certificates to do an automated login to Azure Resource Manager. Not rocket science but easy to setup, so that you use a cert to authenticate to Azure RM automatically.


It seems the Azure docs are already up to date on how to do few bits involved in this, please read the section 'Create service principal with a certificate' in the docs.

The process is almost the same as mentioned in the docs, except the fact that when we do the role assignment, we instead assign the contributor role definition to the service principal, since we want the ability to manage the resources in Azure RM.
Also, we will author a function add it to our profile so that PowerShell authenticates automatically to Azure RM each time it opens. 
So let's begin with it:
  1. Create the self-signed certificate.

    If you are running this on Windows 8.1, then you have to use the script by MVP Vadims Podans from the gallery.


    # For OS below Windows 10, download the script and use that to generate the self-signed cert.
    Import-Module .\New-SelfSignedCertificateEx.ps1
    New-SelfSignedCertificateEx -StoreLocation CurrentUser -StoreName My -Subject "CN=AutomateLogin" -KeySpec Exchange
    $cert = Get-ChildItem -path Cert:\CurrentUser\my | where {$PSitem.Subject -eq 'CN=AutomateLogin' }

    Otherwise, if you are running Windows 10 then the builtin PKI module would suffice. Note - The cert created below has marked private key to be not exportable.

    Run below:


    $cert = New-SelfSignedCertificate -CertStoreLocation "cert:\CurrentUser\My" -Subject "CN=AutomateLogin" -KeySpec KeyExchange -KeyExportPolicy NonExportable


  2. Create the AD app and service principal

    In order to create the Azure AD application, we first need to read the raw certificate data as base64 encoded string (help for the New-AzureRMADApplication clearly states this fact).


    # Get the certificate data as base64 encoded string
    $keyValue = [System.Convert]::ToBase64String($cert.GetRawCertData())

    # Create a new Azure AD application with the associated certificate
    $app = New-AzureRmADApplication -DisplayName "AutomatedCertLoginApp" -HomePage "https://www.dexterposh.com" `
            -IdentifierUris "http://www.dexterposh.com/p/about-me.html" `
            -CertValue $keyValue -EndDate $cert.NotAfter -StartDate $cert.NotBefore

    Once the Azure AD Application is created, it is time to add a corresponding AD service principal. Make a note of this application ID (echoed on the host for reference), since it will be passed as a value to our function later.


    # Also create a corresponding service principal for the Azure AD application
    New-AzureRmADServicePrincipal -ApplicationId $app.ApplicationId
    Write-Host -ForeGround Cyan -Object $app.ApplicationId
    Start-Sleep -Seconds 15
  3. Role assignment to the service principalNow the time has come to deviate from the original article being referenced in for this post, it is time to grant the contributor access to the AD service principal created above.


    # Assign the Contributor role definition to the service prinicipal
    New-AzureRmRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $app.ApplicationId


  4. Author the automated login function

    Now, I am calling this function Connect-ToAzureRM, in order for us to author this function we would need the current subscription id, which can be fetched using the Get-AzureRMSubscription cmdlet (note the tenantID field).

    Below is how the function is added to my $PROFILE and invoked at the end, you will have to place your subscription tenant id and application id along with the certificate subject name (created above).

    Now, this function is very crude and runs each time PowerShell opens, you might want to customize this by setting the default value of parameters and then invoking the function on demand. You can also get more creative with this concept.


    # Author a new function, add it to $PROFILE and call it everytime PS opens
    Function Connect-ToAzureRM {
        [CmdletBinding()]
        param(
            [Parameter()]
            [String]$TenantId,

            [Parameter()]
            [String]$ApplicationId,

            [Parameter()]
            [String]$CertificateSubjectName
        )
        # first fetch the certificate from the Cert store
        $cert = Get-ChildItem -path Cert:\CurrentUser\my | where {$PSitem.Subject -eq $CertificateSubjectName }

        # now use the above cert to authenticate to Azure
        Add-AzureRmAccount -ServicePrincipal -CertificateThumbprint $cert.Thumbprint -ApplicationId $ApplicationId -TenantId $TenantId
    }
     Connect-ToAzureRM -TenantId "place ur Tenant ID" -ApplicationId "place ur app id" -CertificateSubjectName CN=AutomateLogin
References :







Popular posts from this blog

Test connectivity via a specific network interface

Recently while working on a Private cloud implementation, I came across a scenario where I needed to test connectivity of a node to the AD/DNS via multiple network adapters.  Many of us would know that having multiple network routes is usually done to take care of redundancy. So that if a network adapter goes down, one can use the other network interface to reach out to the node. In order to make it easy for everyone to follow along, below is an analogy for the above scenario: My laptop has multiple network adapters (say Wi-Fi and Ethernet) connected to the same network. Now how do I test connectivity to a Server on the network only over say Wi-Fi network adapter?

PowerShell + SCCM : Run CM cmdlets remotely

Today I saw a tweet about using implicit remoting to load the Configuration Manager on my machine by Justin Mathews . It caught my eye as I have never really tried it, but theoretically it can be done. Note - The second tweet says "Cannot find a provider with the name CMSite", resolution to which is in the Troubleshooting section at the end.

PowerShell : Trust network share to load modules & ps1

Problem Do you have a central network share, where you store all the scripts or PowerShell modules ? What happens if you try to run the script from a network share ? or if you have scripts (local) which invoke scripts or import PowerShell modules stored on this network share ? Well you would see a security warning like below (Note - I have set execution policy as 'Unrestricted' not 'bypass' here): Run a .ps1 from the network share Well this is a similar warning, which you get when you download scripts from Internet. As the message says run Unblock-File cmdlet to unblock the script and then run it, let's try it.