Skip to content

Commit bff322b

Browse files
HCRittergaelcolas
authored andcommitted
Christian Ritter - Added slides and content
Added my two sessions.
1 parent 2f46372 commit bff322b

17 files changed

+829
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
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
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
$SessionsURI = "https://sessionize.com/api/v2/j7w9zn0t/view/sessions"
2+
$Sessions = (Invoke-RestMethod -Method Get -Uri $SessionsURI).Sessions
3+
4+
$Sessions | Where-Object {$_.ID -eq "590978"}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#Region Import the external data
2+
3+
$SessionsURI = "https://sessionize.com/api/v2/j7w9zn0t/view/sessions"
4+
$Sessions = (Invoke-RestMethod -Method Get -Uri $SessionsURI).Sessions
5+
6+
#EndRegion
7+
8+
#Region transform the sessions into external items-layout
9+
10+
$ConnectionItemList = foreach($Session in $Sessions){
11+
@{
12+
id = $Session.Id
13+
properties = @{
14+
title = $Session.title
15+
description = $Session.questionAnswers.answer -join ', '
16+
speakers = ($Session.speakers).name -join ', '
17+
startsAt = ($Session.startsAt).tostring()
18+
Room = $Session.room
19+
}
20+
content = @{
21+
value = $Session.description
22+
type = 'text'
23+
}
24+
acl = @(
25+
@{
26+
accessType = "grant"
27+
type = "everyone"
28+
value = "everyone"
29+
}
30+
)
31+
activities = @(@{
32+
"@odata.type" = "#microsoft.graph.externalConnectors.externalActivity"
33+
type = "created"
34+
startDateTime = (Get-Date).AddDays(-1)
35+
performedBy = @{
36+
type = "user"
37+
id = $UserID
38+
}
39+
})
40+
41+
}
42+
}
43+
44+
#EndRegion
45+
46+
#Region Ingest the external items into the connector
47+
48+
$ConnectionItemList.Foreach({
49+
Set-MgExternalConnectionItem -ExternalConnectionId $PreparedConnectionID -ExternalItemId $_.Id -BodyParameter $_ -ErrorAction Stop
50+
})
51+
52+
#EndRegion
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
3+
"version": "1.3",
4+
"body": [
5+
{
6+
"columns": [
7+
{
8+
"width": "auto",
9+
"height": "stretch",
10+
"items": [
11+
{
12+
"horizontalAlignment": "Center",
13+
"url": "https://searchuxcdn.blob.core.windows.net/designerapp/images/DefaultMRTIcon.png",
14+
"size": "Small",
15+
"altText": "Result logo",
16+
"type": "Image"
17+
}
18+
],
19+
"type": "Column"
20+
},
21+
{
22+
"width": 8,
23+
"horizontalAlignment": "Center",
24+
"spacing": "Medium",
25+
"items": [
26+
{
27+
"weight": "Bolder",
28+
"color": "Accent",
29+
"size": "Medium",
30+
"text": "[${title}]",
31+
"type": "TextBlock"
32+
},
33+
{
34+
"maxLines": 3,
35+
"wrap": true,
36+
"text": "${speakers}",
37+
"type": "TextBlock"
38+
},
39+
{
40+
"text": "${description}",
41+
"wrap": true,
42+
"type": "TextBlock",
43+
"maxLines": 3
44+
},
45+
{
46+
"spacing": "Small",
47+
"text": "${startsAt}",
48+
"type": "TextBlock"
49+
},
50+
{
51+
"spacing": "Small",
52+
"text": "${room}",
53+
"type": "TextBlock"
54+
}
55+
],
56+
"type": "Column"
57+
}
58+
],
59+
"type": "ColumnSet"
60+
}
61+
],
62+
"type": "AdaptiveCard"
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
function prompt{'PSConfEU>'}
2+
Clear-Host

0 commit comments

Comments
 (0)