Using Azure Functions with the Lithnet MIIS Automation Powershell Module to query your Microsoft Identity Manager Metaverse

This is the 2nd blog continuing on from this post which is an introduction to using Azure Functions with the Lithnet FIM/MIM Powershell Modules. If you haven’t read that one please do so to get up to speed before this one as it has more detail around the setup.

Overview

This post details similar functionality to the first post but with integration to the FIM/MIM Synchronisation Server and the FIM/MIM Metaverse rather than the FIM/MIM Service.

The solution is based around an Azure Function that;

  • takes a HTTP WebRequest that contains a payload with the ObjectType, AttributeName and AttributeValue to search for in the Metaverse
  • The Azure Function uses Remote Powershell to call the Lithnet MIIS Automation Powershell Module installed on the FIM/MIM Sync Server
  • The Lithnet Powershell Module takes the query from the Azure Function, executes the query and returns the result to the Azure Function and the requesting client
  • Note: My MIM Infrastructure is all located in Azure so there are configuration steps in this solution to allow access into my Azure environment. If your FIM/MIM infrastructure is elsewhere you’ll need to transpose the appropriate firewall rules for your architecture

Let’s get started.

Prerequisites

The prerequisites for this solution are;

  • An Azure Tenant
  • FIM/MIM Sync Server (as per the diagram above) with data in your Metaverse from a connected directory service (such as Active Directory)
  • I’ll also be using the awesome Lithnet MIIS Powershell Module from here for Microsoft FIM/MIM from Ryan Newington. A fantastic contribution to the FIM/MIM community
    • You’ll need to download and install it on your FIM/MIM Synchronisation Server. This differs from the Lithnet Module from the first post in this series as this one is specific to the Metaverse not the FIM/MIM Service.

Enable Powershell Remoting on the FIM/MIM Sync Server

On the FIM/MIM Sync Server where we will be sending requests from the Function App we need to enable Powershell Remoting. This is so we can leverage the Lithnet MIIS Automation Powershell module (that is a prerequisite to be installed on your FIM/MIM Sync Server).

On the FIM/MIM Synchronisation Server open Powershell (as Administrator) and execute the command  Enable-PSRemoting -Force 

 

Test from another server in your network that you can access the MIM Sync Server. I did this from my MIM Service Server.

 

PSRemote Inbound Security Rule (Azure NSG)

Using Powershell Remote means we need to have an incoming rule into the Azure Network where my MIM Sync Server is located to allow connections from Azure Functions to my MIM Sync Server. Create an Inbound Rule in your Azure Network Security Group for TCP Port 5986 as per the rule below.

 

Create a Self Signed Cert on the FIM/MIM Sync Server

To secure the connection using Remote Powershell we will secure the HTTPS connection with a certificate. This is because the Azure Function is not a member of the domain where your FIM/MIM Sync Server is located. In this example I’m using a self-signed certificate.

In Powershell (as Administrator) on your FIM/MIM Sync Server run the following command where the DNSName is the DNS name of your FIM/MIM Sync that will resolve from Azure Functions to your FIM/MIM Sync server.

New-SelfSignedCertificate -DnsName mymimsyncserver.westus.cloudapp.azure.com -CertStoreLocation Cert:\LocalMachine\My

Create a Remote Powershell HTTPS Listener

Copy the thumbprint from the self-signed certificate above and use it along with the DNS name of your FIM/MIM Sync Server to run the following command in an Administrator command prompt on your FIM/MIM Sync Server.

winrm create winrm/config/Listener?Address=*+Transport=HTTPS @{Hostname=”mymimsyncserver.westus.cloudapp.azure.com”;CertificateThumbp
rint=”536E41D6089F35ABCDEFD8C52BE754EFF0B279B”}

 

Allow Powershell Remote (HTTPS) through your firewall on your FIM/MIM Sync Server

In an Administrator command prompt run the following command to create a new inbound firewall rule for the Remote Powershell session from your Azure Function.

