Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <#
- This script is intended to run hourly via a scheduled task, to sync users with past due training in knowbe4
- to an active directory security group. Separately, Azure AD Connect/Entra ID Connect/Cloud Connect will then
- sync this group up to Microsoft Entra, where a conditional access policy can be assigned to increase MFA prompts
- or however you would like to treat these users as 'high risk'. Once they complete their past due training, they
- will be removed from the group the next time the script is ran.
- #>
- $EAP = $ErrorActionPreference
- $ErrorActionPreference = 'SilentlyContinue' # Because possibly dealing with converting a null value to 'datetime', below.
- $AccessToken = '---enter-knowbe4-reporting-api-token-here---'
- $GroupName = 'High Risk Users' # AD Group name
- $EmailDomainSuffix = '@contoso.com' # cheap hack to convert knowbe4 email addresses to AD sAMAccountName. must include the @ symbol!
- #Force PowerShell to use TLS 1.2
- [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::TLS12
- #Set Required Headers
- $auth = @{
- "ContentType" = 'application/json'
- "Method" = 'GET'
- "Headers" = @{
- "Authorization" = "Bearer $AccessToken"
- "Accept" = "application/json"
- }
- }
- $URL = 'https://us.api.knowbe4.com/v1/training/campaigns/'
- $campaigns = $null
- $campaigns = Invoke-RestMethod -Uri $URL @auth
- $campaigns | ForEach-Object {
- if ($_.start_date -ne $null) { $_.start_date = [datetime]"$($_.start_date)" }
- if ($_.start_date -eq $null) { $_.start_date = [nullable[datetime]]$null }
- if ($_.end_date -ne $null) { $_.end_date = [datetime]"$($_.end_date)" }
- if ($_.end_date -eq $null) { $_.end_date = [nullable[datetime]]$null }
- }
- $PastDue = @()
- $campaigns | Where-Object { $_.Status -ne "closed" -and $_.Status -ne "created" -and $_.completion_percentage -lt '100' } | Sort-Object name | ForEach-Object {
- # Write-Host $_.campaign_id -ForegroundColor Yellow -NoNewline
- # Write-Host " - "$_.name -ForegroundColor Cyan -NoNewline
- if ($_.relative_duration) {
- $_relative_duration = $_.relative_duration
- #Write-Host " - Rel. Dur.:"$_.relative_duration -NoNewline
- }
- if ($_.end_date -ne $null) {
- $_relative_duration = "$(New-TimeSpan -Start $($_.start_date) -End $($_.end_date)).Days days"
- #Write-Host " (End date: $($_.end_date))" -ForegroundColor Green
- }
- if ($_.end_date -eq $null) {
- #Write-Host " (No End date)"
- }
- #>
- $URL = "https://us.api.knowbe4.com/v1/training/enrollments?campaign_id=$($_.campaign_id)?per_page=500"
- $enrollments = $null
- $enrollments = Invoke-RestMethod -Uri $URL @auth
- $enrollments = $enrollments | Select-Object campaign_name, completion_date, content_type, enrollment_date, enrollment_id, module_name, policy_acknowledged, start_date, status, user_status, user, id, first_name, last_name, email
- $enrollments | ForEach-Object {
- $_.id = $_.user.id
- $_.first_name = $_.user.first_name
- $_.last_name = $_.user.last_name
- $_.email = $_.user.email
- }
- if ($_.relative_duration -eq $null) {}
- $PastDue += $enrollments | Where-Object { $_.status -eq "past due" } | Select-Object campaign_name, enrollment_date, @{ Name = 'duration'; Expression = { $_relative_duration } }, days_late, module_name, status, user_status, id, first_name, last_name, email
- }
- $ErrorActionPreference = $EAP
- $PastDue | Sort-Object campaign_name, email | ForEach-Object {
- $duration_period = (($_.duration).Trim()).Split(' ')
- if ($duration_period[1] -match "weeks") { $_days = ((Get-Date).AddDays( - ([int]$duration_period[0] * 7)) - [Datetime]"$($_.enrollment_date)").Days }
- if ($duration_period[1] -match "months") { $_days = ((Get-Date).AddMonths( - ([int]$duration_period[0])) - [Datetime]"$($_.enrollment_date)").Days }
- if ($duration_period[1] -match "days") { $_days = $duration_period[0] }
- $_.days_late = " $_days "
- $_.enrollment_date = [datetime]"$($_.enrollment_date)"
- }
- # Is the user 'Active' or 'Archived'?
- $PastDue | ForEach-Object {
- $StatusURL = "https://us.api.knowbe4.com/v1/users/$($_.id)"
- $_.user_status = (Invoke-RestMethod -Uri $StatusURL @auth).Status
- }
- $PastDue = $PastDue | Where-Object { $_.user_status -eq "Active" }
- $PastDueUsers = @()
- foreach ($User in $PastDue) {
- $PastDueUsers += $User.email -Replace "$EmailDomainSuffix",''
- }
- $PastDueUsers = $PastDueUsers | Select-Object -Unique
- # Update AD Group members to match array
- $Group = Get-AdGroup -Identity $GroupName
- # Get current members of the group
- $CurrentMembers = Get-AdGroupMember -Identity $Group | Select-Object -ExpandProperty SamAccountName
- $AddedUsers = 0
- $RemovedUsers = 0
- # Add users to the group if they are in the $PastDueUsers array and not currently in the group
- foreach ($User in $PastDueUsers) {
- if ($User -notin $CurrentMembers) {
- Add-AdGroupMember -Identity $Group -Members $User
- #Write-Host "Added $User to $GroupName"
- Write-Host "Added $User to `'$GroupName`'" -ForegroundColor DarkCyan
- $AddedUsers += 1
- }
- }
- if ($AddedUsers -eq 0) {
- Write-Host "No new users added to `'$GroupName`'" -ForegroundColor DarkCyan
- }
- # Remove users from the group if they are not in the $PastDueUsers array
- foreach ($Member in $CurrentMembers) {
- if ($Member -notin $PastDueUsers) {
- Remove-AdGroupMember -Identity $Group -Members $Member -Confirm:$false
- #Write-Host "Removed $Member from $GroupName"
- Write-Host "Removed $Member from `'$GroupName`'" -ForegroundColor DarkCyan
- $RemovedUsers += 1
- }
- }
- if ($RemovedUsers -eq 0) {
- Write-Host "No users were removed from `'$GroupName`'" -ForegroundColor DarkCyan
- }
- $TotalHighRiskUsers = (Get-AdGroupMember -Identity $Group | Select-Object -ExpandProperty SamAccountName).count
- if ($null -eq $TotalHighRiskUsers) { $TotalHighRiskUsers = 0 }
- Write-Host "$TotalHighRiskUsers total members of `'$GroupName`'" -ForegroundColor DarkCyan
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement