<# .SYNOPSIS Personio Sync Script (Personio -> MEHRKANAL AD) .DESCRIPTION Dieses Script übernimmt Personenbezogene Daten aus Personio in die Active Directory .EXAMPLE PS C:\POSTV>.\mk.ps1 .NOTES Author: Sebastian Mendyka Date: Sep 13, 2017 .Link URL: https://developer.personio.de/v1.0/reference #> ###################################################################################### ###################################################################################### # Variablen setzen ###################################################################################### ###################################################################################### $application = "https://api.personio.de"; $company = "5989"; # Define the user credentials $username = "#TOREPLACE#"; $password = "#TOREPLACE#"; # Force TLS1.2 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $LOGDATE = Get-Date -Format "yyyy-MM-dd_" $OWNPID = $([System.Diagnostics.Process]::GetCurrentProcess()).ID $ScriptDir = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition) $ini = .\functions\functions.ps1 "$ScriptDir\config.ini" $IMPERSONATEADMIN = $ini.exchange.impersonateuser ###################################################################################### ###################################################################################### # Functions ###################################################################################### ###################################################################################### # Active Directory Modul laden . .\functions\json_function.ps1 # Active Directory Modul laden . .\functions\activedirectory_function.ps1 # Füge Log Klasse hinzu, Inspiriert von https://gist.github.com/9to5IT/9620565 . .\functions\log_function.ps1 # Füge Exchange Klassen hinzu . .\functions\exchange_function.ps1 # Füge Personio Klassen hinzu . .\functions\personio.ps1 # Füge SQLITE Klassen hinzu . .\functions\sqlite.ps1 Write-Log -Message "Starte DIFF Import" -Level Info # http://www.spech.de/2016/06/sqlite-mit-der-powershell-nutzen/ if (! $(Get-Command Invoke-SqliteQuery -ErrorAction SilentlyContinue)) { Write-Log -Message "Aktiviere SQLITE Modul" -Level Warn #Import-Module "$($ScriptDir)\modules\sqlite\PSSQLite.psm1" Import-Module PSSQLite } if (! $(Get-Command Invoke-SqliteQuery -ErrorAction SilentlyContinue)) { Send-ErrorMail -Mail "Error: Sqlite Module not found / working" -VACSTART "-" -VACENDE "-" -VACID "-" Write-Log -Message "Aktiviere SQLITE Modul" -Level Error exit } $force = 0 $CHANGEDUSERDATA = $false $CHANGEDAPPOINTMENT = $false ###################################################################################### ###################################################################################### # Prüfe auf "neue" Kalender Daten ###################################################################################### ###################################################################################### try { Write-Log -Message "Get tmp Data (convert to json)" -Level Warn $tmpcontent = $(Get-DiffUserVacation) $tmpcontent | fl | out-file "$ScriptDir\$($ini.general.tmp_path)\data_diff_tmp_test.csv" $getallapidata = $($tmpcontent).content | ConvertFrom-Json | select -expand "data" Write-Log -Message "Create tmp Data (convert to json)" -Level Warn $tmpgetallapidata = ($getallapidata).attributes | convertto-json -depth 8 Write-Log -Message "Write tmp Data" -Level Warn $tmpgetallapidata | fl | out-file "$ScriptDir\$($ini.general.tmp_path)\data_diff_tmp.csv" if (Test-Path "$ScriptDir\$($ini.general.tmp_path)\data_diff.csv") { Write-Log -Message "Compare tmp Data" -Level Warn $fileA = Get-Content "$ScriptDir\$($ini.general.tmp_path)\data_diff.csv" $fileB = Get-Content "$ScriptDir\$($ini.general.tmp_path)\data_diff_tmp.csv" if ( Compare-Object "$fileA" "$fileB") { Write-Log -Message "Daten haben sich geändert..." -Level Info $CHANGEDAPPOINTMENT = $true } else { if ($force -eq "0") { Write-Log -Message "Daten haben sich NICHT geändert... Breche ab" -Level Warn $CHANGEDAPPOINTMENT = $false } else { Write-Log -Message "Daten haben sich NICHT geändert... force aktiv" -Level Info $CHANGEDAPPOINTMENT = $true } } } } catch { Write-Log -Message "Error: $($_.Exception.Message) - check_change - Line Number: $($_.InvocationInfo.ScriptLineNumber)" -Level Error Send-ErrorMail -Mail "Error: get Cal-Data from API: $($_.Exception.Message)" -VACSTART "-" -VACENDE "-" -VACID "-" exit } ############################## DEBUG #$CHANGEDUSERDATA = $true #$CHANGEDAPPOINTMENT = $false ############################## DEBUG if ( $CHANGEDUSERDATA -eq $false -and $CHANGEDAPPOINTMENT -eq $false) { Write-Log -Message "Keine Datenänderungen vorhanden.. Beende Import" -Level Info exit } ###################################################################################### ###################################################################################### # Aktualisiere Kalenderdaten des Users -> $_.ID ###################################################################################### if ( $CHANGEDAPPOINTMENT -eq $true) { Create-ExMsalToken ###################################################################################### ###################################################################################### # Add new Appointments ###################################################################################### ###################################################################################### #2022-09-21T00:00:00+02:00 # $DatePattern = "yyyy-MM-ddTHH:mm:ssK" $DatePattern = "MM/dd/yyyy HH:mm:ss" $getallapidata | where { $_.attributes.status -match "approved" -and [datetime]::ParseExact($_.attributes.start_date, $DatePattern, $null) -gt $STARTDATEOLDEST -and ([DateTime]::ParseExact($_.attributes.start_date, $DatePattern, $null).Year) -ge "2022" } | ForEach-Object { [PSCustomObject]@{ "VACID" = $_.attributes.id | select -First 1 "VACStatus" = $_.attributes.status | select -First 1 "VACStart" = $_.attributes.start_date | select -First 1 "VACEnde" = $_.attributes.end_date | select -First 1 "VACTage" = $_.attributes.days_count | select -First 1 "VACHalbTagAnfang" = $_.attributes.half_day_start | select -First 1 "VACHalbTagEnde" = $_.attributes.half_day_end | select -First 1 "VACTyp" = $_.attributes.time_off_type.attributes.name | select -First 1 "VACTypID" = $_.attributes.time_off_type.attributes.id | select -First 1 "VACEMail" = $_.attributes.employee.attributes.email.value | select -First 1 "VACFirstName" = $_.attributes.employee.attributes.first_name.value | select -First 1 "VACLastName" = $_.attributes.employee.attributes.last_name.value | select -First 1 } } | ForEach-Object { ###################################################################################### ###################################################################################### # Prüfe auf gelöschte Termine ###################################################################################### ###################################################################################### $tmpmail = "$($_.VACEMail)" Write-log -Message "Prüfe $tmpmail" -Level Info $USERMAIL = (Get-ADUser -Filter { EmailAddress -eq $tmpmail }).UserPrincipalName $USERID = (Get-ADUser -Filter { EmailAddress -eq $tmpmail }).SamAccountName if (! (Test-path -Path "$($ScriptDir)\sqlite\$($USERID).db" )) { CREATE-SQLITE $USERID } else { If ((Get-Item "$($ScriptDir)\sqlite\$($USERID).db").length -le 0kb) { Remove-Item "$($ScriptDir)\sqlite\$($USERID).db" CREATE-SQLITE $USERID } } $STARTDATE = Get-Date -date $_.VACStart $STARTDATEOLDEST = (get-date).adddays(-60) $ENDDATE = Get-Date -date $_.VACEnde $ENDDATEOLDEST = (get-date).adddays(+360) [datetime]$VACStart = $_.VACStart [datetime]$VACEnde = $_.VACEnde $VACHalbTagAnfang = $_.VACHalbTagAnfang $VACHalbTagEnde = $_.VACHalbTagEnde $VACTage = $_.VACTage # Berechnung Urlaubsanfang und Urlaubsende if ($VACTAGE -lt 1) { if ($VACHalbTagAnfang -eq "1") { $VACStart = $VACStart } if ($VACHalbTagEnde -eq "1") { $VACStart = $VACStart.AddHours(13) $VACEnde = $VACEnde.AddHours(23).AddMinutes(59) } else { $VACEnde = $VACEnde.AddHours(13) } } else { if ($VACHalbTagAnfang -eq "1") { $VACStart = $VACStart.AddHours(13) } if ($VACHalbTagEnde -eq "1") { $VACEnde = $VACEnde.AddHours(13) } else { $VACEnde = $VACEnde.AddHours(23).AddMinutes(59) } } ###################################################################################### ###################################################################################### # Prüfe auf vorhandensein des Kalendereintrags in SQLITE Objekt ###################################################################################### ###################################################################################### $GETRESPONSE = Get-SQLITE -USERID $USERID -VACPERSONIOID $_.VACID if ($GETRESPONSE -eq $null) { Write-Log -Message "Kalendereintrag: $($_.VACID) für $($USERID) nicht gefunden" -Level Warn $RESPONSE = GET-ExchangeSubject -VacationType $($_.VACTypID) ###################################################################################### ###################################################################################### # Termin ist nicht im SQLITE vorhanden.. ###################################################################################### ###################################################################################### $CREATEEWSOK = New-CalendarItem -Subject "$($RESPONSE.Name)" -Body "Dieser Eintrag wurde automatisch erzeugt. Bindend sind nur die Angaben in Personio (https://mehrkanal.personio.de/login/index )" -Start $VACStart -End $VACEnde -AdminUser "$IMPERSONATEADMIN" -Impersonate $_.VACEMail -FreeBusyStatus "$($RESPONSE.Status)" if ( $CREATEEWSOK -ne $null -or $CREATEEWSOK -ne $false) { echo $CREATEEWSOK INSERT-SQLITE -USERID $USERID -MAIL $_.VACEMail -FIRSTNAME $_.VACFirstName -LASTNAME $_.VACLastName -VACPERSONIOID $_.VACID -VACTYPE $_.VACTYP -VACSTART $VACStart -VACEND $VACEnde -VAEXCHANGEID $CREATEEWSOK Write-Log -Message "Kalendereintrag: $($_.VACID) für $($USERID) wurde hinzugefügt Start: $($_.VACStart) STOP: $VACEnde TYP: $($_.VACTYP)" -Level Warn Write-Log -Message "Kalendereintrag: $($APIRESP)" -Level Warn } else { Write-Log -Message "Urlaubsfreigabe EWS Sync war fehlerhaft..." -Level Error Send-ErrorMail -Mail $($_.VACEMail) -VACSTART $($VACStart) -VACENDE $($VACEnde) -VACID $($_.VACID) } } else { Write-Log -Message "Eintrag wurde gefunden... vergleiche" -Level Info ###################################################################################### ###################################################################################### # Vergleiche API-Response mit vorhandenen SQLITE Daten... ###################################################################################### ###################################################################################### $RESPONSE = GET-ExchangeSubject -VacationType $($_.VACTypID) $APIRESP = New-Object psobject -Property @{USERID = $USERID; MAIL = $_.VACEMail; VACID = $_.VACID; VACTYP = $_.VACTYP; VACSTART = $VACStart; VACENDE = $VACEnde } $SQLITERESP = New-Object psobject -Property @{USERID = ($GETRESPONSE).Userid; MAIL = ($GETRESPONSE).Mail; VACID = ($GETRESPONSE).id; VACTYP = ($GETRESPONSE).Vactype; VACSTART = [datetime]($GETRESPONSE).Vacstart; VACENDE = [datetime]($GETRESPONSE).Vacend } if (Compare-Object $APIRESP $SQLITERESP -Property VACID, MAIL, VACSTART, VACENDE, VACTYPE ) { Write-Log -Message "Kalendereintrag: $($_.VACID) für $($USERID) haben sich geändert" -Level Warn Write-Log -Message "Kalendereintrag: $($APIRESP)" -Level Warn Write-Log -Message "Kalendereintrag: $($SQLITERESP)" -Level Warn ###################################################################################### ###################################################################################### # Termin muss in Exchange geändert werden ###################################################################################### ###################################################################################### $EXCHANGEMEETINGID = ($GETRESPONSE).Vacexchangeid Remove-CalendarItem -CALID ($GETRESPONSE).Vacexchangeid -Impersonate ($GETRESPONSE).Mail DELETE-SQLITE -USERID $USERID -VACPERSONIOID $_.VACID $CREATEEWSOK = New-CalendarItem -Subject "$($RESPONSE.Name)" -Body "Dieser Eintrag wurde automatisch erzeugt. Bindend sind nur die Angaben in Personio (https://mehrkanal.personio.de/login/index )" -Start $VACStart -End $VACEnde -AdminUser "$IMPERSONATEADMIN" -Impersonate $_.VACEMail -FreeBusyStatus "$($RESPONSE.Status)" if ( $CREATEEWSOK -ne $null -or $CREATEEWSOK -ne $false) { echo $CREATEEWSOK INSERT-SQLITE -USERID $USERID -MAIL $_.VACEMail -FIRSTNAME $_.VACFirstName -LASTNAME $_.VACLastName -VACPERSONIOID $_.VACID -VACTYPE $_.VACTYP -VACSTART $VACStart -VACEND $VACEnde -VAEXCHANGEID $CREATEEWSOK } else { Write-Log -Message "Urlaubsfreigabe EWS Sync war fehlerhaft..." -Level Error Send-ErrorMail -Mail $($_.VACEMail) -VACSTART $($VACStart) -VACENDE $($VACEnde) -VACID $($_.VACID) } } } } # Erhalte Kalender-Daten und bereite diese auf... $tmpgetallapidata | fl | out-file "$ScriptDir\$($ini.general.tmp_path)\data_diff.csv" # Starte Logging Write-Log -Message "Beende Import" -Level Info } else { Write-Log -Message "Eintrag ist gleich..." -Level Info }