netsh advfirewall firewall add rule name="WinRM-HTTPS" dir=in localport=5986 protocol=TCP action=allow

Check that the new firewall rule was created successfully.

 

Create your HTTP Request Function

Create a new HTTP Trigger Function choosing Powershell as the language. More detailed steps to do this is in the first post in this series here.

Search FIM/MIM Metaverse Function App Script

Here is the base script to get you started. This differs a little from the first blog post example in that I’ve secured the username and password for connection to my MIM Sync Server. Details on how to do that are also linked to in the first blog post.

Also in this example I’m running Remote Powershell to execute the command on the FIM/MIM Sync Server as that is where the Lithnet MIIS Automation Powershell Module is installed and needs to run.

The following script;

  • Takes an HTTP request with Object Type, AttributeName, AttributeValue
  • It uses a Script Block to take the input variables from the HTTP request and perform a a Powershell Remote command (in this example Get-MVObject)
  • Returns the object to the output

Save the function once you’ve added the script (and updated it for your credentials, target FIM/MIM Sync Server etc).

Bring up the Test dialog and give the script some input values in the Request Body that will result in a successful query result from your Metaverse. Select Run. If you’ve done everything correctly you’ll see an object returned from the Metaverse.

Test the Function App

 

Execute the Azure Function from an HTTP Trigger

Now lets try it remotely. Here is a quick Powershell query to the Azure Function using the Powershell Invoke Rest Method using the same input to the Azure Function. And huzzah a returned object.

Summary

This concept provides a framework to allow a plethora of possibilities all possible through a combination of Azure Functions and the Lithnet MIIS Automation PS Module. The Lithnet MIIS PS Module provides all the functionality you get from being on the MIM Sync Server, but now you can retrieve information remotely or trigger functions remotely.

Follow Darren on Twitter @darrenjrobinson

 

 

 

Microsoft Identity Manager Service and Portal Setup Wizard ended prematurely

Last week I was installing the Microsoft Identity Manager Service and Portal on a relatively fresh build of a Windows 2012R2 Server that also included an automated installation of SharePoint Server 2013 w/ SP1.

After going through all the installation configuration options and having the installation start I got the extremely helpful “Setup Wizard ended prematurely” error message.

Having been in this situation previously on other installs (but for different reasons) I knew it was time to kick off the installation again from the command prompt with logging to an installation log file as shown below.

msiexec /i “e:\Service and Portal\Service and Portal.msi” /l*v c:\temp\install.log 

Providing all the same installation configuration options again the install kicked off again and obviously returned the same “Setup Wizard ended prematurely” error message. But this time I had the installation log file to find out why.

Reading through the log file I found the System.Reflection.TargetInvocationException error as highlighted in the screenshot below. A SharePoint issue. The http://localhost could not be found. What? I could access the SharePoint Central Administration site and I could see everything I’d normally expect.

Until I looked in the Alternate Access Mappings.

For whatever reason my only entry was for the MIM Portal and Service URL that I was trying to install.

I updated the Alternate Access Mappings to included an additional mapping for http://localhost as per the screenshot below.

 

Running the installation process again (and re-entering all the setup configuration) and everything went through as it should. Hope this helps by saving someone else an hour or so.

Follow Darren on Twitter @darrenjrobinson

 

 

Get Users/Groups/Objects from Microsoft/Forefront Identity Manager with Azure Functions and the Lithnet Resource Management Powershell Module

Introduction

As an Identity Management consultant if I had a $1 for every time I’ve been asked “what is user x’s current status in IDAM”, “is user x active?”, “does user x have an account in y?”, “what is user x’s primary email address?”, particularly after Go Live of an IDAM solution my holidays would be a lot more exotic.

From a Service Desk perspective IDAM implementations are often a black box in the middle of the network that for the most part do what they were designed and implemented to do. However as soon as something doesn’t look normal for a user the Service Desk are inclined to point their finger at that black box (IDAM Solution). And the “what is the current value of ..”, “does user x ..” type questions start flying.

