AzureAD Conditional Access ‘Block All except’ selected Apps and MyApps

Azure AD conditional access policies are a key part of O365 security. A common requirement is to be able to apply a policy to all applications, with exceptions for a few selected allocations. The most common use case is as a ‘block’ rule, with the exceptions used to whitelist applications. While you can do this already, by using ‘All’ in the list of applications the policy applies to, this has the side effect of blocking the MyApps portal. Microsoft have recently added MyApps as an application that can be added to CA policies, but it currently (June 2021) doesn’t work. This link is to the Microsoft feedback site where people are asking for this to be fixed :

https://feedback.azure.com/forums/169401-azure-active-directory/suggestions/19738183-support-conditional-access-for-myapps-microsoft-co

The only way to create a policy is to add all of the applications that should be blocked to the ‘includeApplications’ list of the policy manually. This quickly gets impossible to managed in a tenant with many applications. It also means that where there are several different policies, with exceptions for different groups or conditions, they must all be updated manually when a new Enterprise Application is added to the tenant.

This workaround uses Powershell to make calls to the Microsoft Graph REST API to maintain the list of applications in the CA Policies.

WARNING: It is possible to create a CA Policy that blocks ALL access to a Tenant, including Global Administrators. As this code manipulates CA policies it should be used with caution!

Setup

There are a few things that you need to setup in your AzureAD to get this to work:

  • Create an Application Registration, used to assign permissions for the Powershell script to access the Graph REST API
  • Note the Application ID
  • Create a Client secret and make a note of it. (AzureAD only displays this at creation)
  • Assign the following Application API Permissions, in the Graph section:
    • Application.Read.All
    • Policy.Read.All
    • Policy.ReadWrite.ConditionalAccess
  • Create an Enterprise Application. The name doesn’t actually matter, but I used ‘AAAL – Automated All Apps List’. Make a note of the Application ID
  • Create a Conditional Access policy for testing. I’d suggest creating it in Report only mode. Add the AAAL application to the Included applications and one or two applications to ‘Exclude’.
  • Edit the script and update the App Id (for the app registration), Client secret and the AAAL Application ID.

##############################################################################
# Variables
##############################################################################

$AppId = '< Application ID from Azure AD App Registration>'
$AppSecret = '< Application ID from Azure AD App Registration>'

# App ID of AAAL Enterprise App
$AAALiD = "< Application ID of AAAL Enterprise Application"

# Add System.Web for urlencode
Add-Type -AssemblyName System.Web

##############################################################################
# Garph REST API Token
##############################################################################
$Url = "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token"
$Scope = "https://graph.microsoft.com/.default"

# Create body
$Body = @{
    client_id = $AppId
	client_secret = $AppSecret
	scope = $Scope
	grant_type = 'client_credentials'
}

# Splat the parameters for Invoke-Restmethod for cleaner code
$PostSplat = @{
    ContentType = 'application/x-www-form-urlencoded'
    Method = 'POST'
    Body = $Body
    Uri = $Url
}

# Request the token
$Request = Invoke-RestMethod @PostSplat

# Create header
$Header = @{
    Authorization = "$($Request.token_type) $($Request.access_token)"
}

##########################################################################
# Applications
##########################################################################
# Fetch all Applications from AAD
$Uri = "https://graph.microsoft.com/v1.0/applications"
$Applications = $null
$Applications = Invoke-RestMethod -Uri $Uri -Headers $Header -Method Get -ContentType "application/json"

##########################################################################
# CA Policies
##########################################################################
# Fetch Guest CA Policies
$Uri = "https://graph.microsoft.com/V1.0/identity/conditionalAccess/policies"
$CAPolicies = $null
$CAPolicies = Invoke-RestMethod -Uri $Uri -Headers $Header -Method Get -ContentType "application/json"
foreach($CAPolicy in $CAPolicies.value){
# Search for AAAL and Expand
$Include = $null
$Include = $CAPolicy.conditions.applications.includeApplications
if($Include -contains $AAALiD){
    $Exclude = $null
    $Exclude = $CAPolicy.conditions.applications.excludeApplications
    # Comment out the following line Add to exiting list, Uncomment to replace
    # e.g. if you want O365 Apps in the list as well as Ent Aps 
    $Include = @($AAALiD)
    foreach($Application in $Applications.value){
        if($Exclude -notcontains $Application.appId){
            # Add if not on the include list already
            if($Include -notcontains $Application.appId){
                  $Include += $Application.appId
                  }
            }
        }
    write-output "Updating Policy " $CApolicy.displayName
    #Patch the CA Policy
    $Uri = "https://graph.microsoft.com/V1.0/identity/conditionalAccess/policies/" + $CAPolicy.id 
    $RequestBody = @{
                    conditions =@{
                                applications =@{
                                              includeApplications = @( $Include )
                                               }
                                 }
                    }                
    $RequestBodyJSON = $RequestBody | ConvertTo-Json -Depth 3 
    $PatchedPolicy = Invoke-RestMethod -Method Patch -Headers $Header -Uri $Uri -Body $RequestBodyJSON -ContentType "application/json"
    }
}

Sharp Dust Sensor Update – Adding a Temperature sensor.

Bruce Ford suggested that I looked at a paper on using these sensors for PM monitoring. One point of interest is that the sensor output has some link to ambient temperature, so this update adds a TMP36 sensor to the stripboard.

It’s a fairly simple addition, one 3-pin device and a wire to the A1 input on the Nano.

Parts List:

In addition to the parts listed in the previous post : http://connectranet.co.uk/wp/2016/09/23/sharp-dust-sensor-arduino-nano-and-2×16-lcd

  • TMP36 Sensor (TO-92 Package)

http://www.analog.com/media/en/technical-documentation/data-sheets/TMP35_36_37.pdf

 Diagram:

 

Add the TMP36 to the strip board…

Pin 1  to row 8 of the stripboard (+5v)

Pin2 to row 7 (temp sensor output)

Pin3 to row 9 (Gnd)

then add a wire from Row 7 to A1 on the Nano.

 

The Temperature can then be read from A1 using AnolgRead(1).

The output voltage of the TMP36 is 10mV / degree + 0.5v so 25c = 0.750v

temp = ((analogRead(1) * 5 /1024)-0.5)*100;

using the Temperature reading

I don’t have any information or calibration data that suggests how to adjust the reading to account for temperature so the next step is to try  sealing the sensor with clear tape to keep the dust level inside constant, then vary the temperature to see how this varies the dust sensor output.