1
+ # Region Step 1: Create AppRegistration
2
+
3
+ # Establish Connection to the target Tenant
4
+ Connect-MgGraph - Scopes AppRoleAssignment.ReadWrite.All, Application.ReadWrite.All, User.Read.All
5
+
6
+ # PreConfigurations
7
+ $TenantID = $ (Get-MgContext ).TenantId
8
+ # UserID of the user "who" posted the data
9
+ $UserID = (Get-mguser - UserId (get-mgcontext ).Account).ID
10
+
11
+ $DisplayName = " PSConfEU2024 - Connector"
12
+
13
+ $Roles = @ {
14
+ " ExternalConnection.ReadWrite.OwnedBy" = " f431331c-49a6-499f-be1c-62af19c34a9d"
15
+ " ExternalItem.ReadWrite.OwnedBy" = " 8116ae0f-55c2-452d-9944-d18420f5b2c8"
16
+ }
17
+
18
+ $AppIDs = @ {
19
+ " Microsoft.Graph" = " 00000003-0000-0000-c000-000000000000"
20
+ }
21
+
22
+
23
+ # Define a required Resource Access Object
24
+
25
+ $RequiredResourceAccessObject = (@ {
26
+ " resourceAccess" = (
27
+ @ {
28
+ id = $Roles [" ExternalConnection.ReadWrite.OwnedBy" ]
29
+ type = " Role"
30
+ },
31
+ @ {
32
+ id = $Roles [" ExternalItem.ReadWrite.OwnedBy" ]
33
+ type = " Role"
34
+ }
35
+ )
36
+ " resourceAppId" = $AppIDs [" Microsoft.Graph" ]
37
+ })
38
+
39
+ # New AppRegistration
40
+ $newMgApplicationSplat = @ {
41
+ DisplayName = $DisplayName
42
+ RequiredResourceAccess = $requiredResourceAccessObject
43
+ }
44
+
45
+ $AppRegistration = New-MgApplication @newMgApplicationSplat
46
+
47
+ # New ServicePrincipal
48
+ $ServicePrincipalMicrosoftGraphID = $ (Get-MgServicePrincipal - Filter " appId eq '$ ( $AppIDs [" Microsoft.Graph" ]) '" ).Id
49
+ $ServicePrincipalAppRegistration = New-MgServicePrincipal - AppId $AppRegistration.appId
50
+
51
+ # New Admin Consent via AppRoleAssignments for the defined Roles
52
+ $Roles.Values.ForEach ({
53
+
54
+ $newMgServicePrincipalAppRoleAssignmentSplat = @ {
55
+ ServicePrincipalId = $ServicePrincipalAppRegistration.Id
56
+ PrincipalId = $ServicePrincipalAppRegistration.Id
57
+ AppRoleId = $_
58
+ ResourceId = $ServicePrincipalMicrosoftGraphID
59
+ }
60
+ New-MgServicePrincipalAppRoleAssignment @newMgServicePrincipalAppRoleAssignmentSplat
61
+
62
+ })
63
+
64
+ # New Client Secret - Valid 6 Months
65
+ $passwordCredential = @ {
66
+ displayName = " $DisplayName - Secret"
67
+ endDateTime = (Get-Date ).AddMonths(6 )
68
+ }
69
+ $ClientSecret = Add-MgApplicationPassword - ApplicationId $AppRegistration.ID - PasswordCredential $passwordCredential
70
+
71
+ Disconnect-MgGraph
72
+ # EndRegion
73
+
74
+ # Region Step 2: (re)Connect via the AppRegistration
75
+
76
+ [pscredential ]$ClientSecretCredential = New-Object System.Management.Automation.PSCredential ($AppRegistration.AppId , $ (ConvertTo-SecureString ($ClientSecret.SecretText ) - AsPlainText - Force))
77
+ Connect-MgGraph - ClientSecretCredential $ClientSecretCredential - TenantId $TenantID
78
+
79
+ # EndRegion
80
+
81
+ # Region Step 3: Create New AdaptiveCardObject
82
+
83
+ # Initialize to an empty hashtable to explicitly define the type as hashtable.
84
+
85
+ # This is needed to avoid the breaking change introduced in PowerShell 7.3 - https://github.com/PowerShell/PowerShell/issues/18524.
86
+ # https://github.com/microsoftgraph/msgraph-sdk-powershell/issues/2352
87
+
88
+ [hashtable ]$adaptiveCard = @ {}
89
+ $adaptiveCard += Get-Content - Path " .\Layout.json" - Raw | ConvertFrom-Json - AsHashtable
90
+
91
+ # EndRegion
92
+
93
+ # Region Step 4: Design the Schema for Search Items
94
+ $Schema = @ (
95
+ @ {
96
+ name = " title"
97
+ type = " String"
98
+ isQueryable = $true
99
+ isSearchable = $true
100
+ isRetrievable = $true
101
+ labels = @ (
102
+ " title"
103
+ )
104
+ }
105
+ @ {
106
+ name = " speakers"
107
+ type = " String"
108
+ isQueryable = $true
109
+ isSearchable = $true
110
+ isRetrievable = $true
111
+ }
112
+ @ {
113
+ name = " room"
114
+ type = " String"
115
+ isQueryable = $true
116
+ isSearchable = $true
117
+ isRetrievable = $true
118
+ }
119
+ @ {
120
+ name = " startsAt"
121
+ type = " String"
122
+ isQueryable = $true
123
+ isSearchable = $true
124
+ isRetrievable = $true
125
+
126
+ }
127
+ @ {
128
+ name = " description"
129
+ type = " String"
130
+ isQueryable = $true
131
+ isSearchable = $true
132
+ isRetrievable = $true
133
+ }
134
+
135
+
136
+ )
137
+ # EndRegion
138
+
139
+ # Region Step 5: Design the JSON for the Connector
140
+ $baseExternalUrl = " https://sessionize.com/api/v2/j7w9zn0t/view/Session/"
141
+ $searchResultTemplatesID = " psconfeu"
142
+ $ConnectionID = " pscconfeu"
143
+ $ConnectionName = " psconfeu 2024"
144
+ $ConnectionDescription = " PowerShell Conference Europe 2024"
145
+
146
+ $externalConnection = @ {
147
+ userId = $UserID # From Azure Entra ID
148
+ # The name of the connection, as it will appear in the Microsoft Search admin center
149
+ # Defines the details of the connection
150
+ connection = @ {
151
+ id = $ConnectionID
152
+ name = $ConnectionName
153
+ description = $ConnectionDescription
154
+ activitySettings = @ {
155
+ urlToItemResolvers = @ (
156
+ @ {
157
+ " @odata.type" = " #microsoft.graph.externalConnectors.itemIdResolver"
158
+ urlMatchInfo = @ {
159
+ baseUrls = @ (
160
+ " $ ( $baseExternalUrl ) "
161
+ )
162
+ urlPattern = " /(?<slug>[^/]+)"
163
+ }
164
+ itemId = " {slug}"
165
+ priority = 1
166
+ }
167
+ )
168
+ }
169
+ searchSettings = @ {
170
+ searchResultTemplates = @ (
171
+ @ {
172
+ id = $searchResultTemplatesID
173
+ priority = 1
174
+ layout = @ {
175
+ additionalProperties = $adaptiveCard
176
+ }
177
+ }
178
+ )
179
+ }
180
+ }
181
+ # The schema is a way of defining the columns that will be available in the search results and how they are mapped to the content
182
+ # https://learn.microsoft.com/graph/connecting-external-content-manage-schema
183
+ schema = $Schema
184
+ }
185
+ # EndRegion
186
+
187
+ # Region Step 6: Create the Connector
188
+
189
+ # Create the external connection
190
+ New-MgExternalConnection - BodyParameter $externalConnection.connection - ErrorAction Stop
191
+
192
+ # EndRegion
193
+
194
+ # Region Step 7: Update the Schema for the Connector
195
+
196
+ # Update the schema of the external connection
197
+ $body = @ {
198
+ baseType = " microsoft.graph.externalItem"
199
+ properties = $externalConnection.schema
200
+ }
201
+ Update-MgExternalConnectionSchema - ExternalConnectionId $externalConnection.connection.id - BodyParameter $body - ErrorAction Stop
202
+
203
+ # wait for the schema to be applied
204
+ do {
205
+ $connection = Get-MgExternalConnection - ExternalConnectionId $externalConnection.connection.id
206
+ Start-Sleep - Seconds 60
207
+ Write-Host " ." - NoNewLine - ForegroundColor Yellow
208
+ } while ($connection.State -eq ' draft' )
209
+
210
+ # EndRegion
0 commit comments