ProvisionIntuneDevicesV5.ps1
#Requires -Modules @{ModuleName="Microsoft.Graph.Intune";ModuleVersion = "6.1907.1.1"},@{ModuleName="AzureADPreview";ModuleVersion = "2.0.2.62"} # OB Office Branch # Required modules: # Microsoft.Graph.Intune 6.1907.1.0 # AzureADPreview 2.0.2.62 # Az.OperationalInsights 1.3.4 # AZ.Accounts 1.7.1 <#PSScriptInfo .VERSION 1.5 .GUID e0a0afb3-a115-4254-93a0-e8d4c10cf34d .AUTHOR racarb .COMPANYNAME Microsoft .COPYRIGHT Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information. .TAGS Intune RBAC Automation .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES Microsoft.Graph.Intune 6.1907.1.0 AzureADPreview 2.0.2.62 Az.OperationalInsights 1.3.4 AZ.Accounts 1.7.1 .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES .PRIVATEDATA #> <# .DESCRIPTION This script checks for the new devices registered in the last x hours and automatically creates objects in Intune for their management using Intune roles These are the objects created by this script: AdminRole-OB. Intune Role created for users OB, with specific permissions copied from a custom Role RoleAssigment-OB. Role assignment of the role AdminRole-OB. The assignment contains the following: AdminGroup-OB. Scope (Groups). Group that contains the users that has the assignment of that OB. This group will have permission to administer the devices ScopeGroup-OB. Members. Scope Dynamic group that contains all the users that has the ‘State’ AAD field filled with the OB’s name. This group is the scope of the assignment Tag-TG. Scope (Tags). Tag created for every OB. The assignment has this Tag as its scope. The script generates logs that are stored in an storage account in Azure as well as uploaded to a workspace in Log Analytics. This script in intended to be run as a runbook in Azure #References #https://github.com/Azure/azure-powershell/issues/8486 No way to read passord with the Get-AzAutomationCredential #https://github.com/microsoft/Intune-PowerShell-SDK/blob/master/README.md #https://github.com/microsoft/Intune-PowerShell-Management/tree/master/Samples #> Param ( [int]$Hours = "6", [string]$ADField = 'State', [boolean]$LoginAzureMonitor=$true) ############################### INPUT SECTION ############################### # Naming conventions - Prefixes and Sufixes for the OB Name . eg. : <TagPre><OB Name><TagSuf> $TagPre = 'Tag-' $TagSuf = $null $AdminRolePre = 'AdminRole-' $AdminRoleSuf = $null $AdminGroupPre = 'AdminGroup-' $AdminGroupSuf = $null $ScopeGroupPre = 'ScopeGroup-' $ScopeGroupSuf = $null $RoleAssignmentPre = 'RoleAssignment-' $RoleAssignmentSuf = $null # Companies list. Array of companies from where devices are provisioned. Add the desired companies here. # $Companies = @( # "TG", # "WH" # ) #Values $ResourceGroupName = "IntuneProvisioning" $LAworkspaceName = "IntuneProvisioningla" $LAworkspaceKeyvariable = "ProvisioninglaKey" $StorageAccountName = "intuneprovisioningsa" $ShareName = "provisioning" $StorageAccountKeyvariable = "ProvisioningsaKey" $LAworkspaceKeyvariable = "ProvisioninglaKey" $InTuneCredname = "InTuneProvisioningCred" $MSGraphSchema = "beta" #Variables $StorageAccountKey = Get-AutomationVariable -Name $StorageAccountKeyvariable $LAworkspaceKey = Get-AutomationVariable -Name $LAworkspaceKeyvariable ############################### END INPUT SECTION ############################### #region Function Definitions Function Log-Event { Param ( $Text ) Write-Output $Text if (-not(Test-Path $logpath)) { New-Item -ItemType File -Path $logpath } $text | Out-File -FilePath $logpath -Append } Function Log-ErrorEvent { Param ( $Text ) Write-Error $Text } <# .DESCRIPTION This function creates and updates a hashtable using hashtable name, keys and values as parameters .EXAMPLE Write-ResultstoHashTable -Hashtablename ResultsHashTable -Key users -Value $listofusers #> Function Write-ResultstoHashTable { Param( [string]$Hashtablename, [string]$Key, [string]$Value) $hashtableobj = (Get-Variable -Name $Hashtablename).Value if (($hashtableobj).ContainsKey($key)) { $tempvalue = $hashtableobj[$($key)] $tempvalue += $value $hashtableobj[$($key)] = $tempvalue } else { $hashtableobj[$($key)] = @($value) } } <# .DESCRIPTION This function Checks if there is already a tag for the OB and returns $true or $false .EXAMPLE Test-CompanyScopeTag -Company Companyname #> Function Test-CompanyScopeTag { [CmdletBinding()] Param ([string]$Company) $CompanyExists = $false Update-MSGraphEnvironment -SchemaVersion $MSGraphSchema -Quiet | Out-Null $uri = "deviceManagement/roleScopeTags" try { $ScopeTags = Invoke-MSGraphRequest -HttpMethod GET -Url $uri if ("$($TagPre)$($Company)$($TagSuf)" -in ($ScopeTags.value).displayname) { $CompanyExists = $true } else { $CompanyExists = $false } } catch { $($_.exception.message); Log-ErrorEvent "An error ocurred"; exit } return $CompanyExists } <# .DESCRIPTION This function returns the Tag for a OB. If no OB is specified, it returns all the Tags .EXAMPLE Get-CompanyScopeTag Returns all the tags .EXAMPLE Get-CompanyScopeTag -Company OB Returns the tag for OB 'Companyname' #> Function Get-CompanyScopeTag { [CmdletBinding()] Param ([string]$Company) Update-MSGraphEnvironment -SchemaVersion $MSGraphSchema -Quiet | Out-Null $uri = "deviceManagement/roleScopeTags" try { $ScopeTags = Invoke-MSGraphRequest -HttpMethod GET -Url $uri } catch { Write-Error "$($_.exception.message)"; Write-Progress "An error ocurred"; exit } if ($PSBoundParameters.ContainsKey("Company")) { return $ScopeTags.value | where displayname -EQ "$($TagPre)$($Company)$($TagSuf)" } else { return $ScopeTags.value } } <# .DESCRIPTION This function creates a new Tag for a OB .EXAMPLE New-CompanyScopeTag -Company OB #> Function New-CompanyScopeTag { [CmdletBinding()] Param ([string]$Company) Update-MSGraphEnvironment -SchemaVersion $MSGraphSchema -Quiet | Out-Null $ScopeTagJSON = @" { "displayName": "$($TagPre)$($Company)$($TagSuf)", "description": "Tag for OB $Company", "isBuiltIn": false } "@ try { $NewTag = Invoke-MSGraphRequest -HttpMethod POST -Url "deviceManagement/roleScopeTags" -Content $ScopeTagJson } catch { Write-Error "$($_.exception.message)"; Write-Progress "An error ocurred"; exit } return $NewTag } <# .DESCRIPTION This function Checks if there is already a Role Definition for the OB and returns $true or $false .EXAMPLE Test-CompanyRBACRole -Company OB #> Function Test-CompanyRBACRole() { [cmdletbinding()] param ( [string]$Company ) Update-MSGraphEnvironment -SchemaVersion $MSGraphSchema -Quiet | Out-Null $uri = "deviceManagement/roleDefinitions" try { $CompanyRBACRoles = (Invoke-MSGraphRequest -Url $uri -HttpMethod 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 } If ("$($AdminRolePre)$($Company)$($AdminRoleSuf)" -notin ($CompanyRBACRoles).Displayname) { return $false } else { return $true } } <# .DESCRIPTION The function returns the Role definition object for a given OB. If no OB is specified it returns all the Roles .EXAMPLE Get-CompanyRBACRole This example returns all the Roles .EXAMPLE Get-CompanyRBACRole -Company OB This example returns Role defined for OB 'OB' #> Function Get-CompanyRBACRole() { [cmdletbinding()] param ( [string]$Company ) Update-MSGraphEnvironment -SchemaVersion $MSGraphSchema -Quiet | Out-Null $uri = "deviceManagement/roleDefinitions" try { $CompanyRBACRoles = Invoke-MSGraphRequest -Url $uri -HttpMethod GET } 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 } if ($PSBoundParameters.ContainsKey("Company")) { return $CompanyRBACRoles.value | where displayname -EQ "$($AdminRolePre)$($Company)$($AdminRoleSuf)" } else { return $CompanyRBACRoles.value | where isBuiltIn -eq $False } } <# .DESCRIPTION This function creates a new Role Definition for a given OB .EXAMPLE New-CompanyRBACRole -Company OB #> Function New-CompanyRBACRole { [CmdletBinding()] Param ([string]$Company) Update-MSGraphEnvironment -SchemaVersion $MSGraphSchema -Quiet | Out-Null $uri = "deviceManagement/roleDefinitions" if (-not (Test-CompanyScopeTag -Company $Company)) { Log-ErrorEvent "Scope tag for OB $Company doesn't exists"; break } [string]$CompanyScopeTagid = (Get-CompanyScopeTag -Company $Company).id $RBACRoleJSON = @" { "@odata.type": "#microsoft.graph.deviceAndAppManagementRoleDefinition", "displayName": "$($AdminRolePre)$($Company)$($AdminRoleSuf)", "description": "Admin Role automatically created for OB $Company", "isBuiltIn": false, "roleScopeTagIds": [ "$($CompanyScopeTagid)" ], "rolePermissions": [ { "resourceActions": [ { "allowedResourceActions": [ "Microsoft.Intune_AndroidSync_Read", "Microsoft.Intune_CorporateDeviceIdentifiers_Read", "Microsoft.Intune_CorporateDeviceIdentifiers_Create", "Microsoft.Intune_DeviceCompliancePolices_Read", "Microsoft.Intune_DeviceConfigurations_Read", "Microsoft.Intune_DeviceEnrollmentManagers_Read", "Microsoft.Intune_EndpointProtection_Read", "Microsoft.Intune_AppleDeviceSerialNumbers_Read", "Microsoft.Intune_AppleEnrollmentProfiles_Read", "Microsoft.Intune_EnrollmentProgramToken_Read", "Microsoft.Intune_ManagedApps_Read", "Microsoft.Intune_ManagedApps_Wipe", "Microsoft.Intune_ManagedDevices_Delete", "Microsoft.Intune_ManagedDevices_Read", "Microsoft.Intune_ManagedDevices_Update", "Microsoft.Intune_MobileApps_Read", "Microsoft.Intune_Organization_Read", "Microsoft.Intune_RemoteAssistance_Read", "Microsoft.Intune_RemoteTasks_CleanPC", "Microsoft.Intune_RemoteTasks_DisableLostMode", "Microsoft.Intune_RemoteTasks_EnableLostMode", "Microsoft.Intune_RemoteTasks_EnableWindowsIntuneAgent", "Microsoft.Intune_RemoteTasks_GetFileVaultKey", "Microsoft.Intune_RemoteTasks_LocateDevice", "Microsoft.Intune_RemoteTasks_ManageSharedDeviceUsers", "Microsoft.Intune_RemoteTasks_PlayLostModeSound", "Microsoft.Intune_RemoteTasks_RebootNow", "Microsoft.Intune_RemoteTasks_RemoteLock", "Microsoft.Intune_RemoteTasks_RequestRemoteAssistance", "Microsoft.Intune_RemoteTasks_ResetPasscode", "Microsoft.Intune_RemoteTasks_Retire", "Microsoft.Intune_RemoteTasks_RevokeAppleVppLicenses", "Microsoft.Intune_RemoteTasks_RotateBitLockerKeys", "Microsoft.Intune_RemoteTasks_RotateFileVaultKey", "Microsoft.Intune_RemoteTasks_SetDeviceName", "Microsoft.Intune_RemoteTasks_ShutDown", "Microsoft.Intune_RemoteTasks_SyncDevice", "Microsoft.Intune_RemoteTasks_UpdateDeviceAccount", "Microsoft.Intune_RemoteTasks_WindowsDefender", "Microsoft.Intune_RemoteTasks_Wipe", "Microsoft.Intune_Roles_Read", "Microsoft.Intune_SecurityBaselines_Read", "Microsoft.Intune_TelecomExpenses_Read", "Microsoft.Intune_TermsAndConditions_Read" ], "notAllowedResourceActions": [] } ] } ] } "@ try { $CompanyRBACRole = Invoke-MSGraphRequest -HttpMethod POST -Url $uri -Content $RBACRoleJSON } catch { $($_.exception.message); Log-ErrorEvent "An error ocurred"; break } return $CompanyRBACRole } <# .DESCRIPTION This function Checks if there is already a Role Assignment for the OB and returns $true or $false .EXAMPLE Test-RoleAssignment -Company OB #> Function Test-RoleAssignment { [CmdletBinding()] Param ( [string]$Company ) $RoleAssignments = Get-RoleAssignment -Company $Company if ("$($RoleAssignmentPre)$($Company)$($RoleAssignmentSuf)" -notin @($RoleAssignments.displayname)) { return $false } else { return $true } } <# .DESCRIPTION The function returns the Assignments defined for a given OB .EXAMPLE Get-RoleAssignment -Company OB This example returns the Assignments defined for OB 'OB' #> Function Get-RoleAssignment { [CmdletBinding()] Param( [Parameter(Mandatory = $true)] $Company) Update-MSGraphEnvironment -SchemaVersion $MSGraphSchema -Quiet | Out-Null $resource = "deviceManagement/roleDefinitions" try { $CompanyRBACRoleid = (Get-CompanyRBACRole -Company $company).id Update-MSGraphEnvironment -SchemaVersion $MSGraphSchema -Quiet | Out-Null $RoleAssignments = (Invoke-MSGraphRequest -HttpMethod GET -Url "$resource('$($CompanyRBACRoleid)')?`$expand=roleassignments").roleAssignments } 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 } return $RoleAssignments } <# .DESCRIPTION This function creates a new Role Assignment for a given OB .EXAMPLE New-CompanyScRoleAssignment -Company OB #> Function New-RoleAssignment { [Cmdletbinding()] Param ( [string]$Company, [string]$DisplayName = "$($RoleAssignmentPre)$($Company)$($RoleAssignmentSuf)", [string]$Description = "Assignment automaticaly created for OB $($Company)", [string]$AdminGroupname = "$($AdminGroupPre)$($Company)$($AdminGroupSuf)", #Members [string]$ScopeGroupname = "$($ScopeGroupPre)$($Company)$($ScopeGroupSuf)", #Scope (Groups) [string]$RoledefinitionName = "$($AdminRolePre)$($Company)$($AdminRoleSuf)" ) $uri = "deviceManagement/roleAssignments" $AdminGroupid = (Get-AzureADGroup -Filter "DisplayName eq '$($AdminGroupname)'" ).Objectid if ($null -eq $AdminGroupid) { Log-ErrorEvent "No Admin Group exists for OB $company"; break } $UsersGroupid = (Get-AzureADGroup -Filter "DisplayName eq '$($ScopeGroupname)'" ).Objectid if ($null -eq $UsersGroupid) { Log-ErrorEvent "No Scope Group exists for OB $company"; break } $Roledefinitionid = (Get-CompanyRBACRole -Company $Company).id $ScopeTagid = (Get-CompanyScopeTag -Company $Company).id if ($Roledefinitionid -eq $false) { Log-Event -Text "Role Definition $($AdminRolePre)$($Company)$($AdminRoleSuf) not found"; break } $JSONRoleAssignment = @" { "description": "$($Description)", "displayName": "$($DisplayName)", "members": ["$($AdminGroupid)"], "scopeMembers": ["$($UsersGroupid)"], "roleDefinition@odata.bind":"https://graph.microsoft.com/beta/deviceManagement/roleDefinitions/$($Roledefinitionid)" } "@ $JSONRoleAssignment Update-MSGraphEnvironment -SchemaVersion $MSGraphSchema -Quiet | Out-Null Connect-MSGraph -AdminConsent | Out-Null try { $RoleAssignment = Invoke-MSGraphRequest -HttpMethod POST -Url $uri -Content $JSONRoleAssignment #Update the scope Tag Update-RoleAssignmentScopeTag -Company $Company -roleScopeTagids $ScopeTagid } catch { $ex = $_.Exception $ex $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 } return $RoleAssignment } <# .DESCRIPTION This function updates the scope tag for an assignment .PARAMETER ids Array of ids to set .EXAMPLE Update-RoleAssignmentScopeTag -Company OB -RoleScopeTagids ids This example updates the scope tags ids for the Assignment for OB 'OB' #> Function Update-RoleAssignmentScopeTag { [CmdletBinding()] Param ( [string]$Company, [int[]]$RoleScopeTagids) $RoleAssignmentid = (Get-RoleAssignment -Company $company).id $seturl = "https://graph.microsoft.com/beta/deviceManagement/roleAssignments/$RoleAssignmentid/roleScopeTags/`$ref" foreach ($roleScopeTagid in $roleScopeTagids) { $putjson = @" { "@odata.id": "https://graph.microsoft.com/beta/deviceManagement/roleScopeTags/$roleScopeTagid" } "@ try { Invoke-MSGraphRequest -HttpMethod POST -Url $seturl -Content $putjson -Verbose } catch { } } } <# .DESCRIPTION This function updates the scope tag for a device .PARAMETER Deviceid Id of the Device .PARAMETER ScopeTagids Array of ids to set .EXAMPLE Update-DeviceScopeTag -Deviceid $deviceid -ScopeTagids ids This example updates the scope tags ids for the Device specified with its id. #> Function Update-DeviceScopeTag { [CmdletBinding()] Param ( [string]$Deviceid, [int[]]$ScopeTagids) Update-MSGraphEnvironment -SchemaVersion $MSGraphSchema -Quiet | Out-Null $seturl = "deviceManagement/managedDevices('$($Deviceid)')" [string]$ScopeTagidsstring = '"' + ($ScopeTagids -join '","') + '"' $putjson = @" { "roleScopeTagIds": [ $($ScopeTagidsstring) ] } "@ try { Invoke-MSGraphRequest -HttpMethod PATCH -Url $seturl -Content $putjson -Verbose } catch { $_.Exception } } #endregion #region authentication #Connection to Azure $connectionName = "AzureRunAsConnection" $servicePrincipalConnection = Get-AutomationConnection -Name $connectionName Add-AzAccount ` -ServicePrincipal ` -TenantId $servicePrincipalConnection.TenantId ` -ApplicationId $servicePrincipalConnection.ApplicationId ` -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint #Intune Validation $IntuneCred = Get-AutomationPSCredential -Name $InTuneCredname Connect-MSGraph -Credential $IntuneCred -Verbose Update-MSGraphEnvironment -SchemaVersion $MSGraphSchema -Quiet | Out-Null Connect-MSGraph -AdminConsent #View MSGraph environment Get-MSGraphEnvironment #Change to beta API: Update-MSGraphEnvironment -SchemaVersion "beta" #Connect to Azure AD Connect-AzureAD -Credential $IntuneCred #endregion #TODO: Time out control #DONE: Beter Management of the API Graph versions #DONE: Clean older logs in the storage account (last year?) #DONE: Clean up Code #DONE: Assign Role for the execution account to allow creation on AD groups: Groups administrator #DONE: Filter Devices. Exclude Windows and MAC and (linux?) #DONE: Copy permission from custom role #DONE: Document functions #DONE: update the catch blocks in every call to the API #Begin of Script racarb $Begindate = Get-Date $Logdate = Get-Date $logpath = "$("{0:yyyy}-{0:MM}-{0:dd}-{0:HH}{0:mm}" -f ($Logdate))-ProvisioningResults.log" $ProvisioningResults = @{ } Log-Event -Text "$($Begindate)" #Get Mobile Devices enrolled in the last xhours $EnrollmentDateTime = (Get-Date).AddHours(-$Hours) Log-Event "Getting devices enrolled since $($EnrollmentDateTime)..." $EnrollmentDateTimefilter = "{0:yyyy}-{0:MM}-{0:dd}T{0:hh}:{0:mm}:{0:ss}Z" -f $EnrollmentDateTime #Mobiles $ManagedDevices = Get-IntuneManagedDevice -Filter ` "(enrolledDateTime ge $($EnrollmentDateTimefilter)) and ` ((deviceType eq 'android') or ` (deviceType eq 'androidEnterprise') or ` (deviceType eq 'androidForWork') or ` (deviceType eq 'iPhone') or ` (deviceType eq 'iPod') or ` (deviceType eq 'iPad') or ` (deviceType eq 'windowsPhone') or ` (deviceType eq 'macMDM')) and ` ((managementAgent eq 'mdm') or ` (managementAgent eq 'easMdm') or ` (managementAgent eq 'configurationManagerClientMdm'))" ` | Get-MSGraphAllPages | Where-Object { ($null -ne $_.userPrincipalName) -and ($_.userPrincipalName) -ne "" } #region getting info if ($ManagedDevices) { Log-Event "Got info from $($ManagedDevices.count) devices enrolled in the last $Hours hours" $ManagedDeviceshash = $ManagedDevices | Group-Object -Property userPrincipalName -AsHashTable -AsString Log-Event "Begin provisioning..." foreach ($userupnhash in $ManagedDeviceshash.GetEnumerator()) { if (($userupnhash.key -eq "") -or ($null -eq $userupnhash.key )) { continue } #Checks if upn of the user is missing and bypasses the user try { $Company = (Get-AzureADUser -ObjectId $userupnhash.Key -ErrorAction Stop).$ADfield } catch { $_.Exception; continue } #Error when retrieving the OB Log-Event -Text "Provisioning user $($userupnhash.Key)" Log-Event -Text "Checking Tags,Roles and Groups for user's OB: $($Company)" # if ($Company -notin $Companies) { # Log-Event -Text "User's OB not in the list"; # Write-ResultstoHashTable -Hashtablename ProvisioningResults -key Skippedusers -value $($userupnhash.key); continue # } #Checks if the OB is included in the list and if not bypasses the user else { Write-ResultstoHashTable -Hashtablename ProvisioningResults -key Newusers -value $($userupnhash.key) } #Test if there's a Tag for that OB and create it if necesary if (-not (Test-CompanyScopeTag -Company $Company)) { Log-Event -Text "Scope Tag for OB $Company not found" try { $CompanyScopeTag = New-CompanyScopeTag -Company $Company Log-Event -Text "Scope Tag for OB $Company Created" Write-ResultstoHashTable -Hashtablename ProvisioningResults -key NewTags -value $CompanyScopeTag.displayName } catch { $_.Exception; Log-ErrorEvent -Text "Scope Tag for OB $Company could not be created"; break } } #Test if there's a RBAC Role for that OB and create it if necesary if (-not (Test-CompanyRBACRole -Company $Company)) { Log-Event "RBAC Role for OB $Company not found" try { $CompanyRBACRole = New-CompanyRBACRole -Company $Company Log-Event "RBAC Role for OB $Company Created" Write-ResultstoHashTable -Hashtablename ProvisioningResults -key NewRBACRoles -value $CompanyRBACRole.displayName } catch { $_.Exception; Log-ErrorEvent -Text "RBAC Role for OB $Company could not be created"; break } } else { Log-Event "RBAC Role for OB $Company already exists" if (((Get-CompanyScopeTag -Company $Company).id) -notin (@((Get-CompanyRBACRole -Company $Company).roleScopeTagIds))) { Log-Event "Tags doesn't match, IMPLEMENT FUNCTION" } } #Test if there's an Admin Group for that OB and create it if necesary if ($null -eq (Get-AzureADGroup -Filter "DisplayName eq '$($AdminGroupPre)$($Company)$($AdminGroupSuf)'")) { Log-Event "Admin Group for OB $Company not found" try { $AdminGroup = New-AzureADGroup -DisplayName "$($AdminGroupPre)$($Company)$($AdminGroupSuf)" -SecurityEnabled $true -MailEnabled $false -MailNickName "$($AdminGroupPre)$($Company -replace " ")$($AdminGroupSuf)" -Description "Admin Group for $OB $company Automatically Created" Log-Event "Admin Group for OB $Company Created" Write-ResultstoHashTable -Hashtablename ProvisioningResults -key NewAdminGroups -value $AdminGroup.displayName } catch { $_.Exception; Log-ErrorEvent -Text "Admin Group for OB $Company could not be created"; break } } else { Log-Event "Admin Group for OB $Company already exists" } #Test if there's a Scope Dynamic Group for that OB and create it if necesary if ($null -eq (Get-AzureADMSGroup -Filter "DisplayName eq '$($ScopeGroupPre)$($Company)$($ScopeGroupSuf)'")) { Log-Event "Scope Dynamic Group for OB $Company not found" try { $ScopeGroup = New-AzureADMSGroup -DisplayName "$($ScopeGroupPre)$($Company)$($ScopeGroupSuf)" -MailEnabled $False -MailNickName "$($AdminGroupPre)$($Company -replace " ")$($AdminGroupSuf)" -GroupTypes "DynamicMembership" -MembershipRule "(user.state -eq `"$Company`")" -MembershipRuleProcessingState On -SecurityEnabled $true -Description "Scope Group for $OB $company Automatically Created" Log-Event "Scope Dynamic Group for OB $Company Created" Write-ResultstoHashTable -Hashtablename ProvisioningResults -key NewScopeGroups -value $ScopeGroup.displayName } catch { $_.Exception; Log-ErrorEvent -Text "Scope Group for OB $Company could not be created"; break } } else { Log-Event "Scope Dynamic Group for OB $Company already exists" } #Test if there's a Role Assignment for that OB and create it if necesary if (Test-RoleAssignment -Company $Company) { "Role Assignment for OB $Company already exists" } else { Log-Event "Role Assignment for OB $Company not found" try { $RoleAssignment = New-RoleAssignment -Company $Company Log-Event "Role Assignment for OB $Company Created" Write-ResultstoHashTable -Hashtablename ProvisioningResults -key NewRoleAssignments -value $RoleAssignment.displayName } catch { $_.Exception; Log-ErrorEvent -Text "Role Assignment for OB $Company could not be created"; break } } #Enroll the devices for the user Log-Event -Text "Provisioning $(($userupnhash.Value).count) Device(s) for user $($userupnhash.Key):" foreach ($userdevice in $userupnhash.Value) { Log-Event -Text "Provisioning Device $($userdevice.deviceName):" try { Update-DeviceScopeTag -Deviceid $userdevice.id -ScopeTagids (Get-CompanyScopeTag -Company $company).id Write-ResultstoHashTable -Hashtablename ProvisioningResults -key NewUserDevices -value $userdevice.managedDeviceName } catch { $_.Exception } } } } else { Write-Output "" Log-Event "No device was enrolled in the last $Hours Hour(s)" Write-Output "" } #Summary Log-Event "Results:" $ProvisioningResults $Enddate = Get-Date Log-Event "Script execution time: $(($Enddate - $Begindate).Minutes) minutes, $(($Enddate - $Begindate).Seconds) seconds" Log-Event "End provisioning..." #Uploading results to an Storage Account $xmlpath = "$("{0:yyyy}-{0:MM}-{0:dd}-{0:HH}{0:mm}" -f ($Logdate))-ProvisioningResults.xml" $ProvisioningResults | Export-Clixml -Path $xmlpath $sacontext = New-AzStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $StorageAccountKey $shareobj = Get-AzStorageShare -Context $sacontext -Name $ShareName Set-AzStorageFileContent -Share $shareobj -Source $xmlpath -Path $xmlpath -Force Set-AzStorageFileContent -Share $shareobj -Source $logpath -Path $logpath -Force Get-ChildItem $logpath Get-Content $logpath Log-Event "Results have been uploaded to Storage account $($StorageAccountName)" #Remove older logs ( More than a Year) $Filestodelete = Get-AzStorageFile -Share $shareobj | Where-Object { ($_.Name).Substring(0, 10) -as [datetime] -lt ($Logdate.AddYears(-1)) } | Remove-AzStorageFile #Forward Logs to Azure Monitor if specified if ($LoginAzureMonitor) { #function to create the authorization signature Function Build-Signature ($customerId, $sharedKey, $date, $contentLength, $method, $contentType, $resource) { $xHeaders = "x-ms-date:" + $date $stringToHash = $method + "`n" + $contentLength + "`n" + $contentType + "`n" + $xHeaders + "`n" + $resource $bytesToHash = [Text.Encoding]::UTF8.GetBytes($stringToHash) $keyBytes = [Convert]::FromBase64String($sharedKey) $sha256 = New-Object System.Security.Cryptography.HMACSHA256 $sha256.Key = $keyBytes $calculatedHash = $sha256.ComputeHash($bytesToHash) $encodedHash = [Convert]::ToBase64String($calculatedHash) $authorization = 'SharedKey {0}:{1}' -f $customerId,$encodedHash return $authorization } #Function to create and post the request Function Post-LogAnalyticsData($customerId, $sharedKey, $body, $logType) { $method = "POST" $contentType = "application/json" $resource = "/api/logs" $rfc1123date = [DateTime]::UtcNow.ToString("r") $contentLength = $body.Length $signature = Build-Signature ` -customerId $customerId ` -sharedKey $sharedKey ` -date $rfc1123date ` -contentLength $contentLength ` -method $method ` -contentType $contentType ` -resource $resource "Signature:" $Signature | fl * $uri = "https://" + $customerId + ".ods.opinsights.azure.com" + $resource + "?api-version=2016-04-01" $headers = @{ "Authorization" = $signature; "Log-Type" = $logType; "x-ms-date" = $rfc1123date; "time-generated-field" = $TimeStampField; } $response = Invoke-WebRequest -Uri $uri -Method $method -ContentType $contentType -Headers $headers -Body $body -UseBasicParsing return $response.StatusCode } $logType = "IntuneProvisioning" $xmlfile = Get-Item $xmlpath $hashobject = Import-Clixml $xmlfile.FullName $TimeStampField = $xmlfile.CreationTimeUtc $hashobject["CreatedTime"] = $xmlfile.CreationTimeUtc $json = ConvertTo-Json -InputObject $hashobject # Submit the data to the API endpoint $CustomerId = (Get-AzOperationalInsightsWorkspace -Name $LAworkspaceName -ResourceGroupName $ResourceGroupName).CustomerId.guid try {Post-LogAnalyticsData -customerId $customerId -sharedKey $LAworkspaceKey -body ([System.Text.Encoding]::UTF8.GetBytes($json)) -logType $logType Log-Event "Results have been uploaded to Log Analytics Workspace $($LAworkspaceName)"} catch {Log-Event "Error. Results couldn't been uploaded to Log Analytics Workspace $($LAworkspaceName)"} } #End of Script racarb |