Skip to content

Commit

Permalink
Adding slide deck / demo content. (#26)
Browse files Browse the repository at this point in the history
* adding slide decks

* adding gitignore and new id shields

* adding id sields and gitignore

* updated Slide Deck

* slide deck updated

* updated code

* empty demo files created

* demo code almost ready

* maybe im done?

* Update run.ps1

* updating scaffold

* updating files

* cleaning

* adding video to session

* reorganizing everything

Co-authored-by: Steven Hosking <[email protected]>
  • Loading branch information
tabs-not-spaces and onpremcloudguy authored Jun 25, 2022
1 parent d5e6d02 commit 4be09f7
Show file tree
Hide file tree
Showing 12 changed files with 509 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
~*.pptx
131 changes: 131 additions & 0 deletions BenReader/AAD_Dynamic_Groups/01.AADGraphCode.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#region params
$result = [System.Collections.ArrayList]::new()
$appName = "Notepad++"
$encodedAppName = [System.Web.HttpUtility]::UrlEncode($appName)
$groupId = 'd20a418e-a00f-47a5-a8ed-e12a9d98f83a'
$baseGraphUri = 'https://graph.microsoft.com/beta'
$env:appId = ''
$env:secret = ''
$env:tenant = ''

$cred = (New-Object System.Management.Automation.PSCredential $env:appId, ($env:secret | ConvertTo-SecureString -AsPlainText -Force))
Connect-AzAccount -ServicePrincipal -Credential $cred -Tenant $env:tenant | Out-Null
$token = (Get-AzAccessToken -ResourceUrl 'https://graph.microsoft.com').Token
$script:authHeader = @{Authorization = "Bearer $token" }
#endregion

#region functions
function Invoke-GraphCall {
[cmdletbinding()]
param (
[parameter(Mandatory = $false)]
[ValidateSet('Get', 'Post', 'Delete')]
[string]$Method = 'Get',

[parameter(Mandatory = $false)]
[hashtable]$Headers = $script:authHeader,

[parameter(Mandatory = $true)]
[string]$Uri,

[parameter(Mandatory = $false)]
[string]$ContentType = 'Application/Json',

[parameter(Mandatory = $false)]
[hashtable]$Body
)
try {
$params = @{
Method = $Method
Headers = $Headers
Uri = $Uri
ContentType = $ContentType
}
if ($Body) {
$params.Body = $Body | ConvertTo-Json -Depth 20
}
$query = Invoke-RestMethod @params
return $query
}
catch {
Write-Warning $_.Exception.Message
}
}
function Format-Result {
[cmdletbinding()]
param (
[parameter(Mandatory = $true)]
[string]$DeviceID,

[parameter(Mandatory = $true)]
[string]$DeviceName,

[parameter(Mandatory = $true)]
[bool]$IsCompliant,

[parameter(Mandatory = $true)]
[bool]$IsMember,

[parameter(Mandatory = $true)]
[ValidateSet('Added', 'Removed', 'NoActionTaken')]
[string]$Action
)
$result = [PSCustomObject]@{
DeviceID = $DeviceID
DeviceName = $DeviceName
IsCompliant = $IsCompliant
IsMember = $IsMember
Action = $Action
}
return $result
}
#endregion

#region Get existing group members
$graphUri = "$baseGraphUri/groups/$groupId/members"
$groupMembers = Invoke-GraphCall -Uri $graphUri
#endregion

#region Get devices with notepad++ installed
$detectedAppsBaseUri = "$baseGraphUri/deviceManagement/detectedApps"
$daItem = (Invoke-GraphCall -Uri "$($detectedAppsBaseUri)?`$filter=(contains(displayName,'$([System.Web.HttpUtility]::UrlEncode($encodedAppName))'))").value
if ($daItem.deviceCount -gt 0) {
$detectedDevices = (Invoke-GraphCall -Uri "$detectedAppsBaseUri/$($daItem.id)/managedDevices").value | Select-Object id, deviceName
foreach ($device in $detectedDevices) {
#region Swap the detected device for Intune + AAD object from Intune object
$intuneDevice = Invoke-GraphCall -Uri "$baseGraphUri/deviceManagement/managedDevices/$($device.id)"
$aadDevice = (Invoke-GraphCall -Uri "$baseGraphUri/devices?`$filter=(deviceId eq '$($intuneDevice.azureADDeviceId)')").value
$device | Add-Member -MemberType NoteProperty -Name "deviceId" -Value $aadDevice.deviceId
#endregion
#region add devices
if ($groupMembers.value.deviceId -notcontains $aadDevice.deviceId) {
#region Device not in group and has software
$graphUri = "$baseGraphUri/groups/$groupId/members/`$ref"
$body = @{"@odata.id" = "$baseGraphUri/directoryObjects/$($aadDevice.id)" }
Invoke-GraphCall -Uri $graphUri -Method Post -Body $body
$result.Add($(Format-Result -DeviceId $device.deviceId -DeviceName $device.deviceName -IsCompliant $true -IsMember $true -Action Added)) | Out-Null
#endregion
}
else {
#region device is compliant and already a member
$result.Add($(Format-Result -DeviceId $device.deviceId -DeviceName $device.deviceName -IsCompliant $true -IsMember $true -Action NoActionTaken)) | Out-Null
#endregion
}
#endregion
}
#region Remove devices
$devicesToRemove = $groupMembers.value | Where-Object { $_.deviceId -notIn $detectedDevices.deviceId}
if ($devicesToRemove.count -gt 0) {
foreach ($dtr in $devicesToRemove){
#region Device found in group, but doesnt have software.
$graphUri = "$baseGraphUri/groups/$groupId/members/$($dtr.id)/`$ref"
Invoke-GraphCall -Uri $graphUri -Method Delete
$result.Add($(Format-Result -DeviceId $dtr.deviceId -DeviceName $dtr.displayName -IsCompliant $false -IsMember $false -Action Removed)) | Out-Null
#endregion
}

}
#endregion
}
#endregion
$result
37 changes: 37 additions & 0 deletions BenReader/AAD_Dynamic_Groups/02.SimpleExplanation.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
@baseGraphUri = https://graph.microsoft.com/beta
@groupId = d20a418e-a00f-47a5-a8ed-e12a9d98f83a


### Get the current members of the security group
GET {{baseGraphUri}}/groups/{{groupId}}/members HTTP/1.1
Authorization: Bearer 123...

### Find the detected app
GET {{baseGraphUri}}/deviceManagement/detectedApps?$filter=(displayname, 'notepad++') HTTP/1.1
Authorization: Bearer 123...

### Get the devices from the detected app
GET {{baseGraphUri}}/deviceManagement/detectedApps/{{detectedAppID}}/managedDevices HTTP/1.1
Authorization: Bearer 123...

# Iterate through each device and get the data we need:
### Intune Device
GET {{baseGraphUri}}/deviceManagement/detectedApps/{{detectedAppID}}/managedDevices/{{IntuneID}} HTTP/1.1
Authorization: Bearer 123...

### AAD Device ID
GET {{baseGraphUri}}/devices?$filter=(deviceId eq '{{IntuneDeviceAadDeviceId}}') HTTP/1.1
Authorization: Bearer 123...

# Now we have all the data. do the logic
### Add to group
POST {{baseGraphUri}}/groups/{{groupId}}/members/$ref HTTP/1.1
Authorization: Bearer 123...

{
"@odata.id": "$baseGraphUri/directoryObjects/{{AADDeviceID}})"
}

### OR Delete from group
DELETE {{baseGraphUri}}/groups/{{groupId}}/members/{{AADDeviceId}}/$ref HTTP/1.1
Authorization: Bearer 123..
98 changes: 98 additions & 0 deletions BenReader/AAD_Dynamic_Groups/99.AadMsiRoles.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
Connect-AzAccount -UseDeviceAuthentication
$script:token = (Get-AzAccessToken -ResourceUrl 'https://graph.microsoft.com').Token

#region functions
function Add-GraphApiRoleToMSI {
[cmdletbinding()]
param (
[parameter(Mandatory = $true)]
[string]$ApplicationName,

[parameter(Mandatory = $true)]
[string[]]$GraphApiRole
)

$baseUri = 'https://graph.microsoft.com/v1.0/servicePrincipals'
$graphAppId = '00000003-0000-0000-c000-000000000000'
$spSearchFiler = '"displayName:{0}" OR "appId:{1}"' -f $ApplicationName, $graphAppId

try {
$msiParams = @{
Method = 'Get'
Uri = '{0}?$search={1}' -f $baseUri, $spSearchFiler
Headers = @{Authorization = "Bearer $script:token"; ConsistencyLevel = "eventual" }
}
$spList = (Invoke-RestMethod @msiParams).Value
$msiId = ($spList | Where-Object { $_.displayName -eq $applicationName }).Id
$graphId = ($spList | Where-Object { $_.appId -eq $graphAppId }).Id
$msiItem = Invoke-RestMethod @msiParams -Uri "$($baseUri)/$($msiId)?`$expand=appRoleAssignments"

$graphRoles = (Invoke-RestMethod @msiParams -Uri "$baseUri/$($graphId)/appRoles").Value |
Select-Object AllowedMemberTypes, id, value
foreach ($role in $GraphApiRole) {
$roleItem = $graphRoles | Where-Object { $_.value -eq $role }
if ($roleItem.id -notIn $msiItem.appRoleAssignments.appRoleId) {
Write-Host "Adding role ($($roleItem.value)) to identity: $($applicationName).."
$params = @{
managedIdentityId = $msiId
graphId = $graphId
apiRoleId = $roleItem.id
token = $script:token
}
Send-RoleToMSI @params
}
else {
Write-Host "role ($($roleItem.value)) already found in $($applicationName).."
}
}

}
catch {
Write-Warning $_.Exception.Message
}

}
function Send-RoleToMSI {
[cmdletbinding()]
param (
[parameter(Mandatory = $true)]
[string]$managedIdentityId,

[parameter(Mandatory = $true)]
[string]$graphId,

[parameter(Mandatory = $true)]
[string]$apiRoleId,

[parameter(Mandatory = $true)]
[string]$token
)
try {
$baseUri = 'https://graph.microsoft.com/v1.0/servicePrincipals'
$body = @{
"principalId" = $managedIdentityId
"resourceId" = $graphId
"appRoleId" = $apiRoleId
} | ConvertTo-Json
$restParams = @{
Method = "Post"
Uri = "$baseUri/$($graphId)/appRoleAssignedTo"
Body = $body
Headers = @{Authorization = "Bearer $script:token" }
ContentType = 'Application/Json'
}
$roleRequest = Invoke-RestMethod @restParams
return $roleRequest
}
catch {
Write-Warning $_.Exception.Message
}
}
#endregion

$roles = @(
"GroupMember.ReadWrite.All"
"Device.Read.All"
"DeviceManagementManagedDevices.Read.All"
)
Add-GraphApiRoleToMSI -ApplicationName "PSCONFEU2022-AADDEMO" -GraphApiRole $roles
Binary file added BenReader/AAD_Dynamic_Groups/NewFunctionApp.mp4
Binary file not shown.
Binary file not shown.
Binary file not shown.
5 changes: 5 additions & 0 deletions BenReader/PowerShell_Intune_Measure_Once/demo1.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
. wt

#region CHEAT SHEET
Build-IntuneConfigReport -Tenant Intune.training -OutputFolder "C:\data\reports\"
#endregion
22 changes: 22 additions & 0 deletions BenReader/PowerShell_Intune_Measure_Once/demo2.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
$baseUri = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts"
$token = Get-MsalToken -TenantId 'intune.training' -ClientId "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" -DeviceCode

#region list all the scripts
$header = @{ Authorization = $token.CreateAuthorizationHeader() }
$params = @{
Method = "Get"
Uri = "$baseUri"
Headers = $header
ContentType = 'Application/Json'
}
$result = Invoke-RestMethod @params
$result.value
#endregion

#region get the script fron the policy
$scriptId = ($result.value | Where-Object { $_.displayName -eq 'VeryImportantScript'}).id
$scriptUri = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts/$scriptId"
$scriptContent = (Invoke-RestMethod @params -Uri $scriptUri).scriptContent
$decodedContent = [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String("$($scriptContent)"))
$decodedContent
#endregion
56 changes: 56 additions & 0 deletions BenReader/PowerShell_Intune_Measure_Once/demo3.0.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
Connect-AzAccount
$baseUri = "https://graph.microsoft.com/beta/deviceManagement/auditEvents"
$token = Get-MsalToken -TenantId 'intune.training' -ClientId "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" -DeviceCode

#region Look at all "PowerShell" create events
$alertFilter = "?`$filter=(activityOperationType eq 'Create' and activityType eq 'createDeviceManagementScript DeviceManagementScript')"
$header = @{ Authorization = $token.CreateAuthorizationHeader() }
$params = @{
Method = "Get"
Uri = "$($baseUri)$alertFilter"
Headers = $header
ContentType = 'Application/Json'
}
$result = Invoke-RestMethod @params
$result.value
#endregion

#region show me scripts added by the intern in the last day
$dateRange = [datetime]::now.AddDays(-1).ToUniversalTime().ToString("yyyy-MM-dd")
$alertFilter = "?`$filter=(activityOperationType eq 'Create' and activityType eq 'createDeviceManagementScript DeviceManagementScript' and activityDateTime gt $dateRange)"
$result = Invoke-RestMethod @params -Uri "$($baseUri)$alertFilter"
$naughtyScript = $result.value | Where-Object { $_.actor.userPrincipalName -eq "[email protected]" }
$scriptId = $naughtyScript.resources.resourceId
#endregion

#region get the script fron the policy
$scriptUri = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts/$scriptId"
$scriptContent = Invoke-RestMethod @params -Uri $scriptUri
$decodedContent = [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String("$($scriptContent)"))
$decodedContent
#endregion

#region get the scripts fron the policy
foreach ($script in $naughtyScript){
$scriptUri = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts/$($script.resources.resourceId)"
$params = @{
Method = "Get"
Uri = $scriptUri
Headers = $header
ContentType = 'Application/Json'
}
$scriptContent = (Invoke-RestMethod @params)
$decodedContent = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("$($scriptContent.scriptContent)"))
$tempFile = New-TemporaryFile
$decodedContent | Out-File $tempFile -Force -Encoding utf8

Write-Output "Getting storage context.."
$ctx = New-AzStorageContext -ConnectionString $env:AzureWebJobsStorage
Write-Output "Getting storage container.. $($env:AZURE_CONTAINER)"
$container = (Get-AzStorageContainer -Name $env:AZURE_CONTAINER -Context $ctx).CloudBlobContainer
Write-Output "uploading file.."
$result = Set-AzStorageBlobContent -File $tempFile -Blob $scriptContent.fileName -Container $container.Name -Context $ctx
$result
Send-TeamsMessage -ActorUpn $script.actor.userPrincipalName -ScriptDisplayName $scriptContent.displayName -UrlToScript $result.ICloudBlob.Uri.AbsoluteUri
}
#endregion
Loading

0 comments on commit 4be09f7

Please sign in to comment.