The new permission in Graph API – Sites.Selected – is a step in the right direction. Since long we have been looking for ways of scoping the accesses to live up to the least privilege principle. It was either nothing or everything. I have tried out the new Sites.Selected permission and here are my findings.
First of all, if you haven’t heard about Sites.Selected, please visit these pages to find out more. I am skipping the introduction, since there are already good resources on that out there.
Once you have your Azure AD App and the admin consent for Graph Sites.Selected, all you need is the Azure AD Application Id and Site Collection Administrator on a particular site. The simplest way is to use PnP.PowerShell:
The only way to the application permissions is PowerShell or Graph, there is no indication on the site.
What about governance
A site collection administrator can grant Read or Write permissions on a site. It gives the desired granularity for application access. But on the other side, there is no way (as of writing) to get all the sites that an Azure AD Application has permissions to.
Which leads me to the biggest weakness of the today’s implementation. Of course, we can traverse through all the sites using powershell and get the summary of all application permissions. The problem is that it can be time consuming in a bigger where you have plenty of sites. Also, it requires that your account that runs the script is a Site Collection Administrator on every site, which is a complete opposite of the granularity goal that Sites.Selected permission tries to achieve.
With that you might end up with several applications that have Write permissions to many sites and you might not have any clue wether it is used or not, who has access to those applications and if they need it.
My wish is that:
There will be an api (graph) or azure cli (or similar) that can list all the sites that an application with Sites.Selected has access to, without me being a Site Collection Admin on every site.
There will be transparency in the user interface, so that users and site owners can see which applications can read and write content on their sites, the same way as we can see the members of a site.
They take around 15 minutes to complete, Azure Functions Consumption Plan is limited to 10 minutes. Of course I can split them in several parts, but I am looking for an easy way right now, I have to postpone refactoring because I am not sure if there is a real need for this script solution.
I created a Windows Server 2019 Datacenter Server Core VM to make it as lightweight as possible. I put it in a separate resource group, I didn’t reserve any ip addresses, nor dns names. I disabled even all ports including the RDP to have the highest security.
Size: Standard B1ms
HDD: HDD (no redundancy)
The start logic app (1, 2)
In the same resource group I created a logic app that turns on the VM daily at 00:13 UTC.
Easy, isn’t it.
Once started the vm triggers a scheduled – the Legacy.ps1 script.
In the end of the script there is an http call to my ‘Stop’ logic app:
Obviously, the trigger I use in my next logic app is an http request.
Whenever it is triggered is stops and deallocates the vm.
What does it cost?
I’ll save this discussion for later. Maybe It costs more than serverless applications, for sure, but less than a vm that is on and idle for hours every day. What I propose is a workaround for running huge legacy Windows scripts on Azure, in case you don’t have time to refactor your legacy scripts.
What if you put together Work From Home and Home Automation? Well, removing the common denominator (HOME) would mean Work Automation (sic!). I want to tell you about a tiny hobby project I have had at home, still related to work of mine: Whenever an Azure alert is triggered, my Trådfri smart light from IKEA flashes for a couple of seconds.
Summary (if you want to skip the long story below): The solution is a tiny web application. The publicly accessible url, exposed using ngrok, is registered as a webhook in an Azure Alert. It’s on Github, you’re welcome to use it as you please 😎:
When I was done setting up an alert, I thought: besides a notification in a Teams channel, I thought: what if I could show the alert visually using some LED or similar? Then I thought about Home Automation and a Trådfri RGB bulb I’ve got. That’s the beauty of the mentioned equation: Work From Home and Home Automation. We can pick the best parts of it and combine to something unique.
Since I have a kit from IKEA containing a gateway, a remote, and an RGB lamp, I wanted to do something with that. Unfortunately I didn’t find any routines (Google Home), applets (IFTTT) or automations (Home app in iOS) that could do it.
Luckily, there is a way of controlling the Trådfri lights, best described in this tutorial:
As in this tutorial I also used a Raspberry Pi Zero W, and it went very well, except one thing: Trådfri team introduced a change for the security code, I needed an additional step that was missing, more on that later.
The tutorial says: the world is your lobster. My “lobster” is a webhook that makes lights flash on an alert, so I needed to have a simple web server (http.server) and a tunnel to my network (ngrok). It was best to take one step at a time.
Step 1. Connect
First, I wanted to make sure I could have a simple web server that could host my webhook. I followed the advice from that tutorial and used http.server python module:
I opened that page, (192.168.0.193:8000), and I could see “hej”, time to go further.
Step 2. Connect World
Next step was to open up this “web app” for the world, to make it accessible from outside my local network. ngrok is the best solution for that. I followed that guide to install ngrok on my Raspberry Pi Zero W.
When I knew I could have a simple webhook service, locally (step 1) and on the WWW (step 2), and that I could control the smart light I’ve got from IKEA using code running on my raspberry pi, then connecting everything was easy. I created a repo for that and you can see that it is a very simple one:
The main part is in the server.py. When it gets invoked, it calls the flash function. It uses os.system to call the libcoap-client and time.sleep for delay parts needed in the flash action. The configuration is parsed using configparser and the server is a simple http.server.
In the end I registered the ngrok endpoint in my Azure Alert Rule Action Group:
Then I triggered my test logic app that failed reliably 🙂
This is a game changer: rather than wait for an alert to be triggered, you can just Replay it over and over again while you mickle-muckle your python code locally.
Keep running your server after logout
You just need to to have “nohup” when you start your server, ngrok has already what’s needed: nohup python3 server.py. With that the server will run even when you log out or, your ssh connection disappears.
I’d like to end this post also by saying: The world is your lobster. Try out the flashing lights on Azure Alerts, or why not to replace Azure Alerts with Exoprise Alarms, or some triggers in Power Automate, perhaps, when a new site has popped up 🙂 Or maybe you want to elaborate the flashing behaviour, why not to use Morse code to send a message? Or maybe color-code the different types of alarms/alerts. Once again, the world is your lobster 🦞(or oyster 🦪, well whatever) .
Azure Alerts are awesome for monitoring of solutions in Azure. If you are about to set up your first Alert Rules in Azure, then it’s a guide for you. Configuring alert rules can be quite intimidating at first, with all the options, metrics, evaluation times, etc.
Here is a very very simple setup that can serve as a teaser and help you get started with the Azure Alerts.
I’ll use Teams as an easy way to set up notifications.
The core solution (alert handler) will be an Azure Function, also because it’s fast and easy to set up.
A reliable failing resource
“Reliable failing”, huh? Yes, this oxymoron is the best description of what we are looking for: a resource in Azure that can fail reliably (“fail faster”), so that we can trigger our alerts while developing.
To do that an easy way, we’ll just create a logic app and let it fail all the time.
Run it, and you’ll see how it fails as intended.
When you’re done setting up the alerts, you can remove the failing logic app.
On the other end we need a reliable communication channel.
Let’s pick a channel in a team and create an incoming webhook. I call my webhook alert-hook. (Just to make it easier to follow this guide, it will appear here and there)
Why incoming webhook? Because it is easy to create and send messages to, and also with the right notifications on that channel and the Teams mobile you’ll get the smoothest way of setting up push notifications! Isn’t it great to get your custom alerts directly on you mobile in real time?
When you see the “hello world” from alert-hook in your Teams channel, then you’re ready to proceed with the next step.
Now it’s time to set up the core of that solution – a handler that will receive alerts and pass it to the Teams channel.
Why do we need an Alert Handler? Well, because you can’t send the alerts directly to a Teams channel (or whatever communication channel you choose), they have different schemas. But also, an Alert Handler is an opportunity to make an alert more readable (e.g. by formatting it as an adaptive card), and even filtering out some alerts or parts of them (e.g. in some scenarios only Fired Events (not Resolved) are relevant for notifications).
For the sake of simplicity, let’s just create PowerShell Azure Function in the Azure Portal. Just choose everything latest (in my case it was PowerShell Core 7.0, Consumption Plan, West Europe). If you uncertain, check this post:
We need those 4 steps. I created a simplified diagram of the properties that you need have in mind:
Alert Rule Scope
When you click on “New alert rule”, the Scope will be already defined, it will point to the “Failing Resource”.
Alert Rule Condition
There are so many signals and possibilities. In this guide, just choose “Runs Failed” as a Signal.
In the Alert Logic, select “Greater than or equal”, 1; 5 minutes Granularity Period and 1 minute Frequency of Evaluation. No comment on them right now. Just do it.
When we’re done, re-visit this page and try other things, right now we just want to have an alert directly when our failing resource fails.
Action Group is what gets triggered. It is billed and that’s why it is connected to a Resource Group (it might be another resource group, it does not need to be in the same place as our “Failing Resource”). Just create a new one:
Here is a simplified diagram of an action group:
Action Group Action – Webhook
There are a couple of options for Notifications and Actions to try out. Let’s focus on the Webhook in this guide. In the picture it is called GenericTolleAlertHook.
Copy the Uri from the your function (“Get function url”) and paste it into the Webhook URI.
Important: enable the common alert schema. That will save much of the pain.
Common Alert Schema
The payload in the alert may vary. To make it more predictable for parsing in the alert handler, we just need to enable the common schema, which will be crucial when we will extact and send some data to the Teams channel.
Action Group Bonus Tip: It might be not obvious when you set up it in the Azure Portal, but an alert rule can have 1 or multiple action groups (!). And the other way around: An action group can be used in multiple Alert Rules.
That makes it very flexible, we could create one generic Action Group that notifies Teams and reuse it across alert rules.
Alert Rule Details
The last step is to give the rule a name and description. Keep the Severity as it is right now.
Alert Handler Improvements
We need one more thing to call this guide complete: rather than saying Hello World, we need to have “Alert Fired” and what alert (alert rule name), to make it useful for real.
Let’s re-visit the alert-hook function and make some improvements. Remember the common alert schema? Make sure you enable it in the Alert Rule -> Action Group -> Action. When you do that you will get payloads like these I get:
When you look at them you can see some attributes that we can make use of:
We’ll use the alertRule and monitorCondition properties, that we’ll send in the body of the incoming webhook to Teams:
Let’s test and run. Copy and paste a sample alert payload (with the common alert schema). The links are above.
It should result in a new post in your Teams channel:
A simple alert rule is configured. Enjoy! Discover more and if you would like new challenges here are some tasks that you can try:
Try to update the payload in the Teams incoming webhook to make an adaptive card.
Fired vs. Resolved
It might be good to have different paths for Fired and Resolved. I find it confusing when Resolved Notifications appear alongside with Fired Events. It’s better to suppress the Resolved notifications, or at least format them differently, or maybe even post them as answers to an existing posts (the original Fired posts)?
Azure Alerts are great. Start with a simple set up, see it working and improve continously. An ActionGroup can be reused, you can have a generic Action Group. That makes it easy to set up new alert rules and and you only need to update the action in one place only. Of course, the alert rules can have their specific actions as well, you can connect more than one action group to an alert rule. Use Common Alert Schema to avoid parsing errors and to achieve a generic action group.
Teams is a good notifications destination, especially for your first Alert Rule, it’s easy to set up, does not mean additional costs and (best of all), you and your colleagues can enable notifications the destination channel (channel with your incoming webhook), that way you will be immediately notified when something fails in your Azure Applications, – both on Desktop and in your mobile! Good DevOps, isn’t it?
The steps described in these guides are easy, but that effort made me think about the first pair of pros and cons.
A pipeline variable is faster to configure
A variable in a pipeline takes zero time to set up. Also, A secret variable remains as a secret, since no one can read it in plain text. To configure the Key Vault way of getting secrets requires admin time. Unless you have Admin rights in your Azure Active Directory and your Azure Subscription, you might need to request and argument for one or more of the following:
A service principal (an App registration) with a secret.
An Azure Key Vault (and maybe a resource group) with an Access Policy for the service principal
A service connection in your Azure DevOps Project
Of course, most of it is one-time-job. But still, in many organizations it will require good preparation. The pros for an Azure Key Vault secrets in a pipeline is that
Admins can manage the secrets centrally from Azure
Set it up once and let Azure DevOps people use it and re-use it in many pipelines, but still you need to set up a new Service Connection in every Azure DevOps Project
The fact that it is easier to reuse lets me think of my second pair of pros and cons.
A pipeline secret variable is more secure
Let’s say you need a password to a service account that will upload something important, e.g. an account that will upload a new SPFx package to the SharePoint App Catalog.
Doing it the pipeline variable way means that it remains as a secret on that particular release pipeline. Only release administrators of that project can alter the pipeline steps. No one else.
A tip for productivity: Use Group Variables to share the secrets within a project in Azure DevOps.
Doing it the Key Vault way, means that you must watch out on every part of that chain:
Users who have access to the Key Vault in Azure.
Service Principal that can read the secrets through access policy. Who has access to the secret?
Service Connection in an Azure DevOps Project. Who can use this Service Connection – to add and modify release pipelines? By default, all Release Administrators can do that. To do it more secure, you need to limit the count of Release Administrators. But it means less flexibility in a team and more admin effort for the allowed Release Administrators.
Also, the service principal used for getting the secrets and in the service connection, should not be reused across projects in Azure DevOps. Dedicated Service Principals will make it more secure because misuse can be more easily discovered and stopped – and thats on a project level, not for all service connections.
In flat small organizations, using a Key Vault for using secrets in Azure DevOps Pipelines is great, it saves you time. But it is less secure, and requires time and effort for an appropriate security.
I got my fingers and tried that guide out. This worked good, I spent some time, though, googling (binging) around to get rid of the SSL Warnings for the remote “localhost” on my Mac.
I would like to share this simple instruction on how to trust a self signed certificate from gulp-connect on Mac OS. The implication is that the certificate is on the remote linux machine (on the Visual Studio Environment), that you are connected to through the Visual Studio Code extension.
The first step (after you have connected and set up a project) is to download the certificate. It can be found in the following directory:
These are my favourite tips and tricks. These are only those who me and my colleguages have tried out.
Keep it slim
Functions should do one thing and they should do it well. When you develop it in C# and Visual Studio, it is so tempting to develop a “microservice” in a good way, you add interfaces, implement good patterns, and all of a sudden you get a monolith packaged in a microservice. If your function grows, stop, rethink. Better to see how it input and output bindings can be used. Also orchestration with Logic Apps or Durable Functions can help.
It might be an obvious one, but it is super easy to setup CI/CD for Azure Functions in Azure DevOps. Set it up as early as possible. Don’t rely on publishing from Visual Studio.
Different environments like Production and Staging (Test, UAT, QAT, verification), and DEV are not straight forward anymore, when everything is reactive and micro. But it is good to have at least two setups: one for Production and one for Staging. Especially separating the storage accounts has been proven to be a success story. You can have the same queue name, but different connections. Deploying to Staging and Production will be easier. The functions in different “environments” will write/read a queue with the same name but in different storage accounts.
I also find it convenient to have postfix in the azure function names, like collect-shipments-staging and collect-shipments-production.
If it is possible, use separate resource groups for the “environments”.
Instead of adding queue messages in code, define it as an output. You can even add multiple messages. This saves you instantiating of CloudStorageAccount which is a good thing for performance.
Take Last Run into account
Just check the timer parameter: timer.Schedule.Last for the time when your Azure Function ran last.
This tip is from CloudBurst in Malmö in September 2019. Eventhough your function runs on a consumption plan, the chance is big that your code will run on the same server, which means that you can reuse some resources, like HttpClient.
Recently I have looked more at IoT, Raspberry Pi in my spare time. In my blog post I want to share my experience in a series of posts. This post is about measuring temperature, humidity and pressure with Raspberry Pi 2 Model B and Sense Hat and posting this data to Azure Table Storage.
The python script is on github. Along the way I learned that only python 2.x can be used with azure and table names cannot contain underscore (I got Bad Request error when I tried to create a table with the name “climate_data”). But overall, the process was straightforward. The temperature is not correct, maybe because the sensor is inbetween Raspberry Pi and Sense Hat where it gets warm. But it is just a Proof-of-Concept.