What if we could give the Service Desk a simple query interface into FIM/MIM without needing to give them access to another complicated application?

This is the first (of potentially a series) blog post on leveraging community libraries and Azure PaaS services to provide visibility of FIM/MIM information. This first post really just introduces the concept with a working example in an easy way to understand and replicate. It is not intended for production implementation without additional security and optimisation. 

Overview

The following graphic shows the concept of using Azure Functions to take requests from a client (web app, powershell, some other script) query the FIM/MIM Service and return the result. This post details the setup and configuration for the section in the yellow shaded box with the process outlined in the numbers 1, 2 & 3. This post assumes you already have your FIM/MIM implementation setup and configured according to your connected integrated applications/services such as Active Directory. In my example my connected datasource is actually Twitter.

Prerequisites

The prerequisites for this solution are;

 

Creating your Azure App Service

First up you’ll need to create an Azure App Service in your Azure Tenant. To keep everything logically structured for this example I created an Azure App Service in the same resource group that contains my MIM IaaS infrastructure (MIM Sync Server, MIM Service Server, SQL Server, AD Domain Controller etc).

In the Azure Marketplace select New (+) and search for Function App. Select the Function App item from the results and select Create.

Give your Azure App Service a name, choose the Resource Group where you want to locate it. Choose Dynamic for the Hosting Plan. This means you don’t have to worry about resource management for your Web App and you only pay for execution time which unless you put this into production and have gone crazy with it your costs should be zero as they will (should) be well under the free grant tier.  Put the application in the appropriate location such as close to your FIM/MIM resources that it’ll be interacting with and select Create.

Now that you have your Azure App Service setup, you need to create your Azure Function.

Create an HTTP Trigger Powershell Function App

In the Azure Portal locate your App Services Blade and select the Function App created in the steps above. Mine was named MIMMetaverseSearch in the example above. Select PowerShell as the Language and HttpTrigger-Powershell as the Function type.

Give your Function a name. I’ve kept it simple in this example and named it the same as my App Service Plan. Select Create.

Adding the Lithnet Powershell Module into your Function App.

As you’d expect the Powershell Function App by default only has a handful of core Powershell Modules. As we’re using something pretty specific we’ll need put the module into our Function App so we can load it and use the library.

Download and save the Lithnet Resource Management Powershell Module to your local machine. Something like the Powershell command below will do that.

Next follow this great blog post here from Tao to upload the Lithnet RMA PS Module you downloaded earlier into your function directory. I used WinSCP as my FTP client as I’ve shown below to upload the Lithnet RMA PS Module.

FTP to the host for your App Service and navigate to the /site/wwwroot/

Create a bin folder and upload via FTP the Lithnet RMA PS Module.

Using Kudu navigate to the path and version of the Lithnet RMA PS Module.
I’m using v1.0.6088 and my app is named MIMMetaverseSearch so MY path is D:\home\site\wwwroot\MIMMetaverseSearch\bin\LithnetRMA\1.0.6088

Note: the Lithnet RMA PS Module is 64-bit so you’ll need to configure your Web App for 64-bit as per the info in the same blog you followed to upload the module here.

Test loading the Lithnet RMA PS Module in your Function App

In your Function App select </> Develop. Remove the sample script and in your first line import the Lithnet RMA PS Module using the path from the previous step. Then, to check that it loads add a line that references a cmdlet in the module. I used Help Get-Resource. Select Save then Run.

If you’ve done everything correct when you select Run and look at the Logs you’ll see the module was loaded and the Help Get-Resource command was run in the Logs.

Allow your Function App to access your FIM/MIM Service Server

Even though you have logically placed your Function App in the same Resource Group (if you did it like I have) you’ll need to actually allow the Function App that is running in a shared PaaS environment to connect to your FIM/MIM Service Server.

Create an inbound rule in your Network Security Group to allow access to your FIM/MIM Service Server. The example below isn’t as secure as it could (and should) be as it allows access from anywhere. You should restrict the source of the request(s) accordingly. I’m just showing how to quickly get a working example. TCP Port 5725 is required to access your MIM Service Server. Enter the details as per below and select Ok.

