Category Archives: Azure

CSP delegation on non CSP azure subscriptions

If you’re a Cloud Solution Provider and you supply a CSP azure subscription to that tenant, your AdminAgents will have Owner access to that subscription. Lets say the customer also has an existing subscription.

When you add your accounts as Owner to the existing tenant subscription, your users are added as Guest accounts in the customer’s Azure AD. ThisΒ removes the delegated CSP subscriptions because the reference to the foreign accounts breaks.

So, alternatively, use

Get-AzureRmRoleAssignment -Scope "/subscriptions/<SUBSCRIPTION ID>

on the CSP subscription to get the Foreign Principal ID for your own tenant. Then use

New-AzureRMRoleAssignment -ObjectId <FOREIGN PRINCIPAL ID> -Scope "/subscriptions/ 
<SUBSCRIPTION ID>" -RoleDefinitionName Owner

to add the foreign principal ID to the existing customer subscription to get delegated access πŸ™‚


Setting up Okta User -> Office 365 contact synchronisation

Okta natively does not allow you to sync users to Office 365 contacts; they either exist as users in Office 365, or they don’t exist at all.

In hybrid scenarios where you are doing a staged migration to Office 365, or where you simply manage your contacts in Okta, you may want to populate the Global Address List in Office 365 with your Okta users.

I’ve written a simple solution for this, you will require:

  1. Okta Admin Access (to obtain a token)
  2. Office 365 credentials (to write / modify Contacts)
  3. An Azure Subscription (for automation)

The solution will sync your users in Okta to Office 365, take note of the following: Continue reading Setting up Okta User -> Office 365 contact synchronisation

Parsing a GET request in PHP with an Azure Function

While playing around with PHP (experimental support) in Azure Functions, I noticed that there is no documentation yet and very few examples, so here’s my first simple example on how to build an Azure Function using PHP to parse a very simple GET request.

