Skip to content

Commit

Permalink
Merge pull request #945 from JohnDuprey/dev
Browse files Browse the repository at this point in the history
Hudu Extension
  • Loading branch information
JohnDuprey authored Jul 8, 2024
2 parents 09931d9 + d307b08 commit 8cc64b0
Show file tree
Hide file tree
Showing 16 changed files with 1,045 additions and 21 deletions.
10 changes: 5 additions & 5 deletions Modules/CIPPCore/Public/Add-CIPPApplicationPermission.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ function Add-CIPPApplicationPermission {
if ($RequiredResourceAccess -eq 'CIPPDefaults') {
$RequiredResourceAccess = (Get-Content '.\SAMManifest.json' | ConvertFrom-Json).requiredResourceAccess
}
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -skipTokenCache $true -tenantid $Tenantfilter
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -skipTokenCache $true -tenantid $Tenantfilter -NoAuthCheck $true
$ourSVCPrincipal = $ServicePrincipalList | Where-Object -Property AppId -EQ $ApplicationId
if (!$ourSVCPrincipal) {
#Our Service Principal isn't available yet. We do a sleep and reexecute after 3 seconds.
Start-Sleep -Seconds 5
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -skipTokenCache $true -tenantid $Tenantfilter
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -skipTokenCache $true -tenantid $Tenantfilter -NoAuthCheck $true
$ourSVCPrincipal = $ServicePrincipalList | Where-Object -Property AppId -EQ $ApplicationId
}

$Results = [System.Collections.ArrayList]@()

$CurrentRoles = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals/$($ourSVCPrincipal.id)/appRoleAssignments" -tenantid $Tenantfilter -skipTokenCache $true
$CurrentRoles = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals/$($ourSVCPrincipal.id)/appRoleAssignments" -tenantid $Tenantfilter -skipTokenCache $true -NoAuthCheck $true

$Grants = foreach ($App in $RequiredResourceAccess) {
$svcPrincipalId = $ServicePrincipalList | Where-Object -Property AppId -EQ $App.resourceAppId
Expand All @@ -41,12 +41,12 @@ function Add-CIPPApplicationPermission {
$counter = 0
foreach ($Grant in $Grants) {
try {
$SettingsRequest = New-GraphPOSTRequest -body ($Grant | ConvertTo-Json) -uri "https://graph.microsoft.com/beta/servicePrincipals/$($ourSVCPrincipal.id)/appRoleAssignedTo" -tenantid $Tenantfilter -type POST
$SettingsRequest = New-GraphPOSTRequest -body ($Grant | ConvertTo-Json) -uri "https://graph.microsoft.com/beta/servicePrincipals/$($ourSVCPrincipal.id)/appRoleAssignedTo" -tenantid $Tenantfilter -type POST -NoAuthCheck $true
$counter++
} catch {
$Results.add("Failed to grant $($Grant.appRoleId) to $($Grant.resourceId): $($_.Exception.Message)") | Out-Null
}
}
"Added $counter Application permissions to $($ourSVCPrincipal.displayName)"
return $Results
}
}
2 changes: 1 addition & 1 deletion Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function Add-CIPPAzDataTableEntity {
}
}

$SingleEnt['SplitOverProps'] = ($splitInfoList | ConvertTo-Json).ToString()
$SingleEnt['SplitOverProps'] = ($splitInfoList | ConvertTo-Json -Compress).ToString()
}