Using an Azure Function to query FIM/MIM Service

Note: Again, this is an example to quickly show the concept. In the script below your credentials are in the script in clear text (and of course those below are not valid). For anything other than validating the concept you must protect your credentials. A great example is available here in Tao’s post.

The PS Azure Function gets the incoming request and converts it from JSON. In my request which you’ll see in the next step I’m passing in “displayName” and “objectType”.

In this example I’m using Get-Resource from the Lithnet RMA to get an object from the FIM/MIM Service. First you need to open a connection to the FIM/MIM Service Server. On my Azure IaaS MIM Service Server I’ve configured a DNS name so you can see I’m using that name in line 17 to connect to it using the unsecured credentials from earlier in the script. If you haven’t set up a DNS name for your FIM/MIM Service Server you can use the Public IP Address instead.

Line 20 queries for the ObjectType and DisplayName passed into the Function (see calling the Function in the next step) and returns the response in line 22. Again this is just an example. There is no error checking, validation or anything. I’m just introducing the concept in this post.

Testing your Function App

Now that you have the function script saved, you can test it from the Function App itself. Select Test from the options up in the right from your function. Change the Request Body for what the Function is expecting. In my case displayname and objectType. Select Run and in the Logs if you’ve got everything configured correctly (like inbound network rules, DNS name, your FIM/MIM Service Server is online, your query is for a valid resource) you should see an object returned.

Calling the Function App from a Client

Now that we have our Function App all setup and configured (and tested in the Function App) let’s send a request to the Azure Function using the Powershell Invoke-RestMethod function. The following call I did from my laptop. It is important to note that there is no authN in this example and the function app will be using whatever credentials you gave it to execute the request. In a deployed solution you’ll need to scope who can make the requests, limit on the inbound network rules who can submit requests and of course further protect the account credentials used to connect to your FIM/MIM Service Server.

Successful Response

The following screenshot shows calling the Function App and getting the responding object. Success. In a couple of lines I created a hashtable for the request, converted it to JSON and submitted it and got a response. How powerful is that!?

Summary

Using the awesome Lithnet Resource Management PowerShell Module with Azure Functions it is pretty quick and flexible to access a wealth of information we may want to expose for business benefit.

Now if only there was an affiliation program for Azure Functions that could deposit funds for each IDAM request to an Azure Functions App into my holiday fund.

Stay tuned for more posts on taking this concept to the next level.

Follow Darren on Twitter @darrenjrobinson

How to assign and remove user Office365 licenses using the AzureADPreview Powershell Module

A couple of months ago the AzureADPreview module was released. The first cmdlet that I experimented with was Set-AzureADUserLicense. And it didn’t work, there was no working examples and I gave up and used GraphAPI instead.

Since then the AzureADPreview has gone through a number of revisions and I’ve been messing around a little with each update. The Set-AzureADUserLicense cmdlet has been my litmus test. Now that I have both removing and assigning Office 365 licenses working I’ll save others the pain of working it out and give a couple of working examples.

 

If like me you have been experimenting with the AzureADPreview module you’ll need to force the install of the newest one. And for whatever reason I was getting an error informing me that it wasn’t signed. As I’m messing around in my dev sandpit I skipped the publisher check.
Install-Module -Name AzureADPreview -MinimumVersion 2.0.0.7 -Force -SkipPublisherCheck
Import-Module AzureADPreview RequiredVersion 2.0.0.7

Removing an Office 365 License from a User

Removing a license with Set-AzureADUserLicense looks something like this.

What if there are multiple licenses ? Similar concept but just looping through each one to remove.

Assigning an Office 365 License to a User

Now that we have the removal of licenses sorted, how about adding licenses ?

Assigning a license with Set-AzureADUserLicense looks something like this;

