diff --git a/README - main.md b/README - main.md index fb2fdcc..54fe011 100644 --- a/README - main.md +++ b/README - main.md @@ -5,6 +5,4 @@ Fragen ? -Wie die Daten der Controller bereitgestllt werden -> Einheitliche Definitionen - -12 \ No newline at end of file +Wie die Daten der Controller bereitgestllt werden -> Einheitliche Definitionen \ No newline at end of file diff --git a/controller/Exchange-User-Export.ps1 b/controller/Exchange-User-Export.ps1 new file mode 100644 index 0000000..0511f90 --- /dev/null +++ b/controller/Exchange-User-Export.ps1 @@ -0,0 +1,84 @@ +# Definieren Sie den Pfad zur Ergebnisdatei +$timestamp = (Get-Date).ToString("yyyyMMdd_HHmmss") +$outputFile = "C:\Scripte\MailboxLastLogins_$timestamp.csv" +# Definieren Sie den API-Endpoint +$apiUrl = "http://api.stines.de:8001/report" + +# Your API key +$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" +$headers.Add("Content-Type", "application/json") +$headers.Add("access_token", "^YWUbG7yX*V!tV^KBSd*2c&vdN3wV9a2i7f3hfGFMBYFxi6#mMiJGiaA5KEHE%B*miK%qb7rQ67gmcYP@gqmux8") + + +$ipaddress = Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.InterfaceAlias -like "*Ethernet*" } | Select-Object -ExpandProperty IPAddress + +# Fügen Sie das Exchange-Management-Snap-In hinzu +if (-not (Get-PSSnapin -Name Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction SilentlyContinue)) { + Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 +} + +# Ermitteln Sie alle Benutzerpostfächer +$mailboxes = Get-Mailbox -RecipientTypeDetails UserMailbox -ResultSize Unlimited + +# Initialisieren Sie eine leere Liste für die Ergebnisse +$results = @() + +# Zeitstempel für eine Stunde zuvor +$oneHourAgo = (Get-Date).AddHours(-1) + +# Durchlaufen Sie alle Postfächer und sammeln Sie die letzten Login-Informationen +foreach ($mailbox in $mailboxes) { + # Überprüfen, ob das Konto deaktiviert ist + $exchangeUserAccountControl = $mailbox.ExchangeUserAccountControl + if ($exchangeUserAccountControl -eq "AccountDisabled") { + continue + } + + # Filter für Admin- und Journalpostfächer + if ($mailbox.UserPrincipalName -eq "$" -or + $mailbox.UserPrincipalName -match "Journal" -or + $mailbox.UserPrincipalName -match "admin") { + continue + } + + $mailboxStats = Get-MailboxStatistics -Identity $mailbox.UserPrincipalName + $lastLoginTime = $mailboxStats.LastLogonTime + + # Prüfen, ob der letzte Login in der letzten Stunde war + if ($lastLoginTime -ge $oneHourAgo) { + + $username = $mailbox.UserPrincipalName.Split('@')[0] + + $result = [PSCustomObject]@{ + Mailbox = $username + LastLogon = $lastLoginTime + } + $results += $result + + # Daten für die API-Anfrage vorbereiten + $data = @{ + username = $result.Mailbox + lastaccess = $result.LastLogon.ToString("yyyy-MM-dd HH:mm:ss") + ipaddress = $ipaddress + } + + # POST-Anfrage an den API-Server senden + $jsonData = ($data | ConvertTo-Json -Depth 3 | Out-String).Trim() + $utf8Json = [System.Text.Encoding]::UTF8.GetBytes($jsonData) + $response = Invoke-RestMethod -Uri $apiUrl -Method Post -Body $utf8Json -ContentType "application/json; charset=utf-8" -Headers $headers + + + if ($response -eq "True") { + Write-Output "Successfully sent data for $($result.Mailbox)" + } else { + Write-Output "Failed to send data for $($result.Mailbox): $response" + } + } +} + +# Ergebnisse in CSV exportieren +$results | Export-Csv -Path $outputFile -NoTypeInformation + +# Ergebnisse anzeigen +$results | Format-Table -AutoSize + diff --git a/controller/Office_365-Export.py b/controller/Office_365-Export.py new file mode 100644 index 0000000..2c69ccc --- /dev/null +++ b/controller/Office_365-Export.py @@ -0,0 +1,117 @@ +import msal +import requests +import pandas as pd +from datetime import datetime + +# Konfigurationsvariablen +client_id = '90571c9b-d407-4d2a-aadd-4a523ff85296' +client_secret = 'ryp8Q~qr6LBOUL2G333a.mf-vg5V..ONl7qJTdza' +tenant_id = '9e449aaa-285c-4572-a132-58db027026d0' +api_server_endpoint = "http://api.stines.de:8001/office/post" +# headers = 'access_token':'^YWUbG7yX*V!tV^KBSd*2c&vdN3wV9a2i7f3hfGFMBYFxi6#mMiJGiaA5KEHE%B*miK%qb7rQ67gmcYP@gqmux8' + +# Die URL für das Token +authority = f'https://login.microsoftonline.com/{tenant_id}' + +# Der Scope für die Microsoft Graph API +scope = ['https://graph.microsoft.com/.default'] + +# MSAL-Instanz erstellen +app = msal.ConfidentialClientApplication( + client_id, + authority=authority, + client_credential=client_secret, +) + +# Token erhalten +result = None +result = app.acquire_token_silent(scope, account=None) + +if not result: + print("Kein Caching vorhanden, holen Sie ein neues Token.") + result = app.acquire_token_for_client(scopes=scope) + print(result) + +if "access_token" in result: + # Token erfolgreich erhalten + access_token = result['access_token'] + + print(access_token) + + # API-Endpunkt für aktive Office-Pakete + endpoint = "https://graph.microsoft.com/v1.0/users?$select=userPrincipalName,assignedLicenses,signInActivity" + + + headers = { + 'Authorization': f'Bearer {access_token}', + 'Content-Type': 'application/json' + } + + response = requests.get(endpoint, headers=headers) + + if response.status_code == 200: + # Die Antwort als JSON behandeln + data = response.json() + + # Extrahieren der Benutzerdaten aus dem JSON + users = data.get('value', []) + + # Die `skuId` und `lastNonInteractiveSignInDateTime` extrahieren und hinzufügen + user_list = [] + for user in users: + if 'assignedLicenses' in user: + for license in user['assignedLicenses']: + if 'skuId' in license: + user_copy = user.copy() + user_copy['skuId'] = license['skuId'] + if user_copy.get('signInActivity'): + sign_in_time = user_copy['signInActivity'].get('lastNonInteractiveSignInDateTime') + if sign_in_time: + user_copy['lastNonInteractiveSignInDateTime'] = datetime.strptime(sign_in_time,'%Y-%m-%dT%H:%M:%SZ').strftime('%Y-%m-%d %H:%M:%S') + else: + user_copy['lastNonInteractiveSignInDateTime'] = None + else: + user_copy['lastNonInteractiveSignInDateTime'] = None + user_list.append(user_copy) + + # Filtern der Benutzer, die eine `skuId` haben + users_with_skuId = [user for user in user_list if user['skuId']] + + # Konvertieren der Benutzerdaten in ein DataFrame + df = pd.DataFrame(users_with_skuId) + + # Pandas Anzeigeoptionen anpassen + pd.set_option('display.max_columns', None) + pd.set_option('display.max_rows', None) + pd.set_option('display.max_colwidth', None) + pd.set_option('display.width', 1000) + + # Alles nach dem @ im "User Principal Name" entfernen + if 'userPrincipalName' in df.columns: + df['userPrincipalName'] = df['userPrincipalName'].str.split('@').str[0] + + # Nur die gewünschten Spalten auswählen und an die API-Server übergeben + selected_columns = df[["userPrincipalName", "skuId", "lastNonInteractiveSignInDateTime"]] + reporting_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + for index, row in selected_columns.iterrows(): + payload = { + "itemkey": row["skuId"], + "username": row["userPrincipalName"], + "reportingdate": reporting_date, + "lastaccess": row["lastNonInteractiveSignInDateTime"] + } + api_response = requests.post(api_server_endpoint, json=payload, headers= {'access_token':'^YWUbG7yX*V!tV^KBSd*2c&vdN3wV9a2i7f3hfGFMBYFxi6#mMiJGiaA5KEHE%B*miK%qb7rQ67gmcYP@gqmux8'}) + if api_response.status_code == 200: + print(f"Erfolgreich gesendet: {payload}") + else: + print(f"Fehler beim Senden von {payload}: {api_response.status_code} - {api_response.text}") + + else: + print(f"Fehler beim Abrufen der Daten: {response.status_code}") + print(f"Antwort: {response.text}") +else: + print("Fehler beim Abrufen des Tokens") + print(result.get("error")) + print(result.get("error_description")) + print(result.get("correlation_id")) diff --git a/controller/RDS-User-Export.ps1 b/controller/RDS-User-Export.ps1 new file mode 100644 index 0000000..fd7ca58 --- /dev/null +++ b/controller/RDS-User-Export.ps1 @@ -0,0 +1,88 @@ +# Define the time range for the last 1 day +$startTime = (Get-Date).AddHours(-1) +$endTime = Get-Date + +# Define the filter hashtable with the time range +$filterHashTable = @{ + LogName = 'Security' + Id = 4624 + StartTime = $startTime + EndTime = $endTime +} + +# Get all events with ID 4624 from the Security log within the defined time range +$events = Get-WinEvent -FilterHashtable $filterHashTable + +# Create a hash table to store the last login event for each user +$userLogins = @{} + +# Loop through each event +foreach ($event in $events) { + $eventDetails = [xml]$event.ToXml() + + # Extract relevant information + $timeCreated = $event.TimeCreated + $username = $eventDetails.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetUserName' } | Select-Object -ExpandProperty '#text' + $ipaddress = Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias Ethernet | Select-Object -ExpandProperty IPAddress + $logonType = $eventDetails.Event.EventData.Data | Where-Object { $_.Name -eq 'LogonType' } | Select-Object -ExpandProperty '#text' + + # Exclude events not related to remote logins and HealthMailbox + if ($logonType -ne "10" -or $username -like "DWM*" -or $username -like "*UMFD*") { + continue + } + + $formattedTimeCreated = $timeCreated.ToString("yyyy-MM-dd HH:mm:ss") + + # Store the event if it's the latest one for the user + if (-not $userLogins.ContainsKey($username) -or $userLogins[$username].TimeCreated -lt $timeCreated) { + $userLogins[$username] = [PSCustomObject]@{ + lastaccess = $formattedTimeCreated + username = $username + ipaddress = $ipaddress + LogonType = $logonType + } + } +} + +# Define the JSON file path with current date and hour +$dateString = (Get-Date).ToString("yyyyMMdd_HH-mm") +$jsonPath = "C:\Scripte\LastLogins_$dateString.json" + +# Output the last login event for each user to the JSON file +$userLoginsArray = $userLogins.GetEnumerator() | ForEach-Object { + $_.Value +} + +$userLoginsArray | ConvertTo-Json | Set-Content -Path $jsonPath -Encoding UTF8 + +Write-Output "JSON file created at $jsonPath" + +# API endpoint URL +$apiUrl = "http://api.stines.de:8001/report" + +# Your API key +$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" +$headers.Add("Content-Type", "application/json") +$headers.Add("access_token", "^YWUbG7yX*V!tV^KBSd*2c&vdN3wV9a2i7f3hfGFMBYFxi6#mMiJGiaA5KEHE%B*miK%qb7rQ67gmcYP@gqmux8") + +# Loop through the collected user logins and send each as a JSON payload to the API +foreach ($userLogin in $userLoginsArray) { + $userLoginObject = $userLogin | Select-Object username, lastaccess, ipaddress + + # Convert the user login object to JSON + $jsonPayload = $userLoginObject | ConvertTo-Json -Depth 3 + + # Encode JSON payload in UTF-8 + $utf8JsonPayload = [System.Text.Encoding]::UTF8.GetBytes($jsonPayload) + + # Send the JSON payload to the API + try { + $response = Invoke-RestMethod -Uri $apiUrl -Method Post -Body $utf8JsonPayload -ContentType 'application/json' -Headers $headers + Write-Output "Sent login data for user $($userLoginObject.Username) to the API. Response: $response" + } catch { + Write-Error "Failed to send login data for user $($userLoginObject.Username). Error: $_" + } +} + +Write-Output "Finished sending login data to the API" + diff --git a/controller/office_365.py b/controller/office_365.py new file mode 100644 index 0000000..f23dd01 --- /dev/null +++ b/controller/office_365.py @@ -0,0 +1,117 @@ +import msal +import requests +import pandas as pd +from datetime import datetime + +# Konfigurationsvariablen +client_id = '90571c9b-d407-4d2a-aadd-4a523ff85296' +client_secret = 'ryp8Q~qr6LBOUL2G333a.mf-vg5V..ONl7qJTdza' +tenant_id = '9e449aaa-285c-4572-a132-58db027026d0' +api_server_endpoint = "http://api.stines.de:8001/office/post" +# headers = 'access_token':'^YWUbG7yX*V!tV^KBSd*2c&vdN3wV9a2i7f3hfGFMBYFxi6#mMiJGiaA5KEHE%B*miK%qb7rQ67gmcYP@gqmux8' + +# Die URL für das Token +authority = f'https://login.microsoftonline.com/{tenant_id}' + +# Der Scope für die Microsoft Graph API +scope = ['https://graph.microsoft.com/.default'] + +# MSAL-Instanz erstellen +app = msal.ConfidentialClientApplication( + client_id, + authority=authority, + client_credential=client_secret, +) + +# Token erhalten +result = None +result = app.acquire_token_silent(scope, account=None) + +if not result: + print("Kein Caching vorhanden, holen Sie ein neues Token.") + result = app.acquire_token_for_client(scopes=scope) + print(result) + +if "access_token" in result: + # Token erfolgreich erhalten + access_token = result['access_token'] + + print(access_token) + + # API-Endpunkt für aktive Office-Pakete + endpoint = "https://graph.microsoft.com/v1.0/users?$select=userPrincipalName,assignedLicenses,signInActivity" + + + headers = { + 'Authorization': f'Bearer {access_token}', + 'Content-Type': 'application/json' + } + + response = requests.get(endpoint, headers=headers) + + if response.status_code == 200: + # Die Antwort als JSON behandeln + data = response.json() + + # Extrahieren der Benutzerdaten aus dem JSON + users = data.get('value', []) + + # Die `skuId` und `lastNonInteractiveSignInDateTime` extrahieren und hinzufügen + user_list = [] + for user in users: + if 'assignedLicenses' in user: + for license in user['assignedLicenses']: + if 'skuId' in license: + user_copy = user.copy() + user_copy['skuId'] = license['skuId'] + if user_copy.get('signInActivity'): + sign_in_time = user_copy['signInActivity'].get('lastNonInteractiveSignInDateTime') + if sign_in_time: + user_copy['lastNonInteractiveSignInDateTime'] = datetime.strptime(sign_in_time,'%Y-%m-%dT%H:%M:%SZ').strftime('%Y-%m-%d %H:%M:%S') + else: + user_copy['lastNonInteractiveSignInDateTime'] = None + else: + user_copy['lastNonInteractiveSignInDateTime'] = None + user_list.append(user_copy) + + # Filtern der Benutzer, die eine `skuId` haben + users_with_skuId = [user for user in user_list if user['skuId']] + + # Konvertieren der Benutzerdaten in ein DataFrame + df = pd.DataFrame(users_with_skuId) + + # Pandas Anzeigeoptionen anpassen + pd.set_option('display.max_columns', None) + pd.set_option('display.max_rows', None) + pd.set_option('display.max_colwidth', None) + pd.set_option('display.width', 1000) + + # Alles nach dem @ im "User Principal Name" entfernen + if 'userPrincipalName' in df.columns: + df['userPrincipalName'] = df['userPrincipalName'].str.split('@').str[0] + + # Nur die gewünschten Spalten auswählen und an die API-Server übergeben + selected_columns = df[["userPrincipalName", "skuId", "lastNonInteractiveSignInDateTime"]] + reporting_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + for index, row in selected_columns.iterrows(): + payload = { + "itemkey": row["skuId"], + "username": row["userPrincipalName"], + "reportingdate": reporting_date, + "lastaccess": row["lastNonInteractiveSignInDateTime"] + } + api_response = requests.post(api_server_endpoint, json=payload, headers= {'access_token':'^YWUbG7yX*V!tV^KBSd*2c&vdN3wV9a2i7f3hfGFMBYFxi6#mMiJGiaA5KEHE%B*miK%qb7rQ67gmcYP@gqmux8'}) + if api_response.status_code == 200: + print(f"Erfolgreich gesendet: {payload}") + else: + print(f"Fehler beim Senden von {payload}: {api_response.status_code} - {api_response.text}") + + else: + print(f"Fehler beim Abrufen der Daten: {response.status_code}") + print(f"Antwort: {response.text}") +else: + print("Fehler beim Abrufen des Tokens") + print(result.get("error")) + print(result.get("error_description")) + print(result.get("correlation_id")) \ No newline at end of file diff --git a/controller/sogo.py b/controller/sogo.py new file mode 100644 index 0000000..635e66b --- /dev/null +++ b/controller/sogo.py @@ -0,0 +1,64 @@ +import datetime +import requests +import re +import socket + +def get_local_ip(): + try: + # Ein temporärer Socket erstellen, um die lokale IP-Adresse zu ermitteln + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + # Verbindung zu einem öffentlichen DNS-Server herstellen + s.connect(("8.8.8.8", 80)) + # Die lokale IP-Adresse aus dem Socket abrufen + local_ip = s.getsockname()[0] + s.close() + return local_ip + except Exception as e: + print(f"Fehler beim Ermitteln der lokalen IP-Adresse: {e}") + return None + +# URL des API-Servers +sogo_server = "http://172.19.1.4/api/v1/get/logs/sogo/1000" +sogo_headers = {"x-api-key":"6A039F-CED4C3-D69E9E-A6C713-7EBB6A"} + +api_server = "http://api.stines.de:8001/report" +api_headers = {"access_token":"^YWUbG7yX*V!tV^KBSd*2c&vdN3wV9a2i7f3hfGFMBYFxi6#mMiJGiaA5KEHE%B*miK%qb7rQ67gmcYP@gqmux8"} + +def extract_email_username(log_entry): + # Regex für das Finden der E-Mail-Adresse in der Log-Zeile + match = re.search(r"for user '([^']+)'", log_entry) + if match: + email = match.group(1) + # Entfernen des '@' Zeichens aus der E-Mail-Adresse + username = email.split('@')[0] + return username + else: + return None + +# Funktion zum Abrufen von Daten vom API-Server +def fetch_data_from_api(url): + response = requests.get(url,headers=sogo_headers) + if response.status_code == 200: + return response.json() + else: + print(f"Fehler beim Abrufen der Daten: {response.status_code}") + return None + +# Abrufen der Daten +data = fetch_data_from_api(sogo_server) +if data: + for entry in data: + log_line = entry.get('message') + if log_line and "successful login" in log_line: + username = extract_email_username(log_line) + if username: + payload ={ + "ipaddress": "172.19.1.4", + "username": username, + "lastaccess": datetime.datetime.fromtimestamp(int(entry.get('time'))).strftime('%Y-%m-%d %H:%M:%S') + } + api_response = requests.post(api_server, json=payload, headers=api_headers) + print(api_response.status_code) + print(f"Extrahierter Benutzername: {payload}") +else: + print("Keine Daten gefunden.")