# Check if the entity is still too large
Expand Down
18 changes: 12 additions & 6 deletions Modules/CIPPCore/Public/Add-CIPPDelegatedPermission.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,28 @@ function Add-CIPPDelegatedPermission {
if ($RequiredResourceAccess -eq 'CIPPDefaults') {
$RequiredResourceAccess = (Get-Content '.\SAMManifest.json' | ConvertFrom-Json).requiredResourceAccess
$AdditionalPermissions = Get-Content '.\AdditionalPermissions.json' | ConvertFrom-Json

if ($Tenantfilter -eq $env:TenantID) {
$RequiredResourceAccess = $RequiredResourceAccess + ($AdditionalPermissions | Where-Object { $RequiredResourceAccess.resourceAppId -notcontains $_.resourceAppId })
} else {
# remove the partner center permission if not pushing to partner tenant
$RequiredResourceAccess = $RequiredResourceAccess | Where-Object { $_.resourceAppId -ne 'fa3d9a0c-3fb0-42cc-9193-47c7ecd2edbd' }
}
$RequiredResourceAccess = $RequiredResourceAccess + ($AdditionalPermissions | Where-Object { $RequiredResourceAccess.resourceAppId -notcontains $_.resourceAppId })
}
$Translator = Get-Content '.\PermissionsTranslator.json' | ConvertFrom-Json
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -tenantid $Tenantfilter -skipTokenCache $true
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -tenantid $Tenantfilter -skipTokenCache $true -NoAuthCheck $true
$ourSVCPrincipal = $ServicePrincipalList | Where-Object -Property AppId -EQ $ApplicationId
$Results = [System.Collections.ArrayList]@()

$CurrentDelegatedScopes = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals/$($ourSVCPrincipal.id)/oauth2PermissionGrants" -skipTokenCache $true -tenantid $Tenantfilter
$CurrentDelegatedScopes = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals/$($ourSVCPrincipal.id)/oauth2PermissionGrants" -skipTokenCache $true -tenantid $Tenantfilter -NoAuthCheck $true

foreach ($App in $RequiredResourceAccess) {
$svcPrincipalId = $ServicePrincipalList | Where-Object -Property AppId -EQ $App.resourceAppId
$AdditionalScopes = ($AdditionalPermissions | Where-Object -Property resourceAppId -EQ $App.resourceAppId).resourceAccess
if (!$svcPrincipalId) { continue }
if ($AdditionalScopes) {
$NewScope = (($Translator | Where-Object { $_.id -in $App.ResourceAccess.id }).value + $AdditionalScopes.id | Select-Object -Unique) -join ' '
Write-Host "NEW SCOPE: $NewScope"
$NewScope = (@(($Translator | Where-Object { $_.id -in $App.ResourceAccess.id }).value) + @($AdditionalScopes.id | Select-Object -Unique)) -join ' '
} else {
if ($NoTranslateRequired) {
$NewScope = $App.resourceAccess | ForEach-Object { $_.id } -join ' '
Expand All @@ -51,7 +57,7 @@ function Add-CIPPDelegatedPermission {
resourceId = $svcPrincipalId.id
scope = $NewScope
} | ConvertTo-Json -Compress
$CreateRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/v1.0/oauth2PermissionGrants' -tenantid $Tenantfilter -body $Createbody -type POST
$CreateRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/v1.0/oauth2PermissionGrants' -tenantid $Tenantfilter -body $Createbody -type POST -NoAuthCheck $true
$Results.add("Successfully added permissions for $($svcPrincipalId.displayName)") | Out-Null
} else {
$compare = Compare-Object -ReferenceObject $OldScope.scope.Split(' ') -DifferenceObject $NewScope.Split(' ')
Expand All @@ -62,7 +68,7 @@ function Add-CIPPDelegatedPermission {
$Patchbody = @{
scope = "$NewScope"
} | ConvertTo-Json -Compress
$Patchrequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/v1.0/oauth2PermissionGrants/$($OldScope.id)" -tenantid $Tenantfilter -body $Patchbody -type PATCH
$Patchrequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/v1.0/oauth2PermissionGrants/$($OldScope.id)" -tenantid $Tenantfilter -body $Patchbody -type PATCH -NoAuthCheck $true
$Results.add("Successfully updated permissions for $($svcPrincipalId.displayName): $($NewScope)") | Out-Null
}
}
Expand Down
2 changes: 1 addition & 1 deletion Modules/CIPPCore/Public/Get-CIPPAzDatatableEntity.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function Get-CIPPAzDataTableEntity {
$parts = $entityData.Parts | Sort-Object PartIndex
foreach ($part in $parts) {
foreach ($key in $part.PSObject.Properties.Name) {
if ($key -notin @('OriginalEntityId', 'PartIndex', 'PartitionKey', 'RowKey')) {
if ($key -notin @('OriginalEntityId', 'PartIndex', 'PartitionKey', 'RowKey', 'Timestamp')) {
if ($fullEntity.PSObject.Properties[$key]) {
$fullEntity | Add-Member -MemberType NoteProperty -Name $key -Value ($fullEntity.$key + $part.$key) -Force
} else {
Expand Down
7 changes: 7 additions & 0 deletions Modules/CIPPCore/Public/PermissionsTranslator.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
[
{
"description": "Allows the app to impersonate the signed-in user to access the Partner Center API.",
"displayName": "Partner Center as User",
"id": "1cebfa2a-fb4d-419e-b5f9-839b4383e05a",
"origin": "Delegated (Microsoft Partner Center)",
"value": "user_impersonation"
},
{
"description": "Allows Exchange Management as app",
"displayName": "Manage Exchange As Application ",
Expand Down
12 changes: 12 additions & 0 deletions Modules/CippExtensions/Private/Hudu/Get-HuduFormattedBlock.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
function Get-HuduFormattedBlock ($Heading, $Body) {
return @"
<div class="nasa__block" style="margin-bottom: 20px;">
<header class='nasa__block-header' style="padding-top: 15px;">
<h1>$Heading</h1>
</header>
<div style="padding-left: 15px; padding-right: 15px; padding-bottom: 15px;">
$Body
</div>
</div>
"@
}
13 changes: 13 additions & 0 deletions Modules/CippExtensions/Private/Hudu/Get-HuduFormattedField.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
function Get-HuduFormattedField ($Title, $Value) {
return @"
<div class="card__item">
<div class="card__item-slot">
$Title
</div>
<div class="card__item-slot">
$Value
</div>
</div>
"@
}

3 changes: 3 additions & 0 deletions Modules/CippExtensions/Private/Hudu/Get-HuduLinkBlock.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function Get-HuduLinkBlock($URL, $Icon, $Title) {
return "<div class='o365__app' style='text-align:center'><a href=$URL target=_blank><h3><i class=`"$Icon`">&nbsp;&nbsp;&nbsp;</i>$Title</h3></a></div>"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
function Add-HuduAssetLayoutM365Field {
Param(
$AssetLayoutId
)

$M365Field = @{
position = 0
label = 'Microsoft 365'
field_type = 'RichText'
show_in_list = $false
required = $false
expiration = $false
}

$AssetLayout = Get-HuduAssetLayouts -LayoutId $AssetLayoutId

if ($AssetLayout.fields.label -contains 'Microsoft 365') {
return $AssetLayout
}

$AssetLayoutFields = [System.Collections.Generic.List[object]]::new()
$AssetLayoutFields.Add($M365Field)
foreach ($Field in $AssetLayout.fields) {
$Field.position++
$AssetLayoutFields.Add($Field)
}
Set-HuduAssetLayout -Id $AssetLayoutId -Fields $AssetLayoutFields
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
function Get-ExtensionCacheData {
param(
$TenantFilter
)

$Table = Get-CIPPTable -TableName CacheExtensionSync
$CacheData = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq '$TenantFilter'"

$Return = @{}
foreach ($Data in $CacheData) {
$Return[$Data.RowKey] = $Data.Data | ConvertFrom-Json -ErrorAction SilentlyContinue
}
return [PSCustomObject]$Return
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,16 @@ function Push-ExtensionSyncData {
$TenantFilter,
$Extension
)

$Table = Get-CIPPTable -TableName Extensionsconfig
$Config = (Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json -ea stop

switch ($Extension) {
'Hudu' {
if ($Config.Hudu.Enabled) {
Write-Host 'Perfoming Hudu Extension Sync...'
Invoke-HuduExtensionSync -Configuration $Config.Hudu -TenantFilter $TenantFilter
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ function Register-CIPPExtensionScheduledTasks {
}

$SyncTypes.Add('Overview')
$SyncTypes.Add('Groups')

if ($FieldSync.Users) {
$SyncTypes.Add('Users')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function Sync-CippExtensionData {
@{
id = 'AllRoles'
method = 'GET'
url = '/directoryRoles?$top=999'
url = '/directoryRoles'
},
@{
id = 'Domains'
Expand All @@ -50,11 +50,6 @@ function Sync-CippExtensionData {
method = 'GET'
url = '/subscribedSkus?$top=999'
},
@{
id = 'Groups'
method = 'GET'
url = '/groups?$top=999&$select=id,createdDateTime,displayName,description,mail,mailEnabled,mailNickname,resourceProvisioningOptions,securityEnabled,visibility,organizationId,onPremisesSamAccountName,membershipRule,grouptypes,onPremisesSyncEnabled,resourceProvisioningOptions,userPrincipalName'
},
@{
id = 'ConditionalAccess'
method = 'GET'
Expand All @@ -69,6 +64,16 @@ function Sync-CippExtensionData {
id = 'Subscriptions'
method = 'GET'
url = '/directory/subscriptions?$top=999'
},
@{
id = 'OneDriveUsage'
method = 'GET'
url = "reports/getOneDriveUsageAccountDetail(period='D7')?`$format=application/json"
},
@{
id = 'MailboxUsage'
method = 'GET'
url = "reports/getMailboxUsageDetail(period='D7')?`$format=application/json"
}
)

Expand All @@ -79,6 +84,15 @@ function Sync-CippExtensionData {
noPagination = $true
}
})
$AdditionalRequests = @(
@{
ParentId = 'AllRoles'
graphRequest = @{
url = '/directoryRoles/{0}/members?$select=id,displayName,userPrincipalName'
method = 'GET'
}
}
)
}
'Users' {
[System.Collections.Generic.List[PSCustomObject]]$TenantRequests = @(
Expand All @@ -89,6 +103,24 @@ function Sync-CippExtensionData {
}
)
}
'Groups' {
[System.Collections.Generic.List[PSCustomObject]]$TenantRequests = @(
@{
id = 'Groups'
method = 'GET'
url = '/groups?$top=999&$select=id,createdDateTime,displayName,description,mail,mailEnabled,mailNickname,resourceProvisioningOptions,securityEnabled,visibility,organizationId,onPremisesSamAccountName,membershipRule,grouptypes,onPremisesSyncEnabled,resourceProvisioningOptions,userPrincipalName'
}
)
$AdditionalRequests = @(
@{
ParentId = 'Groups'
graphRequest = @{
url = '/groups/{0}/members?$select=id,displayName,userPrincipalName'
method = 'GET'
}
}
)
}
'Devices' {
[System.Collections.Generic.List[PSCustomObject]]$TenantRequests = @(
@{
Expand All @@ -107,6 +139,16 @@ function Sync-CippExtensionData {
url = '/deviceAppManagement/mobileApps'
}
)

$AdditionalRequests = @(
@{
ParentId = 'DeviceCompliancePolicies'
graphRequest = @{
url = '/deviceManagement/deviceCompliancePolicies/{0}/deviceStatuses?$top=999'
method = 'GET'
}
}
)
}
'Mailboxes' {
$Select = 'id,ExchangeGuid,ArchiveGuid,UserPrincipalName,DisplayName,PrimarySMTPAddress,RecipientType,RecipientTypeDetails,EmailAddresses,WhenSoftDeleted,IsInactiveMailbox'
Expand Down Expand Up @@ -155,6 +197,32 @@ function Sync-CippExtensionData {
}
}

if ($AdditionalRequests) {
foreach ($AdditionalRequest in $AdditionalRequests) {
$ParentId = $AdditionalRequest.ParentId
$GraphRequest = $AdditionalRequest.graphRequest.PSObject.Copy()
$AdditionalRequestQueries = ($TenantResults | Where-Object { $_.id -eq $ParentId }).body.value | ForEach-Object {
[PSCustomObject]@{
id = $_.id
method = $GraphRequest.method
url = $GraphRequest.url -f $_.id
}
}
#Write-Information ($AdditionalRequestQueries | ConvertTo-Json -Depth 10 -Compress)
$AdditionalResults = New-GraphBulkRequest -Requests $AdditionalRequestQueries -tenantid $TenantFilter
$AdditionalResults | ForEach-Object {
Write-Information ($_ | ConvertTo-Json -Depth 10 -Compress)
$Entity = @{
PartitionKey = $TenantFilter
SyncType = $SyncType
RowKey = '{0}_{1}' -f $ParentId, $_.id
Data = [string]($_.body.value | ConvertTo-Json -Depth 10 -Compress)
}
Add-CIPPAzDataTableEntity @CacheTable -Entity $Entity -Force
}
}
}

$TenantResults | Select-Object id, body | ForEach-Object {
$Entity = @{
PartitionKey = $TenantFilter
Expand Down
2 changes: 1 addition & 1 deletion Modules/CippExtensions/Public/Hudu/Get-HuduMapping.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ function Get-HuduMapping {

return $MappingObj

}
}
Loading

0 comments on commit 8cc64b0

Please sign in to comment.