Moving forward this AzureAD Powershell Module will replace the older MSOL Module as I wrote about here. If you’re writing new scripts it’s a good time to start using the new modules.

Follow Darren on Twitter @darrenjrobinson

 

Leveraging the Microsoft Graph API with PowerShell and OAuth 2.0

Background

Microsoft Graph is the evolvement of API’s into Microsoft Cloud Services. For me not being a developer, a key difference is interacting with with Graph API using OAuth 2.0 via PowerShell. Through a number of my previous posts I’ve interacted with the Graph API using client libraries such as the Microsoft.IdentityModel.Clients.ActiveDirectory library. This post details using PowerShell to talk directly to Graph API and managing Authentication and Authorization using OAuth 2.0 and Azure WebApp.

Leveraging the Graph API opens up access to the continually evolving Azure services as shown in the graphic below. Source graph.microsoft.io

Getting started with the Graph API, PowerShell and OAuth 2.0

The key difference between using a client library and going direct is you need to register and configure an Azure WebApp. It is super simple to do. Jump on over to the Office 365 App Registration Tool here. Sign in with an account associated with the Azure Tenant you are going to interact with. Depending on what you’re doing you’ll need to select the appropriate access.

Here’s the settings I selected for access to user profiles. Give the WebApp a name. This is the name that you’ll see in the OAuth Authorization step later on. I’ve highlighted the other key settings. Don’t worry about the SignIn and RedirectURL’s other than configuring HTTPS as we’ll be using PowerShell to access the WebApp.

Once you’ve registered the WebApp successfully you’ll get a Client ID and Client Secret. RECORD/WRITE THESE DOWN NOW as you won’t get access to your Client Secret again.

If you want to change what your WebApp has access to after creating it you can access it via the Classic Azure Portal. Select your Active Directory => Select Applications => Select the WebApp you created earlier  => Select Configure => (scroll to the bottom) Select Add Application. Depending on what you have in your subscription you can add access to your services as shown below.

Authenticating & Authorizing

In order to access the Graph API we need to get our Authorization Code. We only need to do this the first time.

This little script (modify with your Client ID and your Client Secret obtained earlier when we registered our WebApp) will prompt you to authenticate.

Using the account associated with the Web App you registered in the previous step authenticate.

You’ll be requested to authorize your application.

You will then have your AuthCode.

One thing to note above is admin_consent. This is from the URL passed to get the Authorization Code. &prompt=admin_consent is giving Admin Consent to all entities configured on the WebApp over just access for and to a single user.

Accessing the Graph API with OAuth 2.0 Access Token

