Terwijl ik dit schrijf, is Microsoft hard aan het werk om de transitie van de Azure Service Management (ASM) API’s naar de Azure Resource Management (ARM) API’s af te ronden. Beide API’s bieden de mogelijkheid om je Azure resources te beheren en zijn de REST API’s achter Azure Powershell en de Azure portal.

De oudere, ASM API wordt niet voor niks vervangen. Het grote nadeel van deze API is, dat hij niet de mogelijkheid biedt tot fine-grained autorisaties. De enige manier om toegang tot resources te beheren is op het niveau van de subscription. Je kunt niet per resource bepalen wie waar bij mag. In elke organisatie met meer dan een paar resources is dit volledig onacceptabel.

De ARM API is op dit punt een grote stap vooruit. Met ARM kun je Azure Service Management (ASM) APIs to theĀ per resource bepalen wie er bij kan en zelfs regelen wat men precies mag.

Maar dat is niet alles. Naast personen zijn er soms ook applicaties of systemen die toegang nodig hebben tot een of meer Azure resources. Via ASM kon dit door het gebruik van zogenaamde management certificates. De houder van zo’n certificaat had dan volledige controle over een subscription. Met ARM is het mogelijk om ook applicaties gericht toegang te geven tot een subset van je resources. Het is echter niet erg duidelijk hoe dit werkt. In dit blog zal ik dan ook laten zien hoe je een applicatie toegang kan geven tot Azure resources volgnes het principle of least privilege. Voor autorisatie zal ik daarvoor gebruik maken van certificaten, een veiligere methodiek dan wachtwoorden.

Iedereen die, via ARM, toegang tot een subscription heeft moet bekend zijn in de Azure Active Directory (AAD) die bij die subscription hoort. Dit geld niet alleen voor personen, maar ook voor applicaties. Het registreren van een applicatie in de AAD kan helaas nog niet in de nieuwe portal. We moeten dus terug naar de oude portal of gebruik maken van Powershell. Nadat de applicatie geregistreerd is in de AAD, moet deze ook nog geautoriseerd worden op een resourcegroup. Dit kan echter weer alleen in de nieuwe portal of via Powershell. Om die reden kies ik voor Powershell zodat ik niet heen en weer hoef tussen portals.

Om verbinding te maken met de AAD vanuit Powershell is er een specifieke Powershell module (MSOL) nodig, die je hier vindt.

Allereerst registreren we de applicatie:

> # Connect to your active directory
> Connect-MsolService

> #Create the application
> New-MsolServicePrincipal -DisplayName YourApplication
The following symmetric key was created as one was not supplied r...k=

DisplayName : YourApplication
ServicePrincipalNames : {f...1}
ObjectId : c...f
AppPrincipalId : f...1
TrustedForDelegation : False
AccountEnabled : True
Addresses : {}
KeyType : Symmetric
KeyId : 2...4
StartDate : 18-10-2015 15:13:31
EndDate : 18-10-2016 15:13:31
Usage : Verify
> # We will need that AppPrincipalId later, so keep it for reference

> # However, first we remove that Symmetric key we do not need
> # First we find its KeyId
> Get-MsolServicePrincipalCredential -AppPrincipalId f...1
cmdlet Get-MsolServicePrincipalCredential at command pipeline position 1
Supply values for the following parameters:
ReturnKeyValues: 

Type : Symmetric
Value : 
KeyId : 2...4
StartDate : 18-10-2015 15:13:31
EndDate : 18-10-2016 15:13:31
Usage : Verify 

> # Now remove it providing again the ApplicationId and the KeyId.
> # The KeyIds parameter takes an array, hence the parentheses
> Remove-MsolServicePrincipalCredential -AppPrincipalId f...1 -KeyIds ("2...4")

Nu voegen we authenticatie op basis van een certificaat toe:

> # Let's grab the certificate from filesystem and transform it to Base64
> $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate 
> $certificate.Import("c:\...\YourApplication.cer")
> $binaryCertificate = $certificate.GetRawCertData() 
> $base64Certificate = [System.Convert]::ToBase64String($binaryCertificate);

> # Register the certificate as the applications credential
> New-MsolServicePrincipalCredential -AppPrincipalId "f...1" -Type asymmetric -Value $base64Certificate -Usage verify

Tenslotte moeten we de applicatie rechten geven op een resource. Voor dit doel heb ik een resourcegroup ‘poc’ aangemaakt:

> # Every resource under ARM is defined by an URL
> $scope = "/subscriptions/4...f/resourceGroups/poc"

> # Contributor is a pre-assigned role that includes every right, except GRANTS
> New-AzureRoleAssignment -ServicePrincipalName "f...1" -RoleDefinitionName Contributor -Scope $scope

De applicatie schrijven

Nu dat we een applicatie in de AAD geregistreerd hebben, kunnen we de applicatie zelf schrijven. Hieronder vind je een minimaal voorbeeld voor authenticatie en het opvragen van een lijst van alle storage accounts in een rsource group:

var subscriptionId = "4...f"; // The guid assigned to your subscription. If you don't have it, use Get-AzureSubscription
var tenantId = "4...f"; // The guid assigned to your AAD Tenant. If you don't have it, use Get-AzureSubscription
var aadEndpoint = $"https://login.windows.net/{tenantId}";
var clientId = "f...1"; // Again, AppPrincipleId
var certificateThumbprint = "b...a"
var armLocation = "https://management.azure.com/"

var context = new AuthenticationContext(aadEndpoint);
var certificate = GetARMCertificate(certificateThumbprint);
var credentials = new ClientAssertionCertificate(clientId, certificate);
var loginResult = context.AcquireToken(armLocation, credentials);
var token = new TokenCloudCredentials(subscriptionId, loginResult.AccessToken);
var managementClient = new StorageManagementClient(token);

var accounts = managementClient.StorageAccounts.List();

Er zijn twee NuGET packages die je moet installeren om deze code te draaien: Microsoft.IdentityModel.Clients.ActiveDirectory and Microsoft.Azure.Management.Storage

En hier het eindresultaat: Een overzicht van alle storage accounts in de resource group. Andere acties, zoals het toevoegen of verwijderen van storage accounts zijn natuurlijk ook mogelijk..

ARMCertificateAuth