-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding slide deck / demo content. (#26)
* 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
1 parent
d5e6d02
commit 4be09f7
Showing
12 changed files
with
509 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
~*.pptx |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.