I’m assuming you’ve set up your function, go into Files and edit the function.json file:


  "bindings": [
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
      "authLevel": "function"
      "type": "http",
      "direction": "out",
      "name": "res"
  "disabled": false

This sets the function to listen to get requests and ignore the default Azure Table storage stuff.

Then open the run.php file and Continue reading Parsing a GET request in PHP with an Azure Function

On-Demand MSI customization using Azure Functions

This post describes how you can use the WIX Toolkit or any DLL file in an Azure Function, in this case to edit an MSI file on the fly. The WIX Toolkit is free, but only runs on Windows. Azure Functions run on Windows too, isn’t that nice πŸ™‚

So, an example use case could be my OnedriveMapper MSI file, which is installed with a configuration GUID property by an admin to customize OnedriveMapper. If that GUID was already in the MSI, no such parameter would be necessary.

Using an Azure function in a download link or http request, we could insert a GUID on the fly and create personalized MSI files on demand.

I’ll leave other applications to your imagination, let’s get started!

  1. Download the WIX toolkitΒ (binaries)
  2. Extra Microsoft.Deployment.WindowsInstaller.dll
  3. Add it to the function files or host it at an URL somewhere. In my example, I’m hosting it at
  4. Add your MSI file to your function files or host it at an URL somewhere. In my example, I’m hosting it at
  5. Add the following code to the Azure Function:

Continue reading On-Demand MSI customization using Azure Functions

Creating a Dynamic Group using the Graph API

Azure has a very nice feature called ‘Dynamic Groups‘. We use these in our customer tenants to dynamically generate a group with actual users, excluding Guest accounts (marked with #EXT#).

As I couldn’t find any articles detailing how to create a Dynamic Group through the Graph API, I’m posting this for whoever it helps πŸ™‚

$dynamicGroupProperties = @{
    "description" = "Dynamic Group Created through the Graph API";
    "displayName" = "Dynamic Group Created through the Graph API";
    "groupTypes" = @("DynamicMembership");
    "mailEnabled" = $False;
    "mailNickname" = "testnickname";
    "membershipRule" = "(user.userPrincipalName -notContains `"#EXT#@`") -and (user.userType -ne `"Guest`")";
    "membershipRuleProcessingState" = "On";
    "securityEnabled" = $True

invoke-webrequest -Headers $headerParams -uri "" -Body (ConvertTo-Json $dynamicGroupProperties) -method POST -Verbose

If you’re not yet used to working with the Graph API, read up on how to connect to the Graph API using Powershell.

Powershell Lock Function

A handy Powershell function to lock / unlock using .NET, to prevent concurrent read/writes to files or anything else you like.

function handleThreadLock{
        #register a thread lock
        $script:threadLock = New-Object System.Threading.Mutex($false, $lockName)
        $waited = 0
            try{$lockState = $script:threadLock.WaitOne(1000)}catch{$lockState=$False}
                if($waited -gt $timeOut){
                    Throw "failed to get a thread within $timeOut seconds!"
        #release a thread lock

In your script, call it like this:

    handleThreadLock -setLock
}catch{Throw "Failed to set lock!"}

    add-content -Path "c:\yourfile.txt" -Value "log entry" -ErrorAction Stop
    handleThreadLock -releaseLock

The process cannot access the file ‘C:\Windows\system32\config\systemprofile\AppData\Roaming\Windows Azure Powershell\TokenCache.dat’ because it is being used by another process.

While building some multithreading Azure Runbooks that log into multiple subscriptions simultaneously, I noticed that these multiple concurrent runs often end up on the same Azure Automation Host.

Apparently, these runbooks then don’t run in full isolation, and the following error may occur:

The running command stopped because the preference variable “ErrorActionPreference” or common parameter is set to Stop: The process cannot access the file ‘C:\Windows\system32\config\systemprofile\AppData\Roaming\Windows Azure Powershell\TokenCache.dat’ because it is being used by another process.

AzureProfile.json may also get locked. I resolved this by doing a retry on the Save-AzureRMContext, and using a randomized file name for the azure json profile:

$randomProfileName = [System.IO.Path]::GetRandomFileName()

Save-AzureRmContext -Path .\$randomProfileName -Force -Confirm:$False

And for my full Azure Login code snippet:

$randomProfileName = [System.IO.Path]::GetRandomFileName()
            Write-Output "Logging in to Azure $azureSubscription"
            $res = Login-AzureRmAccount -Credential $azureCreds -SubscriptionId $azureSubscription -TenantId $tenantId -ErrorAction Stop
            Select-AzureRmSubscription -SubscriptionId $azureSubscription -ErrorAction Stop -TenantId $tenantId
            if($res.Context.Subscription.Id -eq $azureSubscription){
                Write-Output "Logged in to Azure subscription $($res.Context.Subscription.Id)"
                Throw "Failed, we were logged in to $($res.Context.Subscription.Id) while trying to log in to $azureSubscription"
            Save-AzureRmContext -Path .\$randomProfileName -Force -Confirm:$False
            if($tries -ge 30){
            #sleep on failed attempts, as the azure token cache gets locked by concurrent jobs
            sleep -s (Get-Random -minimum 1 -maximum 6)

Transferring a domain to Azure (dns and billing)

Lately I’ve been playing with custom domains in Azure, Microsoft has been allowing us to directly purchase domain in Azure for a while now. This leverages GoDaddy’s API, but Microsoft bills you for the domain, consolidating your domains, management and usage nicely in Azure.

The portal only allows you to purchase new domains, so how do you transfer existing domains to Azure DNS?

First you’ll need a transfer code, which you can get from your current DNS provider. Then, execute the following script:

Register-AzureRmResourceProvider -ProviderNamespace Microsoft.DomainRegistration
$ResourceLocation = "Global"
$ResourceName = "MYDOMAINNAME.NL"
$PropertiesObject = @{
'Consent' = @{
'AgreementKeys' = @("DNPA","DNTA");
'AgreedBy' = ''; #ip address you're running this script from
'AgreedAt' = '2017-17-07T08:37:40'; #roughly the current time
'authCode' = 'DOMAIN TRANSFER CODE'; #code by current domain provider
'Privacy' = 'true';
'autoRenew' = 'true';

New-AzureRmResource -ResourceName $ResourceName -Location $ResourceLocation -PropertyObject $PropertiesObject -ResourceGroupName $rgName -ResourceType Microsoft.DomainRegistration/domains -ApiVersion 2015-02-01 -Verbose

It will take a long time to run, but you’ll have a custom domain in Azure that you can now connect to websites and/or manage through AzureDNS.

Note:Β this only works for domains OLDER than 60 days and can take 5-7 days until the domain is usable in Azure, all domain records will be copied to an Azure DNS zone.