diff --git a/Applications/Application_Detected_Apps_Get.ps1 b/Applications/Application_Detected_Apps_Get.ps1 new file mode 100644 index 0000000..97a3ebb --- /dev/null +++ b/Applications/Application_Detected_Apps_Get.ps1 @@ -0,0 +1,287 @@ + +<# + +.COPYRIGHT +Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +See LICENSE in the project root for license information. + +#> + +#################################################### + +function Get-AuthToken { + +<# +.SYNOPSIS +This function is used to authenticate with the Graph API REST interface +.DESCRIPTION +The function authenticate with the Graph API Interface with the tenant name +.EXAMPLE +Get-AuthToken +Authenticates you with the Graph API interface +.NOTES +NAME: Get-AuthToken +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + $User +) + +$userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User + +$tenant = $userUpn.Host + +Write-Host "Checking for AzureAD module..." + + $AadModule = Get-Module -Name "AzureAD" -ListAvailable + + if ($AadModule -eq $null) { + + Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview" + $AadModule = Get-Module -Name "AzureADPreview" -ListAvailable + + } + + if ($AadModule -eq $null) { + write-host + write-host "AzureAD Powershell module not installed..." -f Red + write-host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow + write-host "Script can't continue..." -f Red + write-host + exit + } + +# Getting path to ActiveDirectory Assemblies +# If the module count is greater than 1 find the latest version + + if($AadModule.count -gt 1){ + + $Latest_Version = ($AadModule | select version | Sort-Object)[-1] + + $aadModule = $AadModule | ? { $_.version -eq $Latest_Version.version } + + # Checking if there are multiple versions of the same module found + + if($AadModule.count -gt 1){ + + $aadModule = $AadModule | select -Unique + + } + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + + else { + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + +[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null + +[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null + +$clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" + +$redirectUri = "urn:ietf:wg:oauth:2.0:oob" + +$resourceAppIdURI = "https://graph.microsoft.com" + +$authority = "https://login.microsoftonline.com/$Tenant" + + try { + + $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority + + # https://msdn.microsoft.com/en-us/library/azure/microsoft.identitymodel.clients.activedirectory.promptbehavior.aspx + # Change the prompt behaviour to force credentials each time: Auto, Always, Never, RefreshSession + + $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto" + + $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId") + + $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result + + # If the accesstoken is valid then create the authentication header + + if($authResult.AccessToken){ + + # Creating header for Authorization token + + $authHeader = @{ + 'Content-Type'='application/json' + 'Authorization'="Bearer " + $authResult.AccessToken + 'ExpiresOn'=$authResult.ExpiresOn + } + + return $authHeader + + } + + else { + + Write-Host + Write-Host "Authorization Access Token is null, please re-run authentication..." -ForegroundColor Red + Write-Host + break + + } + + } + + catch { + + write-host $_.Exception.Message -f Red + write-host $_.Exception.ItemName -f Red + write-host + break + + } + +} + +#################################################### + +Function Get-DetectedApps(){ + +<# +.SYNOPSIS +This function is used to get Managed Devices from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets Managed Devices +.EXAMPLE +Get-ManagedDevices +Returns Managed Devices configured in Intune +.NOTES +NAME: Get-ManagedDevices +#> + +[cmdletbinding()] + +$graphApiVersion = "Beta" +$Resource = "deviceManagement/detectedApps" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + + $DetectedAppsResponse = (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get) + + + $DetectedApps = $DetectedAppsResponse.value + + $DetectedAppsNextLink = $DetectedAppsResponse."@odata.nextLink" + + while ($DetectedAppsNextLink -ne $null){ + + $DetectedAppsResponse = (Invoke-RestMethod -Uri $DetectedAppsNextLink -Headers $authToken -Method Get) + $DetectedAppsNextLink = $DetectedAppsResponse."@odata.nextLink" + $DetectedApps += $DetectedAppsResponse.value + + } + + return $DetectedApps + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +#region Authentication + +write-host + +# Checking if authToken exists before running authentication +if($global:authToken){ + + # Setting DateTime to Universal time to work in all timezones + $DateTime = (Get-Date).ToUniversalTime() + + # If the authToken exists checking when it expires + $TokenExpires = ($authToken.ExpiresOn.datetime - $DateTime).Minutes + + if($TokenExpires -le 0){ + + write-host "Authentication Token expired" $TokenExpires "minutes ago" -ForegroundColor Yellow + write-host + + # Defining User Principal Name if not present + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + + $global:authToken = Get-AuthToken -User $User + + } +} + +# Authentication doesn't exist, calling Get-AuthToken function + +else { + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + +# Getting the authorization token +$global:authToken = Get-AuthToken -User $User + +} + +#endregion + +#################################################### + +$DetectedApps = Get-DetectedApps + +if($DetectedApps){ + + foreach($detectedApp in $DetectedApps){ + + write-host "Detected app" $detectedApp.displayName "found..." -ForegroundColor Yellow + Write-Host + $detectedApp + + } + +} + +else { + +Write-Host +Write-Host "No detected apps found..." -ForegroundColor Red +Write-Host + +} + + \ No newline at end of file diff --git a/Applications/Application_MDM_Export.ps1 b/Applications/Application_MDM_Export.ps1 index a2584ba..c88c556 100644 --- a/Applications/Application_MDM_Export.ps1 +++ b/Applications/Application_MDM_Export.ps1 @@ -192,7 +192,7 @@ $Resource = "deviceAppManagement/mobileApps" else { $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" - (Invoke-RestMethod -Uri $uri –Headers $authToken –Method Get).Value | ? { (!($_.'@odata.type').Contains("managed")) -and (!($_.'@odata.type').Contains("#microsoft.graph.iosVppApp")) -and (!($_.'@odata.type').Contains("#microsoft.graph.windowsAppX")) -and (!($_.'@odata.type').Contains("#microsoft.graph.androidForWorkApp")) -and (!($_.'@odata.type').Contains("#microsoft.graph.windowsMobileMSI")) -and (!($_.'@odata.type').Contains("#microsoft.graph.androidLobApp")) -and (!($_.'@odata.type').Contains("#microsoft.graph.iosLobApp")) -and (!($_.'@odata.type').Contains("#microsoft.graph.microsoftStoreForBusinessApp")) } + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value | ? { (!($_.'@odata.type').Contains("managed")) -and (!($_.'@odata.type').Contains("#microsoft.graph.iosVppApp")) -and (!($_.'@odata.type').Contains("#microsoft.graph.windowsAppX")) -and (!($_.'@odata.type').Contains("#microsoft.graph.androidForWorkApp")) -and (!($_.'@odata.type').Contains("#microsoft.graph.windowsMobileMSI")) -and (!($_.'@odata.type').Contains("#microsoft.graph.androidLobApp")) -and (!($_.'@odata.type').Contains("#microsoft.graph.iosLobApp")) -and (!($_.'@odata.type').Contains("#microsoft.graph.microsoftStoreForBusinessApp")) } } @@ -422,4 +422,4 @@ else { Write-Host "No MDM Applications added to the Intune Service..." -ForegroundColor Red Write-Host -} \ No newline at end of file +} diff --git a/Applications/Application_iOS_Add.ps1 b/Applications/Application_iOS_Add.ps1 index b1c65b6..caea574 100644 --- a/Applications/Application_iOS_Add.ps1 +++ b/Applications/Application_iOS_Add.ps1 @@ -151,75 +151,76 @@ $authority = "https://login.microsoftonline.com/$Tenant" Function Get-itunesApplication(){ -<# -.SYNOPSIS -This function is used to get an iOS application from the itunes store using the Apple REST API interface -.DESCRIPTION -The function connects to the Apple REST API Interface and returns applications from the itunes store -.EXAMPLE -Get-itunesApplication -SearchString "Microsoft Corporation" -Gets an iOS application from itunes store -.EXAMPLE -Get-itunesApplication -SearchString "Microsoft Corporation" -Limit 10 -Gets an iOS application from itunes store with a limit of 10 results -.NOTES -NAME: Get-itunesApplication -https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/ -#> - -[cmdletbinding()] - -param -( - [Parameter(Mandatory=$true)] - $SearchString, - [int]$Limit -) - - try{ - - Write-Verbose $SearchString - - # Testing if string contains a space and replacing it with a + - $SearchString = $SearchString.replace(" ","+") - - Write-Verbose "SearchString variable converted if there is a space in the name $SearchString" - - if($Limit){ - - $iTunesUrl = "https://itunes.apple.com/search?entity=software&term=$SearchString&attribute=softwareDeveloper&limit=$limit" - + <# + .SYNOPSIS + This function is used to get an iOS application from the itunes store using the Apple REST API interface + .DESCRIPTION + The function connects to the Apple REST API Interface and returns applications from the itunes store + .EXAMPLE + Get-itunesApplication -SearchString "Microsoft Corporation" + Gets an iOS application from itunes store + .EXAMPLE + Get-itunesApplication -SearchString "Microsoft Corporation" -Limit 10 + Gets an iOS application from itunes store with a limit of 10 results + .NOTES + NAME: Get-itunesApplication + https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/ + #> + + [cmdletbinding()] + + param + ( + [Parameter(Mandatory=$true)] + $SearchString, + [int]$Limit + ) + + try{ + + Write-Verbose $SearchString + + # Testing if string contains a space and replacing it with %20 + $SearchString = $SearchString.replace(" ","%20") + + Write-Verbose "SearchString variable converted if there is a space in the name $SearchString" + + if($Limit){ + + $iTunesUrl = "https://itunes.apple.com/search?country=us&media=software&entity=software,iPadSoftware&term=$SearchString&limit=$limit" + + } + + else { + + $iTunesUrl = "https://itunes.apple.com/search?country=us&entity=software&term=$SearchString&attribute=softwareDeveloper" + + } + + write-verbose $iTunesUrl + + $apps = Invoke-RestMethod -Uri $iTunesUrl -Method Get + + # Putting sleep in so that no more than 20 API calls to itunes REST API + # https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/ + Start-Sleep 3 + + return $apps + } - - else { - - $iTunesUrl = "https://itunes.apple.com/search?entity=software&term=$SearchString&attribute=softwareDeveloper" - + + catch { + + write-host $_.Exception.Message -f Red + write-host $_.Exception.ItemName -f Red + write-verbose $_.Exception + write-host + break + } - - write-verbose $iTunesUrl - $apps = Invoke-RestMethod -Uri $iTunesUrl -Method Get - - # Putting sleep in so that no more than 20 API calls to itunes REST API - # https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/ - sleep 3 - - return $apps - - } - - catch { - - write-host $_.Exception.Message -f Red - write-host $_.Exception.ItemName -f Red - write-verbose $_.Exception - write-host - break - + } -} - #################################################### Function Add-iOSApplication(){ @@ -315,15 +316,16 @@ Function Add-iOSApplication(){ iPad=$iPad; iPhoneAndIPod=$iPhone; }; - minimumSupportedOperatingSystem=@{ + minimumSupportedOperatingSystem=@{ v8_0=$osVersion -lt 9.0; - v9_0=$osVersion -eq 9.0; - v10_0=$osVersion -gt 9.0; + v9_0=$osVersion.ToString().StartsWith(9) + v10_0=$osVersion.ToString().StartsWith(10) + v11_0=$osVersion.ToString().StartsWith(11) + v12_0=$osVersion.ToString().StartsWith(12) + v13_0=$osVersion.ToString().StartsWith(13) }; }; - $JSON = ConvertTo-Json $graphApp - # Step 3 - Publish the application to Graph Write-Host "Creating application via Graph" $createResult = Invoke-RestMethod -Uri $uri -Method Post -ContentType "application/json" -Body (ConvertTo-Json $graphApp) -Headers $authToken diff --git a/Applications/Application_iOS_Add_Assign.ps1 b/Applications/Application_iOS_Add_Assign.ps1 index 729afb2..93ae86b 100644 --- a/Applications/Application_iOS_Add_Assign.ps1 +++ b/Applications/Application_iOS_Add_Assign.ps1 @@ -151,210 +151,211 @@ $authority = "https://login.microsoftonline.com/$Tenant" Function Get-itunesApplication(){ -<# -.SYNOPSIS -This function is used to get an iOS application from the itunes store using the Apple REST API interface -.DESCRIPTION -The function connects to the Apple REST API Interface and returns applications from the itunes store -.EXAMPLE -Get-itunesApplication -SearchString "Microsoft Corporation" -Gets an iOS application from itunes store -.EXAMPLE -Get-itunesApplication -SearchString "Microsoft Corporation" -Limit 10 -Gets an iOS application from itunes store with a limit of 10 results -.NOTES -NAME: Get-itunesApplication -#> - -[cmdletbinding()] - -param -( - [Parameter(Mandatory=$true)] - $SearchString, - [int]$Limit -) - - try{ - - Write-Verbose $SearchString - - # Testing if string contains a space and replacing it with a + - $SearchString = $SearchString.replace(" ","+") - - Write-Verbose "SearchString variable converted if there is a space in the name $SearchString" - - if($Limit){ - - $iTunesUrl = "https://itunes.apple.com/search?entity=software&term=$SearchString&attribute=softwareDeveloper&limit=$limit" + <# + .SYNOPSIS + This function is used to get an iOS application from the itunes store using the Apple REST API interface + .DESCRIPTION + The function connects to the Apple REST API Interface and returns applications from the itunes store + .EXAMPLE + Get-itunesApplication -SearchString "Microsoft Corporation" + Gets an iOS application from itunes store + .EXAMPLE + Get-itunesApplication -SearchString "Microsoft Corporation" -Limit 10 + Gets an iOS application from itunes store with a limit of 10 results + .NOTES + NAME: Get-itunesApplication + https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/ + #> + + [cmdletbinding()] + + param + ( + [Parameter(Mandatory=$true)] + $SearchString, + [int]$Limit + ) + + try{ + + Write-Verbose $SearchString + + # Testing if string contains a space and replacing it with %20 + $SearchString = $SearchString.replace(" ","%20") + + Write-Verbose "SearchString variable converted if there is a space in the name $SearchString" + + if($Limit){ + + $iTunesUrl = "https://itunes.apple.com/search?country=us&media=software&entity=software,iPadSoftware&term=$SearchString&limit=$limit" + + } + + else { + + $iTunesUrl = "https://itunes.apple.com/search?country=us&entity=software&term=$SearchString&attribute=softwareDeveloper" + + } + + write-verbose $iTunesUrl + + $apps = Invoke-RestMethod -Uri $iTunesUrl -Method Get + + # Putting sleep in so that no more than 20 API calls to itunes REST API + # https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/ + Start-Sleep 3 + + return $apps } - - else { - - $iTunesUrl = "https://itunes.apple.com/search?entity=software&term=$SearchString&attribute=softwareDeveloper" - - } - - write-verbose $iTunesUrl - $apps = Invoke-RestMethod -Uri $iTunesUrl -Method Get - - # Putting sleep in so that no more than 20 API calls to itunes API - sleep 3 - - return $apps - } + catch { + + write-host $_.Exception.Message -f Red + write-host $_.Exception.ItemName -f Red + write-verbose $_.Exception + write-host + break + + } - catch { - - write-host $_.Exception.Message -f Red - write-host $_.Exception.ItemName -f Red - write-verbose $_.Exception - write-host - break - } -} - #################################################### Function Add-iOSApplication(){ - -<# -.SYNOPSIS -This function is used to add an iOS application using the Graph API REST interface -.DESCRIPTION -The function connects to the Graph API Interface and adds an iOS application from the itunes store -.EXAMPLE -Add-iOSApplication -AuthHeader $AuthHeader -Adds an iOS application into Intune from itunes store -.NOTES -NAME: Add-iOSApplication -#> - -[cmdletbinding()] - -param -( - $itunesApp -) - -$graphApiVersion = "Beta" -$Resource = "deviceAppManagement/mobileApps" - try { + <# + .SYNOPSIS + This function is used to add an iOS application using the Graph API REST interface + .DESCRIPTION + The function connects to the Graph API Interface and adds an iOS application from the itunes store + .EXAMPLE + Add-iOSApplication -AuthHeader $AuthHeader + Adds an iOS application into Intune from itunes store + .NOTES + NAME: Add-iOSApplication + #> - $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + [cmdletbinding()] + + param + ( + $itunesApp + ) + + $graphApiVersion = "Beta" + $Resource = "deviceAppManagement/mobileApps" - $app = $itunesApp - - Write-Verbose $app + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" - Write-Host "Publishing $($app.trackName)" -f Yellow - - # Step 1 - Downloading the icon for the application - $iconUrl = $app.artworkUrl60 - - if ($iconUrl -eq $null){ - - Write-Host "60x60 icon not found, using 100x100 icon" - $iconUrl = $app.artworkUrl100 + $app = $itunesApp + + Write-Verbose $app + + Write-Host "Publishing $($app.trackName)" -f Yellow + + # Step 1 - Downloading the icon for the application + $iconUrl = $app.artworkUrl60 + + if ($iconUrl -eq $null){ + + Write-Host "60x60 icon not found, using 100x100 icon" + $iconUrl = $app.artworkUrl100 + + } + + if ($iconUrl -eq $null){ + + Write-Host "60x60 icon not found, using 512x512 icon" + $iconUrl = $app.artworkUrl512 + + } + + $iconResponse = Invoke-WebRequest $iconUrl + $base64icon = [System.Convert]::ToBase64String($iconResponse.Content) + $iconType = $iconResponse.Headers["Content-Type"] + + if(($app.minimumOsVersion.Split(".")).Count -gt 2){ + + $Split = $app.minimumOsVersion.Split(".") + + $MOV = $Split[0] + "." + $Split[1] + + $osVersion = [Convert]::ToDouble($MOV) + + } + + else { + + $osVersion = [Convert]::ToDouble($app.minimumOsVersion) + + } + + # Setting support Operating System Devices + if($app.supportedDevices -match "iPadMini"){ $iPad = $true } else { $iPad = $false } + if($app.supportedDevices -match "iPhone6"){ $iPhone = $true } else { $iPhone = $false } + + # Step 2 - Create the Hashtable Object of the application + $description = $app.description -replace "[^\x00-\x7F]+","" + + $graphApp = @{ + "@odata.type"="#microsoft.graph.iosStoreApp"; + displayName=$app.trackName; + publisher=$app.artistName; + description=$description; + largeIcon= @{ + type=$iconType; + value=$base64icon; + }; + isFeatured=$false; + appStoreUrl=$app.trackViewUrl; + applicableDeviceType=@{ + iPad=$iPad; + iPhoneAndIPod=$iPhone; + }; + minimumSupportedOperatingSystem=@{ + v8_0=$osVersion -lt 9.0; + v9_0=$osVersion.ToString().StartsWith(9) + v10_0=$osVersion.ToString().StartsWith(10) + v11_0=$osVersion.ToString().StartsWith(11) + v12_0=$osVersion.ToString().StartsWith(12) + v13_0=$osVersion.ToString().StartsWith(13) + }; + }; + + # Step 3 - Publish the application to Graph + Write-Host "Creating application via Graph" + $createResult = Invoke-RestMethod -Uri $uri -Method Post -ContentType "application/json" -Body (ConvertTo-Json $graphApp) -Headers $authToken + Write-Host "Application created as $uri/$($createResult.id)" + write-host } - if ($iconUrl -eq $null){ - - Write-Host "60x60 icon not found, using 512x512 icon" - $iconUrl = $app.artworkUrl512 + catch { + + $ex = $_.Exception + Write-Host "Request to $Uri failed with HTTP Status $([int]$ex.Response.StatusCode) $($ex.Response.StatusDescription)" -f Red + + $errorResponse = $ex.Response.GetResponseStream() - } - - $iconResponse = Invoke-WebRequest $iconUrl - $base64icon = [System.Convert]::ToBase64String($iconResponse.Content) - $iconType = $iconResponse.Headers["Content-Type"] - - if(($app.minimumOsVersion.Split(".")).Count -gt 2){ - - $Split = $app.minimumOsVersion.Split(".") - - $MOV = $Split[0] + "." + $Split[1] - - $osVersion = [Convert]::ToDouble($MOV) - - } - - else { - - $osVersion = [Convert]::ToDouble($app.minimumOsVersion) - - } - - # Setting support Operating System Devices - if($app.supportedDevices -match "iPadMini"){ $iPad = $true } else { $iPad = $false } - if($app.supportedDevices -match "iPhone6"){ $iPhone = $true } else { $iPhone = $false } - - # Step 2 - Create the Hashtable Object of the application - - $description = $app.description -replace "[^\x00-\x7F]+","" - - $graphApp = @{ - "@odata.type"="#microsoft.graph.iosStoreApp"; - displayName=$app.trackName; - publisher=$app.artistName; - description=$description; - largeIcon= @{ - type=$iconType; - value=$base64icon; - }; - isFeatured=$false; - appStoreUrl=$app.trackViewUrl; - applicableDeviceType=@{ - iPad=$iPad; - iPhoneAndIPod=$iPhone; - }; - minimumSupportedOperatingSystem=@{ - v8_0=$osVersion -lt 9.0; - v9_0=$osVersion -eq 9.0; - v10_0=$osVersion -gt 9.0; - }; - }; - - $JSON = ConvertTo-Json $graphApp - - # Step 3 - Publish the application to Graph - Write-Host "Creating application via Graph" - $createResult = Invoke-RestMethod -Uri $uri -Method Post -ContentType "application/json" -Body (ConvertTo-Json $graphApp) -Headers $authToken - Write-Host "Application created as $uri/$($createResult.id)" - write-host - - return $createResult + $ex.Response.GetResponseStream() - } + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break - catch { - - $ex = $_.Exception - Write-Host "Request to $Uri failed with HTTP Status $([int]$ex.Response.StatusCode) $($ex.Response.StatusDescription)" -f Red - - $errorResponse = $ex.Response.GetResponseStream() + } - $ex.Response.GetResponseStream() - - $reader = New-Object System.IO.StreamReader($errorResponse) - $reader.BaseStream.Position = 0 - $reader.DiscardBufferedData() - $responseBody = $reader.ReadToEnd(); - Write-Host "Response content:`n$responseBody" -f Red - Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" - write-host - break - } -} - #################################################### Function Add-ApplicationAssignment(){ diff --git a/Applications/Readme.md b/Applications/Readme.md index c0f3f7a..d1b9d1b 100644 --- a/Applications/Readme.md +++ b/Applications/Readme.md @@ -652,3 +652,12 @@ $Application = Get-IntuneApplication -Name "Microsoft Teams" Get-InstallaStatusForApp -AppId $Application.id ``` +### 20. Application_Detected_Apps_Get.ps1 +This script returns the list of all applications that Intune has detected are installed on managed devices in an organization. + +#### Get-DetectedApps Function +This function is used to get all detected applications from the Intune Service. Because this list tends to be rather large, paging is supported by default. The API will return the display name of the application along with the number of devices it is detected on. + +```PowerShell +# Returns all MDM applications in the Intune Service +Get-DetectedApps diff --git a/Authentication/Auth_AppOnly.ps1 b/Authentication/Auth_AppOnly.ps1 new file mode 100644 index 0000000..8cc165c --- /dev/null +++ b/Authentication/Auth_AppOnly.ps1 @@ -0,0 +1,139 @@ + +<# + +.COPYRIGHT +Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +See LICENSE in the project root for license information. + +#> + +#################################################### + +function Get-AuthToken { + +<# +.SYNOPSIS +This function is used to authenticate with the Graph API REST interface +.DESCRIPTION +The function authenticate with the Graph API Interface with the tenant name +.EXAMPLE +Get-AuthToken +Authenticates you with the Graph API interface +.NOTES +NAME: Get-AuthToken +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$Tenant, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$ClientId, + + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [string]$ClientSecret +) + + $AadModule = Get-Module -Name "AzureAD" -ListAvailable + + if ($AadModule -eq $null) { + + Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview" + $AadModule = Get-Module -Name "AzureADPreview" -ListAvailable + + } + + if ($AadModule -eq $null) { + write-host + write-host "AzureAD Powershell module not installed..." -f Red + write-host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow + write-host "Script can't continue..." -f Red + write-host + exit + } + +# Getting path to ActiveDirectory Assemblies +# If the module count is greater than 1 find the latest version + + if($AadModule.count -gt 1){ + + $Latest_Version = ($AadModule | select version | Sort-Object)[-1] + + $aadModule = $AadModule | ? { $_.version -eq $Latest_Version.version } + + # Checking if there are multiple versions of the same module found + + if($AadModule.count -gt 1){ + + $aadModule = $AadModule | select -Unique + + } + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + + else { + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + +[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null + +[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null + +$redirectUri = "urn:ietf:wg:oauth:2.0:oob" + +$resourceAppIdURI = "https://graph.microsoft.com" + +$authority = "https://login.microsoftonline.com/$Tenant" + + try { + + $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority, $false + + # turn this on for app only auth + $ClientCred = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential" -ArgumentList $clientId, $ClientSecret + + # turn this on for app only auth + $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI, $ClientCred) + + + # If the accesstoken is valid then create the authentication header + $accesstoken = $authResult.Result.CreateAuthorizationHeader() + + $authHeader = @{ + + 'Authorization'=$accesstoken + + } + + return $authHeader + + } + + catch { + + write-host $_.Exception.Message -f Red + write-host $_.Exception.ItemName -f Red + write-host + break + + } + +} + +#################################################### + +$global:authToken = Get-AuthToken -Tenant "tenantname.onmicrosoft.com" -ClientId "ClientId/ApplicationId" -ClientSecret "ClientSecret" + +#################################################### \ No newline at end of file diff --git a/Authentication/Readme.md b/Authentication/Readme.md index 8aba342..5beeaa6 100644 --- a/Authentication/Readme.md +++ b/Authentication/Readme.md @@ -9,7 +9,25 @@ Some script samples retrieve information from your Intune tenant, and others cre Within this section there are the following scripts with the explanation of usage. -### 1. Auth_From_File.ps1 +### 1. Auth_AppOnly.ps1 +This script demonstrates how to use Application Authentication against Graph API. To enable the usage of Application Authentication please review the following documentation from the Microsoft Graph Team: + +https://docs.microsoft.com/en-us/graph/auth-v2-service?context=graph/api/1.0 +https://docs.microsoft.com/en-us/graph/auth-register-app-v2 + +The Get-AuthToken function requires the following variable input: + +- $Tenant - The name of your tenant your authenticating against e.g. tenantname.onmicrosoft.com +- $ClientId - The Client / Application ID created after following https://docs.microsoft.com/en-us/graph/auth-v2-service?context=graph/api/1.0 documentation +- $ClientSecret - The client secret can be created after you've created your app registration in Azure AD - https://docs.microsoft.com/en-us/graph/auth-register-app-v2 + +``` +Get-AuthToken -Tenant "tenantname.onmicrosoft.com" -ClientId "ClientId/ApplicationId" -ClientSecret "ClientSecret" +``` +#### Note: +You will have to assign Microsoft Graph permissions that are "Application" permissions, otherwise when you authenticate against the service Graph calls could fail. Please review documentation above. + +### 2. Auth_From_File.ps1 This script demonstrates how to store a password as a secure string in a file. The file's contents are used during authentication to supply the password, rather than requiring an interactive user login. The Authentication region defines two variables: $User and $Password. The $User variable indicates the user principal name for the credentials, and the $Password variable indicates the location of the file which has the password string (the password file). diff --git a/CertificationAuthority/Validate-NDESConfiguration.ps1 b/CertificationAuthority/Validate-NDESConfiguration.ps1 index 73ac914..2391e19 100644 --- a/CertificationAuthority/Validate-NDESConfiguration.ps1 +++ b/CertificationAuthority/Validate-NDESConfiguration.ps1 @@ -1,4 +1,4 @@ - + <# .SYNOPSIS @@ -21,50 +21,57 @@ Where possible, a link and section description will be provided. https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure #> - -[CmdletBinding(DefaultParameterSetName="NormalRun")] +[CmdletBinding(DefaultParameterSetName="Unattended")] Param( + +[parameter(ParameterSetName="Unattended")] +[alias("ua","silent","s","unattended")] +[switch]$unattend, + [parameter(Mandatory=$true,ParameterSetName="NormalRun")] [alias("sa")] [ValidateScript({ - if ($_ -match ".\\."){ - - $True + + if ($_ -match ".\\.") { - } + $True + } - else { + else { - Throw "Please use the format Domain\Username for the NDES Service Account variable." + Throw "Please use the format Domain\Username for the NDES Service Account variable." - } + } - $EnteredDomain = $_.split("\") - $ads = New-Object -ComObject ADSystemInfo - $Domain = $ads.GetType().InvokeMember('DomainShortName','GetProperty', $Null, $ads, $Null) + $EnteredDomain = $_.split("\") + $ads = New-Object -ComObject ADSystemInfo + $Domain = $ads.GetType().InvokeMember('DomainShortName','GetProperty', $Null, $ads, $Null) - if ($EnteredDomain -like "$Domain") { + if ($EnteredDomain -like "$Domain") { - $True + $True - } + } - else { - - Throw "Incorrect Domain. Ensure domain is '$($Domain)\'" + else { + + Throw "Incorrect Domain. Ensure domain is '$($Domain)\'" + - } + } - } + } + + )] [string]$NDESServiceAccount, [parameter(Mandatory=$true,ParameterSetName="NormalRun")] [alias("ca")] [ValidateScript({ - $Domain = (Get-WmiObject Win32_ComputerSystem).domain - if ($_ -match $Domain) { + $Domain = ((Get-WmiObject Win32_ComputerSystem).domain).split(".\")[0] + if ($_ -match $Domain) { $True @@ -90,11 +97,13 @@ Param( [parameter(ParameterSetName="Help")] [alias("u")] -[switch]$usage +[switch]$usage + - -) + +) +$PsCmdlet.ParameterSetName ####################################################################### Function Log-ScriptEvent { @@ -142,7 +151,7 @@ function Show-Usage { Write-Host "-help -h Displays the help." Write-Host "-usage -u Displays this usage information." Write-Host "-NDESExternalHostname -ed External DNS name for the NDES server (SSL certificate subject will be checked for this. It should be in the SAN of the certificate if" - write-host " clients communicate directly with the NDES server)" + Write-Host " clients communicate directly with the NDES server)" Write-Host "-NDESServiceAccount -sa Username of the NDES service account. Format is Domain\sAMAccountName, such as Contoso\NDES_SVC." Write-Host "-IssuingCAServerFQDN -ca Name of the issuing CA to which you'll be connecting the NDES server. Format is FQDN, such as 'MyIssuingCAServer.contoso.com'." Write-Host "-SCEPUserCertTemplate -t Name of the SCEP Certificate template. Please note this is _not_ the display name of the template. Value should not contain spaces." @@ -195,23 +204,36 @@ $LogFilePath = "$($TempDirPath)\Validate-NDESConfig.log" #region Proceed with Variables... - Write-Host - Write-host "......................................................." - Write-Host - Write-Host "NDES Service Account = "-NoNewline - Write-Host "$($NDESServiceAccount)" -ForegroundColor Cyan - Write-host - Write-Host "Issuing CA Server = " -NoNewline - Write-Host "$($IssuingCAServerFQDN)" -ForegroundColor Cyan - Write-host - Write-Host "SCEP Certificate Template = " -NoNewline - Write-Host "$($SCEPUserCertTemplate)" -ForegroundColor Cyan - Write-Host - Write-host "......................................................." - Write-Host - Write-Host "Proceed with variables? [Y]es, [N]o" + - $confirmation = Read-Host + if ($PSCmdlet.ParameterSetName -eq "Unattended") { + $NDESServiceAccount = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\MicrosoftIntune\PFXCertificateConnector\CA*").Username + $MscepRaEku = '1.3.6.1.4.1.311.20.2.1' # CEP Encryption + # Get cert authority from the Certificate Request Agent cert. + $IssuingCAServerFQDN = Get-Item 'Cert:\LocalMachine\My\*' | where { ($_.EnhancedKeyUsageList -match $MscepRaEku) -and ($_.Extensions.Format(1)[0].split('(')[0] -replace "template=" -match "CEPEncryption" ) } + + $SCEPUserCertTemplate = (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Cryptography\MSCEP).EncryptionTemplate + $confirmation = "y" + } + else { + Write-Host + Write-Host "......................................................." + Write-Host + Write-Host "NDES Service Account = "-NoNewline + Write-Host "$($NDESServiceAccount)" -ForegroundColor Cyan + Write-Host + Write-Host "Issuing CA Server = " -NoNewline + Write-Host "$($IssuingCAServerFQDN)" -ForegroundColor Cyan + Write-Host + Write-Host "SCEP Certificate Template = " -NoNewline + Write-Host "$($SCEPUserCertTemplate)" -ForegroundColor Cyan + Write-Host + Write-Host "......................................................." + Write-Host + Write-Host "Proceed with variables? [Y]es, [N]o" + $confirmation = Read-Host + } + #endregion @@ -219,7 +241,7 @@ $LogFilePath = "$($TempDirPath)\Validate-NDESConfig.log" if ($confirmation -eq 'y'){ Write-Host - Write-host "......................................................." + Write-Host "......................................................." Log-ScriptEvent $LogFilePath "Initializing log file $($TempDirPath)\Validate-NDESConfig.log" NDES_Validation 1 Log-ScriptEvent $LogFilePath "Proceeding with variables=YES" NDES_Validation 1 Log-ScriptEvent $LogFilePath "NDESServiceAccount=$($NDESServiceAccount)" NDES_Validation 1 @@ -233,7 +255,7 @@ $LogFilePath = "$($TempDirPath)\Validate-NDESConfig.log" if (-not (Get-WindowsFeature ADCS-Device-Enrollment).Installed){ Write-Host "Error: NDES Not installed" -BackgroundColor Red - write-host "Exiting....................." + Write-Host "Exiting....................." Log-ScriptEvent $LogFilePath "NDES Not installed" NDES_Validation 3 break @@ -265,8 +287,8 @@ Import-Module ActiveDirectory | Out-Null #region checking OS version Write-Host - Write-host "Checking Windows OS version..." -ForegroundColor Yellow - Write-host + Write-Host "Checking Windows OS version..." -ForegroundColor Yellow + Write-Host Log-ScriptEvent $LogFilePath "Checking OS Version" NDES_Validation 1 $OSVersion = (Get-CimInstance -class Win32_OperatingSystem).Version @@ -274,7 +296,7 @@ $MinOSVersion = "6.3" if ([version]$OSVersion -lt [version]$MinOSVersion){ - Write-host "Error: Unsupported OS Version. NDES Requires 2012 R2 and above." -BackgroundColor Red + Write-Host "Error: Unsupported OS Version. NDES Requires 2012 R2 and above." -BackgroundColor Red Log-ScriptEvent $LogFilePath "Unsupported OS Version. NDES Requires 2012 R2 and above." NDES_Validation 3 } @@ -283,8 +305,8 @@ $MinOSVersion = "6.3" Write-Host "Success: " -ForegroundColor Green -NoNewline Write-Host "OS Version " -NoNewline - write-host "$($OSVersion)" -NoNewline -ForegroundColor Cyan - write-host " supported." + Write-Host "$($OSVersion)" -NoNewline -ForegroundColor Cyan + Write-Host " supported." Log-ScriptEvent $LogFilePath "Server is version $($OSVersion)" NDES_Validation 1 } @@ -295,17 +317,17 @@ $MinOSVersion = "6.3" #region Checking NDES Service Account properties in Active Directory -Write-host -Write-host "......................................................." Write-Host -Write-host "Checking NDES Service Account properties in Active Directory..." -ForegroundColor Yellow -Write-host +Write-Host "......................................................." +Write-Host +Write-Host "Checking NDES Service Account properties in Active Directory..." -ForegroundColor Yellow +Write-Host Log-ScriptEvent $LogFilePath "Checking NDES Service Account properties in Active Directory" NDES_Validation 1 $ADUser = $NDESServiceAccount.split("\")[1] - $ADUserProps = (Get-ADUser $ADUser -Properties SamAccountName,enabled,AccountExpirationDate,accountExpires,accountlockouttime,PasswordExpired,PasswordLastSet,PasswordNeverExpires,LockedOut) + if ($ADUserProps.enabled -ne $TRUE -OR $ADUserProps.PasswordExpired -ne $false -OR $ADUserProps.LockedOut -eq $TRUE){ Write-Host "Error: Problem with the AD account. Please see output below to determine the issue" -BackgroundColor Red @@ -323,52 +345,19 @@ $ADUserProps = (Get-ADUser $ADUser -Properties SamAccountName,enabled,AccountExp } - Get-ADUser $ADUser -Properties SamAccountName,enabled,AccountExpirationDate,accountExpires,accountlockouttime,PasswordExpired,PasswordLastSet,PasswordNeverExpires,LockedOut | fl SamAccountName,enabled,AccountExpirationDate,accountExpires,accountlockouttime,PasswordExpired,PasswordLastSet,PasswordNeverExpires,LockedOut - -#endregion - -####################################################################### - -#region Checking if NDES server is the CA - -Write-host "`n.......................................................`n" -Write-host "Checking if NDES server is the CA...`n" -ForegroundColor Yellow -Log-ScriptEvent $LogFilePath "Checking if NDES server is the CA" NDES_Validation 1 - -$hostname = ([System.Net.Dns]::GetHostByName(($env:computerName))).hostname -$CARoleInstalled = (Get-WindowsFeature ADCS-Cert-Authority).InstallState -eq "Installed" - - if ($hostname -match $IssuingCAServerFQDN){ - - Write-host "Error: NDES is running on the CA. This is an unsupported configuration!" -BackgroundColor Red - Log-ScriptEvent $LogFilePath "NDES is running on the CA" NDES_Validation 3 - } - elseif($CARoleInstalled) - { - Write-host "Error: NDES server has Certification Authority Role installed. This is an unsupported configuration!" -BackgroundColor Red - Log-ScriptEvent $LogFilePath "NDES server has Certification Authority Role installed" NDES_Validation 3 - } - else { - - Write-Host "Success: " -ForegroundColor Green -NoNewline - Write-Host "NDES server is not running on the CA" - Log-ScriptEvent $LogFilePath "NDES server is not running on the CA" NDES_Validation 1 - - } - #endregion ####################################################################### #region Checking NDES Service Account local permissions -Write-host -Write-host "......................................................." -Write-host -Write-host "Checking NDES Service Account local permissions..." -ForegroundColor Yellow -Write-host +Write-Host +Write-Host "......................................................." +Write-Host +Write-Host "Checking NDES Service Account local permissions..." -ForegroundColor Yellow +Write-Host Log-ScriptEvent $LogFilePath "Checking NDES Service Account local permissions" NDES_Validation 1 if ((net localgroup) -match "Administrators"){ @@ -390,9 +379,9 @@ Log-ScriptEvent $LogFilePath "Checking NDES Service Account local permissions" N } - Write-host + Write-Host Write-Host "Checking NDES Service account is a member of the IIS_IUSR group..." -ForegroundColor Yellow - Write-host + Write-Host if ((net localgroup) -match "IIS_IUSRS"){ @@ -411,8 +400,8 @@ Log-ScriptEvent $LogFilePath "Checking NDES Service Account local permissions" N Write-Host "Error: NDES Service Account is not a member of the local IIS_IUSR group" -BackgroundColor red Log-ScriptEvent $LogFilePath "NDES Service Account is not a member of the local IIS_IUSR group" NDES_Validation 3 - Write-host - Write-host "Checking Local Security Policy for explicit rights via gpedit..." -ForegroundColor Yellow + Write-Host + Write-Host "Checking Local Security Policy for explicit rights via gpedit..." -ForegroundColor Yellow Write-Host $TempFile = [System.IO.Path]::GetTempFileName() & "secedit" "/export" "/cfg" "$TempFile" | Out-Null @@ -432,7 +421,7 @@ Log-ScriptEvent $LogFilePath "Checking NDES Service Account local permissions" N Write-Host Write-Host "Note:" -BackgroundColor Red -NoNewline Write-Host 'Consider using the IIS_IUSERS group instead of explicit rights as documented under "Step 1 - Create an NDES service account".' - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" + Write-Host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" } @@ -440,7 +429,7 @@ Log-ScriptEvent $LogFilePath "Checking NDES Service Account local permissions" N Write-Host "Error: NDES Service Account has _NOT_ been assigned the Logon Locally, Logon as a Service or Logon as a batch job rights _explicitly_." -BackgroundColor red Write-Host 'Please review "Step 1 - Create an NDES service account".' - write-host "https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" + Write-Host "https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" Log-ScriptEvent $LogFilePath "NDES Service Account has _NOT_ been assigned the Logon Locally, Logon as a Service or Logon as a batch job rights _explicitly_." NDES_Validation 3 } @@ -452,8 +441,8 @@ Log-ScriptEvent $LogFilePath "Checking NDES Service Account local permissions" N else { Write-Host "Error: No IIS_IUSRS group exists. Ensure IIS is installed." -BackgroundColor red - write-host 'Please review "Step 3.1 - Configure prerequisites on the NDES server".' - write-host "https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" + Write-Host 'Please review "Step 3.1 - Configure prerequisites on the NDES server".' + Write-Host "https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" Log-ScriptEvent $LogFilePath "No IIS_IUSRS group exists. Ensure IIS is installed." NDES_Validation 3 } @@ -473,12 +462,12 @@ Log-ScriptEvent $LogFilePath "Checking NDES Service Account local permissions" N #region Checking Windows Features are installed. -Write-host Write-Host -Write-host "......................................................." -Write-host -Write-host "Checking Windows Features are installed..." -ForegroundColor Yellow -Write-host +Write-Host +Write-Host "......................................................." +Write-Host +Write-Host "Checking Windows Features are installed..." -ForegroundColor Yellow +Write-Host Log-ScriptEvent $LogFilePath "Checking Windows Features are installed..." NDES_Validation 1 $WindowsFeatures = @("Web-Filtering","Web-Net-Ext45","NET-Framework-45-Core","NET-WCF-HTTP-Activation45","Web-Metabase","Web-WMI") @@ -490,8 +479,8 @@ $FeatureDisplayName = $Feature.displayName if($Feature.installed){ - Write-host "Success:" -ForegroundColor Green -NoNewline - write-host "$FeatureDisplayName Feature Installed" + Write-Host "Success:" -ForegroundColor Green -NoNewline + Write-Host "$FeatureDisplayName Feature Installed" Log-ScriptEvent $LogFilePath "$($FeatureDisplayName) Feature Installed" NDES_Validation 1 } @@ -500,7 +489,7 @@ $FeatureDisplayName = $Feature.displayName Write-Host "Error: $FeatureDisplayName Feature not installed!" -BackgroundColor red Write-Host 'Please review "Step 3.1b - Configure prerequisites on the NDES server".' - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" + Write-Host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" Log-ScriptEvent $LogFilePath "$($FeatureDisplayName) Feature not installed" NDES_Validation 3 } @@ -515,11 +504,11 @@ $FeatureDisplayName = $Feature.displayName $ErrorActionPreference = "SilentlyContinue" -Write-host -Write-host "......................................................." -Write-host +Write-Host +Write-Host "......................................................." +Write-Host Write-Host "Checking NDES Install Paramaters..." -ForegroundColor Yellow -Write-host +Write-Host Log-ScriptEvent $LogFilePath "Checking NDES Install Paramaters" NDES_Validation 1 $InstallParams = @(Get-WinEvent -LogName "Microsoft-Windows-CertificateServices-Deployment/Operational" | Where-Object {$_.id -eq "105"}| @@ -528,8 +517,8 @@ Where-Object {$_.message -match "Install-AdcsNetworkDeviceEnrollmentService"}| S if ($InstallParams.Message -match '-SigningProviderName "Microsoft Strong Cryptographic Provider"' -AND ($InstallParams.Message -match '-EncryptionProviderName "Microsoft Strong Cryptographic Provider"')) { Write-Host "Success: " -ForegroundColor Green -NoNewline - write-host "Correct CSP used in install parameters" - Write-host + Write-Host "Correct CSP used in install parameters" + Write-Host Write-Host $InstallParams.Message Log-ScriptEvent $LogFilePath "Correct CSP used in install parameters:" NDES_Validation 1 Log-ScriptEvent $LogFilePath "$($InstallParams.Message)" NDES_Eventvwr 1 @@ -553,11 +542,11 @@ $ErrorActionPreference = "Continue" #region Checking IIS Application Pool health -Write-host -Write-host "......................................................." -Write-host -Write-host "Checking IIS Application Pool health..." -ForegroundColor Yellow -Write-host +Write-Host +Write-Host "......................................................." +Write-Host +Write-Host "Checking IIS Application Pool health..." -ForegroundColor Yellow +Write-Host Log-ScriptEvent $LogFilePath "Checking IIS Application Pool health" NDES_Validation 1 if (-not ($IISNotInstalled -eq $TRUE)){ @@ -579,7 +568,7 @@ Log-ScriptEvent $LogFilePath "Checking IIS Application Pool health" NDES_Validat Write-Host "Error: SCEP Application Pool missing!" -BackgroundColor red Write-Host 'Please review "Step 3.1 - Configure prerequisites on the NDES server"'. - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" + Write-Host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" Log-ScriptEvent $LogFilePath "SCEP Application Pool missing" NDES_Validation 3 } @@ -597,7 +586,7 @@ Log-ScriptEvent $LogFilePath "Checking IIS Application Pool health" NDES_Validat Write-Host "Error: Application Pool is not configured to use the NDES Service Account" -BackgroundColor red Write-Host 'Please review "Step 4.1 - Configure NDES for use with Intune".' - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" + Write-Host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" Log-ScriptEvent $LogFilePath "Application Pool is not configured to use the NDES Service Account" NDES_Validation 3 } @@ -631,74 +620,13 @@ Log-ScriptEvent $LogFilePath "Checking IIS Application Pool health" NDES_Validat ################################################################# -#region Checking Request Filtering +#region Checking registry has been set to allow long URLs Write-Host -Write-host -Write-host "......................................................." -Write-host -Write-Host "Checking Request Filtering (Default Web Site -> Request Filtering -> Edit Feature Setting) has been configured in IIS..." -ForegroundColor Yellow +Write-Host "......................................................." Write-Host -Log-ScriptEvent $LogFilePath "Checking Request Filtering" NDES_Validation 1 - - if (-not ($IISNotInstalled -eq $TRUE)){ - - [xml]$RequestFiltering = (c:\windows\system32\inetsrv\appcmd.exe list config "default web site" /section:requestfiltering) - - if ($RequestFiltering.'system.webserver'.security.requestFiltering.requestLimits.maxQueryString -eq "65534"){ - - Write-Host "Success: " -ForegroundColor Green -NoNewline - write-host "MaxQueryString Set Correctly" - Log-ScriptEvent $LogFilePath "MaxQueryString Set Correctly" NDES_Validation 1 - - } - - else { - - Write-Host "MaxQueryString not set correctly!" -BackgroundColor red - Write-Host 'Please review "Step 4.4 - Configure NDES for use with Intune".' - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" - Log-ScriptEvent $LogFilePath "MaxQueryString not set correctly" NDES_Validation 3 - - } - - if ($RequestFiltering.'system.webserver'.security.requestFiltering.requestLimits.maxUrl -eq "65534"){ - - Write-Host "Success: " -ForegroundColor Green -NoNewline - write-host "MaxUrl Set Correctly" - Log-ScriptEvent $LogFilePath "MaxUrl Set Correctly" NDES_Validation 1 - - } - - else { - - Write-Host "maxUrl not set correctly!" -BackgroundColor red - Write-Host 'Please review "Step 4.4 - Configure NDES for use with Intune".' - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure'" - Log-ScriptEvent $LogFilePath "maxUrl not set correctly" NDES_Validation 3 - - } - - } - - else { - - Write-Host "IIS is not installed." -BackgroundColor red - Log-ScriptEvent $LogFilePath "IIS is not installed" NDES_Validation 3 - - } - -#endregion - -################################################################# - -#region Checking registry has been set to allow long URLs - -Write-host -Write-host "......................................................." -Write-host Write-Host 'Checking registry "HKLM:SYSTEM\CurrentControlSet\Services\HTTP\Parameters" has been set to allow long URLs...' -ForegroundColor Yellow -Write-host +Write-Host Log-ScriptEvent $LogFilePath "Checking registry (HKLM:SYSTEM\CurrentControlSet\Services\HTTP\Parameters) has been set to allow long URLs" NDES_Validation 1 if (-not ($IISNotInstalled -eq $TRUE)){ @@ -708,14 +636,14 @@ Log-ScriptEvent $LogFilePath "Checking registry (HKLM:SYSTEM\CurrentControlSet\S Write-Host "Error: MaxFieldLength not set to 65534 in the registry!" -BackgroundColor red Write-Host Write-Host 'Please review "Step 4.3 - Configure NDES for use with Intune".' - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" + Write-Host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" Log-ScriptEvent $LogFilePath "MaxFieldLength not set to 65534 in the registry" NDES_Validation 3 } else { Write-Host "Success: " -ForegroundColor Green -NoNewline - write-host "MaxFieldLength set correctly" + Write-Host "MaxFieldLength set correctly" Log-ScriptEvent $LogFilePath "MaxFieldLength set correctly" NDES_Validation 1 } @@ -725,7 +653,7 @@ Log-ScriptEvent $LogFilePath "Checking registry (HKLM:SYSTEM\CurrentControlSet\S Write-Host "MaxRequestBytes not set to 65534 in the registry!" -BackgroundColor red Write-Host Write-Host 'Please review "Step 4.3 - Configure NDES for use with Intune".' - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure'" + Write-Host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure'" Log-ScriptEvent $LogFilePath "MaxRequestBytes not set to 65534 in the registry" NDES_Validation 3 } @@ -733,7 +661,7 @@ Log-ScriptEvent $LogFilePath "Checking registry (HKLM:SYSTEM\CurrentControlSet\S else { Write-Host "Success: " -ForegroundColor Green -NoNewline - write-host "MaxRequestBytes set correctly" + Write-Host "MaxRequestBytes set correctly" Log-ScriptEvent $LogFilePath "MaxRequestBytes set correctly" NDES_Validation 1 } @@ -753,12 +681,12 @@ Log-ScriptEvent $LogFilePath "Checking registry (HKLM:SYSTEM\CurrentControlSet\S #region Checking SPN has been set... -Write-host -Write-host "......................................................." -Write-host -Write-Host "Checking SPN has been set..." -ForegroundColor Yellow -Write-host -Log-ScriptEvent $LogFilePath "Checking SPN has been set" NDES_Validation 1 +Write-Host +Write-Host "......................................................." +Write-Host +Write-Host "Checking SPN has been set for $ADUser..." -ForegroundColor Yellow +Write-Host +Log-ScriptEvent $LogFilePath "Checking SPN has been set for $ADUser" NDES_Validation 1 $hostname = ([System.Net.Dns]::GetHostByName(($env:computerName))).hostname @@ -767,8 +695,8 @@ $spn = setspn.exe -L $ADUser if ($spn -match $hostname){ Write-Host "Success: " -ForegroundColor Green -NoNewline - write-host "Correct SPN set for the NDES service account:" - Write-host + Write-Host "Correct SPN set for the NDES service account:" + Write-Host Write-Host $spn -ForegroundColor Cyan Log-ScriptEvent $LogFilePath "Correct SPN set for the NDES service account: $($spn)" NDES_Validation 1 @@ -778,7 +706,7 @@ $spn = setspn.exe -L $ADUser Write-Host "Error: Missing or Incorrect SPN set for the NDES Service Account!" -BackgroundColor red Write-Host 'Please review "Step 3.1c - Configure prerequisites on the NDES server".' - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" + Write-Host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" Log-ScriptEvent $LogFilePath "Missing or Incorrect SPN set for the NDES Service Account" NDES_Validation 3 } @@ -789,11 +717,11 @@ $spn = setspn.exe -L $ADUser #region Checking there are no intermediate certs are in the Trusted Root store -Write-host -Write-host "......................................................." -Write-host +Write-Host +Write-Host "......................................................." +Write-Host Write-Host "Checking there are no intermediate certs are in the Trusted Root store..." -ForegroundColor Yellow -Write-host +Write-Host Log-ScriptEvent $LogFilePath "Checking there are no intermediate certs are in the Trusted Root store" NDES_Validation 1 $IntermediateCertCheck = Get-Childitem cert:\LocalMachine\root -Recurse | Where-Object {$_.Issuer -ne $_.Subject} @@ -824,11 +752,11 @@ $IntermediateCertCheck = Get-Childitem cert:\LocalMachine\root -Recurse | Where- $ErrorActionPreference = "Silentlycontinue" -Write-host -Write-host "......................................................." -Write-host +Write-Host +Write-Host "......................................................." +Write-Host Write-Host "Checking the EnrollmentAgentOffline and CEPEncryption are present..." -ForegroundColor Yellow -Write-host +Write-Host Log-ScriptEvent $LogFilePath "Checking the EnrollmentAgentOffline and CEPEncryption are present" NDES_Validation 1 $certs = Get-ChildItem cert:\LocalMachine\My\ @@ -865,8 +793,8 @@ $certs = Get-ChildItem cert:\LocalMachine\My\ Write-Host "Error: EnrollmentAgentOffline certificate is not present!" -BackgroundColor red Write-Host "This can take place when an account without Enterprise Admin permissions installs NDES. You may need to remove the NDES role and reinstall with the correct permissions." - write-host 'Please review "Step 3.1 - Configure prerequisites on the NDES server".' - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" + Write-Host 'Please review "Step 3.1 - Configure prerequisites on the NDES server".' + Write-Host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" Log-ScriptEvent $LogFilePath "EnrollmentAgentOffline certificate is not present" NDES_Validation 3 } @@ -884,8 +812,8 @@ $certs = Get-ChildItem cert:\LocalMachine\My\ Write-Host "Error: CEPEncryption certificate is not present!" -BackgroundColor red Write-Host "This can take place when an account without Enterprise Admin permissions installs NDES. You may need to remove the NDES role and reinstall with the correct permissions." - write-host 'Please review "Step 3.1 - Configure prerequisites on the NDES server".' - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" + Write-Host 'Please review "Step 3.1 - Configure prerequisites on the NDES server".' + Write-Host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" Log-ScriptEvent $LogFilePath "CEPEncryption certificate is not present" NDES_Validation 3 } @@ -898,18 +826,18 @@ $ErrorActionPreference = "Continue" #region Checking registry has been set with the SCEP certificate template name -Write-host -Write-host "......................................................." -Write-host +Write-Host +Write-Host "......................................................." +Write-Host Write-Host 'Checking registry "HKLM:SOFTWARE\Microsoft\Cryptography\MSCEP" has been set with the SCEP certificate template name...' -ForegroundColor Yellow -Write-host +Write-Host Log-ScriptEvent $LogFilePath "Checking registry (HKLM:SOFTWARE\Microsoft\Cryptography\MSCEP) has been set with the SCEP certificate template name" NDES_Validation 1 if (-not (Test-Path HKLM:SOFTWARE\Microsoft\Cryptography\MSCEP)){ - Write-host "Error: Registry key does not exist. This can occur if the NDES role has been installed but not configured." -BackgroundColor Red - Write-host 'Please review "Step 3 - Configure prerequisites on the NDES server".' - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" + Write-Host "Error: Registry key does not exist. This can occur if the NDES role has been installed but not configured." -BackgroundColor Red + Write-Host 'Please review "Step 3 - Configure prerequisites on the NDES server".' + Write-Host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" Log-ScriptEvent $LogFilePath "MSCEP Registry key does not exist." NDES_Validation 3 } @@ -924,8 +852,8 @@ Log-ScriptEvent $LogFilePath "Checking registry (HKLM:SOFTWARE\Microsoft\Cryptog if ($SignatureTemplate -match $DefaultUsageTemplate -AND $EncryptionTemplate -match $DefaultUsageTemplate -AND $GeneralPurposeTemplate -match $DefaultUsageTemplate){ Write-Host "Error: Registry has not been configured with the SCEP Certificate template name. Default values have _not_ been changed." -BackgroundColor red - write-host 'Please review "Step 3.1 - Configure prerequisites on the NDES server".' - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" + Write-Host 'Please review "Step 3.1 - Configure prerequisites on the NDES server".' + Write-Host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" Write-Host Log-ScriptEvent $LogFilePath "Registry has not been configured with the SCEP Certificate template name. Default values have _not_ been changed." NDES_Validation 3 $FurtherReading = $FALSE @@ -936,14 +864,14 @@ Log-ScriptEvent $LogFilePath "Checking registry (HKLM:SOFTWARE\Microsoft\Cryptog Write-Host "One or more default values have been changed." Write-Host - write-host "Checking SignatureTemplate key..." - Write-host + Write-Host "Checking SignatureTemplate key..." + Write-Host if ($SignatureTemplate -match $SCEPUserCertTemplate){ Write-Host "Success: " -ForegroundColor Green -NoNewline - write-host "SCEP certificate template '$($SCEPUserCertTemplate)' has been written to the registry under the _SignatureTemplate_ key. Ensure this aligns with the usage specificed on the SCEP template." - Write-host + Write-Host "SCEP certificate template '$($SCEPUserCertTemplate)' has been written to the registry under the _SignatureTemplate_ key. Ensure this aligns with the usage specificed on the SCEP template." + Write-Host Log-ScriptEvent $LogFilePath "SCEP certificate template $($SCEPUserCertTemplate)' has been written to the registry under the _SignatureTemplate_ key" NDES_Validation 1 } @@ -952,26 +880,26 @@ Log-ScriptEvent $LogFilePath "Checking registry (HKLM:SOFTWARE\Microsoft\Cryptog Write-Warning '"SignatureTemplate key does not match the SCEP certificate template name. Unless your template is explicitly set for the "Signature" purpose, this can safely be ignored."' Write-Host - write-host "Registry value: " -NoNewline - Write-host "$($SignatureTemplate)" -ForegroundColor Cyan + Write-Host "Registry value: " -NoNewline + Write-Host "$($SignatureTemplate)" -ForegroundColor Cyan Write-Host - write-host "SCEP certificate template value: " -NoNewline - Write-host "$($SCEPUserCertTemplate)" -ForegroundColor Cyan + Write-Host "SCEP certificate template value: " -NoNewline + Write-Host "$($SCEPUserCertTemplate)" -ForegroundColor Cyan Write-Host Log-ScriptEvent $LogFilePath "SignatureTemplate key does not match the SCEP certificate template name.Registry value=$($SignatureTemplate)|SCEP certificate template value=$($SCEPUserCertTemplate)" NDES_Validation 2 } - Write-host "......................." + Write-Host "......................." Write-Host Write-Host "Checking EncryptionTemplate key..." - Write-host + Write-Host if ($EncryptionTemplate -match $SCEPUserCertTemplate){ Write-Host "Success: " -ForegroundColor Green -NoNewline - write-host "SCEP certificate template '$($SCEPUserCertTemplate)' has been written to the registry under the _EncryptionTemplate_ key. Ensure this aligns with the usage specificed on the SCEP template." - Write-host + Write-Host "SCEP certificate template '$($SCEPUserCertTemplate)' has been written to the registry under the _EncryptionTemplate_ key. Ensure this aligns with the usage specificed on the SCEP template." + Write-Host Log-ScriptEvent $LogFilePath "SCEP certificate template $($SCEPUserCertTemplate) has been written to the registry under the _EncryptionTemplate_ key" NDES_Validation 1 @@ -981,26 +909,26 @@ Log-ScriptEvent $LogFilePath "Checking registry (HKLM:SOFTWARE\Microsoft\Cryptog Write-Warning '"EncryptionTemplate key does not match the SCEP certificate template name. Unless your template is explicitly set for the "Encryption" purpose, this can safely be ignored."' Write-Host - write-host "Registry value: " -NoNewline - Write-host "$($EncryptionTemplate)" -ForegroundColor Cyan + Write-Host "Registry value: " -NoNewline + Write-Host "$($EncryptionTemplate)" -ForegroundColor Cyan Write-Host - write-host "SCEP certificate template value: " -NoNewline - Write-host "$($SCEPUserCertTemplate)" -ForegroundColor Cyan + Write-Host "SCEP certificate template value: " -NoNewline + Write-Host "$($SCEPUserCertTemplate)" -ForegroundColor Cyan Write-Host Log-ScriptEvent $LogFilePath "EncryptionTemplate key does not match the SCEP certificate template name.Registry value=$($EncryptionTemplate)|SCEP certificate template value=$($SCEPUserCertTemplate)" NDES_Validation 2 } - Write-host "......................." + Write-Host "......................." Write-Host Write-Host "Checking GeneralPurposeTemplate key..." - Write-host + Write-Host if ($GeneralPurposeTemplate -match $SCEPUserCertTemplate){ Write-Host "Success: " -ForegroundColor Green -NoNewline - write-host "SCEP certificate template '$($SCEPUserCertTemplate)' has been written to the registry under the _GeneralPurposeTemplate_ key. Ensure this aligns with the usage specificed on the SCEP template" + Write-Host "SCEP certificate template '$($SCEPUserCertTemplate)' has been written to the registry under the _GeneralPurposeTemplate_ key. Ensure this aligns with the usage specificed on the SCEP template" Log-ScriptEvent $LogFilePath "SCEP certificate template $($SCEPUserCertTemplate) has been written to the registry under the _GeneralPurposeTemplate_ key" NDES_Validation 1 } @@ -1009,11 +937,11 @@ Log-ScriptEvent $LogFilePath "Checking registry (HKLM:SOFTWARE\Microsoft\Cryptog Write-Warning '"GeneralPurposeTemplate key does not match the SCEP certificate template name. Unless your template is set for the "Signature and Encryption" (General) purpose, this can safely be ignored."' Write-Host - write-host "Registry value: " -NoNewline - Write-host "$($GeneralPurposeTemplate)" -ForegroundColor Cyan + Write-Host "Registry value: " -NoNewline + Write-Host "$($GeneralPurposeTemplate)" -ForegroundColor Cyan Write-Host - write-host "SCEP certificate template value: " -NoNewline - Write-host "$($SCEPUserCertTemplate)" -ForegroundColor Cyan + Write-Host "SCEP certificate template value: " -NoNewline + Write-Host "$($SCEPUserCertTemplate)" -ForegroundColor Cyan Write-Host Log-ScriptEvent $LogFilePath "GeneralPurposeTemplate key does not match the SCEP certificate template name.Registry value=$($GeneralPurposeTemplate)|SCEP certificate template value=$($SCEPUserCertTemplate)" NDES_Validation 2 @@ -1024,10 +952,10 @@ Log-ScriptEvent $LogFilePath "Checking registry (HKLM:SOFTWARE\Microsoft\Cryptog if ($furtherreading-EQ $true){ - Write-host "......................." + Write-Host "......................." Write-Host - Write-host 'For further reading, please review "Step 4.2 - Configure NDES for use with Intune".' - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" + Write-Host 'For further reading, please review "Step 4.2 - Configure NDES for use with Intune".' + Write-Host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" } @@ -1041,11 +969,11 @@ $ErrorActionPreference = "Continue" #region Checking server certificate. -Write-host -Write-host "......................................................." -Write-host +Write-Host +Write-Host "......................................................." +Write-Host Write-Host "Checking IIS SSL certificate is valid for use..." -ForegroundColor Yellow -Write-host +Write-Host Log-ScriptEvent $LogFilePath "Checking IIS SSL certificate is valid for use" NDES_Validation 1 $hostname = ([System.Net.Dns]::GetHostByName(($env:computerName))).hostname @@ -1082,10 +1010,10 @@ $ServerCertObject = Get-ChildItem Cert:\LocalMachine\My\$BoundServerCertThumb if ($ServerCertObject.EnhancedKeyUsageList -match $serverAuthEKU -AND (($ServerCertObject.Subject -match $hostname) -or ($ServerCertObject.DnsNameList -match $hostname)) -AND $ServerCertObject.Issuer -notmatch $ServerCertObject.Subject){ Write-Host "Success: " -ForegroundColor Green -NoNewline - write-host "Certificate bound in IIS is valid:" + Write-Host "Certificate bound in IIS is valid:" Write-Host Write-Host "Subject: " -NoNewline - Write-host "$($ServerCertObject.Subject)" -ForegroundColor Cyan + Write-Host "$($ServerCertObject.Subject)" -ForegroundColor Cyan Write-Host Write-Host "Thumbprint: " -NoNewline Write-Host "$($ServerCertObject.Thumbprint)" -ForegroundColor Cyan @@ -1096,8 +1024,8 @@ $ServerCertObject = Get-ChildItem Cert:\LocalMachine\My\$BoundServerCertThumb Write-Host "If this NDES server is in your perimeter network, please ensure the external hostname is shown below:" -ForegroundColor Blue -BackgroundColor White $DNSNameList = $ServerCertObject.DNSNameList.unicode Write-Host - write-host "Internal and External hostnames: " -NoNewline - Write-host "$($DNSNameList)" -ForegroundColor Cyan + Write-Host "Internal and External hostnames: " -NoNewline + Write-Host "$($DNSNameList)" -ForegroundColor Cyan Log-ScriptEvent $LogFilePath "Certificate bound in IIS is valid. Subject:$($ServerCertObject.Subject)|Thumbprint:$($ServerCertObject.Thumbprint)|ValidUntil:$($ServerCertObject.NotAfter)|Internal&ExternalHostnames:$($DNSNameList)" NDES_Validation 1 } @@ -1105,7 +1033,7 @@ $ServerCertObject = Get-ChildItem Cert:\LocalMachine\My\$BoundServerCertThumb else { Write-Host "Error: The certificate bound in IIS is not valid for use. Reason:" -BackgroundColor red - write-host + Write-Host if ($ServerCertObject.EnhancedKeyUsageList -match $serverAuthEKU) { @@ -1118,7 +1046,7 @@ $ServerCertObject = Get-ChildItem Cert:\LocalMachine\My\$BoundServerCertThumb $EKUValid = $false - write-host "Correct EKU: " -NoNewline + Write-Host "Correct EKU: " -NoNewline Write-Host "$($EKUValid)" -ForegroundColor Cyan Write-Host @@ -1134,8 +1062,8 @@ $ServerCertObject = Get-ChildItem Cert:\LocalMachine\My\$BoundServerCertThumb $SubjectValid = $false - write-host "Correct Subject: " -NoNewline - write-host "$($SubjectValid)" -ForegroundColor Cyan + Write-Host "Correct Subject: " -NoNewline + Write-Host "$($SubjectValid)" -ForegroundColor Cyan Write-Host } @@ -1148,14 +1076,14 @@ $ServerCertObject = Get-ChildItem Cert:\LocalMachine\My\$BoundServerCertThumb else { - write-host "Is Self-Signed: " -NoNewline - write-host "$($SelfSigned)" -ForegroundColor Cyan + Write-Host "Is Self-Signed: " -NoNewline + Write-Host "$($SelfSigned)" -ForegroundColor Cyan Write-Host } Write-Host 'Please review "Step 4 - Configure NDES for use with Intune>To Install and bind certificates on the NDES Server".' - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" + Write-Host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" Log-ScriptEvent $LogFilePath "The certificate bound in IIS is not valid for use. CorrectEKU=$($EKUValid)|CorrectSubject=$($SubjectValid)|IsSelfSigned=$($SelfSigned)" NDES_Validation 3 } @@ -1166,16 +1094,16 @@ $ServerCertObject = Get-ChildItem Cert:\LocalMachine\My\$BoundServerCertThumb #region Checking Client certificate. -Write-host -Write-host "......................................................." -Write-host -Write-Host "Checking Client certificate (NDES Policy module) is valid for use..." -ForegroundColor Yellow -Write-host -Log-ScriptEvent $LogFilePath "Checking Client certificate (NDES Policy module) is valid for use" NDES_Validation 1 +Write-Host +Write-Host "......................................................." +Write-Host +Write-Host "Checking encrypting certificate is valid for use..." -ForegroundColor Yellow +Write-Host +Log-ScriptEvent $LogFilePath "Checking encrypting certificate is valid for use..." NDES_Validation 1 $hostname = ([System.Net.Dns]::GetHostByName(($env:computerName))).hostname $clientAuthEku = "1.3.6.1.5.5.7.3.2" # Client Authentication -$NDESCertThumbprint = (Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Cryptography\MSCEP\Modules\NDESPolicy -Name NDESCertThumbprint).NDESCertThumbprint +$NDESCertThumbprint = (Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MicrosoftIntune\PFXCertificateConnector -Name EncryptionCertThumbprint).EncryptionCertThumbprint $ClientCertObject = Get-ChildItem Cert:\LocalMachine\My\$NDESCertThumbprint if ($ClientCertObject.Issuer -match $ClientCertObject.Subject){ @@ -1190,13 +1118,13 @@ $ClientCertObject = Get-ChildItem Cert:\LocalMachine\My\$NDESCertThumbprint } - if ($ClientCertObject.EnhancedKeyUsageList -match $clientAuthEku -AND $ClientCertObject.Subject -match $hostname -AND $ClientCertObject.Issuer -notmatch $ClientCertObject.Subject){ + if ($ClientCertObject.EnhancedKeyUsageList -match $clientAuthEku -AND $ClientCertObject.Issuer -notmatch $ClientCertObject.Subject){ Write-Host "Success: " -ForegroundColor Green -NoNewline - write-host "Client certificate bound to NDES Connector is valid:" + Write-Host "Client certificate bound to NDES Connector is valid:" Write-Host Write-Host "Subject: " -NoNewline - Write-host "$($ClientCertObject.Subject)" -ForegroundColor Cyan + Write-Host "$($ClientCertObject.Subject)" -ForegroundColor Cyan Write-Host Write-Host "Thumbprint: " -NoNewline Write-Host "$($ClientCertObject.Thumbprint)" -ForegroundColor Cyan @@ -1210,7 +1138,7 @@ $ClientCertObject = Get-ChildItem Cert:\LocalMachine\My\$NDESCertThumbprint else { Write-Host "Error: The certificate bound to the NDES Connector is not valid for use. Reason:" -BackgroundColor red - write-host + Write-Host if ($ClientCertObject.EnhancedKeyUsageList -match $clientAuthEku) { @@ -1222,28 +1150,13 @@ $ClientCertObject = Get-ChildItem Cert:\LocalMachine\My\$NDESCertThumbprint $ClientCertEKUValid = $false - write-host "Correct EKU: " -NoNewline + Write-Host "Correct EKU: " -NoNewline Write-Host "$($ClientCertEKUValid)" -ForegroundColor Cyan Write-Host } - if ($ClientCertObject.Subject -match $hostname) { - - $ClientCertSubjectValid = $true - - } - - else { - - $ClientCertSubjectValid = $false - - write-host "Correct Subject: " -NoNewline - write-host "$($ClientCertSubjectValid)" -ForegroundColor Cyan - Write-Host - - } - + if ($ClientCertSelfSigned -eq $false){ Out-Null @@ -1252,15 +1165,15 @@ $ClientCertObject = Get-ChildItem Cert:\LocalMachine\My\$NDESCertThumbprint else { - write-host "Is Self-Signed: " -NoNewline - write-host "$($ClientCertSelfSigned)" -ForegroundColor Cyan + Write-Host "Is Self-Signed: " -NoNewline + Write-Host "$($ClientCertSelfSigned)" -ForegroundColor Cyan Write-Host } Write-Host 'Please review "Step 4 - Configure NDES for use with Intune>To Install and bind certificates on the NDES Server".' - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" - Log-ScriptEvent $LogFilePath "The certificate bound to the NDES Connector is not valid for use. CorrectEKU=$($ClientCertEKUValid)|CorrectSubject=$($ClientCertSubjectValid)|IsSelfSigned=$($ClientCertSelfSigned)" NDES_Validation 3 + Write-Host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" + Log-ScriptEvent $LogFilePath "The certificate bound to the NDES Connector is not valid for use. CorrectEKU=$($ClientCertEKUValid))|IsSelfSigned=$($ClientCertSelfSigned)" NDES_Validation 3 } @@ -1271,13 +1184,13 @@ $ClientCertObject = Get-ChildItem Cert:\LocalMachine\My\$NDESCertThumbprint #region Checking behaviour of internal NDES URL -Write-host -Write-host "......................................................." +Write-Host +Write-Host "......................................................." $hostname = ([System.Net.Dns]::GetHostByName(($env:computerName))).hostname -Write-host +Write-Host Write-Host "Checking behaviour of internal NDES URL: " -NoNewline -ForegroundColor Yellow Write-Host "https://$hostname/certsrv/mscep/mscep.dll" -ForegroundColor Cyan -Write-host +Write-Host Log-ScriptEvent $LogFilePath "Checking behaviour of internal NDES URL" NDES_Validation 1 Log-ScriptEvent $LogFilePath "Https://$hostname/certsrv/mscep/mscep.dll" NDES_Validation 1 @@ -1285,7 +1198,7 @@ $Statuscode = try {(Invoke-WebRequest -Uri https://$hostname/certsrv/mscep/mscep if ($statuscode -eq "200"){ - Write-host "Error: https://$hostname/certsrv/mscep/mscep.dll returns 200 OK. This usually signifies an error with the Intune Connector registering itself or not being installed." -BackgroundColor Red + Write-Host "Error: https://$hostname/certsrv/mscep/mscep.dll returns 200 OK. This usually signifies an error with the Intune Connector registering itself or not being installed." -BackgroundColor Red Log-ScriptEvent $LogFilePath "https://$hostname/certsrv/mscep/mscep.dll returns 200 OK. This usually signifies an error with the Intune Connector registering itself or not being installed" NDES_Validation 3 } @@ -1304,9 +1217,9 @@ $Statuscode = try {(Invoke-WebRequest -Uri https://$hostname/certsrv/mscep/mscep if ($CACaps){ Write-Host "Success: " -ForegroundColor Green -NoNewline - write-host "CA Capabilities retrieved:" + Write-Host "CA Capabilities retrieved:" Write-Host - write-host $CACaps + Write-Host $CACaps Log-ScriptEvent $LogFilePath "CA Capabilities retrieved:$CACaps" NDES_Validation 1 } @@ -1315,8 +1228,8 @@ $Statuscode = try {(Invoke-WebRequest -Uri https://$hostname/certsrv/mscep/mscep else { - Write-host "Error: Unexpected Error code! This usually signifies an error with the Intune Connector registering itself or not being installed" -BackgroundColor Red - Write-host "Expected value is a 403. We received a $($Statuscode). This could be down to a missing reboot post policy module install. Verify last boot time and module install time further down the validation." + Write-Host "Error: Unexpected Error code! This usually signifies an error with the Intune Connector registering itself or not being installed" -BackgroundColor Red + Write-Host "Expected value is a 403. We received a $($Statuscode). This could be down to a missing reboot post policy module install. Verify last boot time and module install time further down the validation." Log-ScriptEvent $LogFilePath "Unexpected Error code. Expected:403|Received:$Statuscode" NDES_Validation 3 } @@ -1327,17 +1240,17 @@ $Statuscode = try {(Invoke-WebRequest -Uri https://$hostname/certsrv/mscep/mscep #region Checking Servers last boot time -Write-host -Write-host "......................................................." -Write-host +Write-Host +Write-Host "......................................................." +Write-Host Write-Host "Checking Servers last boot time..." -ForegroundColor Yellow -Write-host +Write-Host Log-ScriptEvent $LogFilePath "Checking Servers last boot time" NDES_Validation 1 $LastBoot = (Get-WmiObject win32_operatingsystem | select csname, @{LABEL='LastBootUpTime' ;EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}}).lastbootuptime -write-host "Server last rebooted: "-NoNewline +Write-Host "Server last rebooted: "-NoNewline Write-Host "$($LastBoot). " -ForegroundColor Cyan -NoNewline Write-Host "Please ensure a reboot has taken place _after_ all registry changes and installing the NDES Connector. IISRESET is _not_ sufficient." Log-ScriptEvent $LogFilePath "LastBootTime:$LastBoot" NDES_Validation 1 @@ -1348,20 +1261,33 @@ Log-ScriptEvent $LogFilePath "LastBootTime:$LastBoot" NDES_Validation 1 #region Checking Intune Connector is installed -Write-host -Write-host "......................................................." -Write-host +Write-Host +Write-Host "......................................................." +Write-Host Write-Host "Checking Intune Connector is installed..." -ForegroundColor Yellow -Write-host +Write-Host Log-ScriptEvent $LogFilePath "Checking Intune Connector is installed" NDES_Validation 1 - if ($IntuneConnector = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | ? {$_.DisplayName -eq "Microsoft Intune Connector"}){ + if ($IntuneConnector = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | ? {$_.DisplayName -eq "Certificate Connector for Microsoft Intune"}){ Write-Host "Success: " -ForegroundColor Green -NoNewline Write-Host "$($IntuneConnector.DisplayName) was installed on " -NoNewline Write-Host "$($IntuneConnector.InstallDate) " -ForegroundColor Cyan -NoNewline - write-host "and is version " -NoNewline + Write-Host "and is version " -NoNewline Write-Host "$($IntuneConnector.DisplayVersion)" -ForegroundColor Cyan -NoNewline + Write-Host + Log-ScriptEvent $LogFilePath "ConnectorVersion:$IntuneConnector" NDES_Validation 1 + + } + elseif ($IntuneConnector = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | ? {$_.DisplayName -eq "Microsoft Intune Connector"}){ + + Write-Host "Success: " -ForegroundColor Green -NoNewline + Write-Host "$($IntuneConnector.DisplayName) was installed on " -NoNewline + Write-Host "$($IntuneConnector.InstallDate) " -ForegroundColor Cyan -NoNewline + write-host "and is version " -NoNewline + Write-Host "$($IntuneConnector.DisplayVersion)" -ForegroundColor Cyan + write-warning "This version of the Intune certificate connector has been replaced by the Certificate Connector for Microsoft Intune" + write-warning "URL: https://learn.microsoft.com/en-us/mem/intune/protect/certificate-connector-overview" Write-host Log-ScriptEvent $LogFilePath "ConnectorVersion:$IntuneConnector" NDES_Validation 1 @@ -1371,7 +1297,7 @@ Log-ScriptEvent $LogFilePath "Checking Intune Connector is installed" NDES_Valid Write-Host "Error: Intune Connector not installed" -BackgroundColor red Write-Host 'Please review "Step 5 - Enable, install, and configure the Intune certificate connector".' - write-host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" + Write-Host "URL: https://docs.microsoft.com/en-us/intune/certificates-scep-configure#configure-your-infrastructure" Write-Host Log-ScriptEvent $LogFilePath "ConnectorNotInstalled" NDES_Validation 3 @@ -1384,11 +1310,11 @@ Log-ScriptEvent $LogFilePath "Checking Intune Connector is installed" NDES_Valid #region Checking Intune Connector registry keys (KeyRecoveryAgentCertificate, PfxSigningCertificate and SigningCertificate) -Write-host -Write-host "......................................................." -Write-host +Write-Host +Write-Host "......................................................." +Write-Host Write-Host "Checking Intune Connector registry keys are intact" -ForegroundColor Yellow -Write-host +Write-Host Log-ScriptEvent $LogFilePath "Checking Intune Connector registry keys are intact" NDES_Validation 1 $ErrorActionPreference = "SilentlyContinue" @@ -1398,7 +1324,7 @@ $SigningCertificate = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MicrosoftIntune\NDE if (-not ($KeyRecoveryAgentCertificate)){ - Write-host "Error: KeyRecoveryAgentCertificate Registry key does not exist." -BackgroundColor Red + Write-Host "Error: KeyRecoveryAgentCertificate Registry key does not exist." -BackgroundColor Red Write-Host Log-ScriptEvent $LogFilePath "KeyRecoveryAgentCertificate Registry key does not exist." NDES_Validation 3 @@ -1429,7 +1355,7 @@ $SigningCertificate = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MicrosoftIntune\NDE if (-not ($PfxSigningCertificate)){ - Write-host "Error: PfxSigningCertificate Registry key does not exist." -BackgroundColor Red + Write-Host "Error: PfxSigningCertificate Registry key does not exist." -BackgroundColor Red Write-Host Log-ScriptEvent $LogFilePath "PfxSigningCertificate Registry key does not exist." NDES_Validation 3 @@ -1461,7 +1387,7 @@ $SigningCertificate = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MicrosoftIntune\NDE if (-not ($SigningCertificate)){ - Write-host "Error: SigningCertificate Registry key does not exist." -BackgroundColor Red + Write-Host "Error: SigningCertificate Registry key does not exist." -BackgroundColor Red Write-Host Log-ScriptEvent $LogFilePath "SigningCertificate Registry key does not exist" NDES_Validation 3 @@ -1503,18 +1429,18 @@ $ErrorActionPreference = "Continue" $ErrorActionPreference = "SilentlyContinue" $EventLogCollDays = ((Get-Date).AddDays(-5)) #Number of days to go back in the event log -Write-host -Write-host "......................................................." -Write-host +Write-Host +Write-Host "......................................................." +Write-Host Write-Host "Checking Event logs for pertinent errors..." -ForegroundColor Yellow -Write-host +Write-Host Log-ScriptEvent $LogFilePath "Checking Event logs for pertinent errors" NDES_Validation 1 if (-not (Get-EventLog -LogName "Microsoft Intune Connector" -EntryType Error -After $EventLogCollDays -ErrorAction silentlycontinue)) { Write-Host "Success: " -ForegroundColor Green -NoNewline - write-host "No errors found in the Microsoft Intune Connector" - Write-host + Write-Host "No errors found in the Microsoft Intune Connector" + Write-Host Log-ScriptEvent $LogFilePath "No errors found in the Microsoft Intune Connector" NDES_Validation 1 } @@ -1541,8 +1467,8 @@ Log-ScriptEvent $LogFilePath "Checking Event logs for pertinent errors" NDES_Val if (-not (Get-EventLog -LogName "Application" -EntryType Error -Source NDESConnector,Microsoft-Windows-NetworkDeviceEnrollmentService -After $EventLogCollDays -ErrorAction silentlycontinue)) { Write-Host "Success: " -ForegroundColor Green -NoNewline - write-host "No errors found in the Application log from source NetworkDeviceEnrollmentService or NDESConnector" - Write-host + Write-Host "No errors found in the Application log from source NetworkDeviceEnrollmentService or NDESConnector" + Write-Host Log-ScriptEvent $LogFilePath "No errors found in the Application log from source NetworkDeviceEnrollmentService or NDESConnector" NDES_Validation 1 } @@ -1573,22 +1499,25 @@ $ErrorActionPreference = "Continue" #region Zip up logfiles -Write-host -Write-host "......................................................." -Write-host -Write-host "Log Files..." -ForegroundColor Yellow -Write-host -write-host "Do you want to gather troubleshooting files? This includes IIS, NDES Connector, NDES Plugin, CRP, and MSCEP log files, in addition to the SCEP template configuration. [Y]es, [N]o:" -$LogFileCollectionConfirmation = Read-Host - +Write-Host +Write-Host "......................................................." +Write-Host +Write-Host "Log Files..." -ForegroundColor Yellow +Write-Host +if ($PSCmdlet.ParameterSetName -eq "Unattended") { + Write-Host "Automatically gathering files." + $LogFileCollectionConfirmation = "y" + } +else { + Write-Host "Do you want to gather troubleshooting files? This includes IIS, NDES Connector, NDES Plugin, CRP, and MSCEP log files, in addition to the SCEP template configuration. [Y]es, [N]o:" + $LogFileCollectionConfirmation = Read-Host + } + if ($LogFileCollectionConfirmation -eq "y"){ $IISLogPath = (Get-WebConfigurationProperty "/system.applicationHost/sites/siteDefaults" -name logfile.directory).Value + "\W3SVC1" -replace "%SystemDrive%",$env:SystemDrive $IISLogs = Get-ChildItem $IISLogPath| Sort-Object -Descending -Property LastWriteTime | Select-Object -First 3 - $NDESConnectorLogs = Get-ChildItem "C:\Program Files\Microsoft Intune\NDESConnectorSvc\Logs\Logs\NDESConnector*" | Sort-Object -Descending -Property LastWriteTime | Select-Object -First 3 - $NDESPluginLogs = Get-ChildItem "C:\Program Files\Microsoft Intune\NDESPolicyModule\Logs\NDESPlugin.log" - $MSCEPLogs = Get-ChildItem "c:\users\*\mscep.log" | Sort-Object -Descending -Property LastWriteTime | Select-Object -First 3 - $CRPLogs = Get-ChildItem "C:\Program Files\Microsoft Intune\NDESConnectorSvc\Logs\Logs\CertificateRegistrationPoint*" | Sort-Object -Descending -Property LastWriteTime | Select-Object -First 3 + $NDESConnectorLogs = Get-ChildItem "$env:SystemRoot\System32\Winevt\Logs\Microsoft-Intune-CertificateConnectors*" foreach ($IISLog in $IISLogs){ @@ -1627,13 +1556,13 @@ $LogFileCollectionConfirmation = Read-Host Add-Type -assembly "system.io.compression.filesystem" $Currentlocation = $env:temp - $date = Get-Date -Format ddMMyyhhmm - [io.compression.zipfile]::CreateFromDirectory($TempDirPath, "$($Currentlocation)\$($date)-Logs-$($hostname).zip") + $date = Get-Date -Format ddMMyyhhmmss + [io.compression.zipfile]::CreateFromDirectory($TempDirPath, "$($Currentlocation)\$($date)-CertConnectorLogs-$($hostname).zip") - Write-host + Write-Host Write-Host "Success: " -ForegroundColor Green -NoNewline - write-host "Log files copied to $($Currentlocation)\$($date)-Logs-$($hostname).zip" - Write-host + Write-Host "Log files copied to $($Currentlocation)\$($date)-Logs-$($hostname).zip" + Write-Host } @@ -1651,20 +1580,27 @@ $LogFileCollectionConfirmation = Read-Host #region Ending script -Write-host -Write-host "......................................................." -Write-host -Write-host "End of NDES configuration validation" -ForegroundColor Yellow +Write-Host +Write-Host "......................................................." +Write-Host +Write-Host "End of NDES configuration validation" -ForegroundColor Yellow Write-Host if ($WriteLogOutputPath -eq $True) { - write-host "Log file copied to $($LogFilePath)" + Write-Host "Log file copied to $($LogFilePath)" Write-Host + # for ODC + $copyPath = "$env:temp\CollectedData\Intune\Files\NDES" + if ($PSCmdlet.ParameterSetName -eq "Unattended" ){ + if ( -not (test-path $copyPath) ) { mkdir $copyPath -Force } + copy $LogFilePath $copyPath + } + } -write-host "Ending script..." -ForegroundColor Yellow -Write-host +Write-Host "Ending script..." -ForegroundColor Yellow +Write-Host #endregion @@ -1675,9 +1611,9 @@ Write-host else { Write-Host -Write-host "......................................................." +Write-Host "......................................................." Write-Host -Write-host "Incorrect variables. Please run the script again..." -ForegroundColor Red +Write-Host "Incorrect variables. Please run the script again..." -ForegroundColor Red Write-Host Write-Host "Exiting................................................" Write-Host diff --git a/CertificationAuthority/Validate-NDESUrl.ps1 b/CertificationAuthority/Validate-NDESUrl.ps1 index 8e50e03..f562f48 100644 --- a/CertificationAuthority/Validate-NDESUrl.ps1 +++ b/CertificationAuthority/Validate-NDESUrl.ps1 @@ -303,7 +303,8 @@ Write-host Write-Host "Using a query size of $($querysize)KB... " Write-Host $challengeBase = "NDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallengeNDESLongUrlValidatorFakeChallenge"; - +$testChallenge = $null + for ($i=1; $i -le $querySize; $i++){ $testChallenge += $challengeBase + ($i + 1) @@ -354,4 +355,4 @@ Write-Host write-host "Ending script..." -ForegroundColor Yellow Write-host -#endregion \ No newline at end of file +#endregion diff --git a/DeviceConfiguration/DeviceConfiguration_Add_Assign.ps1 b/DeviceConfiguration/DeviceConfiguration_Add_Assign.ps1 index c43d2ea..d156146 100644 --- a/DeviceConfiguration/DeviceConfiguration_Add_Assign.ps1 +++ b/DeviceConfiguration/DeviceConfiguration_Add_Assign.ps1 @@ -214,84 +214,230 @@ Write-Verbose "Resource: $DCP_resource" Function Add-DeviceConfigurationPolicyAssignment(){ -<# -.SYNOPSIS -This function is used to add a device configuration policy assignment using the Graph API REST interface -.DESCRIPTION -The function connects to the Graph API Interface and adds a device configuration policy assignment -.EXAMPLE -Add-DeviceConfigurationPolicyAssignment -ConfigurationPolicyId $ConfigurationPolicyId -TargetGroupId $TargetGroupId -Adds a device configuration policy assignment in Intune -.NOTES -NAME: Add-DeviceConfigurationPolicyAssignment -#> - -[cmdletbinding()] - -param -( - $ConfigurationPolicyId, - $TargetGroupId -) - -$graphApiVersion = "Beta" -$Resource = "deviceManagement/deviceConfigurations/$ConfigurationPolicyId/assign" + <# + .SYNOPSIS + This function is used to add a device configuration policy assignment using the Graph API REST interface + .DESCRIPTION + The function connects to the Graph API Interface and adds a device configuration policy assignment + .EXAMPLE + Add-DeviceConfigurationPolicyAssignment -ConfigurationPolicyId $ConfigurationPolicyId -TargetGroupId $TargetGroupId -AssignmentType Included + Adds a device configuration policy assignment in Intune + .NOTES + NAME: Add-DeviceConfigurationPolicyAssignment + #> + + [cmdletbinding()] + + param + ( + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + $ConfigurationPolicyId, + + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + $TargetGroupId, + + [parameter(Mandatory=$true)] + [ValidateSet("Included","Excluded")] + [ValidateNotNullOrEmpty()] + [string]$AssignmentType + ) + + $graphApiVersion = "Beta" + $Resource = "deviceManagement/deviceConfigurations/$ConfigurationPolicyId/assign" + + try { + + if(!$ConfigurationPolicyId){ + + write-host "No Configuration Policy Id specified, specify a valid Configuration Policy Id" -f Red + break + + } + + if(!$TargetGroupId){ + + write-host "No Target Group Id specified, specify a valid Target Group Id" -f Red + break + + } + + # Checking if there are Assignments already configured in the Policy + $DCPA = Get-DeviceConfigurationPolicyAssignment -id $ConfigurationPolicyId + + $TargetGroups = @() + + if(@($DCPA).count -ge 1){ + + if($DCPA.targetGroupId -contains $TargetGroupId){ + + Write-Host "Group with Id '$TargetGroupId' already assigned to Policy..." -ForegroundColor Red + Write-Host + break + + } + + # Looping through previously configured assignements + + $DCPA | foreach { + + $TargetGroup = New-Object -TypeName psobject + + if($_.excludeGroup -eq $true){ + + $TargetGroup | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value '#microsoft.graph.exclusionGroupAssignmentTarget' + + } + + else { + + $TargetGroup | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value '#microsoft.graph.groupAssignmentTarget' + + } + + $TargetGroup | Add-Member -MemberType NoteProperty -Name 'groupId' -Value $_.targetGroupId + + $Target = New-Object -TypeName psobject + $Target | Add-Member -MemberType NoteProperty -Name 'target' -Value $TargetGroup + + $TargetGroups += $Target + + } + + # Adding new group to psobject + $TargetGroup = New-Object -TypeName psobject + + if($AssignmentType -eq "Excluded"){ + + $TargetGroup | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value '#microsoft.graph.exclusionGroupAssignmentTarget' + + } + + elseif($AssignmentType -eq "Included") { + + $TargetGroup | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value '#microsoft.graph.groupAssignmentTarget' + + } + + $TargetGroup | Add-Member -MemberType NoteProperty -Name 'groupId' -Value "$TargetGroupId" + + $Target = New-Object -TypeName psobject + $Target | Add-Member -MemberType NoteProperty -Name 'target' -Value $TargetGroup + + $TargetGroups += $Target + + } + + else { + + # No assignments configured creating new JSON object of group assigned + + $TargetGroup = New-Object -TypeName psobject + + if($AssignmentType -eq "Excluded"){ + + $TargetGroup | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value '#microsoft.graph.exclusionGroupAssignmentTarget' + + } + + elseif($AssignmentType -eq "Included") { + + $TargetGroup | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value '#microsoft.graph.groupAssignmentTarget' + + } + + $TargetGroup | Add-Member -MemberType NoteProperty -Name 'groupId' -Value "$TargetGroupId" + + $Target = New-Object -TypeName psobject + $Target | Add-Member -MemberType NoteProperty -Name 'target' -Value $TargetGroup + + $TargetGroups = $Target + + } + + # Creating JSON object to pass to Graph + $Output = New-Object -TypeName psobject + + $Output | Add-Member -MemberType NoteProperty -Name 'assignments' -Value @($TargetGroups) + + $JSON = $Output | ConvertTo-Json -Depth 3 + + # POST to Graph Service + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + Invoke-RestMethod -Uri $uri -Headers $authToken -Method Post -Body $JSON -ContentType "application/json" - try { - - if(!$ConfigurationPolicyId){ - - write-host "No Configuration Policy Id specified, specify a valid Configuration Policy Id" -f Red - break - } - - if(!$TargetGroupId){ - - write-host "No Target Group Id specified, specify a valid Target Group Id" -f Red + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host break - + } - - $ConfPolAssign = "$ConfigurationPolicyId" + "_" + "$TargetGroupId" - -$JSON = @" - -{ - "deviceConfigurationGroupAssignments": [ - { - "@odata.type": "#microsoft.graph.deviceConfigurationGroupAssignment", - "id": "$ConfPolAssign", - "targetGroupId": "$TargetGroupId" + } - ] -} -"@ - - $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" - Invoke-RestMethod -Uri $uri -Headers $authToken -Method Post -Body $JSON -ContentType "application/json" +#################################################### - } +Function Get-DeviceConfigurationPolicyAssignment(){ + + <# + .SYNOPSIS + This function is used to get device configuration policy assignment from the Graph API REST interface + .DESCRIPTION + The function connects to the Graph API Interface and gets a device configuration policy assignment + .EXAMPLE + Get-DeviceConfigurationPolicyAssignment $id guid + Returns any device configuration policy assignment configured in Intune + .NOTES + NAME: Get-DeviceConfigurationPolicyAssignment + #> + + [cmdletbinding()] + + param + ( + [Parameter(Mandatory=$true,HelpMessage="Enter id (guid) for the Device Configuration Policy you want to check assignment")] + $id + ) + + $graphApiVersion = "Beta" + $DCP_resource = "deviceManagement/deviceConfigurations" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)/$id/groupAssignments" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } - catch { - - $ex = $_.Exception - $errorResponse = $ex.Response.GetResponseStream() - $reader = New-Object System.IO.StreamReader($errorResponse) - $reader.BaseStream.Position = 0 - $reader.DiscardBufferedData() - $responseBody = $reader.ReadToEnd(); - Write-Host "Response content:`n$responseBody" -f Red - Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" - write-host - break - } - -} - -#################################################### + + #################################################### Function Test-JSON(){ @@ -700,7 +846,7 @@ Write-Host "Device Restriction Policy created as" $CreateResult_Android.id write-host write-host "Assigning Device Restriction Policy to AAD Group '$AADGroup'" -f Cyan -$Assign_Android = Add-DeviceConfigurationPolicyAssignment -ConfigurationPolicyId $CreateResult_Android.id -TargetGroupId $TargetGroupId +$Assign_Android = Add-DeviceConfigurationPolicyAssignment -ConfigurationPolicyId $CreateResult_Android.id -TargetGroupId $TargetGroupId -AssignmentType Included Write-Host "Assigned '$AADGroup' to $($CreateResult_Android.displayName)/$($CreateResult_Android.id)" Write-Host @@ -716,7 +862,7 @@ Write-Host "Device Restriction Policy created as" $CreateResult_iOS.id write-host write-host "Assigning Device Restriction Policy to AAD Group '$AADGroup'" -f Cyan -$Assign_iOS = Add-DeviceConfigurationPolicyAssignment -ConfigurationPolicyId $CreateResult_iOS.id -TargetGroupId $TargetGroupId +$Assign_iOS = Add-DeviceConfigurationPolicyAssignment -ConfigurationPolicyId $CreateResult_iOS.id -TargetGroupId $TargetGroupId -AssignmentType Included Write-Host "Assigned '$AADGroup' to $($CreateResult_iOS.displayName)/$($CreateResult_iOS.id)" Write-Host diff --git a/DeviceConfiguration/DeviceConfiguration_Export.ps1 b/DeviceConfiguration/DeviceConfiguration_Export.ps1 index 3e97351..ab069ea 100644 --- a/DeviceConfiguration/DeviceConfiguration_Export.ps1 +++ b/DeviceConfiguration/DeviceConfiguration_Export.ps1 @@ -219,51 +219,38 @@ $ExportPath if($JSON -eq "" -or $JSON -eq $null){ - write-host "No JSON specified, please specify valid JSON..." -f Red + write-host "No JSON specified, please specify valid JSON..." -f Red } elseif(!$ExportPath){ - write-host "No export path parameter set, please provide a path to export the file" -f Red + write-host "No export path parameter set, please provide a path to export the file" -f Red } elseif(!(Test-Path $ExportPath)){ - write-host "$ExportPath doesn't exist, can't export JSON Data" -f Red + write-host "$ExportPath doesn't exist, can't export JSON Data" -f Red } else { - $JSON1 = ConvertTo-Json $JSON -Depth 5 + $JSON1 = ConvertTo-Json $JSON -Depth 5 - $JSON_Convert = $JSON1 | ConvertFrom-Json + $JSON_Convert = $JSON1 | ConvertFrom-Json - $displayName = $JSON_Convert.displayName + $displayName = $JSON_Convert.displayName - # Updating display name to follow file naming conventions - https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx - $DisplayName = $DisplayName -replace '\<|\>|:|"|/|\\|\||\?|\*', "_" + # Updating display name to follow file naming conventions - https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx + $DisplayName = $DisplayName -replace '\<|\>|:|"|/|\\|\||\?|\*', "_" - $Properties = ($JSON_Convert | Get-Member | ? { $_.MemberType -eq "NoteProperty" }).Name - - $FileName_CSV = "$DisplayName" + "_" + $(get-date -f dd-MM-yyyy-H-mm-ss) + ".csv" $FileName_JSON = "$DisplayName" + "_" + $(get-date -f dd-MM-yyyy-H-mm-ss) + ".json" - $Object = New-Object System.Object - - foreach($Property in $Properties){ - - $Object | Add-Member -MemberType NoteProperty -Name $Property -Value $JSON_Convert.$Property - - } - write-host "Export Path:" "$ExportPath" - $Object | Export-Csv -LiteralPath "$ExportPath\$FileName_CSV" -Delimiter "," -NoTypeInformation -Append $JSON1 | Set-Content -LiteralPath "$ExportPath\$FileName_JSON" - write-host "CSV created in $ExportPath\$FileName_CSV..." -f cyan write-host "JSON created in $ExportPath\$FileName_JSON..." -f cyan } @@ -365,8 +352,8 @@ $ExportPath = Read-Host -Prompt "Please specify a path to export the policy data Write-Host -$DCPs = Get-DeviceConfigurationPolicy - +# Filtering out iOS and Windows Software Update Policies +$DCPs = Get-DeviceConfigurationPolicy | Where-Object { ($_.'@odata.type' -ne "#microsoft.graph.iosUpdateConfiguration") -and ($_.'@odata.type' -ne "#microsoft.graph.windowsUpdateForBusinessConfiguration") } foreach($DCP in $DCPs){ write-host "Device Configuration Policy:"$DCP.displayName -f Yellow diff --git a/DeviceConfiguration/DeviceConfiguration_Get_Assign.ps1 b/DeviceConfiguration/DeviceConfiguration_Get_Assign.ps1 new file mode 100644 index 0000000..72e68ef --- /dev/null +++ b/DeviceConfiguration/DeviceConfiguration_Get_Assign.ps1 @@ -0,0 +1,620 @@ + +<# + +.COPYRIGHT +Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +See LICENSE in the project root for license information. + +#> + +#################################################### + +function Get-AuthToken { + +<# +.SYNOPSIS +This function is used to authenticate with the Graph API REST interface +.DESCRIPTION +The function authenticate with the Graph API Interface with the tenant name +.EXAMPLE +Get-AuthToken +Authenticates you with the Graph API interface +.NOTES +NAME: Get-AuthToken +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + $User +) + +$userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User + +$tenant = $userUpn.Host + +Write-Host "Checking for AzureAD module..." + + $AadModule = Get-Module -Name "AzureAD" -ListAvailable + + if ($AadModule -eq $null) { + + Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview" + $AadModule = Get-Module -Name "AzureADPreview" -ListAvailable + + } + + if ($AadModule -eq $null) { + write-host + write-host "AzureAD Powershell module not installed..." -f Red + write-host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow + write-host "Script can't continue..." -f Red + write-host + exit + } + +# Getting path to ActiveDirectory Assemblies +# If the module count is greater than 1 find the latest version + + if($AadModule.count -gt 1){ + + $Latest_Version = ($AadModule | select version | Sort-Object)[-1] + + $aadModule = $AadModule | ? { $_.version -eq $Latest_Version.version } + + # Checking if there are multiple versions of the same module found + + if($AadModule.count -gt 1){ + + $aadModule = $AadModule | select -Unique + + } + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + + else { + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + +[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null + +[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null + +$clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" + +$redirectUri = "urn:ietf:wg:oauth:2.0:oob" + +$resourceAppIdURI = "https://graph.microsoft.com" + +$authority = "https://login.microsoftonline.com/$Tenant" + + try { + + $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority + + # https://msdn.microsoft.com/en-us/library/azure/microsoft.identitymodel.clients.activedirectory.promptbehavior.aspx + # Change the prompt behaviour to force credentials each time: Auto, Always, Never, RefreshSession + + $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto" + + $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId") + + $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result + + # If the accesstoken is valid then create the authentication header + + if($authResult.AccessToken){ + + # Creating header for Authorization token + + $authHeader = @{ + 'Content-Type'='application/json' + 'Authorization'="Bearer " + $authResult.AccessToken + 'ExpiresOn'=$authResult.ExpiresOn + } + + return $authHeader + + } + + else { + + Write-Host + Write-Host "Authorization Access Token is null, please re-run authentication..." -ForegroundColor Red + Write-Host + break + + } + + } + + catch { + + write-host $_.Exception.Message -f Red + write-host $_.Exception.ItemName -f Red + write-host + break + + } + +} + +#################################################### + +Function Get-DeviceConfigurationPolicy(){ + +<# +.SYNOPSIS +This function is used to get device configuration policies from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets any device configuration policies +.EXAMPLE +Get-DeviceConfigurationPolicy +Returns any device configuration policies configured in Intune +.NOTES +NAME: Get-DeviceConfigurationPolicy +#> + +[cmdletbinding()] + +param +( + $name +) + +$graphApiVersion = "beta" +$DCP_resource = "deviceManagement/deviceConfigurations" + + try { + + if($Name){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)?`$filter=displayName eq '$name'" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).value + + } + + else { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Get-DeviceConfigurationPolicyAssignment(){ + +<# +.SYNOPSIS +This function is used to get device configuration policy assignment from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets a device configuration policy assignment +.EXAMPLE +Get-DeviceConfigurationPolicyAssignment $id guid +Returns any device configuration policy assignment configured in Intune +.NOTES +NAME: Get-DeviceConfigurationPolicyAssignment +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true,HelpMessage="Enter id (guid) for the Device Configuration Policy you want to check assignment")] + $id +) + +$graphApiVersion = "Beta" +$DCP_resource = "deviceManagement/deviceConfigurations" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)/$id/groupAssignments" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Add-DeviceConfigurationPolicyAssignment(){ + +<# +.SYNOPSIS +This function is used to add a device configuration policy assignment using the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and adds a device configuration policy assignment +.EXAMPLE +Add-DeviceConfigurationPolicyAssignment -ConfigurationPolicyId $ConfigurationPolicyId -TargetGroupId $TargetGroupId +Adds a device configuration policy assignment in Intune +.NOTES +NAME: Add-DeviceConfigurationPolicyAssignment +#> + +[cmdletbinding()] + +param +( + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + $ConfigurationPolicyId, + + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + $TargetGroupId, + + [parameter(Mandatory=$true)] + [ValidateSet("Included","Excluded")] + [ValidateNotNullOrEmpty()] + [string]$AssignmentType +) + +$graphApiVersion = "Beta" +$Resource = "deviceManagement/deviceConfigurations/$ConfigurationPolicyId/assign" + + try { + + if(!$ConfigurationPolicyId){ + + write-host "No Configuration Policy Id specified, specify a valid Configuration Policy Id" -f Red + break + + } + + if(!$TargetGroupId){ + + write-host "No Target Group Id specified, specify a valid Target Group Id" -f Red + break + + } + + # Checking if there are Assignments already configured in the Policy + $DCPA = Get-DeviceConfigurationPolicyAssignment -id $ConfigurationPolicyId + + $TargetGroups = @() + + if(@($DCPA).count -ge 1){ + + if($DCPA.targetGroupId -contains $TargetGroupId){ + + Write-Host "Group with Id '$TargetGroupId' already assigned to Policy..." -ForegroundColor Red + Write-Host + break + + } + + # Looping through previously configured assignements + + $DCPA | foreach { + + $TargetGroup = New-Object -TypeName psobject + + if($_.excludeGroup -eq $true){ + + $TargetGroup | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value '#microsoft.graph.exclusionGroupAssignmentTarget' + + } + + else { + + $TargetGroup | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value '#microsoft.graph.groupAssignmentTarget' + + } + + $TargetGroup | Add-Member -MemberType NoteProperty -Name 'groupId' -Value $_.targetGroupId + + $Target = New-Object -TypeName psobject + $Target | Add-Member -MemberType NoteProperty -Name 'target' -Value $TargetGroup + + $TargetGroups += $Target + + } + + # Adding new group to psobject + $TargetGroup = New-Object -TypeName psobject + + if($AssignmentType -eq "Excluded"){ + + $TargetGroup | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value '#microsoft.graph.exclusionGroupAssignmentTarget' + + } + + elseif($AssignmentType -eq "Included") { + + $TargetGroup | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value '#microsoft.graph.groupAssignmentTarget' + + } + + $TargetGroup | Add-Member -MemberType NoteProperty -Name 'groupId' -Value "$TargetGroupId" + + $Target = New-Object -TypeName psobject + $Target | Add-Member -MemberType NoteProperty -Name 'target' -Value $TargetGroup + + $TargetGroups += $Target + + } + + else { + + # No assignments configured creating new JSON object of group assigned + + $TargetGroup = New-Object -TypeName psobject + + if($AssignmentType -eq "Excluded"){ + + $TargetGroup | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value '#microsoft.graph.exclusionGroupAssignmentTarget' + + } + + elseif($AssignmentType -eq "Included") { + + $TargetGroup | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value '#microsoft.graph.groupAssignmentTarget' + + } + + $TargetGroup | Add-Member -MemberType NoteProperty -Name 'groupId' -Value "$TargetGroupId" + + $Target = New-Object -TypeName psobject + $Target | Add-Member -MemberType NoteProperty -Name 'target' -Value $TargetGroup + + $TargetGroups = $Target + + } + + # Creating JSON object to pass to Graph + $Output = New-Object -TypeName psobject + + $Output | Add-Member -MemberType NoteProperty -Name 'assignments' -Value @($TargetGroups) + + $JSON = $Output | ConvertTo-Json -Depth 3 + + # POST to Graph Service + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + Invoke-RestMethod -Uri $uri -Headers $authToken -Method Post -Body $JSON -ContentType "application/json" + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Get-AADGroup(){ + +<# +.SYNOPSIS +This function is used to get AAD Groups from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets any Groups registered with AAD +.EXAMPLE +Get-AADGroup +Returns all users registered with Azure AD +.NOTES +NAME: Get-AADGroup +#> + +[cmdletbinding()] + +param +( + $GroupName, + $id, + [switch]$Members +) + +# Defining Variables +$graphApiVersion = "v1.0" +$Group_resource = "groups" + + try { + + if($id){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Group_resource)?`$filter=id eq '$id'" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + elseif($GroupName -eq "" -or $GroupName -eq $null){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Group_resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + else { + + if(!$Members){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Group_resource)?`$filter=displayname eq '$GroupName'" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + elseif($Members){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Group_resource)?`$filter=displayname eq '$GroupName'" + $Group = (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + if($Group){ + + $GID = $Group.id + + $Group.displayName + write-host + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Group_resource)/$GID/Members" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + } + + } + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +#region Authentication + +write-host + +# Checking if authToken exists before running authentication +if($global:authToken){ + + # Setting DateTime to Universal time to work in all timezones + $DateTime = (Get-Date).ToUniversalTime() + + # If the authToken exists checking when it expires + $TokenExpires = ($authToken.ExpiresOn.datetime - $DateTime).Minutes + + if($TokenExpires -le 0){ + + write-host "Authentication Token expired" $TokenExpires "minutes ago" -ForegroundColor Yellow + write-host + + # Defining User Principal Name if not present + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + + $global:authToken = Get-AuthToken -User $User + + } +} + +# Authentication doesn't exist, calling Get-AuthToken function + +else { + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + +# Getting the authorization token +$global:authToken = Get-AuthToken -User $User + +} + +#endregion + +#################################################### + +# Setting application AAD Group to assign Policy + +$AADGroup = Read-Host -Prompt "Enter the Azure AD Group name where policies will be assigned" + +$TargetGroupId = (get-AADGroup -GroupName "$AADGroup").id + + + if($TargetGroupId -eq $null -or $TargetGroupId -eq ""){ + + Write-Host "AAD Group - '$AADGroup' doesn't exist, please specify a valid AAD Group..." -ForegroundColor Red + Write-Host + exit + + } + +#################################################### + +$PolicyName = "Device Configuration Policy Name" + +$DCP = Get-DeviceConfigurationPolicy -name "$PolicyName" + +if($DCP){ + + $Assignment = Add-DeviceConfigurationPolicyAssignment -ConfigurationPolicyId $DCP.id -TargetGroupId $TargetGroupId -AssignmentType Included + Write-Host "Assigned '$AADGroup' to $($DCP.displayName)/$($DCP.id)" -ForegroundColor Green + Write-Host + +} + +else { + + Write-Host "Can't find Device Configuration Policy with name '$PolicyName'..." -ForegroundColor Red + Write-Host + +} \ No newline at end of file diff --git a/DeviceConfiguration/Readme.md b/DeviceConfiguration/Readme.md index c567bef..62438d8 100644 --- a/DeviceConfiguration/Readme.md +++ b/DeviceConfiguration/Readme.md @@ -225,9 +225,10 @@ This function is used to assign a policy to an AAD Group. This function has two + ConfigurationPolicyId - The policy ID defined in the Intune Service + TargetGroupId - The AAD Group ID where the policy should be assigned ++ AssignmentType - Choose whether the assignment is an inclusion or exclusion ```PowerShell -Add-DeviceConfigurationPolicyAssignment -ConfigurationPolicyId $CreateResult_Android.id -TargetGroupId $TargetGroupId +Add-DeviceConfigurationPolicyAssignment -ConfigurationPolicyId $CreateResult_Android.id -TargetGroupId $TargetGroupId -AssignmentType Included ``` #### Get-AADGroup Function @@ -406,4 +407,4 @@ This function is used to assign a device management script to an AAD Group. This ```PowerShell Add-DeviceManagementScriptAssignment -ScriptId $Create_Local_Script.id -TargetGroupId $TargetGroupId -``` \ No newline at end of file +``` diff --git a/EndpointSecurity/EndpointSecurityPolicy_Export.ps1 b/EndpointSecurity/EndpointSecurityPolicy_Export.ps1 new file mode 100644 index 0000000..4e16918 --- /dev/null +++ b/EndpointSecurity/EndpointSecurityPolicy_Export.ps1 @@ -0,0 +1,587 @@ + +<# + +.COPYRIGHT +Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +See LICENSE in the project root for license information. + +#> + +#################################################### + +function Get-AuthToken { + +<# +.SYNOPSIS +This function is used to authenticate with the Graph API REST interface +.DESCRIPTION +The function authenticate with the Graph API Interface with the tenant name +.EXAMPLE +Get-AuthToken +Authenticates you with the Graph API interface +.NOTES +NAME: Get-AuthToken +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + $User +) + +$userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User + +$tenant = $userUpn.Host + +Write-Host "Checking for AzureAD module..." + + $AadModule = Get-Module -Name "AzureAD" -ListAvailable + + if ($AadModule -eq $null) { + + Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview" + $AadModule = Get-Module -Name "AzureADPreview" -ListAvailable + + } + + if ($AadModule -eq $null) { + write-host + write-host "AzureAD Powershell module not installed..." -f Red + write-host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow + write-host "Script can't continue..." -f Red + write-host + exit + } + +# Getting path to ActiveDirectory Assemblies +# If the module count is greater than 1 find the latest version + + if($AadModule.count -gt 1){ + + $Latest_Version = ($AadModule | select version | Sort-Object)[-1] + + $aadModule = $AadModule | ? { $_.version -eq $Latest_Version.version } + + # Checking if there are multiple versions of the same module found + + if($AadModule.count -gt 1){ + + $aadModule = $AadModule | select -Unique + + } + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + + else { + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + +[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null + +[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null + +$clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" + +$redirectUri = "urn:ietf:wg:oauth:2.0:oob" + +$resourceAppIdURI = "https://graph.microsoft.com" + +$authority = "https://login.microsoftonline.com/$Tenant" + + try { + + $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority + + # https://msdn.microsoft.com/en-us/library/azure/microsoft.identitymodel.clients.activedirectory.promptbehavior.aspx + # Change the prompt behaviour to force credentials each time: Auto, Always, Never, RefreshSession + + $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto" + + $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId") + + $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result + + # If the accesstoken is valid then create the authentication header + + if($authResult.AccessToken){ + + # Creating header for Authorization token + + $authHeader = @{ + 'Content-Type'='application/json' + 'Authorization'="Bearer " + $authResult.AccessToken + 'ExpiresOn'=$authResult.ExpiresOn + } + + return $authHeader + + } + + else { + + Write-Host + Write-Host "Authorization Access Token is null, please re-run authentication..." -ForegroundColor Red + Write-Host + break + + } + + } + + catch { + + write-host $_.Exception.Message -f Red + write-host $_.Exception.ItemName -f Red + write-host + break + + } + +} + +#################################################### + +Function Get-EndpointSecurityTemplate(){ + +<# +.SYNOPSIS +This function is used to get all Endpoint Security templates using the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets all Endpoint Security templates +.EXAMPLE +Get-EndpointSecurityTemplate +Gets all Endpoint Security Templates in Endpoint Manager +.NOTES +NAME: Get-EndpointSecurityTemplate +#> + + +$graphApiVersion = "Beta" +$ESP_resource = "deviceManagement/templates?`$filter=(isof(%27microsoft.graph.securityBaselineTemplate%27))" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($ESP_resource)" + (Invoke-RestMethod -Method Get -Uri $uri -Headers $authToken).value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Get-EndpointSecurityPolicy(){ + +<# +.SYNOPSIS +This function is used to get all Endpoint Security policies using the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets all Endpoint Security templates +.EXAMPLE +Get-EndpointSecurityPolicy +Gets all Endpoint Security Policies in Endpoint Manager +.NOTES +NAME: Get-EndpointSecurityPolicy +#> + + +$graphApiVersion = "Beta" +$ESP_resource = "deviceManagement/intents" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($ESP_resource)" + (Invoke-RestMethod -Method Get -Uri $uri -Headers $authToken).value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Get-EndpointSecurityTemplateCategory(){ + +<# +.SYNOPSIS +This function is used to get all Endpoint Security categories from a specific template using the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets all template categories +.EXAMPLE +Get-EndpointSecurityTemplateCategory -TemplateId $templateId +Gets an Endpoint Security Categories from a specific template in Endpoint Manager +.NOTES +NAME: Get-EndpointSecurityTemplateCategory +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + $TemplateId +) + +$graphApiVersion = "Beta" +$ESP_resource = "deviceManagement/templates/$TemplateId/categories" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($ESP_resource)" + (Invoke-RestMethod -Method Get -Uri $uri -Headers $authToken).value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Get-EndpointSecurityCategorySetting(){ + +<# +.SYNOPSIS +This function is used to get an Endpoint Security category setting from a specific policy using the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets a policy category setting +.EXAMPLE +Get-EndpointSecurityCategorySetting -PolicyId $policyId -categoryId $categoryId +Gets an Endpoint Security Categories from a specific template in Endpoint Manager +.NOTES +NAME: Get-EndpointSecurityCategory +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + $PolicyId, + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + $categoryId +) + +$graphApiVersion = "Beta" +$ESP_resource = "deviceManagement/intents/$policyId/categories/$categoryId/settings?`$expand=Microsoft.Graph.DeviceManagementComplexSettingInstance/Value" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($ESP_resource)" + (Invoke-RestMethod -Method Get -Uri $uri -Headers $authToken).value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Export-JSONData(){ + +<# +.SYNOPSIS +This function is used to export JSON data returned from Graph +.DESCRIPTION +This function is used to export JSON data returned from Graph +.EXAMPLE +Export-JSONData -JSON $JSON +Export the JSON inputted on the function +.NOTES +NAME: Export-JSONData +#> + +param ( + +$JSON, +$ExportPath + +) + + try { + + if($JSON -eq "" -or $JSON -eq $null){ + + write-host "No JSON specified, please specify valid JSON..." -f Red + + } + + elseif(!$ExportPath){ + + write-host "No export path parameter set, please provide a path to export the file" -f Red + + } + + elseif(!(Test-Path $ExportPath)){ + + write-host "$ExportPath doesn't exist, can't export JSON Data" -f Red + + } + + else { + + $JSON1 = ConvertTo-Json $JSON -Depth 5 + + $JSON_Convert = $JSON1 | ConvertFrom-Json + + $displayName = $JSON_Convert.displayName + + # Updating display name to follow file naming conventions - https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx + $DisplayName = $DisplayName -replace '\<|\>|:|"|/|\\|\||\?|\*', "_" + + # Added milliseconds to date format due to duplicate policy name + $FileName_JSON = "$DisplayName" + "_" + $(get-date -f dd-MM-yyyy-H-mm-ss.fff) + ".json" + + write-host "Export Path:" "$ExportPath" + + $JSON1 | Set-Content -LiteralPath "$ExportPath\$FileName_JSON" + write-host "JSON created in $ExportPath\$FileName_JSON..." -f cyan + + } + + } + + catch { + + $_.Exception + + } + +} + +#################################################### + +#region Authentication + +write-host + +# Checking if authToken exists before running authentication +if($global:authToken){ + + # Setting DateTime to Universal time to work in all timezones + $DateTime = (Get-Date).ToUniversalTime() + + # If the authToken exists checking when it expires + $TokenExpires = ($authToken.ExpiresOn.datetime - $DateTime).Minutes + + if($TokenExpires -le 0){ + + write-host "Authentication Token expired" $TokenExpires "minutes ago" -ForegroundColor Yellow + write-host + + # Defining User Principal Name if not present + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + + $global:authToken = Get-AuthToken -User $User + + } +} + +# Authentication doesn't exist, calling Get-AuthToken function + +else { + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + +# Getting the authorization token +$global:authToken = Get-AuthToken -User $User + +} + +#endregion + +#################################################### + +#region ExportPath + +$ExportPath = Read-Host -Prompt "Please specify a path to export the policy data to e.g. C:\IntuneOutput" + + # If the directory path doesn't exist prompt user to create the directory + $ExportPath = $ExportPath.replace('"','') + + if(!(Test-Path "$ExportPath")){ + + Write-Host + Write-Host "Path '$ExportPath' doesn't exist, do you want to create this directory? Y or N?" -ForegroundColor Yellow + + $Confirm = read-host + + if($Confirm -eq "y" -or $Confirm -eq "Y"){ + + new-item -ItemType Directory -Path "$ExportPath" | Out-Null + Write-Host + + } + + else { + + Write-Host "Creation of directory path was cancelled..." -ForegroundColor Red + Write-Host + break + + } + + } + +Write-Host + +#endregion + +#################################################### + +# Get all Endpoint Security Templates +$Templates = Get-EndpointSecurityTemplate + +#################################################### + +# Get all Endpoint Security Policies configured +$ESPolicies = Get-EndpointSecurityPolicy | Sort-Object displayName + +#################################################### + +# Looping through all policies configured +foreach($policy in $ESPolicies){ + + Write-Host "Endpoint Security Policy:"$policy.displayName -ForegroundColor Yellow + $PolicyName = $policy.displayName + $PolicyDescription = $policy.description + $policyId = $policy.id + $TemplateId = $policy.templateId + $roleScopeTagIds = $policy.roleScopeTagIds + + $ES_Template = $Templates | ? { $_.id -eq $policy.templateId } + + $TemplateDisplayName = $ES_Template.displayName + $TemplateId = $ES_Template.id + $versionInfo = $ES_Template.versionInfo + + if($TemplateDisplayName -eq "Endpoint detection and response"){ + + Write-Host "Export of 'Endpoint detection and response' policy not included in sample script..." -ForegroundColor Magenta + Write-Host + + } + + else { + + #################################################### + + # Creating object for JSON output + $JSON = New-Object -TypeName PSObject + + Add-Member -InputObject $JSON -MemberType 'NoteProperty' -Name 'displayName' -Value "$PolicyName" + Add-Member -InputObject $JSON -MemberType 'NoteProperty' -Name 'description' -Value "$PolicyDescription" + Add-Member -InputObject $JSON -MemberType 'NoteProperty' -Name 'roleScopeTagIds' -Value $roleScopeTagIds + Add-Member -InputObject $JSON -MemberType 'NoteProperty' -Name 'TemplateDisplayName' -Value "$TemplateDisplayName" + Add-Member -InputObject $JSON -MemberType 'NoteProperty' -Name 'TemplateId' -Value "$TemplateId" + Add-Member -InputObject $JSON -MemberType 'NoteProperty' -Name 'versionInfo' -Value "$versionInfo" + + #################################################### + + # Getting all categories in specified Endpoint Security Template + $Categories = Get-EndpointSecurityTemplateCategory -TemplateId $TemplateId + + # Looping through all categories within the Template + + foreach($category in $Categories){ + + $categoryId = $category.id + + $Settings += Get-EndpointSecurityCategorySetting -PolicyId $policyId -categoryId $categoryId + + } + + # Adding All settings to settingsDelta ready for JSON export + Add-Member -InputObject $JSON -MemberType 'NoteProperty' -Name 'settingsDelta' -Value @($Settings) + + #################################################### + + Export-JSONData -JSON $JSON -ExportPath "$ExportPath" + + Write-Host + + # Clearing up variables so previous data isn't exported in each policy + Clear-Variable JSON + Clear-Variable Settings + + } + +} \ No newline at end of file diff --git a/EndpointSecurity/EndpointSecurityPolicy_Get.ps1 b/EndpointSecurity/EndpointSecurityPolicy_Get.ps1 new file mode 100644 index 0000000..0adbf8f --- /dev/null +++ b/EndpointSecurity/EndpointSecurityPolicy_Get.ps1 @@ -0,0 +1,470 @@ + +<# + +.COPYRIGHT +Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +See LICENSE in the project root for license information. + +#> + +#################################################### + +function Get-AuthToken { + +<# +.SYNOPSIS +This function is used to authenticate with the Graph API REST interface +.DESCRIPTION +The function authenticate with the Graph API Interface with the tenant name +.EXAMPLE +Get-AuthToken +Authenticates you with the Graph API interface +.NOTES +NAME: Get-AuthToken +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + $User +) + +$userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User + +$tenant = $userUpn.Host + +Write-Host "Checking for AzureAD module..." + + $AadModule = Get-Module -Name "AzureAD" -ListAvailable + + if ($AadModule -eq $null) { + + Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview" + $AadModule = Get-Module -Name "AzureADPreview" -ListAvailable + + } + + if ($AadModule -eq $null) { + write-host + write-host "AzureAD Powershell module not installed..." -f Red + write-host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow + write-host "Script can't continue..." -f Red + write-host + exit + } + +# Getting path to ActiveDirectory Assemblies +# If the module count is greater than 1 find the latest version + + if($AadModule.count -gt 1){ + + $Latest_Version = ($AadModule | select version | Sort-Object)[-1] + + $aadModule = $AadModule | ? { $_.version -eq $Latest_Version.version } + + # Checking if there are multiple versions of the same module found + + if($AadModule.count -gt 1){ + + $aadModule = $AadModule | select -Unique + + } + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + + else { + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + +[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null + +[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null + +$clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" + +$redirectUri = "urn:ietf:wg:oauth:2.0:oob" + +$resourceAppIdURI = "https://graph.microsoft.com" + +$authority = "https://login.microsoftonline.com/$Tenant" + + try { + + $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority + + # https://msdn.microsoft.com/en-us/library/azure/microsoft.identitymodel.clients.activedirectory.promptbehavior.aspx + # Change the prompt behaviour to force credentials each time: Auto, Always, Never, RefreshSession + + $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto" + + $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId") + + $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result + + # If the accesstoken is valid then create the authentication header + + if($authResult.AccessToken){ + + # Creating header for Authorization token + + $authHeader = @{ + 'Content-Type'='application/json' + 'Authorization'="Bearer " + $authResult.AccessToken + 'ExpiresOn'=$authResult.ExpiresOn + } + + return $authHeader + + } + + else { + + Write-Host + Write-Host "Authorization Access Token is null, please re-run authentication..." -ForegroundColor Red + Write-Host + break + + } + + } + + catch { + + write-host $_.Exception.Message -f Red + write-host $_.Exception.ItemName -f Red + write-host + break + + } + +} + +#################################################### + +Function Get-EndpointSecurityTemplate(){ + +<# +.SYNOPSIS +This function is used to get all Endpoint Security templates using the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets all Endpoint Security templates +.EXAMPLE +Get-EndpointSecurityTemplate +Gets all Endpoint Security Templates in Endpoint Manager +.NOTES +NAME: Get-EndpointSecurityTemplate +#> + + +$graphApiVersion = "Beta" +$ESP_resource = "deviceManagement/templates?`$filter=(isof(%27microsoft.graph.securityBaselineTemplate%27))" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($ESP_resource)" + (Invoke-RestMethod -Method Get -Uri $uri -Headers $authToken).value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Get-EndpointSecurityPolicy(){ + +<# +.SYNOPSIS +This function is used to get all Endpoint Security policies using the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets all Endpoint Security templates +.EXAMPLE +Get-EndpointSecurityPolicy +Gets all Endpoint Security Policies in Endpoint Manager +.NOTES +NAME: Get-EndpointSecurityPolicy +#> + + +$graphApiVersion = "Beta" +$ESP_resource = "deviceManagement/intents" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($ESP_resource)" + (Invoke-RestMethod -Method Get -Uri $uri -Headers $authToken).value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Get-EndpointSecurityTemplateCategory(){ + +<# +.SYNOPSIS +This function is used to get all Endpoint Security categories from a specific template using the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets all template categories +.EXAMPLE +Get-EndpointSecurityTemplateCategory -TemplateId $templateId +Gets an Endpoint Security Categories from a specific template in Endpoint Manager +.NOTES +NAME: Get-EndpointSecurityTemplateCategory +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + $TemplateId +) + +$graphApiVersion = "Beta" +$ESP_resource = "deviceManagement/templates/$TemplateId/categories" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($ESP_resource)" + (Invoke-RestMethod -Method Get -Uri $uri -Headers $authToken).value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Get-EndpointSecurityCategorySetting(){ + +<# +.SYNOPSIS +This function is used to get an Endpoint Security category setting from a specific policy using the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets a policy category setting +.EXAMPLE +Get-EndpointSecurityCategorySetting -PolicyId $policyId -categoryId $categoryId +Gets an Endpoint Security Categories from a specific template in Endpoint Manager +.NOTES +NAME: Get-EndpointSecurityCategory +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + $PolicyId, + [Parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + $categoryId +) + +$graphApiVersion = "Beta" +$ESP_resource = "deviceManagement/intents/$policyId/categories/$categoryId/settings?`$expand=Microsoft.Graph.DeviceManagementComplexSettingInstance/Value" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($ESP_resource)" + (Invoke-RestMethod -Method Get -Uri $uri -Headers $authToken).value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +#region Authentication + +write-host + +# Checking if authToken exists before running authentication +if($global:authToken){ + + # Setting DateTime to Universal time to work in all timezones + $DateTime = (Get-Date).ToUniversalTime() + + # If the authToken exists checking when it expires + $TokenExpires = ($authToken.ExpiresOn.datetime - $DateTime).Minutes + + if($TokenExpires -le 0){ + + write-host "Authentication Token expired" $TokenExpires "minutes ago" -ForegroundColor Yellow + write-host + + # Defining User Principal Name if not present + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + + $global:authToken = Get-AuthToken -User $User + + } +} + +# Authentication doesn't exist, calling Get-AuthToken function + +else { + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + +# Getting the authorization token +$global:authToken = Get-AuthToken -User $User + +} + +#endregion + +#################################################### + +# Get all Endpoint Security Templates +$Templates = Get-EndpointSecurityTemplate + +#################################################### + +# Get all Endpoint Security Policies configured +$ESPolicies = Get-EndpointSecurityPolicy | Sort-Object displayName + +#################################################### + +if($ESPolicies){ + + # Looping through all policies configured + + foreach($policy in ($ESPolicies | sort displayName)){ + + Write-Host "Endpoint Security Policy:"$policy.displayName -ForegroundColor Yellow + $PolicyName = $policy.displayName + $PolicyDescription = $policy.description + $policyId = $policy.id + $TemplateId = $policy.templateId + $roleScopeTagIds = $policy.roleScopeTagIds + + $ES_Template = $Templates | ? { $_.id -eq $policy.templateId } + + $TemplateDisplayName = $ES_Template.displayName + $TemplateId = $ES_Template.id + + #################################################### + + # Creating object for JSON output + $JSON = New-Object -TypeName PSObject + + Add-Member -InputObject $JSON -MemberType 'NoteProperty' -Name 'displayName' -Value "$PolicyName" + Add-Member -InputObject $JSON -MemberType 'NoteProperty' -Name 'description' -Value "$PolicyDescription" + Add-Member -InputObject $JSON -MemberType 'NoteProperty' -Name 'roleScopeTagIds' -Value $roleScopeTagIds + Add-Member -InputObject $JSON -MemberType 'NoteProperty' -Name 'TemplateDisplayName' -Value "$TemplateDisplayName" + Add-Member -InputObject $JSON -MemberType 'NoteProperty' -Name 'TemplateId' -Value "$TemplateId" + + #################################################### + + # Getting all categories in specified Endpoint Security Template + $Categories = Get-EndpointSecurityTemplateCategory -TemplateId $TemplateId + + # Looping through all categories within the Template + + foreach($category in $Categories){ + + $categoryId = $category.id + + $Settings += Get-EndpointSecurityCategorySetting -PolicyId $policyId -categoryId $categoryId + + } + + # Adding All settings to settingsDelta ready for JSON export + Add-Member -InputObject $JSON -MemberType 'NoteProperty' -Name 'settingsDelta' -Value @($Settings) + + #################################################### + + # If you want output in JSON format update line below to "$JSON | ConvertTo-Json" + $JSON + + } + +} + +else { + + Write-Host "No Endpoint Security Policies found..." -ForegroundColor Red + Write-Host + +} \ No newline at end of file diff --git a/EndpointSecurity/EndpointSecurityPolicy_Import_FromJSON.ps1 b/EndpointSecurity/EndpointSecurityPolicy_Import_FromJSON.ps1 new file mode 100644 index 0000000..ab39f75 --- /dev/null +++ b/EndpointSecurity/EndpointSecurityPolicy_Import_FromJSON.ps1 @@ -0,0 +1,490 @@ + +<# + +.COPYRIGHT +Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +See LICENSE in the project root for license information. + +#> + +#################################################### + +function Get-AuthToken { + +<# +.SYNOPSIS +This function is used to authenticate with the Graph API REST interface +.DESCRIPTION +The function authenticate with the Graph API Interface with the tenant name +.EXAMPLE +Get-AuthToken +Authenticates you with the Graph API interface +.NOTES +NAME: Get-AuthToken +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + $User +) + +$userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User + +$tenant = $userUpn.Host + +Write-Host "Checking for AzureAD module..." + + $AadModule = Get-Module -Name "AzureAD" -ListAvailable + + if ($AadModule -eq $null) { + + Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview" + $AadModule = Get-Module -Name "AzureADPreview" -ListAvailable + + } + + if ($AadModule -eq $null) { + write-host + write-host "AzureAD Powershell module not installed..." -f Red + write-host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow + write-host "Script can't continue..." -f Red + write-host + exit + } + +# Getting path to ActiveDirectory Assemblies +# If the module count is greater than 1 find the latest version + + if($AadModule.count -gt 1){ + + $Latest_Version = ($AadModule | select version | Sort-Object)[-1] + + $aadModule = $AadModule | ? { $_.version -eq $Latest_Version.version } + + # Checking if there are multiple versions of the same module found + + if($AadModule.count -gt 1){ + + $aadModule = $AadModule | select -Unique + + } + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + + else { + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + +[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null + +[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null + +$clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" + +$redirectUri = "urn:ietf:wg:oauth:2.0:oob" + +$resourceAppIdURI = "https://graph.microsoft.com" + +$authority = "https://login.microsoftonline.com/$Tenant" + + try { + + $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority + + # https://msdn.microsoft.com/en-us/library/azure/microsoft.identitymodel.clients.activedirectory.promptbehavior.aspx + # Change the prompt behaviour to force credentials each time: Auto, Always, Never, RefreshSession + + $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto" + + $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId") + + $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result + + # If the accesstoken is valid then create the authentication header + + if($authResult.AccessToken){ + + # Creating header for Authorization token + + $authHeader = @{ + 'Content-Type'='application/json' + 'Authorization'="Bearer " + $authResult.AccessToken + 'ExpiresOn'=$authResult.ExpiresOn + } + + return $authHeader + + } + + else { + + Write-Host + Write-Host "Authorization Access Token is null, please re-run authentication..." -ForegroundColor Red + Write-Host + break + + } + + } + + catch { + + write-host $_.Exception.Message -f Red + write-host $_.Exception.ItemName -f Red + write-host + break + + } + +} + +#################################################### + +Function Get-EndpointSecurityTemplate(){ + +<# +.SYNOPSIS +This function is used to get all Endpoint Security templates using the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets all Endpoint Security templates +.EXAMPLE +Get-EndpointSecurityTemplate +Gets all Endpoint Security Templates in Endpoint Manager +.NOTES +NAME: Get-EndpointSecurityTemplate +#> + + +$graphApiVersion = "Beta" +$ESP_resource = "deviceManagement/templates?`$filter=(isof(%27microsoft.graph.securityBaselineTemplate%27))" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($ESP_resource)" + (Invoke-RestMethod -Method Get -Uri $uri -Headers $authToken).value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Add-EndpointSecurityPolicy(){ + +<# +.SYNOPSIS +This function is used to add an Endpoint Security policy using the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and adds an Endpoint Security policy +.EXAMPLE +Add-EndpointSecurityDiskEncryptionPolicy -JSON $JSON -TemplateId $templateId +Adds an Endpoint Security Policy in Endpoint Manager +.NOTES +NAME: Add-EndpointSecurityPolicy +#> + +[cmdletbinding()] + +param +( + $TemplateId, + $JSON +) + +$graphApiVersion = "Beta" +$ESP_resource = "deviceManagement/templates/$TemplateId/createInstance" +Write-Verbose "Resource: $ESP_resource" + + try { + + if($JSON -eq "" -or $JSON -eq $null){ + + write-host "No JSON specified, please specify valid JSON for the Endpoint Security Policy..." -f Red + + } + + else { + + Test-JSON -JSON $JSON + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($ESP_resource)" + Invoke-RestMethod -Uri $uri -Headers $authToken -Method Post -Body $JSON -ContentType "application/json" + + } + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Test-JSON(){ + +<# +.SYNOPSIS +This function is used to test if the JSON passed to a REST Post request is valid +.DESCRIPTION +The function tests if the JSON passed to the REST Post is valid +.EXAMPLE +Test-JSON -JSON $JSON +Test if the JSON is valid before calling the Graph REST interface +.NOTES +NAME: Test-JSON +#> + +param ( + +$JSON + +) + + try { + + $TestJSON = ConvertFrom-Json $JSON -ErrorAction Stop + $validJson = $true + + } + + catch { + + $validJson = $false + $_.Exception + + } + + if (!$validJson){ + + Write-Host "Provided JSON isn't in valid JSON format" -f Red + break + + } + +} + +#################################################### + +#region Authentication + +write-host + +# Checking if authToken exists before running authentication +if($global:authToken){ + + # Setting DateTime to Universal time to work in all timezones + $DateTime = (Get-Date).ToUniversalTime() + + # If the authToken exists checking when it expires + $TokenExpires = ($authToken.ExpiresOn.datetime - $DateTime).Minutes + + if($TokenExpires -le 0){ + + write-host "Authentication Token expired" $TokenExpires "minutes ago" -ForegroundColor Yellow + write-host + + # Defining User Principal Name if not present + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + + $global:authToken = Get-AuthToken -User $User + + } +} + +# Authentication doesn't exist, calling Get-AuthToken function + +else { + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + +# Getting the authorization token +$global:authToken = Get-AuthToken -User $User + +} + +#endregion + +#################################################### + +$ImportPath = Read-Host -Prompt "Please specify a path to a JSON file to import data from e.g. C:\IntuneOutput\Policies\policy.json" + +# Replacing quotes for Test-Path +$ImportPath = $ImportPath.replace('"','') + +if(!(Test-Path "$ImportPath")){ + +Write-Host "Import Path for JSON file doesn't exist..." -ForegroundColor Red +Write-Host "Script can't continue..." -ForegroundColor Red +Write-Host +break + +} + +#################################################### + +# Getting content of JSON Import file +$JSON_Data = gc "$ImportPath" + +# Converting input to JSON format +$JSON_Convert = $JSON_Data | ConvertFrom-Json + +# Pulling out variables to use in the import +$JSON_DN = $JSON_Convert.displayName +$JSON_TemplateDisplayName = $JSON_Convert.TemplateDisplayName +$JSON_TemplateId = $JSON_Convert.templateId + +Write-Host +Write-Host "Endpoint Security Policy '$JSON_DN' found..." -ForegroundColor Cyan +Write-Host "Template Display Name: $JSON_TemplateDisplayName" +Write-Host "Template ID: $JSON_TemplateId" + +#################################################### + +# Get all Endpoint Security Templates +$Templates = Get-EndpointSecurityTemplate + +#################################################### + +# Checking if templateId from JSON is a valid templateId +$ES_Template = $Templates | ? { $_.id -eq $JSON_TemplateId } + +#################################################### + +# If template is a baseline Edge, MDATP or Windows, use templateId specified +if(($ES_Template.templateType -eq "microsoftEdgeSecurityBaseline") -or ($ES_Template.templateType -eq "securityBaseline") -or ($ES_Template.templateType -eq "advancedThreatProtectionSecurityBaseline")){ + + $TemplateId = $JSON_Convert.templateId + +} + +#################################################### + +# Else If not a baseline, check if template is deprecated +elseif($ES_Template){ + + # if template isn't deprecated use templateId + if($ES_Template.isDeprecated -eq $false){ + + $TemplateId = $JSON_Convert.templateId + + } + + # If template deprecated, look for lastest version + elseif($ES_Template.isDeprecated -eq $true) { + + $Template = $Templates | ? { $_.displayName -eq "$JSON_TemplateDisplayName" } + + $Template = $Template | ? { $_.isDeprecated -eq $false } + + $TemplateId = $Template.id + + } + +} + +#################################################### + +# Else If Imported JSON template ID can't be found check if Template Display Name can be used +elseif($ES_Template -eq $null){ + + Write-Host "Didn't find Template with ID $JSON_TemplateId, checking if Template DisplayName '$JSON_TemplateDisplayName' can be used..." -ForegroundColor Red + $ES_Template = $Templates | ? { $_.displayName -eq "$JSON_TemplateDisplayName" } + + If($ES_Template){ + + if(($ES_Template.templateType -eq "securityBaseline") -or ($ES_Template.templateType -eq "advancedThreatProtectionSecurityBaseline")){ + + Write-Host + Write-Host "TemplateID '$JSON_TemplateId' with template Name '$JSON_TemplateDisplayName' doesn't exist..." -ForegroundColor Red + Write-Host "Importing using the updated template could fail as settings specified may not be included in the latest template..." -ForegroundColor Red + Write-Host + break + + } + + else { + + Write-Host "Template with displayName '$JSON_TemplateDisplayName' found..." -ForegroundColor Green + + $Template = $ES_Template | ? { $_.isDeprecated -eq $false } + + $TemplateId = $Template.id + + } + + } + + else { + + Write-Host + Write-Host "TemplateID '$JSON_TemplateId' with template Name '$JSON_TemplateDisplayName' doesn't exist..." -ForegroundColor Red + Write-Host "Importing using the updated template could fail as settings specified may not be included in the latest template..." -ForegroundColor Red + Write-Host + break + + } + +} + +#################################################### + +# Excluding certain properties from JSON that aren't required for import +$JSON_Convert = $JSON_Convert | Select-Object -Property * -ExcludeProperty TemplateDisplayName,TemplateId,versionInfo + +$DisplayName = $JSON_Convert.displayName + +$JSON_Output = $JSON_Convert | ConvertTo-Json -Depth 5 + +write-host +$JSON_Output +write-host +Write-Host "Adding Endpoint Security Policy '$DisplayName'" -ForegroundColor Yellow +Add-EndpointSecurityPolicy -TemplateId $TemplateId -JSON $JSON_Output diff --git a/EndpointSecurity/EndpointSecurityTemplates_Get.ps1 b/EndpointSecurity/EndpointSecurityTemplates_Get.ps1 new file mode 100644 index 0000000..43595f4 --- /dev/null +++ b/EndpointSecurity/EndpointSecurityTemplates_Get.ps1 @@ -0,0 +1,256 @@ + +<# + +.COPYRIGHT +Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +See LICENSE in the project root for license information. + +#> + +#################################################### + +function Get-AuthToken { + +<# +.SYNOPSIS +This function is used to authenticate with the Graph API REST interface +.DESCRIPTION +The function authenticate with the Graph API Interface with the tenant name +.EXAMPLE +Get-AuthToken +Authenticates you with the Graph API interface +.NOTES +NAME: Get-AuthToken +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + $User +) + +$userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User + +$tenant = $userUpn.Host + +Write-Host "Checking for AzureAD module..." + + $AadModule = Get-Module -Name "AzureAD" -ListAvailable + + if ($AadModule -eq $null) { + + Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview" + $AadModule = Get-Module -Name "AzureADPreview" -ListAvailable + + } + + if ($AadModule -eq $null) { + write-host + write-host "AzureAD Powershell module not installed..." -f Red + write-host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow + write-host "Script can't continue..." -f Red + write-host + exit + } + +# Getting path to ActiveDirectory Assemblies +# If the module count is greater than 1 find the latest version + + if($AadModule.count -gt 1){ + + $Latest_Version = ($AadModule | select version | Sort-Object)[-1] + + $aadModule = $AadModule | ? { $_.version -eq $Latest_Version.version } + + # Checking if there are multiple versions of the same module found + + if($AadModule.count -gt 1){ + + $aadModule = $AadModule | select -Unique + + } + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + + else { + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + +[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null + +[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null + +$clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" + +$redirectUri = "urn:ietf:wg:oauth:2.0:oob" + +$resourceAppIdURI = "https://graph.microsoft.com" + +$authority = "https://login.microsoftonline.com/$Tenant" + + try { + + $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority + + # https://msdn.microsoft.com/en-us/library/azure/microsoft.identitymodel.clients.activedirectory.promptbehavior.aspx + # Change the prompt behaviour to force credentials each time: Auto, Always, Never, RefreshSession + + $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto" + + $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId") + + $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result + + # If the accesstoken is valid then create the authentication header + + if($authResult.AccessToken){ + + # Creating header for Authorization token + + $authHeader = @{ + 'Content-Type'='application/json' + 'Authorization'="Bearer " + $authResult.AccessToken + 'ExpiresOn'=$authResult.ExpiresOn + } + + return $authHeader + + } + + else { + + Write-Host + Write-Host "Authorization Access Token is null, please re-run authentication..." -ForegroundColor Red + Write-Host + break + + } + + } + + catch { + + write-host $_.Exception.Message -f Red + write-host $_.Exception.ItemName -f Red + write-host + break + + } + +} + +#################################################### + +Function Get-EndpointSecurityTemplate(){ + +<# +.SYNOPSIS +This function is used to get all Endpoint Security templates using the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets all Endpoint Security templates +.EXAMPLE +Get-EndpointSecurityTemplate +Gets all Endpoint Security Templates in Endpoint Manager +.NOTES +NAME: Get-EndpointSecurityTemplate +#> + + +$graphApiVersion = "Beta" +$ESP_resource = "deviceManagement/templates?`$filter=(isof(%27microsoft.graph.securityBaselineTemplate%27))" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($ESP_resource)" + (Invoke-RestMethod -Method Get -Uri $uri -Headers $authToken).value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +#region Authentication + +write-host + +# Checking if authToken exists before running authentication +if($global:authToken){ + + # Setting DateTime to Universal time to work in all timezones + $DateTime = (Get-Date).ToUniversalTime() + + # If the authToken exists checking when it expires + $TokenExpires = ($authToken.ExpiresOn.datetime - $DateTime).Minutes + + if($TokenExpires -le 0){ + + write-host "Authentication Token expired" $TokenExpires "minutes ago" -ForegroundColor Yellow + write-host + + # Defining User Principal Name if not present + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + + $global:authToken = Get-AuthToken -User $User + + } +} + +# Authentication doesn't exist, calling Get-AuthToken function + +else { + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + +# Getting the authorization token +$global:authToken = Get-AuthToken -User $User + +} + +#endregion + +#################################################### + +# Get all Endpoint Security Templates +$Templates = Get-EndpointSecurityTemplate + +foreach($Template in ($Templates | sort displayName)){ + + Write-Host $Template.displayName -ForegroundColor Yellow + $Template + +} \ No newline at end of file diff --git a/EndpointSecurity/Readme.md b/EndpointSecurity/Readme.md new file mode 100644 index 0000000..7a5acb2 --- /dev/null +++ b/EndpointSecurity/Readme.md @@ -0,0 +1,195 @@ +# Intune Endpoint Security Policy script samples + +This repository of PowerShell sample scripts show how to access Intune service resources. They demonstrate this by making HTTPS RESTful API requests to the Microsoft Graph API from PowerShell. + +Documentation for Intune and Microsoft Graph can be found here [Intune Graph Documentation](https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/intune_graph_overview). + +#### Disclaimer +Some script samples retrieve information from your Intune tenant, and others create, delete or update data in your Intune tenant.  Understand the impact of each sample script prior to running it; samples should be run using a non-production or "test" tenant account.  + +Within this section there are the following scripts with the explanation of usage. + +### 1. EndpointSecurityPolicy_Export.ps1 +This script gets all Endpoint Security policies from the Intune Service that you have authenticated with. The script will then export the policy to .json format in the directory of your choice. + +```PowerShell +$ExportPath = Read-Host -Prompt "Please specify a path to export the policy data to e.g. C:\IntuneOutput" + + # If the directory path doesn't exist prompt user to create the directory + + if(!(Test-Path "$ExportPath")){ + + Write-Host + Write-Host "Path '$ExportPath' doesn't exist, do you want to create this directory? Y or N?" -ForegroundColor Yellow + + $Confirm = read-host + + if($Confirm -eq "y" -or $Confirm -eq "Y"){ + + new-item -ItemType Directory -Path "$ExportPath" | Out-Null + Write-Host + + } + + else { + + Write-Host "Creation of directory path was cancelled..." -ForegroundColor Red + Write-Host + break + + } + + } +``` +#### Get-EndpointSecurityTemplate Function +This function is used to get all Endpoint Security Templates available in the Intune service for your tenant. + +```PowerShell +# Returns all Endpoint Security Templates configured in Intune +Get-EndpointSecurityTemplate +``` + +#### Get-EndpointSecurityPolicy Function +This function is used to get all Endpoint Security policies from the Intune Service. + +```PowerShell +# Returns all Endpoint Security policies configured in Intune +Get-EndpointSecurityPolicy +``` + +#### Get-EndpointSecurityTemplateCategory Function +This function is used to get all Endpoint Security categories from a specific template available in the Intune Service. + +It requires a single parameters as an input to the function to pull data from the service. + +```PowerShell +# Returns all Endpoint Security categories from a template available in Intune +Get-EndpointSecurityTemplateCategory -TemplateId $TemplateId +``` + +#### Get-EndpointSecurityCategorySetting Function +This function is used to get an Endpoint Security category setting from a specific policy available in the Intune Service. + +It requires multiple parameters as an input to the function to pull data from the service. + +```PowerShell +# Returns a specific setting from an Endpoint Security policy category configured in Intune +Get-EndpointSecurityCategorySetting -PolicyId $policyId -categoryId $categoryId +``` + +#### Export-JSONData Function +This function is used to export the policy information. It has two required parameters -JSON and -ExportPath. + ++ JSON - The JSON data ++ ExportPath - The path where the .json should be exported to + +```PowerShell +Export-JSONData -JSON $JSON -ExportPath "$ExportPath" +``` + +#### Export JSON sample +In the JSON you will find the following extra properties which are used for the import of the policy. Example below: + +```PowerShell +"TemplateDisplayName": "Windows Security experience", +"TemplateId": "da332b88-bd29-4def-a442-e0993ed08e24", +"versionInfo": "2005", +``` + +### 2. EndpointSecurityPolicy_Get.ps1 +This script gets all the Endpoint Security policies from the Intune Service that you have authenticated with. + +#### Get-EndpointSecurityTemplate Function +This function is used to get all Endpoint Security Templates available in the Intune service for your tenant. + +```PowerShell +# Returns all Endpoint Security Templates configured in Intune +Get-EndpointSecurityTemplate +``` + +#### Get-EndpointSecurityPolicy Function +This function is used to get all Endpoint Security policies from the Intune Service. + +```PowerShell +# Returns all Endpoint Security policies configured in Intune +Get-EndpointSecurityPolicy +``` + +#### Get-EndpointSecurityTemplateCategory Function +This function is used to get all Endpoint Security categories from a specific template available in the Intune Service. + +It requires a single parameters as an input to the function to pull data from the service. + +```PowerShell +# Returns all Endpoint Security categories from a template available in Intune +Get-EndpointSecurityTemplateCategory -TemplateId $TemplateId +``` + +#### Get-EndpointSecurityCategorySetting Function +This function is used to get an Endpoint Security category setting from a specific policy available in the Intune Service. + +It requires multiple parameters as an input to the function to pull data from the service. + +```PowerShell +# Returns a specific setting from an Endpoint Security policy category configured in Intune +Get-EndpointSecurityCategorySetting -PolicyId $policyId -categoryId $categoryId +``` + +### 3. EndpointSecurityPolicy_Import_FromJSON.ps1 +This script imports from a JSON file an Endpoint Security policy into the Intune Service that you have authenticated with. + +When you run the script it will prompt for a path to a .json file, if the path is valid the Add-EndpointSecurityPolicy function will be called. + +```PowerShell +$ImportPath = Read-Host -Prompt "Please specify a path to a JSON file to import data from e.g. C:\IntuneOutput\Policies\policy.json" + +# Replacing quotes for Test-Path +$ImportPath = $ImportPath.replace('"','') + +if(!(Test-Path "$ImportPath")){ + +Write-Host "Import Path for JSON file doesn't exist..." -ForegroundColor Red +Write-Host "Script can't continue..." -ForegroundColor Red +Write-Host +break + +} +``` + +#### JSON Import Exclusions +As the export added extra properties, once the JSON is exported the following properties will be excluded as part of the Add-EndpointSecurityPolicy function. + +* TemplateDisplayName +* TemplateId +* versionInfo + +Note: These properties are used to aid in the import of the policy. + +#### Get-EndpointSecurityTemplate Function +This function is used to get all Endpoint Security Templates available in the Intune service for your tenant. + +```PowerShell +# Returns all Endpoint Security Templates configured in Intune +Get-EndpointSecurityTemplate +``` + +#### Add-EndpointSecurityPolicy Function +This function used to add an Endpoint Security policy to the Intune Service. It requires multiple parameters: + +* TemplateId - Endpoint Security Template ID +* JSON - JSON data needs to be an input to the function so it can be passed to the service. + +```PowerShell +Add-EndpointSecurityPolicy -TemplateId $TemplateId -JSON $JSON +``` + +### 4. EndpointSecurityTemplates_Get.ps1 +This script gets all the Endpoint Security Templates from the Intune Service that you have authenticated with. + +#### Get-EndpointSecurityTemplate Function +This function is used to get all Endpoint Security Templates available in the Intune service for your tenant. + +```PowerShell +# Returns all Endpoint Security Templates configured in Intune +Get-EndpointSecurityTemplate +``` diff --git a/Filters/AssociatedFilter_Get.ps1 b/Filters/AssociatedFilter_Get.ps1 new file mode 100644 index 0000000..bdb4307 --- /dev/null +++ b/Filters/AssociatedFilter_Get.ps1 @@ -0,0 +1,1216 @@ +<# + +.COPYRIGHT +Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +See LICENSE in the project root for license information. + +#> + +#################################################### + +function Get-AuthToken { + +<# +.SYNOPSIS +This function is used to authenticate with the Graph API REST interface +.DESCRIPTION +The function authenticate with the Graph API Interface with the tenant name +.EXAMPLE +Get-AuthToken +Authenticates you with the Graph API interface +.NOTES +NAME: Get-AuthToken +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + $User +) + +$userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User + +$tenant = $userUpn.Host + +Write-Host "Checking for AzureAD module..." + + $AadModule = Get-Module -Name "AzureAD" -ListAvailable + + if ($AadModule -eq $null) { + + Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview" + $AadModule = Get-Module -Name "AzureADPreview" -ListAvailable + + } + + if ($AadModule -eq $null) { + write-host + write-host "AzureAD Powershell module not installed..." -f Red + write-host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow + write-host "Script can't continue..." -f Red + write-host + exit + } + +# Getting path to ActiveDirectory Assemblies +# If the module count is greater than 1 find the latest version + + if($AadModule.count -gt 1){ + + $Latest_Version = ($AadModule | select version | Sort-Object)[-1] + + $aadModule = $AadModule | ? { $_.version -eq $Latest_Version.version } + + # Checking if there are multiple versions of the same module found + + if($AadModule.count -gt 1){ + + $aadModule = $AadModule | select -Unique + + } + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + + else { + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + +[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null + +[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null + +$clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" + +$redirectUri = "urn:ietf:wg:oauth:2.0:oob" + +$resourceAppIdURI = "https://graph.microsoft.com" + +$authority = "https://login.microsoftonline.com/$Tenant" + + try { + + $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority + + # https://msdn.microsoft.com/en-us/library/azure/microsoft.identitymodel.clients.activedirectory.promptbehavior.aspx + # Change the prompt behaviour to force credentials each time: Auto, Always, Never, RefreshSession + + $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto" + + $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId") + + $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result + + # If the accesstoken is valid then create the authentication header + + if($authResult.AccessToken){ + + # Creating header for Authorization token + + $authHeader = @{ + 'Content-Type'='application/json' + 'Authorization'="Bearer " + $authResult.AccessToken + 'ExpiresOn'=$authResult.ExpiresOn + } + + return $authHeader + + } + + else { + + Write-Host + Write-Host "Authorization Access Token is null, please re-run authentication..." -ForegroundColor Red + Write-Host + break + + } + + } + + catch { + + write-host $_.Exception.Message -f Red + write-host $_.Exception.ItemName -f Red + write-host + break + + } + +} + +#################################################### + +Function Get-AADGroups(){ + +<# +.SYNOPSIS +This function is used to get AAD Groups from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets any Groups registered with AAD +.EXAMPLE +Get-AADGroup +Returns all users registered with Azure AD +.NOTES +NAME: Get-AADGroup +#> + +[cmdletbinding()] + +param +( + $GroupName, + $id, + [switch]$Members +) + +# Defining Variables +$graphApiVersion = "beta" +$Group_resource = "groups" + + try { + + if($id){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Group_resource)?`$filter=id eq '$id'" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + elseif($GroupName -eq "" -or $GroupName -eq $null){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Group_resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + else { + + if(!$Members){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Group_resource)?`$filter=displayname eq '$GroupName'" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + elseif($Members){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Group_resource)?`$filter=displayname eq '$GroupName'" + $Group = (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + if($Group){ + + $GID = $Group.id + + $Group.displayName + write-host + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Group_resource)/$GID/Members" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + } + + } + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Get-DeviceCompliancePolicy(){ + +<# +.SYNOPSIS +This function is used to get device compliance policies from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets any device compliance policies +.EXAMPLE +Get-DeviceCompliancePolicy +Returns any device compliance policies configured in Intune +.EXAMPLE +Get-DeviceCompliancePolicy -Android +Returns any device compliance policies for Android configured in Intune +.EXAMPLE +Get-DeviceCompliancePolicy -iOS +Returns any device compliance policies for iOS configured in Intune +.NOTES +NAME: Get-DeviceCompliancePolicy +#> + +[cmdletbinding()] + +param +( + $Name, + [Parameter(HelpMessage = "Compliance Platform")] + [ValidateSet("Android","iOS","Windows10","AndroidEnterprise","macOS")] + $Platform + +) + +$graphApiVersion = "Beta" +$Resource = "deviceManagement/deviceCompliancePolicies?`$expand=assignments" + + try { + + + if($Platform -eq "Android"){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value | Where-Object { ($_.'@odata.type').contains("android") } + + } + + elseif($Platform -eq "iOS"){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value | Where-Object { ($_.'@odata.type').contains("ios") } + + } + + elseif($Platform -eq "Windows10"){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value | Where-Object { ($_.'@odata.type').contains("windows10CompliancePolicy") } + + } + + elseif($Name){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value | Where-Object { ($_.'displayName').contains("$Name") } + + } + + else { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Get-DeviceConfigurationPolicy(){ + +<# +.SYNOPSIS +This function is used to get device configuration policies from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets any device configuration policies +.EXAMPLE +Get-DeviceConfigurationPolicy +Returns any device configuration policies configured in Intune +.NOTES +NAME: Get-DeviceConfigurationPolicy +#> + +[cmdletbinding()] + +param +( + $name +) + +$graphApiVersion = "Beta" +$DCP_resource = "deviceManagement/deviceConfigurations?`$expand=assignments" + + try { + + if($Name){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value | Where-Object { ($_.'displayName').contains("$Name") } + + } + + else { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Get-AdministrativeTemplates(){ + +<# +.SYNOPSIS +This function is used to get Administrative Templates from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets any Administrative Templates +.EXAMPLE +Get-AdministrativeTemplates +Returns any Administrative Templates configured in Intune +.NOTES +NAME: Get-AdministrativeTemplates +#> + +[cmdletbinding()] + +param +( + $name +) + +$graphApiVersion = "beta" +$Resource = "deviceManagement/groupPolicyConfigurations?`$expand=assignments" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Get-AssignmentFilters(){ + +<# +.SYNOPSIS +This function is used to get assignment filters from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets any assignment filters +.EXAMPLE +Get-AssignmentFilters +Returns any assignment filters configured in Intune +.NOTES +NAME: Get-AssignmentFilters +#> + +[cmdletbinding()] + +param +( + $name +) + +$graphApiVersion = "beta" +$Resource = "deviceManagement/assignmentFilters" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Get-SettingsCatalogPolicy(){ + +<# +.SYNOPSIS +This function is used to get Settings Catalog policies from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets any Settings Catalog policies +.EXAMPLE +Get-SettingsCatalogPolicy +Returns any Settings Catalog policies configured in Intune +Get-SettingsCatalogPolicy -Platform windows10 +Returns any Windows 10 Settings Catalog policies configured in Intune +Get-SettingsCatalogPolicy -Platform macOS +Returns any MacOS Settings Catalog policies configured in Intune +.NOTES +NAME: Get-SettingsCatalogPolicy +#> + +[cmdletbinding()] + +param +( + [parameter(Mandatory=$false)] + [ValidateSet("windows10","macOS")] + [ValidateNotNullOrEmpty()] + [string]$Platform, + [parameter(Mandatory=$false)] + [ValidateNotNullOrEmpty()] + $id +) + +$graphApiVersion = "beta" + + if($Platform){ + + $Resource = "deviceManagement/configurationPolicies?`$filter=platforms has '$Platform' and technologies has 'mdm'" + + } + + elseif($id){ + + $Resource = "deviceManagement/configurationPolicies('$id')/assignments" + + } + + else { + + $Resource = "deviceManagement/configurationPolicies?`$filter=technologies has 'mdm'" + + } + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Get-IntuneApplication(){ + +<# +.SYNOPSIS +This function is used to get applications from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets any applications added +.EXAMPLE +Get-IntuneApplication +Returns any applications configured in Intune +.NOTES +NAME: Get-IntuneApplication +#> + +[cmdletbinding()] + +param +( + $Name +) + +$graphApiVersion = "Beta" +$Resource = "deviceAppManagement/mobileApps?`$expand=assignments" + + try { + + if($Name){ + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value | Where-Object { ($_.'displayName').contains("$Name") -and (!($_.'@odata.type').Contains("managed")) -and (!($_.'@odata.type').Contains("#microsoft.graph.iosVppApp")) } + + } + + else { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value | Where-Object { (!($_.'@odata.type').Contains("managed")) } + + } + + } + + catch { + + $ex = $_.Exception + Write-Host "Request to $Uri failed with HTTP Status $([int]$ex.Response.StatusCode) $($ex.Response.StatusDescription)" -f Red + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +#region Authentication + +write-host + +# Checking if authToken exists before running authentication +if($global:authToken){ + + # Setting DateTime to Universal time to work in all timezones + $DateTime = (Get-Date).ToUniversalTime() + + # If the authToken exists checking when it expires + $TokenExpires = ($authToken.ExpiresOn.datetime - $DateTime).Minutes + + if($TokenExpires -le 0){ + + write-host "Authentication Token expired" $TokenExpires "minutes ago" -ForegroundColor Yellow + write-host + + # Defining Azure AD tenant name, this is the name of your Azure Active Directory (do not use the verified domain name) + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + + $global:authToken = Get-AuthToken -User $User + + } +} + +# Authentication doesn't exist, calling Get-AuthToken function + +else { + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + +# Getting the authorization token +$global:authToken = Get-AuthToken -User $User + +} + +#endregion + +#################################################### + +write-host "Filters Name:" -f Yellow +$FilterName = Read-Host + +if($FilterName -eq $null -or $FilterName -eq ""){ + + write-host "Filter Name is Null..." -ForegroundColor Red + Write-Host "Script can't continue..." -ForegroundColor Red + Write-Host + break + +} + +#################################################### + +$Filters = Get-AssignmentFilters + +$Filter = $Filters | ? { $_.displayName -eq "$FilterName" } + +if(!$Filter){ + + Write-Host + Write-Host "Filter with Name '$FilterName' doesn't exist..." -ForegroundColor Red + Write-Host "Script can't continue..." -ForegroundColor Red + Write-Host + break + +} + +if($Filter.count -gt 1){ + + Write-Host + Write-Host "There are multiple filters with the same display name '$FilterName', unique names should be used..." -ForegroundColor Red + Write-Host "Script can't continue..." -ForegroundColor Red + Write-Host + break + +} + +Write-Host +write-host "-------------------------------------------------------------------" +Write-Host +Write-Host "Filter found..." -f Green +Write-Host "Filter Id: " $Filter.id +Write-Host "Filter Name: " $Filter.displayName +Write-Host "Filter Platform: " $Filter.platform +Write-Host "Filter Rule: " $filter.rule +Write-Host "Filter Scope Tag:" $filter.roleScopeTags +Write-Host + +#################################################### + +$Activity = "Filter Usage Check" + +#################################################### + +#region CompliancePolicies + +$CPs = Get-DeviceCompliancePolicy + +write-host "-------------------------------------------------------------------" +write-host "Device Compliance Policies" -f Cyan +write-host "-------------------------------------------------------------------" + +if(@($CPs).count -ge 1){ + + $CPCount = @($CPs).count + $i = 1 + + $CP_Count = 0 + + foreach($CP in $CPs){ + + $id = $CP.id + + $DCPA = $CP.assignments + + if($DCPA){ + + foreach($Com_Group in $DCPA){ + + if($Com_Group.target.deviceAndAppManagementAssignmentFilterId -eq $Filter.id){ + + Write-Host + Write-Host "Policy Name: " -NoNewline + Write-Host $CP.displayName -f green + Write-Host "Filter Type:" $Com_Group.target.deviceAndAppManagementAssignmentFilterType + + if($Com_Group.target.'@odata.type' -eq "#microsoft.graph.allDevicesAssignmentTarget"){ + + Write-Host "AAD Group Name: All Devices" + + } + + elseif($Com_Group.target.'@odata.type' -eq "#microsoft.graph.allLicensedUsersAssignmentTarget"){ + + Write-Host "AAD Group Name: All Users" + + } + + else { + + Write-Host "AAD Group Name:" (Get-AADGroups -id $Com_Group.target.groupId).displayName + + } + + Write-Host + $CP_Count++ + + } + + } + + } + + Write-Progress -Activity "$Activity" -status "Checking Device Compliance Policy $i of $CPCount" ` + -percentComplete ($i / $CPCount*100) + $i++ + + } + + Write-Progress -Completed -Activity "$Activity" + + if($CP_Count -eq 0){ + + Write-Host + Write-Host "Filter '$FilterName' not used..." -ForegroundColor Yellow + Write-Host + + } + +} + +else { + +Write-Host +write-host "No Device Compliance Policies Found..." -f Red +write-host + +} + +#endregion + +#################################################### + +#region ConfigurationPolicies + +$DCPs = Get-DeviceConfigurationPolicy + +write-host "-------------------------------------------------------------------" +write-host "Device Configuration Policies" -f Cyan +write-host "-------------------------------------------------------------------" + +if($DCPs){ + + $DCPsCount = @($DCPs).count + $i = 1 + + $DCP_Count = 0 + + foreach($DCP in $DCPs){ + + $id = $DCP.id + + $CPA = $DCP.assignments + + if($CPA){ + + foreach($Com_Group in $CPA){ + + if($Com_Group.target.deviceAndAppManagementAssignmentFilterId -eq $Filter.id){ + + Write-Host + Write-Host "Policy Name: " -NoNewline + Write-Host $DCP.displayName -f green + Write-Host "Filter Type:" $Com_Group.target.deviceAndAppManagementAssignmentFilterType + + if($Com_Group.target.'@odata.type' -eq "#microsoft.graph.allDevicesAssignmentTarget"){ + + Write-Host "AAD Group Name: All Devices" + + } + + elseif($Com_Group.target.'@odata.type' -eq "#microsoft.graph.allLicensedUsersAssignmentTarget"){ + + Write-Host "AAD Group Name: All Users" + + } + + else { + + Write-Host "AAD Group Name:" (Get-AADGroups -id $Com_Group.target.groupId).displayName + + } + + Write-Host + $DCP_Count++ + + } + + + } + + } + + Write-Progress -Activity "$Activity" -status "Checking Device Configuration Policy $i of $DCPsCount" ` + -percentComplete ($i / $DCPsCount*100) + $i++ + + } + + Write-Progress -Completed -Activity "$Activity" + + if($DCP_Count -eq 0){ + + Write-Host + Write-Host "Filter '$FilterName' not used..." -ForegroundColor Yellow + Write-Host + + } + +} + +else { + + Write-Host + write-host "No Device Configuration Policies Found..." + Write-Host + +} + +#endregion + +#################################################### + +#region SettingsCatalog + +$SCPolicies = Get-SettingsCatalogPolicy + +write-host "-------------------------------------------------------------------" +write-host "Settings Catalog Policies" -f Cyan +write-host "-------------------------------------------------------------------" + +if($SCPolicies){ + + $SCPCount = @($SCPolicies).count + $i = 1 + + $SC_Count = 0 + + foreach($SCPolicy in $SCPolicies){ + + $id = $SCPolicy.id + + $SCPolicyAssignment = Get-SettingsCatalogPolicy -id $id + + if($SCPolicyAssignment){ + + foreach($Com_Group in $SCPolicyAssignment){ + + if($Com_Group.target.deviceAndAppManagementAssignmentFilterId -eq $Filter.id){ + + Write-Host + Write-Host "Policy Name: " -NoNewline + Write-Host $SCPolicy.name -f green + Write-Host "Filter Type:" $Com_Group.target.deviceAndAppManagementAssignmentFilterType + + if($Com_Group.target.'@odata.type' -eq "#microsoft.graph.allDevicesAssignmentTarget"){ + + Write-Host "AAD Group Name: All Devices" + + } + + elseif($Com_Group.target.'@odata.type' -eq "#microsoft.graph.allLicensedUsersAssignmentTarget"){ + + Write-Host "AAD Group Name: All Users" + + } + + else { + + Write-Host "AAD Group Name:" (Get-AADGroups -id $Com_Group.target.groupId).displayName + + } + + Write-Host + $SC_Count++ + + } + + } + + } + + Write-Progress -Activity "$Activity" -status "Checking Settings Catalog $i of $SCPCount" ` + -percentComplete ($i / $SCPCount*100) + $i++ + + } + + Write-Progress -Completed -Activity "$Activity" + + if($SC_Count -eq 0){ + + Write-Host + Write-Host "Filter '$FilterName' not used..." -ForegroundColor Yellow + Write-Host + + } + +} + +else { + + write-host + write-host "No Settings Catalog Policies Found..." + Write-Host + +} + +#endregion + +#################################################### + +#region ADMX Templates + +$ADMXPolicies = Get-AdministrativeTemplates + +write-host "-------------------------------------------------------------------" +write-host "Administrative Templates Policies" -f Cyan +write-host "-------------------------------------------------------------------" + +if($ADMXPolicies){ + + $ATCount = @($ADMXPolicies).count + $i = 1 + + $AT_Count = 0 + + foreach($ADMXPolicy in $ADMXPolicies){ + + $id = $ADMXPolicy.id + + $ATPolicyAssignment = $ADMXPolicy.assignments + + if($ATPolicyAssignment){ + + foreach($Com_Group in $ATPolicyAssignment){ + + if($Com_Group.target.deviceAndAppManagementAssignmentFilterId -eq $Filter.id){ + + Write-Host + Write-Host "Policy Name: " -NoNewline + Write-Host $ADMXPolicy.displayName -f green + Write-Host "Filter Type:" $Com_Group.target.deviceAndAppManagementAssignmentFilterType + + if($Com_Group.target.'@odata.type' -eq "#microsoft.graph.allDevicesAssignmentTarget"){ + + Write-Host "AAD Group Name: All Devices" + + } + + elseif($Com_Group.target.'@odata.type' -eq "#microsoft.graph.allLicensedUsersAssignmentTarget"){ + + Write-Host "AAD Group Name: All Users" + + } + + else { + + Write-Host "AAD Group Name:" (Get-AADGroups -id $Com_Group.target.groupId).displayName + + } + + Write-Host + $AT_Count++ + + } + + } + + } + + Write-Progress -Activity "$Activity" -status "Checking Administrative Templates Policy $i of $ATCount" ` + -percentComplete ($i / $ATCount*100) + $i++ + + } + + Write-Progress -Completed -Activity "$Activity" + + if($AT_Count -eq 0){ + + Write-Host + Write-Host "Filter '$FilterName' not used..." -ForegroundColor Yellow + Write-Host + + } + +} + +else { + +Write-Host +write-host "No Administrative Templates Policies Found..." +Write-Host + +} + +#endregion + +#################################################### + +#region IntuneApplications + +$Apps = Get-IntuneApplication + +write-host "-------------------------------------------------------------------" +write-host "Intune Applications" -f Cyan +write-host "-------------------------------------------------------------------" + +if($Apps){ + + $AppsCount = @($Apps).count + $i = 1 + + $App_Count = 0 + + foreach($App in $Apps){ + + $id = $App.id + + $AppAssignment = $app.assignments + + if($AppAssignment){ + + foreach($Com_Group in $AppAssignment){ + + if($Com_Group.target.deviceAndAppManagementAssignmentFilterId -eq $Filter.id){ + + Write-Host + Write-Host "Application Name: " -NoNewline + Write-Host $App.displayName -f green + Write-Host "Filter Type:" $Com_Group.target.deviceAndAppManagementAssignmentFilterType + + if($Com_Group.target.'@odata.type' -eq "#microsoft.graph.allDevicesAssignmentTarget"){ + + Write-Host "AAD Group Name: All Devices" + + } + + elseif($Com_Group.target.'@odata.type' -eq "#microsoft.graph.allLicensedUsersAssignmentTarget"){ + + Write-Host "AAD Group Name: All Users" + + } + + else { + + Write-Host "AAD Group Name:" (Get-AADGroups -id $Com_Group.target.groupId).displayName + + } + + Write-Host + $App_Count++ + + } + + } + + } + + Write-Progress -Activity "$Activity" -status "Checking Intune Application $i of $AppsCount" ` + -percentComplete ($i / $AppsCount*100) + $i++ + + } + + Write-Progress -Completed -Activity "$Activity" + + if($App_Count -eq 0){ + + Write-Host + Write-Host "Filter '$FilterName' not used..." -ForegroundColor Yellow + Write-Host + + } + +} + +else { + +write-host +write-host "No Intune Applications Found..." +Write-Host + +} + +#endregion + +#################################################### + +write-host "-------------------------------------------------------------------" +Write-Host "Overall Analysis" -ForegroundColor Cyan +write-host "-------------------------------------------------------------------" +Write-Host "Status of each area of MEM that support Filters assignment status" +Write-Host +Write-Host "Applicable OS Type: " -NoNewline +Write-Host $Filter.Platform -ForegroundColor Yellow +Write-Host +Write-Host "Compliance Policies: " $CP_Count +write-host "Device Configuration Policies: " $DCP_Count +Write-Host "Settings Catalog Policies: " $SC_Count +Write-Host "Administrative Templates: " $AT_Count +Write-Host "Intune Applications: " $App_Count +Write-Host + +$CountFilters = $CP_Count + $DCP_Count + $SC_Count + $AT_Count + $App_Count + +Write-Host "Total Filters Assigned:" $CountFilters +Write-Host + +#################################################### + +write-host "-------------------------------------------------------------------" +Write-Host "Evaluation complete..." -ForegroundColor Green +write-host "-------------------------------------------------------------------" +Write-Host diff --git a/Filters/IntuneFilter_Export.ps1 b/Filters/IntuneFilter_Export.ps1 new file mode 100644 index 0000000..541849f --- /dev/null +++ b/Filters/IntuneFilter_Export.ps1 @@ -0,0 +1,369 @@ +<# + +.COPYRIGHT +Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +See LICENSE in the project root for license information. + +#> + +#################################################### + +function Get-AuthToken { + +<# +.SYNOPSIS +This function is used to authenticate with the Graph API REST interface +.DESCRIPTION +The function authenticate with the Graph API Interface with the tenant name +.EXAMPLE +Get-AuthToken +Authenticates you with the Graph API interface +.NOTES +NAME: Get-AuthToken +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + $User +) + +$userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User + +$tenant = $userUpn.Host + +Write-Host "Checking for AzureAD module..." + + $AadModule = Get-Module -Name "AzureAD" -ListAvailable + + if ($AadModule -eq $null) { + + Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview" + $AadModule = Get-Module -Name "AzureADPreview" -ListAvailable + + } + + if ($AadModule -eq $null) { + write-host + write-host "AzureAD Powershell module not installed..." -f Red + write-host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow + write-host "Script can't continue..." -f Red + write-host + exit + } + +# Getting path to ActiveDirectory Assemblies +# If the module count is greater than 1 find the latest version + + if($AadModule.count -gt 1){ + + $Latest_Version = ($AadModule | select version | Sort-Object)[-1] + + $aadModule = $AadModule | ? { $_.version -eq $Latest_Version.version } + + # Checking if there are multiple versions of the same module found + + if($AadModule.count -gt 1){ + + $aadModule = $AadModule | select -Unique + + } + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + + else { + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + +[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null + +[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null + +$clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" + +$redirectUri = "urn:ietf:wg:oauth:2.0:oob" + +$resourceAppIdURI = "https://graph.microsoft.com" + +$authority = "https://login.microsoftonline.com/$Tenant" + + try { + + $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority + + # https://msdn.microsoft.com/en-us/library/azure/microsoft.identitymodel.clients.activedirectory.promptbehavior.aspx + # Change the prompt behaviour to force credentials each time: Auto, Always, Never, RefreshSession + + $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto" + + $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId") + + $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result + + # If the accesstoken is valid then create the authentication header + + if($authResult.AccessToken){ + + # Creating header for Authorization token + + $authHeader = @{ + 'Content-Type'='application/json' + 'Authorization'="Bearer " + $authResult.AccessToken + 'ExpiresOn'=$authResult.ExpiresOn + } + + return $authHeader + + } + + else { + + Write-Host + Write-Host "Authorization Access Token is null, please re-run authentication..." -ForegroundColor Red + Write-Host + break + + } + + } + + catch { + + write-host $_.Exception.Message -f Red + write-host $_.Exception.ItemName -f Red + write-host + break + + } + +} + +#################################################### + +Function Get-IntuneFilter(){ + +<# +.SYNOPSIS +This function is used to get all filters configured from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets any filters created +.EXAMPLE +Get-IntuneFilter +Returns any Filters configured in Intune +.NOTES +NAME: Get-IntuneFilter +#> + +[cmdletbinding()] + +param +( + $name +) + +$graphApiVersion = "beta" +$Resource = "deviceManagement/assignmentFilters" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Export-JSONData(){ + +<# +.SYNOPSIS +This function is used to export JSON data returned from Graph +.DESCRIPTION +This function is used to export JSON data returned from Graph +.EXAMPLE +Export-JSONData -JSON $JSON +Export the JSON inputted on the function +.NOTES +NAME: Export-JSONData +#> + +param ( + +$JSON, +$ExportPath + +) + + try { + + if($JSON -eq "" -or $JSON -eq $null){ + + write-host "No JSON specified, please specify valid JSON..." -f Red + + } + + elseif(!$ExportPath){ + + write-host "No export path parameter set, please provide a path to export the file" -f Red + + } + + elseif(!(Test-Path $ExportPath)){ + + write-host "$ExportPath doesn't exist, can't export JSON Data" -f Red + + } + + else { + + $JSON1 = ConvertTo-Json $JSON -Depth 5 + + $JSON_Convert = $JSON1 | ConvertFrom-Json + + $displayName = $JSON_Convert.displayName + + # Updating display name to follow file naming conventions - https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx + $DisplayName = $DisplayName -replace '\<|\>|:|"|/|\\|\||\?|\*', "_" + + $FileName_JSON = "$DisplayName" + "_" + $(get-date -f dd-MM-yyyy-H-mm-ss) + ".json" + + write-host "Export Path:" "$ExportPath" + + $JSON1 | Set-Content -LiteralPath "$ExportPath\$FileName_JSON" + write-host "JSON created in $ExportPath\$FileName_JSON..." -f cyan + + } + + } + + catch { + + $_.Exception + + } + +} + +#################################################### + +#region Authentication + +write-host + +# Checking if authToken exists before running authentication +if($global:authToken){ + + # Setting DateTime to Universal time to work in all timezones + $DateTime = (Get-Date).ToUniversalTime() + + # If the authToken exists checking when it expires + $TokenExpires = ($authToken.ExpiresOn.datetime - $DateTime).Minutes + + if($TokenExpires -le 0){ + + write-host "Authentication Token expired" $TokenExpires "minutes ago" -ForegroundColor Yellow + write-host + + # Defining Azure AD tenant name, this is the name of your Azure Active Directory (do not use the verified domain name) + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + + $global:authToken = Get-AuthToken -User $User + + } +} + +# Authentication doesn't exist, calling Get-AuthToken function + +else { + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + +# Getting the authorization token +$global:authToken = Get-AuthToken -User $User + +} + +#endregion + +#################################################### + +$ExportPath = Read-Host -Prompt "Please specify a path to export Intune Filters to e.g. C:\IntuneOutput" + + # If the directory path doesn't exist prompt user to create the directory + $ExportPath = $ExportPath.replace('"','') + + if(!(Test-Path "$ExportPath")){ + + Write-Host + Write-Host "Path '$ExportPath' doesn't exist, do you want to create this directory? Y or N?" -ForegroundColor Yellow + + $Confirm = read-host + + if($Confirm -eq "y" -or $Confirm -eq "Y"){ + + new-item -ItemType Directory -Path "$ExportPath" | Out-Null + Write-Host + + } + + else { + + Write-Host "Creation of directory path was cancelled..." -ForegroundColor Red + Write-Host + break + + } + + } + +#################################################### + +Write-Host + + +$Filters = Get-IntuneFilter + +foreach($Filter in $Filters){ + + write-host "Intune Filter:"$Filter.displayName -f Yellow + Export-JSONData -JSON $Filter -ExportPath "$ExportPath" + Write-Host +} + +Write-Host \ No newline at end of file diff --git a/Filters/IntuneFilter_Get.ps1 b/Filters/IntuneFilter_Get.ps1 new file mode 100644 index 0000000..3409cf0 --- /dev/null +++ b/Filters/IntuneFilter_Get.ps1 @@ -0,0 +1,271 @@ +<# + +.COPYRIGHT +Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +See LICENSE in the project root for license information. + +#> + +#################################################### + +function Get-AuthToken { + +<# +.SYNOPSIS +This function is used to authenticate with the Graph API REST interface +.DESCRIPTION +The function authenticate with the Graph API Interface with the tenant name +.EXAMPLE +Get-AuthToken +Authenticates you with the Graph API interface +.NOTES +NAME: Get-AuthToken +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + $User +) + +$userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User + +$tenant = $userUpn.Host + +Write-Host "Checking for AzureAD module..." + + $AadModule = Get-Module -Name "AzureAD" -ListAvailable + + if ($AadModule -eq $null) { + + Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview" + $AadModule = Get-Module -Name "AzureADPreview" -ListAvailable + + } + + if ($AadModule -eq $null) { + write-host + write-host "AzureAD Powershell module not installed..." -f Red + write-host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow + write-host "Script can't continue..." -f Red + write-host + exit + } + +# Getting path to ActiveDirectory Assemblies +# If the module count is greater than 1 find the latest version + + if($AadModule.count -gt 1){ + + $Latest_Version = ($AadModule | select version | Sort-Object)[-1] + + $aadModule = $AadModule | ? { $_.version -eq $Latest_Version.version } + + # Checking if there are multiple versions of the same module found + + if($AadModule.count -gt 1){ + + $aadModule = $AadModule | select -Unique + + } + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + + else { + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + +[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null + +[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null + +$clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" + +$redirectUri = "urn:ietf:wg:oauth:2.0:oob" + +$resourceAppIdURI = "https://graph.microsoft.com" + +$authority = "https://login.microsoftonline.com/$Tenant" + + try { + + $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority + + # https://msdn.microsoft.com/en-us/library/azure/microsoft.identitymodel.clients.activedirectory.promptbehavior.aspx + # Change the prompt behaviour to force credentials each time: Auto, Always, Never, RefreshSession + + $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto" + + $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId") + + $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result + + # If the accesstoken is valid then create the authentication header + + if($authResult.AccessToken){ + + # Creating header for Authorization token + + $authHeader = @{ + 'Content-Type'='application/json' + 'Authorization'="Bearer " + $authResult.AccessToken + 'ExpiresOn'=$authResult.ExpiresOn + } + + return $authHeader + + } + + else { + + Write-Host + Write-Host "Authorization Access Token is null, please re-run authentication..." -ForegroundColor Red + Write-Host + break + + } + + } + + catch { + + write-host $_.Exception.Message -f Red + write-host $_.Exception.ItemName -f Red + write-host + break + + } + +} + +#################################################### + +Function Get-IntuneFilter(){ + +<# +.SYNOPSIS +This function is used to get all filters configured from the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and gets any filters created +.EXAMPLE +Get-IntuneFilter +Returns any Filters configured in Intune +.NOTES +NAME: Get-IntuneFilter +#> + +[cmdletbinding()] + +param +( + $name +) + +$graphApiVersion = "beta" +$Resource = "deviceManagement/assignmentFilters" + + try { + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +#region Authentication + +write-host + +# Checking if authToken exists before running authentication +if($global:authToken){ + + # Setting DateTime to Universal time to work in all timezones + $DateTime = (Get-Date).ToUniversalTime() + + # If the authToken exists checking when it expires + $TokenExpires = ($authToken.ExpiresOn.datetime - $DateTime).Minutes + + if($TokenExpires -le 0){ + + write-host "Authentication Token expired" $TokenExpires "minutes ago" -ForegroundColor Yellow + write-host + + # Defining Azure AD tenant name, this is the name of your Azure Active Directory (do not use the verified domain name) + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + + $global:authToken = Get-AuthToken -User $User + + } +} + +# Authentication doesn't exist, calling Get-AuthToken function + +else { + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + +# Getting the authorization token +$global:authToken = Get-AuthToken -User $User + +} + +#endregion + +#################################################### + +$Filters = get-IntuneFilter + +if($Filters){ + + foreach($Filter in $Filters){ + + Write-Host "Filter Display Name:" $Filter.displayName -ForegroundColor Cyan + $filter + + } + +} + +else { + + Write-Host "No Filters created..." -ForegroundColor Yellow + Write-Host + +} \ No newline at end of file diff --git a/Filters/IntuneFilter_Import_FromJSON.ps1 b/Filters/IntuneFilter_Import_FromJSON.ps1 new file mode 100644 index 0000000..212c3e5 --- /dev/null +++ b/Filters/IntuneFilter_Import_FromJSON.ps1 @@ -0,0 +1,342 @@ + +<# + +.COPYRIGHT +Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +See LICENSE in the project root for license information. + +#> + +#################################################### + +function Get-AuthToken { + +<# +.SYNOPSIS +This function is used to authenticate with the Graph API REST interface +.DESCRIPTION +The function authenticate with the Graph API Interface with the tenant name +.EXAMPLE +Get-AuthToken +Authenticates you with the Graph API interface +.NOTES +NAME: Get-AuthToken +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + $User +) + +$userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User + +$tenant = $userUpn.Host + +Write-Host "Checking for AzureAD module..." + + $AadModule = Get-Module -Name "AzureAD" -ListAvailable + + if ($AadModule -eq $null) { + + Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview" + $AadModule = Get-Module -Name "AzureADPreview" -ListAvailable + + } + + if ($AadModule -eq $null) { + write-host + write-host "AzureAD Powershell module not installed..." -f Red + write-host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow + write-host "Script can't continue..." -f Red + write-host + exit + } + +# Getting path to ActiveDirectory Assemblies +# If the module count is greater than 1 find the latest version + + if($AadModule.count -gt 1){ + + $Latest_Version = ($AadModule | select version | Sort-Object)[-1] + + $aadModule = $AadModule | ? { $_.version -eq $Latest_Version.version } + + # Checking if there are multiple versions of the same module found + + if($AadModule.count -gt 1){ + + $aadModule = $AadModule | select -Unique + + } + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + + else { + + $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll" + $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll" + + } + +[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null + +[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null + +$clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" + +$redirectUri = "urn:ietf:wg:oauth:2.0:oob" + +$resourceAppIdURI = "https://graph.microsoft.com" + +$authority = "https://login.microsoftonline.com/$Tenant" + + try { + + $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority + + # https://msdn.microsoft.com/en-us/library/azure/microsoft.identitymodel.clients.activedirectory.promptbehavior.aspx + # Change the prompt behaviour to force credentials each time: Auto, Always, Never, RefreshSession + + $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto" + + $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId") + + $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result + + # If the accesstoken is valid then create the authentication header + + if($authResult.AccessToken){ + + # Creating header for Authorization token + + $authHeader = @{ + 'Content-Type'='application/json' + 'Authorization'="Bearer " + $authResult.AccessToken + 'ExpiresOn'=$authResult.ExpiresOn + } + + return $authHeader + + } + + else { + + Write-Host + Write-Host "Authorization Access Token is null, please re-run authentication..." -ForegroundColor Red + Write-Host + break + + } + + } + + catch { + + write-host $_.Exception.Message -f Red + write-host $_.Exception.ItemName -f Red + write-host + break + + } + +} + +#################################################### + +Function Add-IntuneFilter(){ + +<# +.SYNOPSIS +This function is used to add an Intune Filter using the Graph API REST interface +.DESCRIPTION +The function connects to the Graph API Interface and adds an Intune Filter +.EXAMPLE +Add-IntuneFilter -JSON $JSON +Adds an Intune Filter in Intune +.NOTES +NAME: Add-IntuneFilter +#> + +[cmdletbinding()] + +param +( + $JSON +) + +$graphApiVersion = "beta" +$Resource = "deviceManagement/assignmentFilters" + + try { + + if($JSON -eq "" -or $JSON -eq $null){ + + write-host "No JSON specified, please specify valid JSON for the Device Configuration Policy..." -f Red + + } + + else { + + Test-JSON -JSON $JSON + + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + Invoke-RestMethod -Uri $uri -Headers $authToken -Method Post -Body $JSON -ContentType "application/json" + + } + + } + + catch { + + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + write-host + break + + } + +} + +#################################################### + +Function Test-JSON(){ + +<# +.SYNOPSIS +This function is used to test if the JSON passed to a REST Post request is valid +.DESCRIPTION +The function tests if the JSON passed to the REST Post is valid +.EXAMPLE +Test-JSON -JSON $JSON +Test if the JSON is valid before calling the Graph REST interface +.NOTES +NAME: Test-AuthHeader +#> + +param ( + +$JSON + +) + + try { + + $TestJSON = ConvertFrom-Json $JSON -ErrorAction Stop + $validJson = $true + + } + + catch { + + $validJson = $false + $_.Exception + + } + + if (!$validJson){ + + Write-Host "Provided JSON isn't in valid JSON format" -f Red + break + + } + +} + +#################################################### + +#region Authentication + +write-host + +# Checking if authToken exists before running authentication +if($global:authToken){ + + # Setting DateTime to Universal time to work in all timezones + $DateTime = (Get-Date).ToUniversalTime() + + # If the authToken exists checking when it expires + $TokenExpires = ($authToken.ExpiresOn.datetime - $DateTime).Minutes + + if($TokenExpires -le 0){ + + write-host "Authentication Token expired" $TokenExpires "minutes ago" -ForegroundColor Yellow + write-host + + # Defining User Principal Name if not present + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + + $global:authToken = Get-AuthToken -User $User + + } +} + +# Authentication doesn't exist, calling Get-AuthToken function + +else { + + if($User -eq $null -or $User -eq ""){ + + $User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication" + Write-Host + + } + +# Getting the authorization token +$global:authToken = Get-AuthToken -User $User + +} + +#endregion + +#################################################### + +$ImportPath = Read-Host -Prompt "Please specify a path to a JSON file to import data from e.g. C:\IntuneOutput\Policies\policy.json" + +# Replacing quotes for Test-Path +$ImportPath = $ImportPath.replace('"','') + +if(!(Test-Path "$ImportPath")){ + +Write-Host "Import Path for JSON file doesn't exist..." -ForegroundColor Red +Write-Host "Script can't continue..." -ForegroundColor Red +Write-Host +break + +} + +#################################################### + +$JSON_Data = gc "$ImportPath" + +# Excluding entries that are not required - id,createdDateTime,lastModifiedDateTime,version +$JSON_Convert = $JSON_Data | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty id,createdDateTime,lastModifiedDateTime,roleScopeTags + +$DisplayName = $JSON_Convert.displayName + +$JSON_Output = $JSON_Convert | ConvertTo-Json -Depth 5 + +write-host +write-host "Intune Filter '$DisplayName' Found..." -ForegroundColor Yellow +write-host +$JSON_Output +write-host +Write-Host "Adding Intune Filter '$DisplayName'" -ForegroundColor Yellow +Add-IntuneFilter -JSON $JSON_Output \ No newline at end of file diff --git a/Filters/Readme.md b/Filters/Readme.md new file mode 100644 index 0000000..3f95e5a --- /dev/null +++ b/Filters/Readme.md @@ -0,0 +1,162 @@ +# Filters (preview) script samples + +This repository of PowerShell sample scripts show how to access Intune service resources. They demonstrate this by making HTTPS RESTful API requests to the Microsoft Graph API from PowerShell. + +Documentation for Intune and Microsoft Graph can be found here [Intune Graph Documentation](https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/intune_graph_overview). + +#### Disclaimer +Some script samples retrieve information from your Intune tenant, and others create, delete or update data in your Intune tenant.  Understand the impact of each sample script prior to running it; samples should be run using a non-production or "test" tenant account.  + +Within this section there are the following scripts with the explanation of usage. + +### 1. IntuneFilter_Export.ps1 +This script gets all the Intune Filters from the Intune Service that you have authenticated with. The script will then export the filters to .json format in the directory of your choice. + +```PowerShell +$ExportPath = Read-Host -Prompt "Please specify a path to export Intune Filters to e.g. C:\IntuneOutput" + + # If the directory path doesn't exist prompt user to create the directory + + if(!(Test-Path "$ExportPath")){ + + Write-Host + Write-Host "Path '$ExportPath' doesn't exist, do you want to create this directory? Y or N?" -ForegroundColor Yellow + + $Confirm = read-host + + if($Confirm -eq "y" -or $Confirm -eq "Y"){ + + new-item -ItemType Directory -Path "$ExportPath" | Out-Null + Write-Host + + } + + else { + + Write-Host "Creation of directory path was cancelled..." -ForegroundColor Red + Write-Host + break + + } + + } +``` + +#### Get-IntuneFilter Function +This function is used to get all Intune Filters from the Intune Service. + +```PowerShell +# Returns all Intune Filters configured in Intune +Get-IntuneFilter +``` + +#### Export-JSONData Function +This function is used to export the policy information. It has two required parameters -JSON and -ExportPath. + ++ JSON - The JSON data ++ ExportPath - The path where the .json should be exported to + +```PowerShell +Export-JSONData -JSON $JSON -ExportPath "$ExportPath" +``` + +### 2. IntuneFilter_Get.ps1 +This script gets all Intune Filters from the Intune Service that you have authenticated with. + +#### Get-IntuneFilter Function +This function is used to get all Intune Filters from the Intune Service. + +```PowerShell +# Returns all Intune Filters configured in Intune +Get-IntuneFilter +``` + +### 3. IntuneFilter_Import_FromJSON.ps1 +This script imports from a JSON file an Intune Filter into the Intune Service that you have authenticated with. + +When you run the script it will prompt for a path to a .json file, if the path is valid the Add-DeviceConfigurationPolicy function will be called. + +```PowerShell +$ImportPath = Read-Host -Prompt "Please specify a path to a JSON file to import data from e.g. C:\IntuneOutput\Policies\policy.json" + +# Replacing quotes for Test-Path +$ImportPath = $ImportPath.replace('"','') + +if(!(Test-Path "$ImportPath")){ + +Write-Host "Import Path for JSON file doesn't exist..." -ForegroundColor Red +Write-Host "Script can't continue..." -ForegroundColor Red +Write-Host +break + +} +``` + +#### Add-IntuneFilter Function +This function is used to add an Intune Filter to the Intune Service. It supports a single parameter -JSON as an input to the function to pass the JSON data to the service. + +```PowerShell +Add-IntuneFilter -JSON $JSON +``` + +### 4. AssociatedFilter_Get.ps1 +This script checks if an Intune Filter specified is used across any of the elements in Intune that support the Filters (preview) that you have authenticated with. + +When you run the script it will prompt for a filter name configured in the tenant, if the display name is valid via the Get-IntuneFilter function the script will continue. + +```PowerShell +write-host "Filters Name:" -f Yellow +$FilterName = Read-Host + +if($FilterName -eq $null -or $FilterName -eq ""){ + + write-host "Filter Name is Null..." -ForegroundColor Red + Write-Host "Script can't continue..." -ForegroundColor Red + Write-Host + break + +} +``` +#### Get-IntuneFilter Function +This function is used to get all Intune Filters from the Intune Service. + +```PowerShell +# Returns all Intune Filters configured in Intune +Get-IntuneFilter +``` + +If a filter is found the script will output the information about the filter +``` +Filter found... +Filter Id: eebd25bd-4b25-4d46-ab5c-6cc07b801b79 +Filter Name: Android Enterprise - Google Devices +Filter Platform: androidForWork +Filter Rule: (device.manufacturer -eq "Google") +Filter Scope Tag: 0 +``` + +Once and Intune Filter has been found and verified as a single entry, the script will look through the following element types to check if the Intune Filter is being used. + +- Compliance Policies +- Configuration Policies +- Settings Catalog Policies +- Administrative Template Policies +- Intune Applications + +Once this is complete the script will return "Overall Analysis" of where the filter is being used. +``` +------------------------------------------------------------------- +Overall Analysis +------------------------------------------------------------------- +Status of each area of MEM that support Filters assignment status + +Applicable OS Type: androidForWork + +Compliance Policies: 1 +Device Configuration Policies: 1 +Settings Catalog Policies: 0 +Administrative Templates: 0 +Intune Applications: 0 + +Total Filters Assigned: 2 +``` diff --git a/IntuneDataExport/Export-IntuneData.ps1 b/IntuneDataExport/Export-IntuneData.ps1 index d727027..b5a8cf2 100644 --- a/IntuneDataExport/Export-IntuneData.ps1 +++ b/IntuneDataExport/Export-IntuneData.ps1 @@ -648,21 +648,19 @@ function Get-WindowsProtectionSummary { function Get-ManagedAppUsageSummary { Log-Info "Getting Managed App Usage Summary for user $UPN" - $UsageSummary = Get-MsGraphObject "deviceAppManagement/managedAppStatuses('usageSummary')" - $Report = ($UsageSummary.content.report | ConvertFrom-Json) + $UsageSummary = Get-MsGraphObject "deviceAppManagement/managedAppStatuses('appregistrationsummary')?fetch=6000&policyMode=0&columns=UserId,DisplayName,UserEmail,ApplicationName,ApplicationInstanceId,ApplicationVersion,DeviceName,DeviceType,DeviceManufacturer,DeviceModel,AndroidPatchVersion,AzureADDeviceId,MDMDeviceID,Platform,PlatformVersion,ManagementLevel,PolicyName,LastCheckInDate" + $Report = $UsageSummary.content.body $FilteredRows = @() - if ($Report.value.Count -gt 0) { - foreach ($Row in $Report.value) { - if ($Row.userId -ieq $UserId) { + if ($Report.Count -gt 0) { + foreach ($Row in $Report) { + if ($Row.values[0] -ieq $UserId) { $FilteredRows += $Row } } } - - $Report.value = $FilteredRows - - $UsageSummary.content.report = $Report + $Report = $FilteredRows + $UsageSummary.content.body = $Report return $UsageSummary } diff --git a/MDATP/MacOS_MDATP_Deployment_Add.ps1 b/MDATP/MacOS_MDATP_Deployment_Add.ps1 index 84382e8..f8ac7ee 100755 --- a/MDATP/MacOS_MDATP_Deployment_Add.ps1 +++ b/MDATP/MacOS_MDATP_Deployment_Add.ps1 @@ -459,10 +459,10 @@ $MDATP = @" { "@odata.type": "#microsoft.graph.macOSMdatpApp", - "description": "Microsoft Defender Advanced Threat Protection (Microsoft Defender ATP) is a unified platform for preventative protection, post-breach detection, automated investigation, and response. Microsoft Defender ATP protects endpoints from cyber threats; detects advanced attacks and data breaches, automates security incidents and improves security posture.", + "description": "Microsoft Defender for Endpoint (macOS) is a unified platform for preventative protection, post-breach detection, automated investigation, and response. Microsoft Defender ATP protects endpoints from cyber threats; detects advanced attacks and data breaches, automates security incidents and improves security posture.", "developer": "Microsoft", - "displayName": "macOS Microsoft Defender ATP for macOS", - "informationUrl": "https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/microsoft-defender-advanced-threat-protection​", + "displayName": "Microsoft Defender for Endpoint (macOS)", + "informationUrl": "https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/microsoft-defender-endpoint​", "isFeatured": false, "largeIcon": { "type": "image/png", @@ -470,7 +470,7 @@ $MDATP = @" }, "notes": "", "owner": "Microsoft", - "privacyInformationUrl": "https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/mac-privacy​", + "privacyInformationUrl": "https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/mac-privacy​", "publisher": "Microsoft" } @@ -566,4 +566,4 @@ $CreateResult_sysext = Add-DeviceConfigurationPolicy -JSON $MDATP_sysext Write-Host " + Device MDATP System Extension Policy created as" $CreateResult_sysext.id -Write-Host \ No newline at end of file +Write-Host diff --git a/ManagedDevices/Win10_PrimaryUser_Get.ps1 b/ManagedDevices/Win10_PrimaryUser_Get.ps1 index 4dc2c3b..7af451c 100644 --- a/ManagedDevices/Win10_PrimaryUser_Get.ps1 +++ b/ManagedDevices/Win10_PrimaryUser_Get.ps1 @@ -430,6 +430,52 @@ param #################################################### +function Get-IntuneUserName { + +<# +.SYNOPSIS +This lists the Intune device primary user +.DESCRIPTION +This lists the Intune device primary user +.EXAMPLE +Get-IntuneDevicePrimaryUser +.NOTES +NAME: Get-IntuneDevicePrimaryUser +#> + +[cmdletbinding()] + +param +( + [Parameter(Mandatory=$true)] + [string] $userId +) + + $graphApiVersion = "beta" + $Resource = "users" + $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)" + "/" + $userId + try { + + $primaryUser = Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get + + return $primaryUser.DisplayName + + } catch { + $ex = $_.Exception + $errorResponse = $ex.Response.GetResponseStream() + $reader = New-Object System.IO.StreamReader($errorResponse) + $reader.BaseStream.Position = 0 + $reader.DiscardBufferedData() + $responseBody = $reader.ReadToEnd(); + Write-Host "Response content:`n$responseBody" -f Red + Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)" + throw "Get-IntuneUserName error" + } +} + + + + #region Authentication write-host @@ -499,6 +545,7 @@ if($Devices){ Write-Host "Intune device id:" $device."id" $IntuneDevicePrimaryUser = Get-IntuneDevicePrimaryUser -deviceId $device.id + $displayName = Get-IntuneUserName $IntuneDevicePrimaryUser if($IntuneDevicePrimaryUser -eq $null){ @@ -509,7 +556,7 @@ if($Devices){ else { Write-Host "Intune Primary user id:" $IntuneDevicePrimaryUser - + Write-Host "Intune Primary user display name: " $displayName } $aadDeviceId = Get-AADDeviceId -deviceId $device."azureActiveDirectoryDeviceId" diff --git a/README-localized/Readme-es-es.md b/README-localized/Readme-es-es.md new file mode 100644 index 0000000..39c45d4 --- /dev/null +++ b/README-localized/Readme-es-es.md @@ -0,0 +1,133 @@ +--- +page_type: sample +products: +- ms-graph +languages: +- powershell +extensions: + contentType: samples + technologies: + - Microsoft Graph + services: + - Intune + createdDate: 4/4/2017 9:41:27 AM +--- +# Ejemplos de Graph de Intune + +Este repositorio de scripts de ejemplo de PowerShell muestra cómo obtener acceso a los recursos del servicio Intune. Lo muestran haciendo solicitudes de la API de REST de HTTPS a la API de Microsoft Graph desde PowerShell. + +La documentación de Intune y Microsoft Graph se encuentra aquí [Documentación de Graph de Intune](https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/intune_graph_overview). + +En estos ejemplos se muestran las acciones de administrador de Intune o de asociado de Microsoft habituales para administrar recursos de Intune. + +Los siguientes ejemplos se incluyen en este repositorio: +- AdminConsent +- AndroidEnterprise +- AppleEnrollment +- Applications +- ApplicationSync +- AppProtectionPolicy +- Auditing +- Authentication +- CertificationAuthority +- CheckStatus +- CompanyPortalBranding +- CompliancePolicy +- CorporateDeviceEnrollment +- DeviceConfiguration +- EnrollmentRestrictions +- IntuneDataExport +- LOB_Application +- ManagedDevices +- Paging +- RBAC +- RemoteActionAudit +- SoftwareUpdates +- TermsAndConditions +- UserPolicyReport + +Los scripts se otorgan bajo licencia "tal cual" en la licencia MIT. + +#### Aviso de declinación de responsabilidades +Algunos ejemplos de script recuperan información de su espacio empresarial de Intune y otras crean, eliminan o actualizan los datos en el espacio empresarial de Intune.  Debe comprender el impacto de cada script de ejemplo antes de ejecutarlo, los ejemplos se deben ejecutar con una cuenta de inquilino que no es de producción o "de prueba".  + +## Usar la API de Graph de Intune +La API de Graph de Intune permite el acceso mediante programación a la información de Intune para su espacio empresarial y la API realiza las mismas operaciones de Intune que las que están disponibles a través de Azure Portal.   + +Intune proporciona datos a Microsoft Graph igual que lo hacen otros servicios en la nube, con navegación de relaciones e información sobre entidades enriquecida.  Use Microsoft Graph para combinar la información de otros servicios e Intune y crear aplicaciones de servicios cruzados completas para profesionales de TI o usuarios finales.      + +## Requisitos previos +El uso de estos ejemplos de PowerShell de Intune de la API de Microsoft Graph requiere lo siguiente: +* Instalar el módulo de AzureAD PowerShell ejecutando "Install-Module AzureAD" o "Install-Module AzureADPreview" desde un símbolo del sistema de PowerShell con privilegios elevados +* Un espacio empresarial de Intune que admita Azure Portal con una licencia de producción o de prueba (https://docs.microsoft.com/en-us/intune-azure/introduction/what-is-microsoft-intune) +* Usar las API de Microsoft Graph para configurar las directivas y los controles de Intune requiere una licencia de Intune. +* Una cuenta con permisos para administrar el servicio de Intune +* PowerShell v5.0 en Windows 10 x64 (PowerShell v4.0 es un requisito mínimo para que los scripts funcionen correctamente) +* Nota: En el caso de PowerShell 4.0 necesitará el módulo [PowershellGet Module for PS 4.0](https://www.microsoft.com/en-us/download/details.aspx?id=51451) para habilitar el uso de la función Install-Module +* El uso de estos scripts por primera vez requiere que un administrador global del espacio empresarial acepte los permisos de la aplicación + +## Introducción +Después de que se instalen o se cumplan los requisitos previos, lleve a cabo los siguientes pasos para usar estos scripts: + +#### 1. Uso del script + +1. Descargue el contenido del repositorio en su equipo local de Windows +* Extraiga los archivos en una carpeta local (por ejemplo, C:\IntuneGraphSamples) +* En el menú Inicio ejecute PowerShell x64 +* Desplácese hasta el directorio (p. ej., cd C:\IntuneGraphSamples) +* Por cada carpeta en el repositorio local, puede ir a ese directorio y ejecutar el script que prefiera. +* Uso de script de aplicación de ejemplo: + * Para usar los scripts de Administrar aplicaciones, en C:\IntuneGraphSamples, ejecute "cd .\Applications\". + * Una vez en la carpeta ejecute .\Application_MDM_Get.ps1 + para obtener todas las aplicaciones agregadas por MDM Esta secuencia de pasos se puede usar para cada carpeta.... + +#### 2. Autenticación con Microsoft Graph +La primera vez que ejecute estos scripts, se le pedirá que proporcione una cuenta para autenticar con el servicio: +``` +Please specify your user principal name for Azure Authentication: +``` +Una vez que haya proporcionado un nombre principal de usuario, se abrirá una ventana emergente en la que se le solicitará la contraseña. Cuando la autenticación de Azure Active Directory se realice correctamente, el token de usuario durará una hora, cuando pase la hora en la sesión de PowerShell, se le solicitará que vuelva a autenticarse. + +Si está ejecutando el script por primera vez en su espacio empresarial, se mostrará un mensaje emergente en el que se indicará lo siguiente: + +``` +Microsoft Intune PowerShell needs permission to: + +* Sign you in and read your profile +* Read all groups +* Read directory data +* Read and write Microsoft Intune Device Configuration and Policies (preview) +* Read and write Microsoft Intune RBAC settings (preview) +* Perform user-impacting remote actions on Microsoft Intune devices (preview) +* Sign in as you +* Read and write Microsoft Intune devices (preview) +* Read and write all groups +* Read and write Microsoft Intune configuration (preview) +* Read and write Microsoft Intune apps (preview) +``` + +Nota: Si su cuenta de usuario tiene como objetivo el acceso condicional basado en el dispositivo, el dispositivo debe estar inscrito o ser compatible para poder realizar la autenticación de forma correcta. + +## Colaboradores + +Si quiere hacer su aportación a este ejemplo, vea CONTRIBUTING.MD. + +Este proyecto ha adoptado el Código de conducta de código abierto de Microsoft. Para obtener más información, vea Preguntas frecuentes sobre el código de conducta o póngase en contacto con opencode@microsoft.com si tiene otras preguntas o comentarios. + +## Preguntas y comentarios + +Nos encantaría recibir sus comentarios sobre el ejemplo de PowerShell de Intune. Puede enviarnos sus preguntas y sugerencias a través de la sección Problemas de este repositorio. + +Su opinión es importante para nosotros. Conéctese con nosotros en Stack Overflow. Etiquete sus preguntas con \[MicrosoftGraph] y \[intune]. + + +## Recursos adicionales +* [Documentación de la API de Microsoft Graph](https://developer.microsoft.com/en-us/graph/docs) +* [Portal de Microsoft Graph](https://developer.microsoft.com/en-us/graph/graph-explorer) +* [Muestras de código de Microsoft ](https://developer.microsoft.com/en-us/graph/code-samples-and-sdks) +* [Documentación de Graph de Intune](https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/intune_graph_overview) + +## Derechos de autor +Copyright (c) 2017 Microsoft. Todos los derechos reservados. + +Este proyecto ha adoptado el [Código de conducta de código abierto de Microsoft](https://opensource.microsoft.com/codeofconduct/). Para obtener más información, vea [Preguntas frecuentes sobre el código de conducta](https://opensource.microsoft.com/codeofconduct/faq/) o póngase en contacto con [opencode@microsoft.com](mailto:opencode@microsoft.com) si tiene otras preguntas o comentarios. diff --git a/README-localized/Readme-fr-fr.md b/README-localized/Readme-fr-fr.md new file mode 100644 index 0000000..9a058be --- /dev/null +++ b/README-localized/Readme-fr-fr.md @@ -0,0 +1,133 @@ +--- +page_type: sample +products: +- ms-graph +languages: +- powershell +extensions: + contentType: samples + technologies: + - Microsoft Graph + services: + - Intune + createdDate: 4/4/2017 9:41:27 AM +--- +# Exemples Intune Graph + +Ce référentiel d’exemples de scripts PowerShell présente comment accéder aux ressources du service Intune. Les exemples illustrent l'envoi de demandes d’API RESTful HTTPS à l’API Microsoft Graph à partir de PowerShell. + +La documentation sur Intune et Microsoft Graph est disponible ici [Documentation Intune Graph](https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/intune_graph_overview). + +Ces exemples illustrent des actions classiques d'administrateurs Intune ou de partenaires Microsoft pour la gestion des ressources Intune. + +Les exemples suivants sont inclus dans le référentiel : +-AdminConsent +-AndroidEnterprise +-AppleEnrollment +-applications +-ApplicationSync +-AppProtectionPolicy +-Auditing +-Authentication +-CertificationAuthority +-CheckStatus +-CompanyPortalBranding +-CompliancePolicy +-CorporateDeviceEnrollment +-DeviceConfiguration +-EnrollmentRestrictions +-IntuneDataExport +-LOB_Application +-ManagedDevices +-pagination +-RBAC +-RemoteActionAudit +-SoftwareUpdates +-TermsAndConditions +-UserPolicyReport + +Les scripts sont sous licence « en l'état » sous la Licence MIT. + +#### Clause d’exclusion de responsabilité +Certains exemples de script récupèrent des informations de votre client Intune, alors que d’autres créent, suppriment ou mettent à jour des données dans votre client Intune.  Veuillez comprendre l’influence de chaque exemple de script avant de l’exécuter ; les exemples doivent être exécutés à l’aide d’un compte client non productif ou en « test ».  + +## Utilisation de l’API Graph Intune +L’API de Microsoft Graph pour Intune permet l’accès programmatique aux informations Intune relatives à votre client ; l’API effectue les mêmes opérations Intune que celles disponibles via le Portail Azure.   + +Intune fournit des données dans Microsoft Graph Intune de la même façon que d’autres services cloud, avec des informations d’identité enrichies et une navigation des relations.  Utilisez Microsoft Graph pour combiner les informations provenant d’autres services et d’Intune et créer des applications interservices enrichies pour les professionnels de l’informatique ou des utilisateurs finaux.      + +## Conditions préalables +Pour utiliser les exemples d’API Intune PowerShell de Microsoft Graph, les éléments suivants sont nécessaires : +* installer le module AzureAD PowerShell en exécutant « Install-Module AzureAD » ou « Install-Module AzureADPreview » à partir d’une invite PowerShell avec élévation de privilèges +* Un client Intune qui prend en charge le Portail Azure avec une licence de production ou d’évaluation (https://docs.microsoft.com/en-us/intune-azure/introduction/what-is-microsoft-intune) +* Une licence Intune est nécessaire pour l'utilisation des API Microsoft pour configurer les stratégies et les contrôles +* Un compte disposant des autorisations pour administrer le service Intune +* PowerShell v5.0 sur Windows 10 x64 (PowerShell v4.0 est une condition minimale requise pour que les scripts fonctionnent correctement) +* Remarque : Pour PowerShell 4.0, vous aurez besoin du [Module PowershellGet pour PS 4.0](https://www.microsoft.com/en-us/download/details.aspx?id=51451) pour activer l’utilisation de la fonctionnalité Install-Module +* La première utilisation de ces scripts nécessite l'acceptation des autorisations d'application par un administrateur général du client. + +## Prise en main +Une fois que vous avez installé ou rempli les conditions préalables, procédez comme suit pour utiliser ces scripts : + +#### 1. Utilisation de script + +1. Téléchargez le contenu du référentiel sur votre ordinateur Windows local +* Faites une extraction des fichiers dans un dossier local (par exemple, C:\IntuneGraphSamples) +* Exécutez PowerShell x64 dans le menu de démarrage +* Accédez au répertoire (par exemple, CD C:\IntuneGraphSamples) +* Pour chaque Dossier du référentiel local, vous pouvez accéder à ce répertoire, puis exécuter le script de votre choix. +* Exemple d’utilisation du script d’application : + * Pour utiliser les scripts Gérer les applications, à partir de C:\IntuneGraphSamples, exécutez « cd .\Applications\ » + * Une fois dans le dossier, exécutez \Application_MDM_Get.ps1 + pour obtenir toutes les applications ajoutées. Cette série d’étapes peut être utilisée pour chaque dossier.... + +#### 2. Authentification d’application à l'aide de Microsoft Graph +Lorsque vous exécutez ces scripts pour la première fois, vous êtes invité à fournir un compte pour vous authentifier auprès du service : +``` +Please specify your user principal name for Azure Authentication: +``` +Une fois que vous avez fourni un nom d’utilisateur principal, une fenêtre contextuelle s’ouvre et vous invite à saisir votre mot de passe. Une fois l’authentification réussie avec Azure Active Directory, le jeton d’utilisateur est valable pendant une heure. Au-delà de cette heure au sein de la session PowerShell, vous êtes invité à vous authentifier de nouveau. + +Si vous exécutez le script pour la première fois chez votre client, une fenêtre contextuelle s’affiche indiquant : + +``` +Microsoft Intune PowerShell needs permission to: + +* Sign you in and read your profile +* Read all groups +* Read directory data +* Read and write Microsoft Intune Device Configuration and Policies (preview) +* Read and write Microsoft Intune RBAC settings (preview) +* Perform user-impacting remote actions on Microsoft Intune devices (preview) +* Sign in as you +* Read and write Microsoft Intune devices (preview) +* Read and write all groups +* Read and write Microsoft Intune configuration (preview) +* Read and write Microsoft Intune apps (preview) +``` + +Remarque : Si votre compte utilisateur est ciblé pour l’accès conditionnel basé sur l’appareil, votre appareil doit être inscrit ou être conforme pour réussir l’authentification. + +## Contribution + +Si vous souhaitez contribuer à cet exemple, voir CONTRIBUTING.MD. + +Ce projet a adopté le Code de conduite Open Source de Microsoft. Pour plus d'informations, reportez-vous à la FAQ relative au Code de conduite ou contactez opencode@microsoft.com pour toute question ou tout commentaire. + +## Questions et commentaires + +Nous serions ravis de connaître votre opinion sur l’exemple Intune PowerShell. Vous pouvez nous faire part de vos questions et suggestions dans la rubrique problèmes de ce référentiel. + +Votre avis compte beaucoup pour nous. Communiquez avec nous sur Stack Overflow. Posez vos questions avec les tags [MicrosoftGraph] et [Intune]. + + +## Ressources supplémentaires +* [Documentation de l’API Microsoft Graph](https://developer.microsoft.com/en-us/graph/docs) +* [Portail Microsoft Graph](https://developer.microsoft.com/en-us/graph/graph-explorer) +* [Exemple de codes Microsoft](https://developer.microsoft.com/en-us/graph/code-samples-and-sdks) +* [Documentation d'Intune Graph](https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/intune_graph_overview) + +## Copyright +Copyright (c) 2017 Microsoft. Tous droits réservés. + +Ce projet a adopté le [code de conduite Open Source de Microsoft](https://opensource.microsoft.com/codeofconduct/). Pour en savoir plus, reportez-vous à la [FAQ relative au code de conduite](https://opensource.microsoft.com/codeofconduct/faq/) ou contactez [opencode@microsoft.com](mailto:opencode@microsoft.com) pour toute question ou tout commentaire. diff --git a/README-localized/Readme-ja-jp.md b/README-localized/Readme-ja-jp.md new file mode 100644 index 0000000..00b0126 --- /dev/null +++ b/README-localized/Readme-ja-jp.md @@ -0,0 +1,133 @@ +--- +page_type: sample +products: +- ms-graph +languages: +- powershell +extensions: + contentType: samples + technologies: + - Microsoft Graph + services: + - Intune + createdDate: 4/4/2017 9:41:27 AM +--- +# Intune Graph のサンプル + +この PowerShell サンプル スクリプトのリポジトリは、Intune サービス リソースにアクセスする方法を示しています。PowerShell から Microsoft Graph API に HTTPS RESTful API 要求を行うことにより、その方法を示します。 + +Intune および Microsoft Graph のドキュメントについては、「[Intune Graph のドキュメント](https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/intune_graph_overview)」を参照してください。 + +これらのサンプルでは、一般的な Intune 管理者、または Intune リソースを管理するための Microsoft パートナーの操作を示します。 + +このリポジトリには、次のサンプルが含まれています: +- AdminConsent +- AndroidEnterprise +- AppleEnrollment +- Applications +- ApplicationSync +- AppProtectionPolicy +- Auditing +- Authentication +- CertificationAuthority +- CheckStatus +- CompanyPortalBranding +- CompliancePolicy +- CorporateDeviceEnrollment +- DeviceConfiguration +- EnrollmentRestrictions +- IntuneDataExport +- LOB_Application +- ManagedDevices +- Paging +- RBAC +- RemoteActionAudit +- SoftwareUpdates +- TermsAndConditions +- UserPolicyReport + +スクリプトは、MIT ライセンスの下、 "現状有姿" でライセンス付与されます。 + +#### 免責事項 +一部のスクリプトサンプルでは、Intune テナントから情報を取得ます。また、他のスクリプト サンプルでは、Intune テナントでデータを作成、削除、更新します。  実行前に、各サンプルスクリプトの影響を理解してください。サンプルは、非運用テナント アカウントまたは "テスト" テナントアカウントを使用して実行する必要があります。  + +## Intune Graph API の使用 +Intune Graph API を使用すると、テナントの Intune の情報へのプログラムによるアクセスが可能となります。API は Azure Portal で使用できるものと同じ Intune 操作を実行します。   + +Intune は、豊富なエンティティ情報とリレーションシップのナビゲーションを使用して、他のクラウド サービスと同じ方法で Microsoft Graph にデータを提供します。  Microsoft Graph を使用して、他のサービスからの情報と Intune を結合し、IT プロフェッショナルやエンド ユーザー向けの豊富なサービス間アプリケーションをビルドします。      + +## 前提条件 +これらの Microsoft Graph API Intune PowerShell のサンプルを使用するには、以下が必要です。 +* 管理者特権の PowerShell プロンプトから「Install-Module AzureAD」または「Install-Module AzureADPreview」を実行して、AzureAD PowerShell モジュールをインストールすること +* 本番ライセンスまたは試用ライセンスで Azure Portal をサポートする Intune テナント (https://docs.microsoft.com/en-us/intune-azure/introduction/what-is-microsoft-intune) +* Microsoft Graph API を使用して Intune 制御とポリシーを構成するには、Intune ライセンスが必要です。 +* Intune サービスを管理する権限を持つアカウント +* Windows 10 x64 上の PowerShell v5.0 (PowerShell v4.0 は、スクリプトが正しく機能するための最小要件です) +* 注:PowerShell 4.0 の場合、インストール モジュール機能の使用を可能にするために [PS 4.0 用PowershellGet モジュール](https://www.microsoft.com/en-us/download/details.aspx?id=51451)が必要です +* これらのスクリプトを初めて使用するために、テナントのグローバル管理者がアプリケーションのアクセス許可を受け入れる必要があります + +## はじめに +前提条件をインストールした後、または前提条件を満たした後、次の手順を実行して、これらのスクリプトを使用します。 + +#### 1.スクリプトの使用方法 + +1. ローカル Windows マシンにリポジトリのコンテンツをダウンロードします +* ローカル フォルダー (例: C:\IntuneGraphSamples) にファイルを抽出します +* スタート メニューで PowerShell x64 を実行します +* ディレクトリ (例: cd C:\IntuneGraphSamples) を参照します +* ローカル リポジトリ内のフォルダーごとに、そのディレクトリを参照し、選択したスクリプトを実行できます。 +* アプリケーション スクリプトの使用例: + * Manage Applications スクリプトを実行するには、C:\IntuneGraphSamples から、"cd .\Applications\" を実行します + * フォルダーで .\Application_MDM_Get.ps1 + を実行し、すべての MDM 追加アプリケーションを取得します。この手順のシーケンスは、各フォルダーで使用できます。 + +#### 2.Microsoft Graph で認証する +これらのスクリプトを初めて実行するときに、サービスで認証するアカウントを指定するように求められます。 +``` +Please specify your user principal name for Azure Authentication: +``` +ユーザー プリンシパル名を入力すると、パスワードの入力を求めるメッセージが表示されます。Azure Active Directory で正常に認証された後、ユーザー トークンは1時間後に、PowerShell セッション内で有効期限が切れると、再認証を求められます。 + +テナントに対して初めてスクリプトを実行する場合は、以下のメッセージが表示されます。 + +``` +Microsoft Intune PowerShell needs permission to: + +* Sign you in and read your profile +* Read all groups +* Read directory data +* Read and write Microsoft Intune Device Configuration and Policies (preview) +* Read and write Microsoft Intune RBAC settings (preview) +* Perform user-impacting remote actions on Microsoft Intune devices (preview) +* Sign in as you +* Read and write Microsoft Intune devices (preview) +* Read and write all groups +* Read and write Microsoft Intune configuration (preview) +* Read and write Microsoft Intune apps (preview) +``` + +注:ユーザー アカウントがデバイス ベースの条件付きアクセスを対象としている場合は、認証させるために、デバイスを登録するか、準拠する必要があります。 + +## 投稿 + +このサンプルに投稿する場合は、CONTRIBUTING.MD を参照してください。 + +このプロジェクトでは、Microsoft オープン ソース倫理規定が採用されています。詳細については、「倫理規定の FAQ」を参照してください。また、その他の質問やコメントがあれば、opencode@microsoft.com までお問い合わせください。 + +## 質問とコメント + +PowerShell のサンプルに関するフィードバックをお寄せください。質問や提案は、このリポジトリの「問題」セクションで送信できます。 + +お客様からのフィードバックを重視しています。スタック オーバーフローでご連絡ください。質問には [MicrosoftGraph] と [intune] でタグ付けしてください。 + + +## その他のリソース +* [Microsoft Graph API ドキュメント](https://developer.microsoft.com/en-us/graph/docs) +* [Microsoft Graph ポータル](https://developer.microsoft.com/en-us/graph/graph-explorer) +* [Microsoft コード サンプル](https://developer.microsoft.com/en-us/graph/code-samples-and-sdks) +* [Intune Graph ドキュメント](https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/intune_graph_overview) + +## 著作権 +Copyright (c) 2017 Microsoft.All rights reserved. + +このプロジェクトでは、[Microsoft オープン ソース倫理規定](https://opensource.microsoft.com/codeofconduct/) が採用されています。詳細については、「[Code of Conduct の FAQ (倫理規定の FAQ)](https://opensource.microsoft.com/codeofconduct/faq/)」を参照してください。また、その他の質問やコメントがあれば、[opencode@microsoft.com](mailto:opencode@microsoft.com) までお問い合わせください。 diff --git a/README-localized/Readme-pt-br.md b/README-localized/Readme-pt-br.md new file mode 100644 index 0000000..14e0f3b --- /dev/null +++ b/README-localized/Readme-pt-br.md @@ -0,0 +1,133 @@ +--- +page_type: sample +products: +- ms-graph +languages: +- powershell +extensions: + contentType: samples + technologies: + - Microsoft Graph + services: + - Intune + createdDate: 4/4/2017 9:41:27 AM +--- +# Exemplos de Gráficos do Intune + +Este repositório de exemplos de scripts do PowerShell mostra como acessar os recursos de serviços do Intune. Eles demonstram isso por meio de solicitações da API RESTful HTTPS à API do Microsoft Graph do PowerShell. + +É possível encontrar a documentação do Intune e do Microsoft Graph aqui [Documentação do Graph para Intune](https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/intune_graph_overview). + +Esses exemplos mostram o administrador típico do Intune ou ações de parceiros da Microsoft para o gerenciamento de recursos do Intune. + +Os exemplos a seguir estão incluídos neste repositório: +- AdminConsent +- AndroidEnterprise +- AppleEnrollment +- Applications +- ApplicationSync +- AppProtectionPolicy +- Auditing +- Authentication +- CertificationAuthority +- CheckStatus +- CompanyPortalBranding +- CompliancePolicy +- CorporateDeviceEnrollment +- DeviceConfiguration +- EnrollmentRestrictions +- IntuneDataExport +- LOB_Application +- ManagedDevices +- Paging +- RBAC +- RemoteActionAudit +- SoftwareUpdates +- TermsAndConditions +- UserPolicyReport + +Os scripts são licenciados no estado em que se encontram sob a Licença MIT. + +#### Aviso de isenção de responsabilidade +Algumas amostras de script recuperam informações de seu locatário do Intune e outras criam, excluem ou atualizam dados no locatário do Intune.  Compreenda o impacto de cada script de exemplo antes de executá-lo. Os exemplos devem ser executados usando uma conta de locatário de teste ou que não seja de produção.  + +## Uso da API do Graph para Intune +A API do Graph para Intune permite o acesso programático a informações do Intune para seu locatário; a API executa as mesmas operações do Intune disponibilizadas pelo Portal do Azure.   + +O Intune fornece dados para o Microsoft Graph da mesma forma que outros serviços de nuvem fazem, com informações avançadas sobre entidades e navegação de relacionamentos.  Use o Microsoft Graph para combinar informações de outros serviços e do Intune e criar aplicativos avançados com serviços variados para profissionais de TI ou usuários finais.      + +## Pré-requisitos +O uso desses exemplos do PowerShell para o Intune na API do Microsoft Graph exige o seguinte: +* Instale o módulo de PowerShell do AzureAD executando "Install-Module AzureAD" ou "Install-Module AzureADPreview" em um prompt de PowerShell elevado +* Um locatário do Intune que suporte o Portal do Azure com uma licença de produção ou de avaliação (https://docs.microsoft.com/en-us/intune-azure/introduction/what-is-microsoft-intune) +* Usar as APIs do Microsoft Graph para configurar os controles e políticas do Intune requer uma licença do Intune +* Uma conta com permissões para administrar o serviço do Intune +* PowerShell v 5.0 no Windows 10 x64 (o PowerShell v 4.0 é o requisito mínimo para os scripts funcionarem corretamente) +* Observação: Para o PowerShell 4.0, você precisará do [Módulo PowershellGet para PS 4.0](https://www.microsoft.com/en-us/download/details.aspx?id=51451) a fim de habilitar o uso da funcionalidade Install-Module +* A primeira utilização desses scripts exige que um Administrador Global do Locatário aceite as permissões do aplicativo + +## Introdução +Após instalar ou atender aos pré-requisitos, execute as etapas a seguir para usar esses scripts: + +#### 1. Uso de script + +1. Baixe o conteúdo do repositório para o seu computador local com Windows +* Extraia os arquivos em uma pasta local (por exemplo, C:\IntuneGraphSamples) +* Execute o PowerShell x64 no menu Iniciar +* Navegue até o diretório (por exemplo, cd C:\IntuneGraphSamples) +* Você pode navegar em cada pasta do repositório local e executar o script de sua escolha +* Exemplo de uso de script de aplicativo: + * Para usar os scripts para Gerenciar Aplicativos em C:\IntuneGraphSamples, execute "cd .\Applications\" + * Quando estiver na pasta, execute .\Application_MDM_Get.ps1 + para obter todos os aplicativos MDM adicionados. Essa sequência de etapas pode ser usada em cada pasta. + +#### 2. Autenticação com o Microsoft Graph +Na primeira vez que executar estes scripts, você será solicitado a fornecer uma conta para autenticação com o serviço: +``` +Please specify your user principal name for Azure Authentication: +``` +Depois de fornecer o nome principal do usuário, um pop-up será aberto para solicitar sua senha. Após uma autenticação bem-sucedida com o Azure Active Directory, o token de usuário dura por uma hora e, quando a hora expirar dentro da sessão do PowerShell, será solicitada uma nova autenticação. + +Se você estiver executando o script pela primeira vez em seu locatário, um pop-up será apresentado: + +``` +Microsoft Intune PowerShell needs permission to: + +* Sign you in and read your profile +* Read all groups +* Read directory data +* Read and write Microsoft Intune Device Configuration and Policies (preview) +* Read and write Microsoft Intune RBAC settings (preview) +* Perform user-impacting remote actions on Microsoft Intune devices (preview) +* Sign in as you +* Read and write Microsoft Intune devices (preview) +* Read and write all groups +* Read and write Microsoft Intune configuration (preview) +* Read and write Microsoft Intune apps (preview) +``` + +Observação: Se sua conta de usuário se destina ao acesso condicional baseado em dispositivo, seu dispositivo deve estar registrado ou em conformidade para passar na autenticação. + +## Colaboração + +Se quiser contribuir para esse exemplo, confira CONTRIBUTING.MD. + +Este projeto adotou o Código de Conduta do Código Aberto da Microsoft. Para saber mais, confira as Perguntas frequentes sobre o Código de Conduta ou contate opencode@microsoft.com se tiver outras dúvidas ou comentários. + +## Perguntas e comentários + +Gostaríamos de saber a sua opinião sobre o exemplo de PowerShell do Intune. Você pode enviar perguntas e sugestões na seção Questões deste repositório. + +Seus comentários são importantes para nós. Junte-se a nós na página do Stack Overflow. Marque as suas perguntas com \[MicrosoftGraph] e \[Inture]. + + +## Recursos adicionais +* [Documentação da API do Microsoft Graph](https://developer.microsoft.com/en-us/graph/docs) +* [Portal do Microsoft Graph](https://developer.microsoft.com/en-us/graph/graph-explorer) +* [Exemplos de códigos da Microsoft](https://developer.microsoft.com/en-us/graph/code-samples-and-sdks) +* [Documentação do Graph para Intune](https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/intune_graph_overview) + +## Direitos autorais +Copyright (c) 2017 Microsoft. Todos os direitos reservados. + +Este projeto adotou o [Código de Conduta de Código Aberto da Microsoft](https://opensource.microsoft.com/codeofconduct/). Para saber mais, confira as [Perguntas frequentes sobre o Código de Conduta](https://opensource.microsoft.com/codeofconduct/faq/) ou entre em contato pelo [opencode@microsoft.com](mailto:opencode@microsoft.com) se tiver outras dúvidas ou comentários. diff --git a/README-localized/Readme-ru-ru.md b/README-localized/Readme-ru-ru.md new file mode 100644 index 0000000..afec624 --- /dev/null +++ b/README-localized/Readme-ru-ru.md @@ -0,0 +1,133 @@ +--- +page_type: sample +products: +- ms-graph +languages: +- powershell +extensions: + contentType: samples + technologies: + - Microsoft Graph + services: + - Intune + createdDate: 4/4/2017 9:41:27 AM +--- +# Примеры для Intune Graph + +Этот репозиторий примеров скриптов PowerShell демонстрирует, как получать доступ к ресурсам службы Intune. Для этого совершаются HTTPS-запросы RESTful API к API Microsoft Graph из PowerShell. + +Документация для Intune и Microsoft Graph можно найти здесь [документации Intune Graph](https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/intune_graph_overview). + +Эти примеры демонстрируют типичные действия администратора Intune или партнера Microsoft по управлению ресурсами Intune. + +Следующие примеры включены в этот репозиторий: +- AdminConsent +- AndroidEnterprise +- AppleEnrollment +- Applications +- ApplicationSync +- AppProtectionPolicy +- Auditing +- Authentication +- CertificationAuthority +- CheckStatus +- CompanyPortalBranding +- CompliancePolicy +- CorporateDeviceEnrollment +- DeviceConfiguration +- EnrollmentRestrictions +- IntuneDataExport +- LOB_Application +- ManagedDevices +- Paging +- RBAC +- RemoteActionAudit +- SoftwareUpdates +- TermsAndConditions +- UserPolicyReport + +Скрипты лицензируются «как есть». под лицензией MIT. + +#### Заявление об отказе +Некоторые образцы сценариев получают информацию от вашего клиента Intune, а другие создают, удаляют или обновляют данные в вашем клиенте Intune.  Понять влияние каждого примера сценария до его запуска; образцы должны быть запущены с использованием непроизводственного или «тестового» счета арендатора.  + +## Использование API Graph для Intune +API-интерфейс Intune обеспечивает программный доступ к информации Intune для вашего клиента, и API выполняет те же операции Intune, что и через портал Azure.   + +Intune предоставляет данные в Microsoft Graph так же, как и другие облачные сервисы, с богатой информацией об объектах и навигацией по отношениям.  Используйте Microsoft Graph для объединения информации из других служб и Intune для создания многофункциональных межсервисных приложений для ИТ-специалистов или конечных пользователей.      + +## Предварительные требования +Для использования этих примеров Microsoft Graph API Intune PowerShell требуется следующее: +* Установите модуль AzureAD PowerShell, запустив «Install-Module AzureAD» или «Install-Module AzureADPreview» из командной строки PowerShell с повышенными привилегиями. +* Клиент Intune, который поддерживает портал Azure с помощью производственная или пробная лицензия (https://docs.microsoft.com/en-us/intune-azure/introduction/what-is-microsoft-intune) +* Для использования API-интерфейсов Microsoft Graph для настройки элементов управления и политик Intune требуется лицензия Intune. +* Учетная запись с разрешениями на администрирование службы Intune. +* PowerShell v5.0 в Windows 10 x64 (PowerShell v4.0 является минимальным требованием для правильной работы сценариев). +* Примечание. В PowerShell 4,0 для работы с приложением PowerShell необходимо использовать модуль [PowershellGet для PS 4,0](https://www.microsoft.com/en-us/download/details.aspx?id=51451), позволяющий использовать функциональные возможности модуля +* при первом использовании этих сценариев необходимо, чтобы глобальный администратор клиента принимал разрешения приложения. + +## Начало работы +После того, как предварительные условия установлены или выполнены, выполните следующие шаги для использования этих сценариев: + +#### 1. Использование сценария + +1. Загрузите содержимое репозитория на локальный компьютер с Windows +* Извлечение файлов в локальную папку (например, C:\IntuneGraphSamples) +* Запустите PowerShell x64 из меню «Пуск» +* Перейдите в каталог (например, cd C:\IntuneGraphSamples). +* Для каждой папки в локальном репозитории вы можете перейти к этому каталогу, а затем запустить скрипт на ваш выбор +* Пример использования скрипта приложения: + * Чтобы использовать сценарии управления приложениями, в C:\IntuneGraphSamples, run "cd .\Applications\" + * Попав в папку, запустите.\Application_MDM_Get.ps1, + чтобы получить все приложения, добавленные в MDM. Эту последовательность шагов можно использовать для каждой папки .... + +#### 2. Аутентификация с помощью Microsoft Graph +При первом запуске этих сценариев вам будет предложено предоставить учетную запись для аутентификации в службе: +``` +Please specify your user principal name for Azure Authentication: +``` +После того, как вы предоставите имя пользователя, откроется всплывающее окно с запросом вашего пароля. После успешной проверки подлинности с помощью Azure Active Directory токен пользователя будет действовать в течение часа, а по истечении часа в сеансе PowerShell вам будет предложено пройти повторную проверку подлинности. + +Если вы в первый раз запускаете скрипт для своего арендатора, появится всплывающее окно с указанием: + +``` +Microsoft Intune PowerShell needs permission to: + +* Sign you in and read your profile +* Read all groups +* Read directory data +* Read and write Microsoft Intune Device Configuration and Policies (preview) +* Read and write Microsoft Intune RBAC settings (preview) +* Perform user-impacting remote actions on Microsoft Intune devices (preview) +* Sign in as you +* Read and write Microsoft Intune devices (preview) +* Read and write all groups +* Read and write Microsoft Intune configuration (preview) +* Read and write Microsoft Intune apps (preview) +``` + +Примечание. Если ваша учетная запись предназначена для условного доступа на основе устройства, ваше устройство должно быть зарегистрировано или соответствовать требованиям для прохождения аутентификации. + +## Участие + +Если вы хотите внести свой вклад в этот образец, см. CONTRIBUTING.MD. + +В этом проекте принят кодекс поведения Microsoft с открытым исходным кодом. Для получения дополнительной информации см. FAQ по Кодексу поведения или свяжитесь с opencode@microsoft.com с любыми дополнительными вопросами или комментариями. + +## Вопросы и комментарии + +Мы хотели бы получить ваши отзывы о образце Intune PowerShell. Вы можете присылать нам свои вопросы и предложения в разделе «Проблемы» этого репозитория. + +Ваш отзыв важен для нас. Для связи с нами используйте сайт Stack Overflow. Отметьте свои вопросы с помощью \[MicrosoftGraph] и \[intune]. + + +## Дополнительные ресурсы +* [Документация по Microsoft Graph API](https://developer.microsoft.com/en-us/graph/docs) +* [Портал Microsoft Graph](https://developer.microsoft.com/en-us/graph/graph-explorer) +* [Примеры программного кода Майкрософт](https://developer.microsoft.com/en-us/graph/code-samples-and-sdks) +* [Документация Intune Graph](https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/intune_graph_overview) + +## Авторские права +(c) Корпорация Майкрософт (Microsoft Corporation), 2017. Все права защищены. + +Этот проект соответствует [Правилам поведения разработчиков открытого кода Майкрософт](https://opensource.microsoft.com/codeofconduct/). Дополнительные сведения см. в разделе [часто задаваемых вопросов о правилах поведения](https://opensource.microsoft.com/codeofconduct/faq/). Если у вас возникли вопросы или замечания, напишите нам по адресу [opencode@microsoft.com](mailto:opencode@microsoft.com). diff --git a/README-localized/Readme-zh-cn.md b/README-localized/Readme-zh-cn.md new file mode 100644 index 0000000..b9db01a --- /dev/null +++ b/README-localized/Readme-zh-cn.md @@ -0,0 +1,133 @@ +--- +page_type: sample +products: +- ms-graph +languages: +- powershell +extensions: + contentType: samples + technologies: + - Microsoft Graph + services: + - Intune + createdDate: 4/4/2017 9:41:27 AM +--- +# Intune Graph 示例 + +此 PowerShell 示例脚本的存储库演示如何访问 Intune 服务资源。他们通过从 PowerShell 向 Microsoft Graph API 发出 HTTPS RESTful API 请求来证明这一点。 + +有关 Intune 和 Microsoft Graph 的文档,请查看[Intune Graph 文档](https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/intune_graph_overview)。 + +这些示例演示了 Intune 管理员或 Microsoft 合作伙伴管理 Intune 资源的典型操作。 + +下列示例包含在此存储库中: +- AdminConsent +- AndroidEnterprise +- AppleEnrollment +- Applications +- ApplicationSync +- AppProtectionPolicy +- Auditing +- Authentication +- CertificationAuthority +- CheckStatus +- CompanyPortalBranding +- CompliancePolicy +- CorporateDeviceEnrollment +- DeviceConfiguration +- EnrollmentRestrictions +- IntuneDataExport +- LOB_Application +- ManagedDevices +- Paging +- RBAC +- RemoteActionAudit +- SoftwareUpdates +- TermsAndConditions +- UserPolicyReport + +在 MIT 许可下,脚本按“原样”授予许可。 + +#### 免责声明 +部分脚本示例从 Intune 租户检索信息,其他脚本在 Intune 租户中创建、删除或更新数据。  运行前,了解每个示例脚本的影响。应使用非生产或“测试”租户帐户运行示例。  + +## 使用 Intune Graph API +Intune Graph API 允许以编程方式访问租户的 Intune 信息,API 会执行 的 Intune 操作与通过 Azure 门户执行的操作相同。   + +Intune 向 Microsoft Graph 提供数据的方式与其他云服务相同,具有丰富的实体信息和关系导航。  使用 Microsoft Graph 将来自其他服务和 Intune 的信息进行组合,为 IT 专业人员和最终用户构建丰富的跨服务应用程序。      + +## 先决条件 +使用这些 Microsoft Graph API Intune PowerShell 示例需要下列内容: +* 通过在提升的 PowerShell 命令提示符处运行 'Install-Module AzureAD' 或 'Install-Module AzureADPreview' 安装 AzureAD PowerShell 模块 +* 具有生产或试用许可证,支持 Azure 门户的 Intune 租户 (https://docs.microsoft.com/en-us/intune-azure/introduction/what-is-microsoft-intune) +* 使用 Microsoft Graph APIs 来配置 Intune 控件和策略需要 Intune 许可证。 +* 一个具有管理 Intune 服务权限的账户 +* 适用于 Windows 10 x64 的 PowerShell v5.0(PowerShell v4.0 是正确运行脚本的最低要求) +* 注意:对于PowerShell 4.0 ,将需要 [PowershellGet Module for PS 4.0](https://www.microsoft.com/en-us/download/details.aspx?id=51451) 以启用使用安装模块功能 +* 首次使用这些脚本,需要租户的全局管理员接受应用的权限 + +## 开始使用 +安装或满足先决条件后,执行以下步骤以使用这些脚本: + +#### 1.脚本使用 + +1. 下载存储库的内容至本地 Windows 计算机 +* 提取文件至本地文件夹(如:C:\IntuneGraphSamples) +* 从开始菜单运行 PowerShell x64 +* 浏览至目录(如 cd C:\IntuneGraphSamples) +* 对于本地存储库中的各文件夹,可浏览至目录并随后运行选定的脚本 +* 示例应用脚本使用: + * 如果要使用来自 C:\IntuneGraphSamples 的“管理应用脚本”,运行 "cd .\Applications\" + * 在文件夹中运行 .\Application_MDM_Get.ps1 + 以获得所有 MDM 添加的应用后,此步骤顺序可用于各文件夹.... + +#### 2.使用 Microsoft Graph 验证身份 +首次运行这些脚本时,系统将要求提供账户,对这些服务进行身份验证: +``` +Please specify your user principal name for Azure Authentication: +``` +提供用户主体名称后,弹出窗口将打开密码提示。成功使用 Azure Active Directory 验证身份后,用户令牌将持续一小时,在 PowerShell 会话内一小时结束后,系统将要求重新进行身份验证。 + +如果首次针对租户运行脚本,弹出窗口将出现,注明: + +``` +Microsoft Intune PowerShell needs permission to: + +* Sign you in and read your profile +* Read all groups +* Read directory data +* Read and write Microsoft Intune Device Configuration and Policies (preview) +* Read and write Microsoft Intune RBAC settings (preview) +* Perform user-impacting remote actions on Microsoft Intune devices (preview) +* Sign in as you +* Read and write Microsoft Intune devices (preview) +* Read and write all groups +* Read and write Microsoft Intune configuration (preview) +* Read and write Microsoft Intune apps (preview) +``` + +注意:如果用户账户面向基于设备的条件性访问,设备必须注册或兼容,才能通过身份验证。 + +## 参与 + +如果想要参与本示例,请参阅 CONTRIBUTING.MD。 + +此项目已采用“Microsoft 开放源代码行为准则”。有关详细信息,请参阅“行为准则常见问题解答”。如有其他任何问题或意见,也可联系 opencode@microsoft.com。 + +## 问题和意见 + +我们乐意倾听你有关 Intune PowerShell 示例的反馈。你可通过该存储库中的“问题”部分向我们发送问题和建议。 + +我们非常重视你的反馈意见。请在堆栈溢出上与我们联系。使用 \[MicrosoftGraph]和 \[intune] 标记出你的问题。 + + +## 其他资源 +* [Microsoft Graph API 文档](https://developer.microsoft.com/en-us/graph/docs) +* [Microsoft Graph 门户](https://developer.microsoft.com/en-us/graph/graph-explorer) +* [Microsoft 代码示例](https://developer.microsoft.com/en-us/graph/code-samples-and-sdks) +* [Intune Graph 文档](https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/intune_graph_overview) + +## 版权信息 +版权所有 (c) 2017 Microsoft。保留所有权利。 + +此项目已采用 [Microsoft 开放源代码行为准则](https://opensource.microsoft.com/codeofconduct/)。有关详细信息,请参阅[行为准则常见问题解答](https://opensource.microsoft.com/codeofconduct/faq/)。如有其他任何问题或意见,也可联系 [opencode@microsoft.com](mailto:opencode@microsoft.com)。 diff --git a/Readme.md b/Readme.md index 4624543..27854e9 100644 --- a/Readme.md +++ b/Readme.md @@ -11,6 +11,7 @@ extensions: services: - Intune createdDate: 4/4/2017 9:41:27 AM +noDependencies: true --- # Intune Graph Samples diff --git a/SoftwareUpdates/SoftwareUpdates_Import_FromJSON.ps1 b/SoftwareUpdates/SoftwareUpdates_Import_FromJSON.ps1 index 020da77..d693f56 100644 --- a/SoftwareUpdates/SoftwareUpdates_Import_FromJSON.ps1 +++ b/SoftwareUpdates/SoftwareUpdates_Import_FromJSON.ps1 @@ -327,7 +327,7 @@ break $JSON_Data = Get-Content "$ImportPath" # Excluding entries that are not required - id,createdDateTime,lastModifiedDateTime,version -$JSON_Convert = $JSON_Data | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty id,createdDateTime,lastModifiedDateTime,version,'groupAssignments@odata.context',groupAssignments +$JSON_Convert = $JSON_Data | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty id,createdDateTime,lastModifiedDateTime,version,'groupAssignments@odata.context',groupAssignments,supportsScopeTags $DisplayName = $JSON_Convert.displayName