Skip to content

Commit c355a54

Browse files
committed
Extension data sync
1 parent ed2378f commit c355a54

5 files changed

Lines changed: 266 additions & 9 deletions

File tree

Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ function Add-CIPPScheduledTask {
22
[CmdletBinding()]
33
param(
44
[pscustomobject]$Task,
5-
[bool]$Hidden
5+
[bool]$Hidden,
6+
[string]$SyncType = $null
67
)
78

89
$Table = Get-CIPPTable -TableName 'ScheduledTasks'
@@ -49,10 +50,13 @@ function Add-CIPPScheduledTask {
4950
Hidden = [bool]$Hidden
5051
Results = 'Planned'
5152
}
53+
if ($SyncType) {
54+
$entity.SyncType = $SyncType
55+
}
5256
try {
5357
Add-CIPPAzDataTableEntity @Table -Entity $entity -Force
5458
} catch {
5559
return "Could not add task: $($_.Exception.Message)"
5660
}
5761
return "Successfully added task: $($entity.Name)"
58-
}
62+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
function Push-ExtensionSyncData {
2+
param(
3+
$TenantFilter,
4+
$Extension
5+
)
6+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
function Register-CIPPExtensionScheduledTasks {
2+
Param(
3+
[switch]$Reschedule
4+
)
5+
6+
# get extension configuration and mappings table
7+
$Table = Get-CIPPTable -TableName Extensionsconfig
8+
$Config = ((Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json -ea stop)
9+
$MappingsTable = Get-CIPPTable -TableName CippMapping
10+
11+
# Get existing scheduled usertasks
12+
$ScheduledTasksTable = Get-CIPPTable -TableName ScheduledTasks
13+
$ScheduledTasks = Get-CIPPAzDataTableEntity @ScheduledTasksTable -Filter 'Hidden eq true' | Where-Object { $_.Command -match 'Sync-CippExtensionData' }
14+
$Tenants = Get-Tenants -IncludeErrors
15+
16+
$Extensions = @('Hudu')
17+
18+
foreach ($Extension in $Extensions) {
19+
$ExtensionConfig = $Config.$Extension
20+
if ($ExtensionConfig.Enabled -eq $true) {
21+
$Mappings = Get-CIPPAzDataTableEntity @MappingsTable -Filter "PartitionKey eq '$($Extension)Mapping'"
22+
$FieldMapping = Get-CIPPAzDataTableEntity @MappingsTable -Filter "PartitionKey eq '$($Extension)FieldMapping'"
23+
$FieldSync = @{}
24+
$SyncTypes = [System.Collections.Generic.List[string]]::new()
25+
26+
foreach ($Mapping in $FieldMapping) {
27+
$FieldSync[$Mapping.RowKey] = !([string]::IsNullOrEmpty($Mapping.IntegrationId))
28+
}
29+
30+
$SyncTypes.Add('Overview')
31+
32+
if ($FieldSync.Users) {
33+
$SyncTypes.Add('Users')
34+
$SyncTypes.Add('Mailboxes')
35+
}
36+
if ($FieldSync.Devices) {
37+
$SyncTypes.Add('Devices')
38+
}
39+
40+
foreach ($Mapping in $Mappings) {
41+
$Tenant = $Tenants | Where-Object { $_.customerId -eq $Mapping.RowKey }
42+
43+
foreach ($SyncType in $SyncTypes) {
44+
$ExistingTask = $ScheduledTasks | Where-Object { $_.Tenant -eq $Tenant.defaultDomainName -and $_.SyncType -eq $SyncType }
45+
if (!$ExistingTask -or $Reschedule.IsPresent) {
46+
$unixtime = [int64](([datetime]::UtcNow) - (Get-Date '1/1/1970')).TotalSeconds
47+
$Task = @{
48+
Name = "Extension Sync - $SyncType"
49+
Command = @{
50+
value = 'Sync-CippExtensionData'
51+
label = 'Sync-CippExtensionData'
52+
}
53+
Parameters = @{
54+
TenantFilter = $Tenant.defaultDomainName
55+
SyncType = $SyncType
56+
}
57+
Recurrence = '1d'
58+
ScheduledTime = $unixtime
59+
TenantFilter = $Tenant.defaultDomainName
60+
}
61+
if ($ExistingTask) {
62+
$Task.RowKey = $ExistingTask.RowKey
63+
}
64+
$null = Add-CIPPScheduledTask -Task $Task -hidden $true -SyncType $SyncType
65+
}
66+
}
67+
}
68+
}
69+
}
70+
71+
}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
function Sync-CippExtensionData {
2+
<#
3+
.FUNCTIONALITY
4+
Internal
5+
#>
6+
[CmdletBinding()]
7+
param(
8+
$TenantFilter,
9+
$SyncType
10+
)
11+
12+
$Table = Get-CIPPTable -TableName ExtensionSync
13+
$Extensions = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq '$($SyncType)'"
14+
$LastSync = $Extensions | Where-Object { $_.RowKey -eq $TenantFilter }
15+
$CacheTable = Get-CIPPTable -tablename 'CacheExtensionSync'
16+
17+
if (!$LastSync) {
18+
$LastSync = @{
19+
PartitionKey = $SyncType
20+
RowKey = $TenantFilter
21+
Status = 'Not Synced'
22+
Error = ''
23+
LastSync = 'Never'
24+
}
25+
Add-CIPPAzDataTableEntity @Table -Entity $LastSync
26+
}
27+
28+
try {
29+
switch ($SyncType) {
30+
'Overview' {
31+
# Build bulk requests array.
32+
[System.Collections.Generic.List[PSCustomObject]]$TenantRequests = @(
33+
@{
34+
id = 'TenantDetails'
35+
method = 'GET'
36+
url = '/organization'
37+
},
38+
@{
39+
id = 'AllRoles'
40+
method = 'GET'
41+
url = '/directoryRoles?$top=999'
42+
},
43+
@{
44+
id = 'Domains'
45+
method = 'GET'
46+
url = '/domains$top=999'
47+
},
48+
@{
49+
id = 'Licenses'
50+
method = 'GET'
51+
url = '/subscribedSkus?$top=999'
52+
},
53+
@{
54+
id = 'Groups'
55+
method = 'GET'
56+
url = '/groups?$top=999&$select=id,createdDateTime,displayName,description,mail,mailEnabled,mailNickname,resourceProvisioningOptions,securityEnabled,visibility,organizationId,onPremisesSamAccountName,membershipRule,grouptypes,onPremisesSyncEnabled,resourceProvisioningOptions,userPrincipalName'
57+
},
58+
@{
59+
id = 'ConditionalAccess'
60+
method = 'GET'
61+
url = '/identity/conditionalAccess/policies'
62+
},
63+
@{
64+
id = 'SecureScoreControlProfiles'
65+
method = 'GET'
66+
url = '/security/secureScoreControlProfiles?$top=999'
67+
},
68+
@{
69+
id = 'Subscriptions'
70+
method = 'GET'
71+
url = '/directory/subscriptions?$top=999'
72+
}
73+
)
74+
75+
$SingleGraphQueries = @(@{
76+
id = 'SecureScore'
77+
graphRequest = @{
78+
uri = 'https://graph.microsoft.com/beta/security/secureScores?$top=1'
79+
noPagination = $true
80+
}
81+
})
82+
}
83+
'Users' {
84+
[System.Collections.Generic.List[PSCustomObject]]$TenantRequests = @(
85+
@{
86+
id = 'Users'
87+
method = 'GET'
88+
url = '/users?$top=999&$select=id,accountEnabled,businessPhones,city,createdDateTime,companyName,country,department,displayName,faxNumber,givenName,isResourceAccount,jobTitle,mail,mailNickname,mobilePhone,onPremisesDistinguishedName,officeLocation,onPremisesLastSyncDateTime,otherMails,postalCode,preferredDataLocation,preferredLanguage,proxyAddresses,showInAddressList,state,streetAddress,surname,usageLocation,userPrincipalName,userType,assignedLicenses,onPremisesSyncEnabled'
89+
}
90+
)
91+
}
92+
'Devices' {
93+
[System.Collections.Generic.List[PSCustomObject]]$TenantRequests = @(
94+
@{
95+
id = 'Devices'
96+
method = 'GET'
97+
url = '/deviceManagement/managedDevices?$top=999'
98+
},
99+
@{
100+
id = 'DeviceCompliancePolicies'
101+
method = 'GET'
102+
url = '/deviceManagement/deviceCompliancePolicies'
103+
},
104+
@{
105+
id = 'DeviceApps'
106+
method = 'GET'
107+
url = '/deviceAppManagement/mobileApps'
108+
}
109+
)
110+
}
111+
'Mailboxes' {
112+
$Select = 'id,ExchangeGuid,ArchiveGuid,UserPrincipalName,DisplayName,PrimarySMTPAddress,RecipientType,RecipientTypeDetails,EmailAddresses,WhenSoftDeleted,IsInactiveMailbox'
113+
$ExoRequest = @{
114+
tenantid = $TenantFilter
115+
cmdlet = 'Get-Mailbox'
116+
cmdParams = @{}
117+
Select = $Select
118+
}
119+
$Mailboxes = (New-ExoRequest @ExoRequest) | Select-Object id, ExchangeGuid, ArchiveGuid, WhenSoftDeleted, @{ Name = 'UPN'; Expression = { $_.'UserPrincipalName' } },
120+
121+
@{ Name = 'displayName'; Expression = { $_.'DisplayName' } },
122+
@{ Name = 'primarySmtpAddress'; Expression = { $_.'PrimarySMTPAddress' } },
123+
@{ Name = 'recipientType'; Expression = { $_.'RecipientType' } },
124+
@{ Name = 'recipientTypeDetails'; Expression = { $_.'RecipientTypeDetails' } },
125+
@{ Name = 'AdditionalEmailAddresses'; Expression = { ($_.'EmailAddresses' | Where-Object { $_ -clike 'smtp:*' }).Replace('smtp:', '') -join ', ' } }
126+
127+
$Entity = @{
128+
PartitionKey = $TenantFilter
129+
SyncType = 'Mailboxes'
130+
RowKey = 'Mailboxes'
131+
Data = [string]($Mailboxes | ConvertTo-Json -Depth 10 -Compress)
132+
}
133+
Add-CIPPAzDataTableEntity @CacheTable -Entity $Entity -Force
134+
}
135+
}
136+
137+
if ($TenantRequests) {
138+
try {
139+
$TenantResults = New-GraphBulkRequest -Requests $TenantRequests -tenantid $TenantFilter
140+
} catch {
141+
Throw "Failed to fetch bulk company data: $_"
142+
}
143+
144+
if ($SingleGraphQueries) {
145+
foreach ($SingleGraphQuery in $SingleGraphQueries) {
146+
$Request = $SingleGraphQuery.graphRequest
147+
$Data = New-GraphGetRequest @Request -tenantid $TenantFilter
148+
$Entity = @{
149+
PartitionKey = $TenantFilter
150+
SyncType = $SyncType
151+
RowKey = $SingleGraphQuery.id
152+
Data = [string]($Data | ConvertTo-Json -Depth 10 -Compress)
153+
}
154+
Add-CIPPAzDataTableEntity @CacheTable -Entity $Entity -Force
155+
}
156+
}
157+
158+
$TenantResults | Select-Object id, body | ForEach-Object {
159+
$Entity = @{
160+
PartitionKey = $TenantFilter
161+
RowKey = $_.id
162+
SyncType = $SyncType
163+
Data = [string]($_.body.value | ConvertTo-Json -Depth 10 -Compress)
164+
}
165+
Add-CIPPAzDataTableEntity @CacheTable -Entity $Entity -Force
166+
}
167+
}
168+
$LastSync.LastSync = [datetime]::UtcNow.ToString('yyyy-MM-ddTHH:mm:ssZ')
169+
$LastSync.Status = 'Completed'
170+
$LastSync.Error = ''
171+
} catch {
172+
$LastSync.Status = 'Failed'
173+
$LastSync.Error = [string](Get-CippException -Exception $_ | ConvertTo-Json -Compress)
174+
throw "Failed to sync data: $($_.Exception.Message)"
175+
} finally {
176+
Add-CIPPAzDataTableEntity @Table -Entity $LastSync -Force
177+
}
178+
}

Modules/CippExtensions/Public/Hudu/Get-HuduFieldMapping.ps1

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ function Get-HuduFieldMapping {
44
$CIPPMapping
55
)
66

7-
$Mappings = Get-ExtensionMapping -Extension 'HuduFields'
7+
$Mappings = Get-ExtensionMapping -Extension 'HuduField'
88

99
$CIPPFieldHeaders = @(
1010
[PSCustomObject]@{
1111
Title = 'Hudu Asset Layouts'
1212
FieldType = 'Layouts'
13-
Description = 'Use the table below to map your Hudu Asset Layouts to the correct CIPP Field'
13+
Description = 'Use the table below to map your Hudu Asset Layouts to the correct CIPP Data Type. A new Rich Text asset layout field will be created if it does not exist.'
1414
}
1515
)
1616
$CIPPFields = @(
@@ -31,8 +31,6 @@ function Get-HuduFieldMapping {
3131
}
3232
)
3333

34-
35-
$Tenants = Get-Tenants -IncludeErrors
3634
$Table = Get-CIPPTable -TableName Extensionsconfig
3735
try {
3836
$Configuration = ((Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json -ea stop).Hudu
@@ -46,8 +44,8 @@ function Get-HuduFieldMapping {
4644
$_.Exception.message
4745
}
4846

49-
Write-LogMessage -Message "Could not get Hudu Companies, error: $Message " -Level Error -tenant 'CIPP' -API 'HuduMapping'
50-
$HuduCompanies = @(@{name = "Could not get Hudu Companies, error: $Message"; value = '-1' })
47+
Write-LogMessage -Message "Could not get Hudu Asset Layouts, error: $Message " -Level Error -tenant 'CIPP' -API 'HuduMapping'
48+
$AssetLayouts = @(@{name = "Could not get Hudu Asset Layouts, error: $Message"; value = '-1' })
5149
}
5250

5351
$Unset = [PSCustomObject]@{
@@ -65,4 +63,4 @@ function Get-HuduFieldMapping {
6563

6664
return $MappingObj
6765

68-
}
66+
}

0 commit comments

Comments
 (0)