Using your ClientID, ClientSecret and AuthCode you can now get your access token. I tripped up here and was getting Invoke-RestMethod : {“error”:”invalid_client”,”error_description”:”AADSTS70002: Error validating credentials.
AADSTS50012: Invalid client secret is provided.  Tracing back my steps and looking at my “Client Secret” I noticed the special characters in it that I hadn’t URL Encoded. After doing that I was successfully able to get my access token.

Looking at our AuthZ we can see that the Scope is what was selected when registering the WebApp.

Now using the Access Token I can query the Graph API. Here is getting my AAD Object.

Summary

In my case I now can access all users via the API. Here is what’s available. Using the Access Token and modifying the Invoke-RestMethod URI and Method (including -Body if you are doing a Post/Patch action) you are ready to rock and roll and all via PowerShell.

Your Access Token is valid for an hour. Before then you will need to refresh it. Just run the $Authorization = Invoke-RestMethod ….. line again. 

Follow Darren on Twitter @darrenjrobinson

Leveraging the PowerBI Beta API for creating PowerBI Tables with Relationships via PowerShell

If anyone actually reads my posts you will have noticed that I’ve been on a bit of a deep dive into PowerBI and how I can use it to provide visualisation of data from Microsoft Identity Manager (here via CSV, and here via API). One point I noticed going direct to PowerBI via the API (v1.0) though was how it is not possible to provide relationships (joins) between tables within datasets (you can via PowerBI Desktop). After a lot of digging and searching I’ve worked out how to actually define the relationships between tables in a dataset via the API and PowerShell. This post is about that.

Overview

In order to define relationships between tables in a dataset (via the API), there are a couple of key points to note:

https://dl.dropboxusercontent.com/u/76015/BlogImages/PowerBIRelationships/BetaAPI-DataSets.PNG

  • You’ll need to modify the PowerBIPS PowerShell Module to leverage the Beta API
    • see the screenshot in the “How to” section

Prerequisites

To use PowerBI via PowerShell and the PowerBI API you’ll need to get:

How to leverage the PowerBI Beta API

In addition to the prerequisites above, in order to leverage the PowerShell PowerBI module for the PowerBI Beta API I just changed the beta flag $True in the PowerBI PowerShell (PowerBIPS.psm1) module to make all calls on the Beta API. See screenshot below. It will probably be located somewhere like ‘C:\Program Files\WindowsPowerShell\Modules\PowerBIPS

https://dl.dropboxusercontent.com/u/76015/BlogImages/PowerBIRelationships/PowerBIPS-BetaAPI.PNG

Example Dataset Creation

The sample script below will create a New Dataset in  PowerBI with two tables. Each table holds “Internet of Things” environmental data. One for data from an Seeed WioLink IoT device located outside and one inside. Both tables contain a column with DateTime that is extracted before the sensors are read and then their data added to their respective tables referencing that DateTime.

That is where the ‘relationships‘ part of the schema comes in. The options for the direction of the relationship filter are OneDirection (default), BothDirections and Automatic. For this simple example I’m using OneDirection on DateTime.

To put some data into the tables here is my simple script. I only have a single IoT unit hooked up so I’m fudging the more constant Indoor Readings. The Outside readings are coming from a Seeed WioLink unit.

Visualisation

So there we have it. Something I thought would have been part of the minimum viable product (MVP) release of the API is available in the Beta and using PowerShell we can define relationships between tables in a dataset and use that in our visualisation.

https://dl.dropboxusercontent.com/u/76015/BlogImages/PowerBIRelationships/PowerBI-Env%20Visual-2.PNG

Follow Darren on Twitter @darrenjrobinson

Connecting to and Using the Azure MFA Web Service SDK Server SOAP API with Powershell

Background

A colleague and I are validating a number of scenarios for a customer who is looking to deploy Azure MFA Server. One of the requirements from an Identity Management perspective is the ability to interact with the MFA Server for user information. That led us on the exploration of what was possible and how best to approach it.

The title of this post has pretty much given it away as to how. But why ? As Azure MFA Server is a product that Microsoft have acquired through the acquisition of Phone Factor, the usual methods of interacting with applications and services in the Microsoft Stack don’t apply. There is practically no information on how to use Powershell to interact with Azure MFA Server. So this blog post details what we’ve learned and how we have been able to get information out of Azure MFA Server using Powershell.

This post covers;

  • Connecting to the Azure MFA Web Service SDK
  • Searching for users in the MFA Database
  • Returning information about users in the MFA Database
  • Making a test call to a users phone via the MFA Server

Prerequisites

There are a number of prerequisites that I’m not covering here as you can quickly locate many guides to installing/configuring Azure MFA Server.

  • You’ll need to have an Azure MFA environment (obviously)
  • Download the Azure MFA Web Service SDK
  • Install and Configure the Azure MFA Web Service SDK
  • If you aren’t using a Public SSL Cert on the Azure MFA Web Service SDK Server you will need to export the certificate from the Azure MFA Web Service SDK Server and import it to the Trusted Root Certificate Store on the workstation you’ll be using Powershell on to connect to the MFA environment.

Connecting to the Azure MFA Web Service SDK

Now that you’ve met the prerequisites listed above you can use Powershell to connect to the API. The URL is the DNS name of the Azure MFA Web Service SDK Server following by the SDK SOAP endpoint. eg. https://mfa.yourdomain.com.au/MultiFactorAuthWebServiceSdk/PfWsSdk.asmx?WSDL

Try out the URL in your browser and using an account that exists in the MFA Server authenticate to the Azure MFA Web Service SDK Server. If it is setup correctly (including your SSL certificate)  you will see the following.

The simple script below will perform the same thing, but via Powershell. Update for your domain, username, password and URL for your MFA Web Service SDK Server.

Searching for users in the MFA Database

Now that we’ve setup a web services proxy connection to the MFA Web Service SOAP API endpoint we can start getting some info out of it. Searching for users uses the ‘FindUsers_4’ call. It has many parameters that can be set to alter the results. I’ve gone simple in this one and used ‘*’ as the criteria to return all users in the MFA Database. Alter for your purposes.

Returning information about users in the MFA Database

Using a slightly different criteria to the Search criteria above I returned one entry and set the $mfauser variable to them. I then use that in the GetPhone, GetUserSettings & GetUserDevices calls as shown belown to retrieve all the info about them.

Making a test call to a users phone via the MFA Server

Finally rather than just consuming information from the MFA environment let’s actually trigger something. Selecting an identity from our test environment that had the mobile phone number of a colleague associated with it, I triggered MFA Server to call them to authorize their session (which they hadn’t obviously requested). I may have done this a few times from the other side of the room watching with amusement as their phone rang requesting authentication approval 🙂

Full script snippets below.

Hope that helps someone else.

Follow Darren on Twitter @darrenjrobinson

Getting Users, Groups & Contacts via the Azure Graph API using Differential Query & PowerShell

This is the final post in a series detailing using PowerShell to leverage the Azure AD Graph API. For those catching up it started here introducing using PowerShell to access the Azure AD via the Graph API, licensing users in Azure AD via Powershell and the Graph API, and returning all objects using paging via Powershell and the Graph API.

In this post I show how to;

  • enumerate objects from Azure AD via Powershell and the Graph API, and set a delta change cookie
  • enumerate changes in Azure AD since the last query
  • return objects that have changed since the last query
  • return just the changed attributes on objects that have changed since the last query
  • get a differential sync from now delta change link

Searching through MSDN and other resources working this out I somehow stumbled upon a reference to changes in the API that detail the search filters. v1.5 and later of the API requires filters using the context ‘Microsoft.DirectoryServices.User|Group|Contact’ etc instead of ‘Microsoft.WindowsAzure.ActiveDirectory.User|Group|Contact’ which you’ll find in the few examples around. If you don’t want to return all these object types update the filter on line 21 in the script below.

Here is the script to return all Users, Groups and Contacts from the tenant along with all the other options I detail in this post. Update the following for your tenant;

  • line 6 for your tenant URI
  • line 10 for your account in the tenant
  • line 11 for the password associated with your account from line 10

Here is a sample output showing the Users, Groups, Contacts and DirectoryLinkChange objects. Note: if you have a large tenant that has been in place for a period of time it may take a while to enumerate.  In this instance you can use the Differential Sync from now option. More on that later.

Running the query again using the Differential DeltaLink from the first run now returns no results. This is as expected as no changes have been made in the tenant on the objects in our query.

Now if I make a change in the tenant and run the query again using the Differential DeltaLink I get 1 result. And I get the full object.

What if I just wanted to know the change that was made?

If we add ‘&ocp-aad-dq-include-only-changed-properties=true’ to the URI that’s exactly what we get. The object and what changed. In my case the Department attribute.

Finally as alluded to earlier there is the Differential Sync from now option. Very useful on large tenants where you can query and get all users, contacts, groups etc without using differential sync, then get the Differential Delta token for future sync queries. So I’ve used the same URI that I used as the beginning of this blog post but in the header specified ‘ocp-aad-dq-include-only-delta-token’ = “true” and as you can see I returned no results but I got the important Differential Query DeltaLink.

Summary

Using Powershell we can leverage the Azure AD Graph RestAPI and use the Differential Sync functions to efficiently query Azure AD for changes rather than needing to enumerate an entire tenant each time. Brilliant.

Follow Darren on Twitter @darrenjrobinson

Enumerating all Users/Groups/Contacts in an Azure tenant using PowerShell and the Azure Graph API ‘odata.nextLink’ paging function

Recently I posted about using PowerShell and the Azure Active Directory Authentication Library to connect to Azure AD here. Whilst that post detailed performing simple tasks like updating an attribute on a user, in this post I’ll use the same method to connect to Azure AD via PowerShell but cover;

  • enumerate users, contacts or groups
  • where the number of objects is greater than the maximum results per page, get all remaining pages of results
  • limit results based on filters

The premise of my script was one that could just be executed without prompts. As such the script contains the ‘username’ and ‘password’ that are used to perform the query. No special access is required for this script. Any standard user account will have ‘read’ permissions to Azure AD and will return results.

Here is the base script to return all objects of a given type from a tenant. For your environment;

  • change line 7 for your tenant name
  • change line 11 for your account in your tenant
  • change line 12 for the password associated with the account specified in line 11
  • change line 18 for the object type (eg. Users, Groups, Contacts)

I’ve hardcoded the number of results to return per page in both line 39 and 64 to the maximum 999. The default is 100. I wanted to return all objects as quickly as possible.

The first query along with returning 999 query results also returns a value for $query.’odata.nextLink’ if there are more than 999 results. The .nextLink value we then use in subsequent API calls to return the remaining pages until we have returned all objects.

Brilliant. So we can now simply change line 18 for different object types (Users, Groups, Contacts) if required. But what if we want to filter on other criteria such as attribute values?

Here is a slightly modified version (to the URI) to include a query filter. Lines 19-24 have a couple of examples of query filters.

So there you have the basics on getting started returning large numbers of objects from Azure AD via Azure Graph from PowerShell. Hopefully the time I spent working out the syntax for the URI’s helps someone else out as there aren’t any examples I could find whilst working this out.

Follow Darren on Twitter @darrenjrobinson

 

 

 

Goodbye Set-MsolUser, Hello Set-AzureADUser & Azure Graph API

Recently Microsoft released the preview of the v2.0 Azure AD PowerShell cmdlets. https://azure.microsoft.com/en-us/updates/azure-ad-new-powershell-cmdlets-preview/

I’ve got a project coming up where I’m looking to change my approach for managing users in Azure using Microsoft Identity Manager. Good timing to do a quick proof of concept to manage users with the new cmdlets and directly using the Graph API in preparation to move away from the msol cmdlets.

New Modules

First up, the Azure AD v2.0 PowerShell module was released in public preview on July 13, 2016. There will likely be changes before they become GA, so keep that in mind.

The v2.0 Azure AD PowerShell Module modules themselves are available for download from here https://www.powershellgallery.com/packages/AzureADPreview/1.1.143.0

If you have Windows Management Framework v5 installed you can download and install from PowerShell (as below).

Once installed, pretty quickly you can import the module, authenticate to your tenant, retrieve a user and update a few attributes (as below).

Whilst functional it doesn’t really work for how we need to interact with Azure from an Identity Management perspective. So how can we still use PowerShell but enumerate and manipulate identities in Azure ?

Now that we have the AzureAD v2.0 module installed we can reference the Active Directory library it installs (Microsoft.IdentityModel.Clients.ActiveDirectory.dll), authenticate to our Tenant retrieve users, and update them. That’s exactly what is shown in the commands below.

Where interacting with the GraphAPI directly really shines however is at the directory services layer and the Differential Query functionality.  https://msdn.microsoft.com/en-us/Library/Azure/Ad/Graph/howto/azure-ad-graph-api-differential-query

As such this is the approach that I’ll be taking for integration of Azure with Microsoft Identity Manager for managing users for entitlements (such as Azure licensing).
I hope this though also saves a few people time in working out how to use PowerShell to manage Azure objects via the Graph API (using both the PowerShell Module or via the RestAPI).