In the past couple of weeks I’ve uploaded a few scripts to help manage Office 365 customer environments in bulk via delegated administration. These scripts work well for us, though they only work when they’re initiated by a delegated administrator here. Sure, we could set them up on a server as a scheduled task, though in the interest of keeping things in the cloud, we’re moving them to Azure Functions.
If you’re interested, the scripts I’ve posted so far regarding Delegated Administration are here:
The Azure Functions service is Microsoft’s Function as a Service offering (FaaS). It’s similar to Hook.io, Google Cloud Functions or AWS Lambda if you’ve used any of those. Basically it lets you run standalone scripts or functions of a program in the cloud. One of Azure Functions’ benefits is that you don’t have to look after the underlying infrastructure, you can just add in your code and you’re pretty much done. You can start an Azure function using a HTTP or Azure Storage Queue trigger, or just set it to run on a timer. Azure Functions can run a variety of languages, though in this scenario, we’ll convert a simple Office 365 PowerShell script into a timer trigger function that runs each weekday.
Consumption Plan vs App Service Plan
For the number of functions we’ll be running, Azure functions are pretty much free with a Consumption Plan. This plan gives you a grant of 1 million executions and 400,000 GB-s of bandwidth, which we’ll be well under. However, Azure functions can also run on top of a paid Azure App Service Plan – which we’ll be taking advantage of.
Why pay for an Azure App Service Plan to run Azure Functions?
One of the limitations of the (almost) free version of Azure Functions is that it’s executions have a 5 minute limit, after which time they are terminated automatically. Apparently this is because the underlying virtual machines that run the functions are regularly recycled. Since some of our scripts have the potential to run longer than five minutes, we need to provision a small Azure App Service resource and then run our Azure functions on top of this. The VM that runs our App service runs continuously and will support long running functions
Here’s what we want to achieve:
Set up an Azure Function App running on an App Service Plan
Connect an Azure Function to Office 365
Modify an existing PowerShell script to run on an Azure function
In another post we’ll look at connecting Azure Functions to Azure Storage to use in reporting via Power BI, and triggers for Microsoft Flow.
Click the Green + button on the left menu, search for Functions, then click Function App
Click Create on the bottom right
Complete the required fields for the Function App
Choose to create a new Resource Group and Storage Account. For the Hosting Plan option, choose App Service Plan, then select an existing subscription or create a new one. In my case, I chose an S1 Plan, which is probably overkill. You’ll be able to get by with something much smaller.
Once you’ve completed the required fields, click Create and wait for it to complete deployment
After it’s finished deploying, open your function app and click the + button to create a new function.
Choose Custom function at the bottom
On the dropdown on the right, choose PowerShell
Choose TimerTigger-PowerShell and enter a name for your Azure Function.
For the Schedule, enter a cron expression. There used to be documentation at the bottom of the page on how to format these, though at the time of writing it hasn’t appeared. For a function that runs Monday to Friday at 9:30 AM GMT time, enter the following:
0 30 9 * * 1-5
Click Create, you’ll be greeted with an almost blank screen where you can start to enter your PowerShell script. Before we do this, we’ll set up the Azure function to connect to Office 365, and secure your credentials within the function app.
Set up your Azure Function to connect to Office 365
In this step, we’ll be doing the following:
Define and retrieve your FTP Details
The FTP Details of the Azure Function are needed to upload resources that the Azure Function requires to connect to Office 365.
Download, then upload the MSOnline PowerShell Module via FTP
Azure Functions have a lot of PowerShell Modules installed by default, though they don’t have the MSOnline module that lets us connect to Office 365. We’ll need to download the module on our local computer, then upload it into the Azure function. This method was borrowed from this article by Alexandre Verkinderen.
Secure your Office 365 Credentials within the Function App
Right now, Azure Functions don’t integrate with the Azure Key Vault service. While we can store credentials within the function, these credentials are stored in plain text where anyone with access to the function can view them. This method was borrowed from this article by Tao Yang.
How to define and retrieve the FTP credentials for your Azure function app
Click on the name of your function on the left menu.
Click Platform Features at the top, then click Deployment Credentials
Define a username and password for your FTP Credentials
Next under General Settings, click Properties.
Copy the FTP Host Name and make a note of it. You’ll need it to connect to the function’s storage via FTP and upload the MSOnline Module
Download, then upload the MSOnline PowerShell Module via FTP
Open PowerShell on your computer, then run the following command. Make sure there’s a folder called ‘temp’ in your C:\ drive.
Wait for it to download, then make sure it exists within C:\temp
Open Windows Explorer, and connect to your function via FTP using the FTP Hostname and credentials we retrieved earlier.
Navigate to site/wwwroot/YourFunctionName then create a new folder called bin
Open the bin directory, and upload the MSOnline folder from your C:\Temp Directory
Secure your Office 365 Credentials within the Azure Function App
On your computer, open PowerShell again and run the following commands. When you’re asked for your password, enter the password for the delegated admin account that you’ll use to manage your customers Office 365 environments. Make sure you press Enter again to run the final command to output the EncryptedPassword.txt file.
This will create two files on in your C:\temp folder. An EncryptedPassword text file and a PassEncryptKey file. Be sure to delete the EncryptedPassword file once we’re done.
Return to the FTP connection and create a directory called keys under the bin directory
Upload the PassEncryptKey file into the keys directory.
Return to your Azure Function Platform Settings, then open Application Settings.
Under Application Settings, create two new Key-Value pairs. One called user, which contains the username of your delegated admin account, and another called password, which contains the contents of your EncryptedPassword.txt file. Once you’ve added this, be sure to delete the EncryptedPassword.txt file from your computer.
Before you leave Application settings, update the Platform from 32 bit to 64 bit.
Wait for the settings to apply, then return to the Develop Section of your Azure Function
Modify your Office 365 PowerShell script for Azure Functions
Update the variables at the top of the script to ensure they match the function name, Module Name and Module Version.For your existing scripts, you may need to update your Write-Host references to Write-Output.This sample script is a modified version of this one. It will set the default password expiration policy for all of your customers’ domains to never expire.You can use this one or create your own script under the # Start Script comment
//gcits.com.au/wp-content/uploads/ConnectAzureFunctionsToOffice365Featured.png330780Elliot Munro//gcits.com.au/wp-content/uploads/GCITSlogowordpress.pngElliot Munro2017-04-16 14:04:272017-04-16 16:38:54Connect an Azure Function to Office 365