~~ODT~~ ====== reportMalwareDevices.php ====== * Analog zu **reportUpdateStates.php** Permissions von deviceManagement read reicht aus * Lass dir von Microsoft einen Intune Malware Report geben und zeige mir alle Systeme auf denen Malware gefunden wurde / kann als Cron Job täglich ausgeführt werden , dann muss **$past_timestamp** entsprechend angepasst werden - damit nicht immer die gleichen Devices angezeigt werden * Infos von Microsoft zu den Reports über die Graph API: https://learn.microsoft.com/en-us/mem/intune/fundamentals/reports-export-graph-available-reports ['proxy'=>'10.0.0.1:8080']]); $curl_token= curl_init(); //Azure AD Administration: Tenant properties / Tenant ID: 12345678-9-10-11 // // Details: https://docs.microsoft.com/en-us/graph/auth-v2-service curl_setopt($curl_token,CURLOPT_URL, "https://login.microsoftonline.com/12345678-9-10-11/oauth2/v2.0/token"); curl_setopt($curl_token,CURLOPT_HEADER,0); curl_setopt($curl_token,CURLOPT_POST,1); curl_setopt($curl_token,CURLOPT_POSTFIELDS,"client_id=APP_ID&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret=SHARED_SECRET_TOKEN&grant_type=client_credentials"); curl_setopt($curl_token,CURLOPT_RETURNTRANSFER,1); $json_response=curl_exec($curl_token) or die("Cannot exec url request"); curl_close($curl_token); $access_array=json_decode($json_response,true) or die("Cannot decode json"); //print_r($access_array); if(!isset($access_array["access_token"])) { die("Cannot receive access_token"); } $curl_token= curl_init(); #if called weekly 86400*7 $past_timestamp=time()-(86400*2); $report_details='{ "reportName": "Malware", "localizationType": "LocalizedValuesAsAdditionalColumn", "format": "csv", "select": [ "DeviceName" ,"DetectionCount", "UPN" , "MalwareName", "MalwareCategory", "InitialDetectionDateTime", "ExecutionState" ] }'; // // curl_setopt($curl_token,CURLOPT_URL, "https://graph.microsoft.com/beta/deviceManagement/reports/exportJobs"); curl_setopt($curl_token,CURLOPT_HEADER,0); curl_setopt($curl_token,CURLOPT_POST,1); curl_setopt($curl_token, CURLOPT_POSTFIELDS, $report_details); curl_setopt($curl_token,CURLOPT_HTTPHEADER,array("Authorization: Bearer ".$access_array["access_token"],'Content-type: application/json')); curl_setopt($curl_token,CURLOPT_RETURNTRANSFER,1); $json_response=curl_exec($curl_token) or die("Cannot exec url request"); curl_close($curl_token); //print_r($json_response); $intune_array=json_decode($json_response,true) or die("Cannot decode json"); if(!isset($intune_array["id"])) { echo "FAIL\n"; print_r($intune_array); exit; } $success=false; $failsafe=1; #Failsafe is 5 hours -> 300 minutes while (!$success && $failsafe != 300 ) { $curl_token= curl_init(); // https://docs.microsoft.com/en-us/graph/api/intune-devices-manageddevice-list?view=graph-rest-1.0 // curl_setopt($curl_token,CURLOPT_URL, "https://graph.microsoft.com/beta/deviceManagement/reports/exportJobs('".$intune_array["id"]."')"); curl_setopt($curl_token,CURLOPT_HEADER,0); curl_setopt($curl_token,CURLOPT_POST,0); curl_setopt($curl_token,CURLOPT_HTTPHEADER,array("Authorization: Bearer ".$access_array["access_token"])); curl_setopt($curl_token,CURLOPT_RETURNTRANSFER,1); $json_response=curl_exec($curl_token) or die("Cannot exec url request"); curl_close($curl_token); $failsafe++; $foo=json_decode($json_response,true); //print_r($foo); sleep(60); if(isset($foo["status"]) && $foo["status"] == "completed" ) { $success=true; } } if($failsafe == 300) { echo "Failsafe time reached - TIMEOUT"; exit; } #echo "Success url: ".$foo["url"]; $zipped_content=file_get_contents($foo["url"]); file_put_contents("/tmp/malware_report.zip",$zipped_content); $filename_unzipped_report=exec("unzip -d /tmp/ -o /tmp/malware_report.zip | grep \"inflating:\" | cut -d\":\" -f\"2\" | tr -d [:space:]"); if(!is_readable($filename_unzipped_report)) { echo "Cannot read $filename_unzipped_report"; exit; } $contents_file=file_get_contents($filename_unzipped_report); $file_handle=fopen($filename_unzipped_report,"r") or die("cannot read report"); $results=array(); while(($line=fgetcsv($file_handle,1000,","))!==FALSE) { array_push($results,$line); } unlink($filename_unzipped_report); if(count($results)>1) { for($i=1 ; $i= $past_timestamp ) { print_r($results[$i]); #"DeviceName" ,"DetectionCount", "UPN" , "MalwareName", "MalwareCategory", "InitialDetectionDateTime", "ExecutionState" echo "0=> DeviceName , 1=> DetectionCount , 2=> UPN des MDM Deployment Benutzers, 3=>MalwareName , 4=>MalwareCategory, 5=> InitialDetectionTime , 6=> ExecutionState\n-------------------------------------------\n"; } } } exit; ?> ====== reportUpdateStates.php ====== * Analog zu **reportRiskUsers.php** * **Update 2022-04-13** - Microsoft hat etwas an der API geändert - Aktuell Fehlermeldung: Array ( [error] => Array ( [code] => BadRequest [message] => Resource not found for the segment 'deviceUpdateStates ..... * Ich möchte einen Report erhalten der mir zeigt wie viele Intune Devices die letztmöglichen Funktions/Qualitäts Updates erhalten haben, um zu sehen ob der Update Ring greift * Es ist wirklich sehr schön die Quality Version Strings in der Form von zB: "10.0.19043.2006" zu bekommen - das Release Date bzw. der Bezug zum Erscheinungsdatum wär auch wünschenswert - leider gibt es offenbar keine einfache Möglichkeit diese Information zu erhalten - daher wird sie über wikipedia bezogen und ggf. geparsed wenn möglich ['proxy'=>'IP_PROXY:PORT_PROXY']]); $curl_token= curl_init(); //Azure AD Administration: Tenant properties / Tenant ID: determine TENANT ID // // Details: https://docs.microsoft.com/en-us/graph/auth-v2-service curl_setopt($curl_token,CURLOPT_URL, "https://login.microsoftonline.com/TENANT_ID/oauth2/v2.0/token"); curl_setopt($curl_token,CURLOPT_HEADER,0); curl_setopt($curl_token,CURLOPT_POST,1); curl_setopt($curl_token,CURLOPT_POSTFIELDS,"client_id=CLIENT_ID&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret=CLIENT_SHARED_SECRET&grant_type=client_credentials"); curl_setopt($curl_token,CURLOPT_RETURNTRANSFER,1); $json_response=curl_exec($curl_token) or die("Cannot exec url request"); curl_close($curl_token); $access_array=json_decode($json_response,true) or die("Cannot decode json"); //print_r($access_array); if(!isset($access_array["access_token"])) { fwrite(STDERR,"Cannot receive access_token"); die("Cannot receive access_token"); } $curl_token= curl_init(); #2022-11-10 cc: Nice this way i get tendant wide security alerts that have occured .. another project :) #curl_setopt($curl_token,CURLOPT_URL,"https://graph.microsoft.com/beta/security/alerts_v2"); #2022-11-10 cc: This way i get all the configuration for all devices in json style objects with ID's - i need Update configuration ID foo #curl_setopt($curl_token,CURLOPT_URL,"https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations"); /* [6] => stdClass Object ( [@odata.type] => #microsoft.graph.windowsUpdateForBusinessConfiguration [id] => DEVICE_CONFIGURATION_ID [lastModifiedDateTime] => 2022-11-09T08:38:57.0592898Z [roleScopeTagIds] => Array ( [0] => 0 ) [supportsScopeTags] => 1 [deviceManagementApplicabilityRuleOsEdition] => [deviceManagementApplicabilityRuleOsVersion] => [deviceManagementApplicabilityRuleDeviceMode] => [createdDateTime] => 2020-12-21T10:13:02.1935774Z [description] => Windows Update-Richtlinie [displayName] => Windows Update-Richtlinie [version] => 10 [deliveryOptimizationMode] => httpWithPeeringNat [prereleaseFeatures] => notAllowed [automaticUpdateMode] => autoInstallAndRebootAtMaintenanceTime [microsoftUpdateServiceAllowed] => 1 [driversExcluded] => [qualityUpdatesDeferralPeriodInDays] => 0 [featureUpdatesDeferralPeriodInDays] => 0 [qualityUpdatesPaused] => [featureUpdatesPaused] => [qualityUpdatesPauseExpiryDateTime] => 0001-01-01T00:00:00Z [featureUpdatesPauseExpiryDateTime] => 0001-01-01T00:00:00Z [businessReadyUpdatesOnly] => businessReadyOnly [skipChecksBeforeRestart] => 1 [updateWeeks] => [qualityUpdatesPauseStartDate] => [featureUpdatesPauseStartDate] => [featureUpdatesRollbackWindowInDays] => 30 [qualityUpdatesWillBeRolledBack] => [featureUpdatesWillBeRolledBack] => [qualityUpdatesRollbackStartDateTime] => 0001-01-01T00:00:00Z [featureUpdatesRollbackStartDateTime] => 0001-01-01T00:00:00Z [engagedRestartDeadlineInDays] => [engagedRestartSnoozeScheduleInDays] => [engagedRestartTransitionScheduleInDays] => [deadlineForFeatureUpdatesInDays] => [deadlineForQualityUpdatesInDays] => [deadlineGracePeriodInDays] => [postponeRebootUntilAfterDeadline] => [autoRestartNotificationDismissal] => notConfigured [scheduleRestartWarningInHours] => [scheduleImminentRestartWarningInMinutes] => 15 [userPauseAccess] => disabled [userWindowsUpdateScanAccess] => disabled [updateNotificationLevel] => restartWarningsOnly [allowWindows11Upgrade] => [installationSchedule] => stdClass Object ( [@odata.type] => #microsoft.graph.windowsUpdateActiveHoursInstall [activeHoursStart] => 08:00:00.0000000 [activeHoursEnd] => 17:00:00.0000000 ) ) ) ) */ /* Request contains the Configuration ID of the defined Update Ring */ curl_setopt($curl_token,CURLOPT_URL,"https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations/DEVICE_CONFIGURATION_ID/microsoft.graph.windowsUpdateForBusinessConfiguration/deviceUpdateStates"); curl_setopt($curl_token,CURLOPT_HEADER,0); curl_setopt($curl_token,CURLOPT_POST,0); curl_setopt($curl_token,CURLOPT_HTTPHEADER,array("Authorization: Bearer ".$access_array["access_token"])); curl_setopt($curl_token,CURLOPT_RETURNTRANSFER,1); $json_response=curl_exec($curl_token) or die("Cannot exec url request"); curl_close($curl_token); //print_r(json_decode($json_response,true)); $update_array=json_decode($json_response,true); if(!$update_array) { fwrite(STDERR,"Cannot decode json"); die("Cannot decode json"); } $update_array=$update_array["value"]; $quality_updates=array(); fwrite(STDOUT,"Number of Update Ring Devices the ms oracle sees: ".count($update_array)."\n"); $featureNotLatest=0; $updateStateNotOk=0; fwrite(STDOUT,"------------------------"."\n"); for($i=0; $i ID [deviceId] => ID [userId] => ID [deviceDisplayName] => FOOHOO [userPrincipalName] => FOOHOO@SCHOOL [status] => upToDate [qualityUpdateVersion] => 10.0.19043.2006 [featureUpdateVersion] => Latest [lastScanDateTime] => 2022-11-03T17:34:03Z [lastSyncDateTime] => 2022-11-10T02:28:53.6236504Z ) * */ /* Array ( [0] => Array ( [versionId] => 10.0.22000.1219[58] [releaseInfo] => Release Preview Channel and public release:November 8, 2022 ) ) */ function searchWindowsVersion($url,$version) { $html=file_get_contents($url); if(!$html) { return false; } #2022-11-14 cc: Thanks https://www.tutorialspoint.com/php/php_dom_parser_example.htm# /*** a new dom object ***/ $dom = new domDocument; /*** load the html into the object ***/ @$dom->loadHTML($html); /*** discard white space ***/ $dom->preserveWhiteSpace = false; /*** the table by its tag name ***/ $tables = $dom->getElementsByTagName('table'); $results=array(); for($i=0 ; $i< $tables->length ; $i++) { /*** get all rows from the table ***/ $rows = $tables->item($i)->getElementsByTagName('tr'); /*** loop over the table rows ***/ foreach ($rows as $row) { /*** get each column by tag name ***/ $cols = $row->getElementsByTagName('td'); if(isset($cols->item(0)->nodeValue) ) { if(stripos($cols->item(0)->nodeValue,$version)!==false) { $result=array(); $result["versionId"]=@$cols->item(0)->nodeValue; #2022-11-14 cc: Decide if you want KBINFO or not - it's not consistent in the Wikipedia pages #$result["releaseInfo"]=@$cols->item(1)->nodeValue." ".@$cols->item(2)->nodeValue; $result["releaseInfo"]=@$cols->item(2)->nodeValue; array_push($results,$result); } } } } return $results; } ?> ===== Azure App Registrierung ===== * Erforderliche Permissions ermitteln - https://learn.microsoft.com/en-us/graph/api/intune-shared-windowsupdatestate-get?view=graph-rest-beta {{:know-how:4-update-states-permissions-to-app.png?400|}} ====== reportLegacyNotebooks.php ====== * Analog zu **reportRiskUsers.php** * Finde alle Notebooks zu denen es keine User mehr gibt d.h. User die den Standort verlassen haben "UserPrincipalName",1=>"proxyAddresses")); $data = ldap_get_entries($ds, $sr); //print_r($data); //exit; if($data["count"]===0) { echo "FAIL - Device: ".$intuneDevices[$k]["deviceName"]." / ManagedName: ".$intuneDevices[$k]["managedDeviceName"]." has no user Account anymore: ".$intuneDevices[$k]["userPrincipalName"]."\n"; $errUser++; } else { $okUser++; } ldap_close($ds); } echo "Summary:\n"; echo "All notebook objects found: ".$countAll."\n"; echo "All notebook objects ok: ".$okUser."\n"; echo "Consistency integrity: "; printf("%.2f \n",(($okUser/$countAll)*100)); echo "Errors Notebook/User count: ".$errUser."\n"; echo "OU's that i looked for :\n"; print_r($dn); echo "\n"; function getIntuneDevices() { $curl_token= curl_init(); //Azure AD Administration: Tenant properties / Tenant ID: 123-123-123 // // Details: https://docs.microsoft.com/en-us/graph/auth-v2-service curl_setopt($curl_token,CURLOPT_URL, "https://login.microsoftonline.com/123-123-123/oauth2/v2.0/token"); curl_setopt($curl_token,CURLOPT_HEADER,0); curl_setopt($curl_token,CURLOPT_POST,1); curl_setopt($curl_token,CURLOPT_POSTFIELDS,"client_id=123-123-123&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret=SHARED_SECRET_CREDENTIALS&grant_type=client_credentials"); curl_setopt($curl_token,CURLOPT_RETURNTRANSFER,1); $json_response=curl_exec($curl_token) or die("Cannot exec url request"); curl_close($curl_token); $access_array=json_decode($json_response,true) or die("Cannot decode json"); //print_r($access_array); if(!isset($access_array["access_token"])) { die("Cannot receive access_token"); } $curl_token= curl_init(); // https://docs.microsoft.com/en-us/graph/api/intune-devices-manageddevice-list?view=graph-rest-1.0 // curl_setopt($curl_token,CURLOPT_URL, "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices"); curl_setopt($curl_token,CURLOPT_HEADER,0); curl_setopt($curl_token,CURLOPT_POST,0); curl_setopt($curl_token,CURLOPT_HTTPHEADER,array("Authorization: Bearer ".$access_array["access_token"])); curl_setopt($curl_token,CURLOPT_RETURNTRANSFER,1); $json_response=curl_exec($curl_token) or die("Cannot exec url request"); curl_close($curl_token); //print_r($json_response); $intune_array=json_decode($json_response,true) or die("Cannot decode json"); $intune_array=$intune_array["value"]; return $intune_array; } ?> * **Update** Viel einfachere Variante - laut **Beobachtung des Systemverhaltens** - die UPNs dürfen offenbar nicht **null** sein deswegen wird ein 33 stelliger Hashwert als Prefix dem ursprünglichen Benutzer angefügt /ohne LDAP Verbindung zum lokalen AD ... if(preg_match("/^[a-z,0-9]{33}/i",$intuneDevices[$k]["userPrincipalName"])===1) { echo "FAIL - Device: ".$intuneDevices[$k]["deviceName"]." / ManagedName: ".$intuneDevices[$k]["managedDeviceName"]." has no user Account anymore: ".$intuneDevices[$k]["userPrincipalName"]."\n"; $errUser++; } else { $okUser++; } ... ====== reportMissingNotebooksOwnerBased.php ====== * Analog zu **reportMissingNotebooks.php** nur um die Schüler der 3. und 4. Klasse ergänzt * **Achtung** - Da die API bei 500 Devices deckelt muss ab 500 eine andere Lösung gefunden werden / Ermittle alle betroffenen User über LDAP im AD und ermittle für jeden einzelnen User die Zugehörigkeit zu einem registrierten Gerät * **Update** - es ist doch möglich mehr als 500 Devices zu erhalten mit pagination kann zum nächsten **Link** geblättert werden - danke an Herrn Christoph Pachler "OU_PATH_ALL_PUPILS"); $classesRegex="/^(1|2|3|4).*$/"; $search="(objectClass=user)"; $errUser=0; $countAll=0; $okUser=0; echo "All Users that haven't enrolled a device: "."\n"; for ($j=0; $j"UserPrincipalName",1=>"distinguishedName",2=>"department",3=>"description")); $data = ldap_get_entries($ds, $sr); // $countAll+=$data["count"]; for ($i=0; $i<$data["count"]; $i++) { //echo ($data[$i]["distinguishedname"][0])."\n"; //echo ($data[$i]["userprincipalname"][0])."\n"; //echo ($data[$i]["department"][0])."\n"; $distinguishedName=strtolower($data[$i]["distinguishedname"][0]); $userPrincipalName=strtolower($data[$i]["userprincipalname"][0]); $department=strtolower(@$data[$i]["department"][0]); $regMatch=preg_match($classesRegex,$department); if($regMatch !== 0) { if(!isset($data[$i]["department"][0])) { echo "FAIL - User: ".$distinguishedName." has no Department"."\n"; $errUser++; } $countAll++; //Debugging is phun //echo $distinguishedName."\n"; //echo $department."\n"; $notFound=true; $intuneDevices=getIntuneDevices($userPrincipalName); #Don't hammer microsofts api sleep(rand(3,15)); for ($k=0; $k Personal [deviceVersion] => 2 [displayName] => LAPTOP [domainName] => [enrollmentProfileName] => [enrollmentType] => UserEnrollment [externalSourceName] => [isCompliant] => 1 [isManaged] => 1 [isRooted] => [managementType] => MDM [manufacturer] => LENOVO */ if($intuneDevices[$k]["enrollmentType"]=="UserEnrollment" && $intuneDevices[$k]["manufacturer"]=="LENOVO" &&$intuneDevices[$k]["deviceOwnership"]== "Personal" ) { $notFound=false; } } if($notFound) { echo "FAIL - User: ".$distinguishedName." has no enrolled device"."\n"; $errUser++; } else { $okUser++; } // Device Details: print_r($intuneDevices[--$k]); } } // close connection ldap_close($ds); } echo "Summary:\n"; echo "All user objects found: ".$countAll."\n"; echo "All user objects ok: ".$okUser."\n"; echo "Consistency integrity: "; printf("%.2f \n",(($okUser/$countAll)*100)); echo "Errors User count: ".$errUser."\n"; echo "Regex Classroom check: ".$classesRegex."\n"; echo "OU's that i looked for :\n"; print_r($dn); echo "\n"; function getIntuneDevices($userUPN) { $curl_token= curl_init(); //Azure AD Administration: Tenant properties / Tenant ID: 123-123-123-123 // // Details: https://docs.microsoft.com/en-us/graph/auth-v2-service curl_setopt($curl_token,CURLOPT_URL, "https://login.microsoftonline.com/123-123-123-123/oauth2/v2.0/token"); curl_setopt($curl_token,CURLOPT_HEADER,0); curl_setopt($curl_token,CURLOPT_POST,1); curl_setopt($curl_token,CURLOPT_POSTFIELDS,"client_id=CLIENT_ID_APP&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret=SHARED_SECRET&grant_type=client_credentials"); curl_setopt($curl_token,CURLOPT_RETURNTRANSFER,1); $json_response=curl_exec($curl_token) or die("Cannot exec url request"); curl_close($curl_token); $access_array=json_decode($json_response,true) or die("Cannot decode json"); //print_r($access_array); if(!isset($access_array["access_token"])) { die("Cannot receive access_token"); } $curl_token= curl_init(); curl_setopt($curl_token,CURLOPT_URL, "https://graph.microsoft.com/v1.0/users/".$userUPN."/ownedDevices"); curl_setopt($curl_token,CURLOPT_HEADER,0); curl_setopt($curl_token,CURLOPT_POST,0); curl_setopt($curl_token,CURLOPT_HTTPHEADER,array("Authorization: Bearer ".$access_array["access_token"])); curl_setopt($curl_token,CURLOPT_RETURNTRANSFER,1); $json_response=curl_exec($curl_token) or die("Cannot exec url request"); curl_close($curl_token); //print_r($json_response); $intune_array=json_decode($json_response,true) or die("Cannot decode json"); $intune_array=$intune_array["value"]; return $intune_array; } ?> ====== reportMissingNotebooks.php ====== * Analog zu **reportRiskUsers.php** * Finde alle Schüler der 1. und 2. Klasse die kein Notebook enrolled haben / zB: als Cron Job * Im LDAP Attribut **Department** befindet sich die Klassenbzeichnung zB: 2E * **Achtung** Graph API deckelt bei 500 Devices d.h. ab 500 Notebooks muss eine andere Lösung gefunden werden * **Update** Es ist doch möglich mehr als 500 Devices zu erhalten - es muss in den Results geblättert werden über den nächsten **Link** -> ** if(isset($intune_array["@odata.nextLink"])) ** , Vielen Dank an Herrn Christoph Pachler "OU_PATH_ALL_PUPILS"); $classesRegex="/^(1|2).*$/"; $search="(objectClass=user)"; $errUser=0; $countAll=0; $okUser=0; $intuneDevices=getIntuneDevices(); if(!is_array($intuneDevices)) { die("Cannot read intuneDevices"); } for ($j=0; $j"UserPrincipalName",1=>"distinguishedName",2=>"department",3=>"description")); $data = ldap_get_entries($ds, $sr); for ($i=0; $i<$data["count"]; $i++) { //debugging is phun //echo ($data[$i]["distinguishedname"][0])."\n"; //echo ($data[$i]["userprincipalname"][0])."\n"; //echo ($data[$i]["department"][0])."\n"; $distinguishedName=strtolower($data[$i]["distinguishedname"][0]); $userPrincipalName=strtolower($data[$i]["userprincipalname"][0]); $department=strtolower(@$data[$i]["department"][0]); $regMatch=preg_match($classesRegex,$department); if($regMatch !== 0) { if(!isset($data[$i]["department"][0])) { echo "FAIL - User: ".$distinguishedName." has no Department"."\n"; $errUser++; } $countAll++; //Debugging is phun //echo $distinguishedName."\n"; //echo $department."\n"; $notFound=true; for ($j=0; $j ====== reportIntuneDevices.php ====== * Analog zu **reportRiskUsers.php** * Auszug aus dem relevanten Code für https://docs.microsoft.com/en-us/graph/api/intune-devices-manageddevice-list?view=graph-rest-1.0 * **Update** bei mehr als 500 Geräten muss geblättert werden **nextLink** * Es sollen alle im Intune registrierten Geräte gezogen werden ... ... Bearer Access Token organisieren wie bei reportRiskUsers.php ... ... $devicesLink="https://graph.microsoft.com/v1.0/deviceManagement/managedDevices"; $intune_all=array(); while(strlen($devicesLink)) { $curl_token= curl_init(); // https://docs.microsoft.com/en-us/graph/api/intune-devices-manageddevice-list?view=graph-rest-1.0 // curl_setopt($curl_token,CURLOPT_URL, $devicesLink); curl_setopt($curl_token,CURLOPT_HEADER,0); curl_setopt($curl_token,CURLOPT_POST,0); curl_setopt($curl_token,CURLOPT_HTTPHEADER,array("Authorization: Bearer ".$access_array["access_token"])); curl_setopt($curl_token,CURLOPT_RETURNTRANSFER,1); $json_response=curl_exec($curl_token) or die("Cannot exec url request"); curl_close($curl_token); //print_r($json_response); $intune_array=json_decode($json_response,true) or die("Cannot decode json"); if(!isset($intune_array["@odata.nextLink"])) { $devicesLink=""; } else { $devicesLink=$intune_array["@odata.nextLink"]; } $intune_array=$intune_array["value"]; $intune_all=array_merge($intune_all,$intune_array); } return $intune_all; } /* [0] => Array ( [id] => id [userId] => id [deviceName] => DESKTOP-HXND [managedDeviceOwnerType] => personal [enrolledDateTime] => 2021-06-28T09:13:53Z [lastSyncDateTime] => 2021-07-01T05:23:27Z [operatingSystem] => Windows [complianceState] => compliant [jailBroken] => Unknown [managementAgent] => mdm [osVersion] => 10.0.14393.0 [easActivated] => 1 [easDeviceId] => id [easActivationDateTime] => 0001-01-01T00:00:00Z [azureADRegistered] => 1 [deviceEnrollmentType] => userEnrollment [activationLockBypassCode] => [emailAddress] => max.mustermann@mail [azureADDeviceId] => id [deviceRegistrationState] => registered [deviceCategoryDisplayName] => Unknown [isSupervised] => [exchangeLastSuccessfulSyncDateTime] => 0001-01-01T00:00:00Z [exchangeAccessState] => none [exchangeAccessStateReason] => none [remoteAssistanceSessionUrl] => [remoteAssistanceSessionErrorDetails] => [isEncrypted] => [userPrincipalName] => UPN [model] => VirtualBox [manufacturer] => innotek GmbH [imei] => [complianceGracePeriodExpirationDateTime] => 2021-06-30T07:05:43Z [serialNumber] => 0 [phoneNumber] => [androidSecurityPatchLevel] => [userDisplayName] => Name User [configurationManagerClientEnabledFeatures] => [wiFiMacAddress] => [deviceHealthAttestationState] => [subscriberCarrier] => [meid] => [totalStorageSpaceInBytes] => 53160706048 [freeStorageSpaceInBytes] => 38004588544 [managedDeviceName] => funky name [partnerReportedThreatState] => unknown [iccid] => [udid] => [notes] => [ethernetMacAddress] => [physicalMemoryInBytes] => 0 [deviceActionResults] => Array ( ) ) */ ?> ====== reportRiskUsers.php ====== * Um **regelmäßige** **automatisierte** Risk User Reports zu bekommen braucht es eine **Premium P2** Azure/AAD Lizenz * Mit **P1** Lizenz gibts die Reports über Browser: https://portal.azure.com/#blade/Microsoft_AAD_IAM/SecurityMenuBlade/RiskyUsers * Das Skript soll sich **automatisiert** über die Graph API **alle Risk Infos** der letzten 24 Stunden holen und die betroffenen User ausgeben * Es ist dennoch möglich zuzugreifen über die Microsoft Graph API / Es muss eine **App** im Azure erstellt werden und die Werte im PHP Skript entsprechend angepasst / Als täglicher Cron Job auf einem **Linux** Server im Einsatz - wobei stdout per Mail versand wird an administrativen Mail Account :) * Beispielskript um Risk Detection automatisiert nutzen zu können / https://docs.microsoft.com/de-at/graph/api/riskdetection-list **reportRiskUsers.php** = $threshold_past ) { echo "-----------------------------"; echo "\nUser: ".$riskEvent["userPrincipalName"]; echo "\nRisk Type: ".$riskEvent["riskType"]; echo "\nRisk Level: ".$riskEvent["riskLevel"]; echo "\nActivity: ".$riskEvent["activity"]; echo "\nSource: ".$riskEvent["source"]; echo "\nActivity Date: ".date("c",$activityTimestamp); echo "\nLocation: ".$riskEvent["location"]["countryOrRegion"]."/".$riskEvent["location"]["state"]; echo "\nPlease visit: https://portal.azure.com/#blade/Microsoft_AAD_IAM/SecurityMenuBlade/RiskDetections"; echo "\n-----------------------------\n"; } } /* [15] => Array ( [id] => foo [requestId] => foo [correlationId] => foo [riskType] => unlikelyTravel [riskEventType] => unlikelyTravel [riskState] => atRisk [riskLevel] => hidden [riskDetail] => hidden [source] => IdentityProtection [detectionTimingType] => offline [activity] => signin [tokenIssuerType] => AzureAD [ipAddress] => ip [activityDateTime] => date [detectedDateTime] => date [lastUpdatedDateTime] => date [userId] => foo [userDisplayName] => name [userPrincipalName] => foo@mail [additionalInfo] => [json_foo] [location] => Array ( [city] => Astoria [state] => New York [countryOrRegion] => US [geoCoordinates] => Array ( [latitude] => 0 [longitude] => 0 ) ) ) */ ?> ===== Azure App Registrierung ===== * Damit die Graph API zB: mit Shared Secret benutzt werden kann * Tenant ID / Mandanten ID ermitteln (https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/Overview) {{:know-how:0_app_portal_aure_com.png?400|}} \\ * App Registrations d.h. damit eine neue "App" hinzugefügt werden kann {{:know-how:1_app_registrations.png?400|}} * App Bezeichnung **RiskDetections** um alle **risky** Users zu ermitteln {{:know-how:2_app_risk_detections.png?400|}} * **Permissions** ermitteln die gebraucht werden und der App hinzufügen / siehe Microsoft Dokumentation zur jeweiligen API {{:know-how:3_app_permission_graph_api.png?400|}} * Manche müssen noch **granted** d.h. erlaubt werden {{:know-how:4_app_grant_permission.png?400|}} \\ {{:know-how:5_app_granted_permission.png?400|}} * Shared Secret für App erstellen lassen / Nach dem **Hinzufügen** kann **value** des neuen Eintrags per copy und paste genommen werden {{:know-how:6_app_shared_secret.png?400|}} ====== Powershell Skripte ====== ===== check_last_updates.ps1 ===== * Kerberos Authentifizierung analog zu unterem Beispiel * Wann wurde zuletzt erfolgreich nach Updates gesucht oder erfolgreich Updates installiert - ist der Threshold größer als 35 Tage d.h. ist es länger als 35 Tage her möchte ich eine Notifikation erhalten #Thanks: https://github.com/Futur-Tech/futur-tech-zabbix-windows-update $threshold=35 try { $lastSuccessSearch= ((New-Object -com "Microsoft.Update.AutoUpdate").Results.LastSearchSuccessDate) $lastSuccessInstallation =((New-Object -com "Microsoft.Update.AutoUpdate").Results.LastInstallationSuccessDate) $today =Date $daysPassedSearch=($today - $lastSuccessSearch ).Days $daysPassedInstallation= ($today - $lastSuccessInstallation).Days if( ($daysPassedSearch -gt $threshold) -or ($daysPassedInstallation -gt $threshold) ) { $message= "ATTENTION: Last successfull search was $daysPassedSearch ($lastSuccessSearch) days ago , Last successfull installation of updates: $daysPassedInstallation ($lastSuccessInstallation) days" write-host $message #don't hammer the web support service with too much concurrent requests Start-Sleep -seconds (Get-Random -Minimum 1 -Maximum 5 ) $postParams = @{room=$env:computername;submit='1';description=$message;action='3'} Invoke-WebRequest -Uri https://support.schule.intern/support.php -Method POST -Body $postParams -UseDefaultCredentials } } catch { write-host "ERROR - cannot get values related to last updates " } ===== check_Updates_Notification_GPO_Startup.ps1 ===== * Unter https://support.schule.intern wird per Kerberos auf Apache2 Ebene authentifiziert und das support.php Skript übernimmt die weitere Verarbeitung d.h. implicit Authentication - bei Computer GPO als "Rechner$" * Welche Qualitätsupdates wurden noch nicht installiert und sind ausständig ? Achtung hier gibt es auch eine Variante bei der die optionalen Updates ebenfalls aufscheinen könne (Type 1) # Thank you: https://gist.github.com/Grimthorr/44727ea8cf5d3df11cf7 try { $UpdateSession = New-Object -ComObject Microsoft.Update.Session $UpdateSearcher = $UpdateSession.CreateupdateSearcher() $Updates = @($UpdateSearcher.Search("IsHidden=0 and IsInstalled=0").Updates) $Updates= $Updates | Where-Object Type -eq 1 #2024-01-22 cc: Exclude Microcode Update Intel (KB4589208) and Defender Signature Updates $Updates= $Updates | Where-Object Title -NotLike "*Microsoft Defender Antivirus*" $Updates= $Updates | Where-object Title -NotLike "*(KB4589208)" $message = $Updates | Select Title | Out-String -Width 250 if ($message.Length ) { write-host "Updates available !" #don't hammer the web support service with too much concurrent requests Start-Sleep -seconds (Get-Random -Minimum 1 -Maximum 5 ) $postParams = @{room=$env:computername;submit='1';description=$message;action='3'} Invoke-WebRequest -Uri https://support.schule.intern/support.php -Method POST -Body $postParams -UseDefaultCredentials } } catch { write-host "An Error occured" } ===== checkAPC-UPS.ps1 ===== * APC Management Card über SNMP (v1) checken und System ggf. herunterfahren + E-Mail Verständigung * Offizielle Software von APC - Power Chute bedingt einsetzbar / nicht erkennbar ob Kommunikation zwischen PowerChute und USV funktioniert FIXME * FIXME Testen der Thresholds und Werte + Timeouts FIXME #Achtung - Force TLS1.2 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 / Install-Module SNMP # Konfiguration der APC Management-Karte $apcIPAddress = "IP" # Die IP-Adresse der APC Management-Karte $snmpCommunity = "Community" # Die SNMP-Community der APC Management-Karte $snmpVersion = 1 # SNMP-Version (1 oder 2) # Schwellenwerte für die USV $batteryThreshold = 25 $remainingTimeThreshold = 5 $timeout= 10 # E-Mail-Konfiguration $mailServerIP = "IP_Mailserver" # Die IP-Adresse des E-Mail-Servers (ohne Authentifizierung) $mailFrom = "server@mail." # Die Absender-E-Mail-Adresse $mailTo = "monitoring@mail" # Die Empfänger-E-Mail-Adresse $mailSubject = "USV-Warnung: Herunterfahren von maschine xy" # Der Betreff der E-Mail # USV-Status, verbleibende Leistung und verbleibende Zeit abrufen / On Battery seems to be 3 $statusOID = "1.3.6.1.4.1.318.1.1.1.4.1.1.0" # OID für den USV-Status #2023-12-13 cc: Thanks https://www.opsview.com/resources/monitoring/blog/apc-ups-monitoring-useful-oids / runtime remaining divisor 6000 for minutes $batteryCapacityOID = "1.3.6.1.4.1.318.1.1.1.2.2.1.0" # OID für die verbleibende Batterieleistung $remainingTimeOID = "1.3.6.1.4.1.318.1.1.1.2.2.3.0" # OID für die verbleibende Zeit try { #2023-12-13 cc: Important !!! Convert to INT [int]$status = (Get-SnmpData -IP $apcIPAddress -OID $statusOID -Community $snmpCommunity -Version $snmpVersion -TimeOut $timeout).Data [float]$batteryCapacity = (Get-SnmpData -IP $apcIPAddress -OID $batteryCapacityOID -Community $snmpCommunity -Version $snmpVersion -TimeOut $timeout).Data $remainingTime = (Get-SnmpData -IP $apcIPAddress -OID $remainingTimeOID -Community $snmpCommunity -Version $snmpVersion -TimeOut $timeout).Data [float]$remainingTime = $remainingTime.Substring(0,$remainingTime.IndexOf(" ")) / 6000 # parse the strange format e.g. 36000 (06:00) -> 6 minutes Write-host "Remaining time: $remainingTime" Write-host "Battery: $batteryCapacity" Write-host "Status: $status" if ( $status -eq 3 -and $batteryCapacity -lt $batteryThreshold -and $remainingTime -lt $remainingTimeThreshold ) { $message = "Die USV läuft auf Batterie, die verbleibende Leistung ist unter $batteryThreshold%, und es verbleiben weniger als $remainingTimeThreshold Minuten. Der Computer wird heruntergefahren." # E-Mail senden Send-MailMessage -From $mailFrom -To $mailTo -Subject $mailSubject -Body $message -SmtpServer $mailServerIP Write-Host "E-Mail wurde gesendet: $message" # Herunterfahren des Computers Write-Host "Der Computer wird heruntergefahren." Stop-Computer -Force } else { Write-Host "Die USV befindet sich nicht auf Batterie, die verbleibende Leistung oder Zeit ist ausreichend. Keine Aktion erforderlich." } exit 0 } catch { Write-Host "Probleme beim Ermitteln der Daten" exit 1 } ===== Get-licenseKey.ps1 ===== * FIXME Testen über Intune * Sollte der Windows Key im BIOS gespeichert sein schreibe ihn lokal in eine Datei und mach diese Datei ausschließlich für Benutzer , die Mitglied der Gruppe der Administratoren und für den User SYSTEM zugänglich $CHECK_PATH="C:\Windows_Product_Key.txt" if( -not (Test-Path($CHECK_PATH))) { $productKey=(Get-WmiObject -query 'select * from SoftwareLicensingService').OA3xOriginalProductKey if( -not ($productKey -le 0) ) { echo "Windows Product Key: $productKey" > $CHECK_PATH # Define the new access rule for the Administrators group and SYSTEM user $adminRule = New-Object System.Security.AccessControl.FileSystemAccessRule("Administratoren", "FullControl", "Allow") $systemRule = New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM", "FullControl", "Allow") $aclProtected= Get-Acl -Path $CHECK_PATH $aclProtected.SetAccessRule($adminRule) $aclProtected.SetAccessRule($systemRule); $aclProtected.setAccessRuleProtection($true,$false) Set-Acl -Path $CHECK_PATH -AclObject $aclProtected echo "Successfully saved Windows Key to : $CHECK_PATH" } else { echo "Key could not be retrieved" exit 2 } } else { echo "Key has already been written to: $CHECK_PATH" } exit 0 ===== Get-BitlockerRecoveryKeys.ps1 ===== * Es sollen insofern Bitlocker auf einem Laufwerk aktiviert wurde für alle Laufwerke die Recovery Keys lokal abgelegt werden / Die lokal abgelegte Datei soll ausschließlich für Benutzer die Mitglied der Gruppe der Administratoren ist und für den User SYSTEM zugänglich gemacht werden (Wordpad als Administrator ausführen) / Falls bereits die Datei abgelegt wurde soll keine erneute Überprüfung durchgeführt werden / In erster Linie für das Systemlaufwerk  # Thanks: https://helpdesk.eoas.ubc.ca/kb/articles/use-powershell-to-get-the-bitlocker-recovery-key $CHECK_PATH="C:\Bitlocker_Recovery_Keys.txt" if ( -not (Test-Path $CHECK_PATH)) { $BitlockerVolumers = Get-BitLockerVolume # For each volume, get the RecoveryPassowrd and display it. $BitlockerVolumers | ForEach-Object { $MountPoint = $_.MountPoint $RecoveryKey = [string]($_.KeyProtector).RecoveryPassword if ($RecoveryKey.Length -gt 5) { echo "Laufwerk: $MountPoint " >> $CHECK_PATH echo "Recovery Key: $RecoveryKey " >> $CHECK_PATH echo "-------" >> $CHECK_PATH } } if(Test-Path $CHECK_PATH) { # Define the new access rule for the Administrators group and SYSTEM user $adminRule = New-Object System.Security.AccessControl.FileSystemAccessRule("Administratoren", "FullControl", "Allow") $systemRule = New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM", "FullControl", "Allow") $aclProtected= Get-Acl -Path $CHECK_PATH $aclProtected.SetAccessRule($adminRule) $aclProtected.SetAccessRule($systemRule); $aclProtected.setAccessRuleProtection($true,$false) Set-Acl -Path $CHECK_PATH -AclObject $aclProtected echo "Successfully saved bitlocker recovery keys to : $CHECK_PATH" } } else { echo "Nothing to do: $CHECK_PATH already present" } exit 0 ===== addLocalAdminAccount.ps1 ===== * Folgender Fall: * Das betroffene Gerät wurde von einem User über BYOD mit dem Cloud Account zum MDM Intune hinzugefügt zB: **christian.czeczil@schule.at** / Wenn der User die Schule oder Firma verlässt existiert sein Account nicht mehr und er wird sich mit dem Account nicht mehr einloggen können / Um diesem Fall entgegen zu wirken soll ein lokaler administrativer User Account: **.\christian.czeczil** mit zufälligem Passwort angelegt werden und dessen Zugangsdaten auf dem betroffenen Gerät abgelegt werden / Wenn der User sich das erste Mal mit den Zugangsdaten die nur für administrative Benutzer zugänglich sind (**zB: Wordpad als Administrator zum Öffnen** einloggt muss das Passwort geändert werden * **Achtung** Wenn über **intune** ausgerollt muss bei den Optionen noch **Skript in 64-Bit-PowerShell-Host ausführen** ausführen , da es Get-LocalUser nur auf 64Bit Systemen gibt und die intune Logik offenbar sonst im 32 Bit Kontext ausgeführt wird $PROTOCOL_PATH="C:\PATH_TO_USER_INFO.txt" $TENANT_FAILSAFE_CHECK="TENANT_ID_LONG_ID" $TENANT_DOMAIN_CHECK="TENANT_DOMAIN_SUFFIX" if ( -not (Test-Path $PROTOCOL_PATH)) { #Thanks: https://www.powershellgallery.com/packages/ModernWorkplaceClientCenter/0.1.3/Content/Functions%5CGet-DsRegStatus.ps1 #2022-04-19 cc: Not working in context of intune execution "Command not found" - is working when being executed as local administrator account #function Get-DsRegStatus { <# .Synopsis Returns the output of dsregcmd /status as a PSObject. .Description Returns the output of dsregcmd /status as a PSObject. All returned values are accessible by their property name. .Example # Displays a full output of dsregcmd / status. Get-DsRegStatus #> # $dsregcmd = dsregcmd /status # $o = New-Object -TypeName PSObject # $dsregcmd | Select-String -Pattern " *[A-z]+ : [A-z]+ *" | ForEach-Object { # Add-Member -InputObject $o -MemberType NoteProperty -Name (([String]$_).Trim() -split " : ")[0] -Value (([String]$_).Trim() -split " : ")[1] # } # return $o #} function getRandomPassword { Add-Type -AssemblyName 'System.Web' $minLength = 16 $maxLength = 20 $length = Get-Random -Minimum $minLength -Maximum $maxLength $nonAlphaChars = Get-Random -Minimum 1 -Maximum 3 $password = [System.Web.Security.Membership]::GeneratePassword($length,$nonAlphaChars) return $password } #Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\CloudDomainJoin\JoinInfo\ #Thanks : https://nerdymishka.com/articles/azure-ad-domain-join-registry-keys/ $subKey = Get-Item "HKLM:/SYSTEM/CurrentControlSet/Control/CloudDomainJoin/JoinInfo" $guids = $subKey.GetSubKeyNames() foreach($guid in $guids) { $guidSubKey = $subKey.OpenSubKey($guid) $userTenant = $guidSubKey.getValue("TenantId") $userEmail = $guidSubKey.GetValue("UserEmail") } if($userTenant -eq $TENANT_FAILSAFE_CHECK ) { $plainPass=getRandomPassword $randomSecurePassword=ConvertTo-SecureString -String $plainPass -AsPlainText -Force $azureUserName=$userEmail #Inconsistent results with $azureRegistrationStatus get-DsRegStatus -> User Identity not available anymore :( $localInfos=$azureUserName -split "@",2 $localUser=$localInfos[0] $mailDomain=$localInfos[1] if($mailDomain -eq $TENANT_DOMAIN_CHECK -and -not (Get-LocalUser -Name $localUser -ErrorAction SilentlyContinue)) { $newUserObject=New-LocalUser -AccountNeverExpires -Password $randomSecurePassword -Name $localUser if($?) { #2023-04-18 cc: Does not force the user to change the password FAIL #Set-LocalUser -InputObject $newuserObject -PasswordNeverExpires $false #Thanks: https://stackoverflow.com/questions/65295175/changepasswordatlogon-for-localuser $user = [ADSI]"WinNT://$env:ComputerName/$localUser,user" $user.PasswordExpired = 1 $user.SetInfo() Add-LocalGroupMember -Group "Administratoren" -Member $newUserObject if($?) { echo "Lokaler Benutzer Details: " > $PROTOCOL_PATH # Define the new access rule for the Administrators group and SYSTEM user $adminRule = New-Object System.Security.AccessControl.FileSystemAccessRule("Administratoren", "FullControl", "Allow") $systemRule = New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM", "FullControl", "Allow") $aclProtected= Get-Acl -Path $PROTOCOL_PATH $aclProtected.SetAccessRule($adminRule) $aclProtected.SetAccessRule($systemRule); $aclProtected.setAccessRuleProtection($true,$false) Set-Acl -Path $PROTOCOL_PATH -AclObject $aclProtected echo "User: .\$localUser" >> $PROTOCOL_PATH echo "Password: $plainPass" >> $PROTOCOL_PATH echo "Successfully created: .\$localUser - look at $PROTOCOL_PATH for details" } else { echo "Could not add user to the right group" } } else { echo "Could not add local User" } } else { echo "User already available on current system or preflight Domain check not ok" } } else { echo "This machine doesn't seem to be azure AD joined using the right Tenant" } } else { echo "It seems a local user has already been created" } exit 0 ===== checkHarddisks.ps1 ===== * Überprüfe ob es defekte Festplatten gibt * Wenn ja sende ein Mail an eine bestimmte E-Mail Adresse über SMTP Relay ohne Authentifizierung (Ip des Servers wird für Mailversand erlaubt) oder Krypto * **As simple as possible** um Notifikation durchzuführen * Auf dem betroffenen System läuft eine SSD als Systemplatte und 4 Legacy Platten im Storage Pool (Mirror) d.h. Windows **sollte** alle Festplatten (AHCI/SATA) nativ sehen - kein Hardwareraid * Kann als "Aufgabe" hinzugefügt werden um die Überprüfung täglich zu starten (Programm: powershell.exe Paramter: -ExecutionPolicy bypass C:\PFAD_ZUM_SKRIPT.ps1 ) $PSEmailServer= "IP_MAILSERVER_RELAY" $mailto= "DESTINATION_MAIL" $mailfrom= "SENDER_MAIL" #2022-03-10 cc: Thanks: http://woshub.com/check-hard-drive-health-smart-windows/ $diskFailureInfo=Get-PhysicalDisk | Where-Object {$_.HealthStatus -ne 'Healthy'} | Out-String $diskFailPredict=Get-WmiObject -namespace root\wmi -class MSStorageDriver_FailurePredictStatus | Where-Object {$_.PredictFailure -eq $true } | Out-String if( ($diskFailureInfo.Length -gt 0 ) -or ($diskFailPredict.Length -gt 0)) { $info=$diskFailureInfo+$diskFailPredict Send-MailMessage -to $mailto -Subject "$(hostname) Plattenprobleme - ueberpruefen ! " -Body $info -from $mailfrom -port 25 -SmtpServer $PSEmailServer write-host "Alert $info" exit 2 } exit 0 ===== checkLicense.ps1 ===== * Passwort aus dem BIOS auslesen und falls das Notebook noch nicht aktiviert wurde gleich aktivieren $foo=Get-CimInstance SoftwareLicensingProduct -Filter "Name like 'Windows%'" | where { $_.PartialProductKey } | select -expand LicenseStatus if ( -not ( $foo -eq "1" )) { $productKey=(Get-WmiObject -query 'select * from SoftwareLicensingService').OA3xOriginalProductKey if( -not ($productKey -le 0) ) { slmgr /ipk $productKey slmgr /ato } else { write-host "Cannot find productKey" } } else { write-host "Already activated" } ===== lastPasswordChange.ps1 ===== * Finde alle **aktiven** User deren letzte Passwortänderung länger als **$daysLastPasswordChange** zurück liegt $countAll=0 $daysLastPasswordChange=365 $timeThreshold=(Get-Date).Adddays(-($daysLastPasswordChange)) $userObjects = Get-ADUser -Filter {Enabled -eq $True -and pwdLastSet -lt $timeThreshold} -SearchBase 'LDAP_BASE_USERS' -Properties UserPrincipalName,LastLogonTimeStamp,whenChanged,whenCreated,lastLogon,objectGUID,pwdLastSet,mail Start-Transcript -path lastPasswordChangeUserTrack.txt Foreach ($user in $userObjects) { $lastLogon=[datetime]::FromFileTime($user.lastLogon) $lastPasswordUpdate=[datetime]::FromFileTime($user.pwdLastSet) write-host "$($user.UserPrincipalName) - lastPasswordUpdate: $lastPasswordUpdate last Logon: $lastLogon WhenChanged: $($user.whenChanged) WhenCreated: $($user.whenCreated) " $countAll+=1 } write-host "All Elements counted: $countAll" write-host "Days Last Password Update Threshold: $daysLastLogon Days" Stop-Transcript ===== lastPasswordChangeUserNotification.ps1 ===== * Finde alle **aktiven** User deren letzte Passwortänderung länger als **$daysLastPasswordChange** zurück liegt und schicke ihnen eine E-Mail , damit sie ihr Passwort ändern # Mail related $smtp_server="smtp.office365.com" $subject = "Passwort zu alt !" $mail_username="USERNAME_AUTH" $mail_password="PASSWORD_AUTH" $securePass = ConvertTo-SecureString $mail_password -AsPlainText -Force $mailAuth = New-Object System.Management.Automation.PSCredential ($mail_username, $securePass) # End mail related # AD Password Threshold related $countAll=0 $daysLastPasswordChange=365 $timeThreshold=(Get-Date).Adddays(-($daysLastPasswordChange)) # End mail Threshold related $userObjects = Get-ADUser -Filter { Enabled -eq $True -and pwdLastSet -lt $timeThreshold } -SearchBase 'LDAP_BASE_AD' -Properties UserPrincipalName,LastLogonTimeStamp,whenChanged,whenCreated,lastLogon,objectGUID,pwdLastSet,mail Start-Transcript -path lastPasswordChangeUserTrack.txt #Force TLS1.2 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Foreach ($user in $userObjects) { $lastLogon=[datetime]::FromFileTime($user.lastLogon) $lastPasswordUpdate=[datetime]::FromFileTime($user.pwdLastSet) write-host "$($user.UserPrincipalName) - lastPasswordUpdate: $lastPasswordUpdate last Logon: $lastLogon WhenChanged: $($user.whenChanged) WhenCreated: $($user.whenCreated) " if($user.mail) { $destination= $user.mail $mail_content="Bitte aendere deine Zugangsdaten im Schulnetzwerk sobald wie moeglich, deine letzte Passwortaenderung ist zu lange her: $lastPasswordUpdate" Send-MailMessage -smtpserver $smtp_server -Subject $subject -From $mail_username -Body $mail_content -Credential $mailAuth -to $destination -UseSsl if($?) { #No hammering the smtp server ! / We have no idea what microsofts skynet thinks about sending bulk mail Start-Sleep -seconds (Get-Random -Minimum 2 -Maximum 10 ) write-host "SUCCESSFULLLY notified $($user.userPrincipalName) using $($user.mail) " } else { write-host "ERROR could not notify $($user.userPrincipalName) using $($user.mail) " } } else { write-host "ERROR could not notify $($user.userPrincipalName) NO mail address listed" } $countAll+=1 } write-host "All Elements counted: $countAll" write-host "Days Last Password Update Threshold: $daysLastPasswordChange Days" Stop-Transcript ===== showWindowsKey.ps1 ===== * Wenn ers schafft Windows Key auslesen (bei der digitalen Geräteinitiative für die Kids - rechtsklick "Mit powershell ausführen" / Pic mit Handy machen Copy & Paste bei der Konsole Ausgabe des Keys Add-Type -AssemblyName System.Windows.Forms #wmic path softwarelicensingservice get OA3xOriginalProductKey $productKey=(Get-WmiObject -query 'select * from SoftwareLicensingService').OA3xOriginalProductKey if ( $productKey -le 0 ) { [System.Windows.Forms.MessageBox]::Show("Fehler: Konnte Key nicht auslesen","Windows 10 Produktschluessel",0 ,[System.Windows.Forms.MessageBoxIcon]::Error ) } else { [System.Windows.Forms.MessageBox]::Show("ProductKey: $productKey","Windows 10 Produktschluessel",0,[System.Windows.Forms.MessageBoxIcon]::Information) } Write-Host "ProductKey: $productKey" pause ===== checkIntuneDevices.ps1 powershell ===== * Wenn Geräte durch User enrolled wurden die es nicht mehr gibt können diese im Intune gelöscht werden * **FIXME** mehr checks ID <-> mail <-> UPN und zur Sicherheit noch ein "Mindestabstand" zum Enrollment date Connect-MSGraph -AdminConsent Connect-MsolService $allDevices=0 $deletedDevices=0 $errorDeletedDevices=0 foreach ($currentDevice in Get-IntuneManagedDevice ) { $magicCount=(Get-MsolUser -All -searchString $($currentDevice.emailAddress) | Measure-Object).Count if($magicCount -eq 0) { write-host "Current Device Name: $($currentDevice.deviceName)" write-host "Current Device Enrollment: $($currentDevice.enrolledDateTime)" write-host "Current Device LastSync Time: $($currentDevice.lastSyncDateTime)" write-host "Current Device Enrolled by: $($currentDevice.emailAddress) cannot be found" Remove-IntuneManagedDevice -managedDeviceId $($currentDevice.id) if($?) { write-host "SUCCESS: $($currentDevice.deviceName) has been deleted" $deletedDevices++ } else { write-host "FAIL: $($currentDevice.deviceName) couldn't be deleted" $errorDeletedDevices++ } write-host "-----------------------------------------" } $allDevices++ } write-host "---------------------" write-host "Number of devices checked: $allDevices" write-host "Number of devices successfully deleted from Intune: $deletedDevices" write-host "Number of devices unsuccessfully deleted from Intune: $errorDeletedDevices" write-host "---------------------" ===== AnalyzeHomeDirectories.ps1 powershell ===== * FIXME Beschreibung $rootDirectories=@("\\FILESERVER_DOMAINS\USER_SHARES_ROOT\*\*","\\FILESERVER_DOMAINS\USER_SHARES_ROOT\_Ausgeschieden\*") $upnSuffix="@DOMÄNE.INTERN" $dn="DN_LDAP" $adServer="AD_SERVER" Start-Transcript -path "AnalyzeHomeDirectories.txt" -append ForEach ($rootDirectory in $rootDirectories) { $directories=Get-ChildItem -Directory $rootDirectory ForEach ($directory in $directories) { #write-host "Directory: $directory" #$directory | Get-Member $upnDirectory=$directory.Name+$upnSuffix $adUser=Get-ADUser -server $adServer -searchbase $dn -Properties * -Filter "userPrincipalName -eq '$upnDirectory' -and department -eq 'EIGENSCHAFT' " if($adUser) { #$adUser | Get-Member #write-host "Ad User found" $adUserFound=1 if($adUser.homeDirectory -eq $directory.FullName) { $homeDirectoriesMatch=1 } else { $homeDirectoriesMatch=0 } } else { $adUserFound=0 } if($adUserFound -eq 1) { if($homeDirectoriesMatch -eq 1) { #write-host "OK - USER SEEMS FINE;Just Name: $($directory.Name);Constructed UPN Name: $upnDirectory;Physical Full Name: $($directory.FullName);AD HomeDirectory: $($adUser.homeDirectory)" } else { $directoryCount = Get-ChildItem $($directory.FullName) -Recurse -Depth 5 -file | Measure-Object if ( -not ($directoryCount.count -eq 0 )) { if( Test-Path $($adUser.homeDirectory) ) { $adDirectoryCount = Get-ChildItem $($adUser.homeDirectory) -Recurse -Depth 5 -file | Measure-Object } write-host "ERROR - USER NOT FINE;Just Name: $($directory.Name);Constructed UPN Name: $upnDirectory;Physical Full Name: $($directory.FullName);AD HomeDirectory: $($adUser.homeDirectory)" #if ( ( -not ( Test-Path $($adUser.homeDirectory) ) ) -or ($adDirectoryCount.count -eq 0) ) robocopy $($directory.FullName) $($adUser.homeDirectory) /S /E /DCOPY:DA /COPY:DATS /SECFIX /R:2 /W:2 /XO /NP /LOG:C:\Scripts\CopyLog\$($directory.Name).log if ($? -eq 0) { #Remove-Item $($directory.FullName) } } } } else { #write-host "FAIL - NO AD USER; Just Name: $($directory.Name);Constructed UPN Name: $upnDirectory;Physical Full Name: $($directory.FullName);" } } } #write-host "Constructed UPN name: $upnDirectory" #write-host "Full Name: $($directory.FullName)" Stop-Transcript ===== repairHomeDirectories.ps1 powershell ===== * Home Verzeichnisse für User sind nicht vorhanden oder Rechte auf die Home Verzeichnisse passen nicht * Von cc geringfügig modifiziert ##################################################################### # AUTHOR : Victor Ashiedu # DATE : 01-10-2014 # WEB : iTechguides.com # BLOG : iTechguides.com/blog # COMMENT : This PowerShell script creates a home folder for all users in Active Directory # (Accessed only by the user) If this script was helpful to you, # please take time to rate it at: http://gallery.technet.microsoft.com/PowerShell-script-to-832e08ed ##################################################################### ############################VERY IMPORTANT:########################## #before you run this script enure that you read the ReadMe text file ###################################################################### #This script has the following functionalities:####################### #1 Creates a persoanl (home folder) for all AD users #2 Provides option to create users folders as DisplayName or sAMAccountname (Log on name) #3 Grants each users "Full Control" to his or her folder #4 Maps the users folder as drive 'H' (Configured via AD Users property, #5 Ensures that users canot access another user's folder ####################################################################### ####################################################################### #BEGIN SCRIPT #Define variable for a server to use with query. #This might be necessary if you operate in a Windows Server 2003 Domain # and have AD web services installed in a particular DC $ADServer = 'SERVER_AD' #Get Admin accountb credential #$GetAdminact = Get-Credential Import-Module ActiveDirectory #define search base - the OU where you want to # search for users to modify. you can define the #domain as your searchbase #add OU in the format OU=OU 1,Users OU,DC=domain,DC=com $searchbase = "SEARCHBASE_DN" #Search for AD users to modify #-Credential $GetAdminact #$ADUsers = Get-ADUser -server $ADServer -Filter * -searchbase $searchbase -Properties * $ADUsers = Get-ADUser -server $ADServer -searchbase $searchbase -Properties * -Filter * ForEach ($ADUser in $ADUsers) { #Happy Debugging #$ADUser -properties SamAccountName | Format-List #$ADUser | Select-Object -Property SamAccountName,homedirectory | Format-List [string]$pathHomeDirectory = $( $ADUser.homedirectory ) [string]$userPrincipalName= $($ADUser.userPrincipalName ) if ( -not ( Test-Path $pathHomeDirectory ) ) { write-host("--------"); write-host("Home Directory not found: "+$path); write-host("AccountName: "+$ADUser.samAccountName); #Create Missing directory $homeShare = New-Item -path $pathHomeDirectory -ItemType Directory -force -ea Stop Write-Host ("HomeDirectory created at {0}" -f $homeShare) } else { $homeShare=$pathHomeDirectory write-host ("Username: {0}" -f $userPrincipalName) } $acl = Get-Acl $homeShare $FileSystemRights = [System.Security.AccessControl.FileSystemRights]“Modify“ $AccessControlType = [System.Security.AccessControl.AccessControlType]::Allow $InheritanceFlags = [System.Security.AccessControl.InheritanceFlags]“ContainerInherit, ObjectInherit“ $PropagationFlags = [System.Security.AccessControl.PropagationFlags]“None“ $AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule ($ADUser.SID, $FileSystemRights, $InheritanceFlags, $PropagationFlags , $AccessControlType) $acl.AddAccessRule($AccessRule) Set-Acl -Path $homeShare -AclObject $acl -ea Stop write-host ("ACL's have been modified {0}" -f $homeShare) } #END SCRIPT ===== SimpleAssignLicenses.ps1 powershell ===== * Domäne zB: schule.at * Kompatibel mit **Virtualschool** Style des AD's / Auf Grundlagen des Lizenzzuweisungsskripts von Virtualschool nur **trivialer** * Sollte es noch genug A3 Lehrer Lizenzen geben und es sich um einen Lehrer handeln weise A3 Lehrer Lizenz zu * Sollte es nicht mehr genug A3 Lehrer Lizenzen geben und es sich um einen Lehrer handeln weise A3 Schüler Lizenz zu * Sollte es sich um keinen Lehrer handeln und noch genug A3 Schüler Lizenzen vorhanden sein weise A3 Schüler Lizenz zu Connect-MsolService Start-Transcript -path SimpleAssignLicenes.log $countEntries=0 $StudentA3License=(Get-MsolAccountSku | where {$_.AccountSkuId -like "*M365EDU_A3_STUUSEBNFT"}).AccountSkuId $TeacherA3License=(Get-MsolAccountSku | where {$_.AccountSkuId -like "*M365EDU_A3_FACULTY"}).AccountSkuId write-host "Student: $StudentA3License" write-host "Teacher: $TeacherA3License" if ( !$StudentA3License -Or ! $TeacherA3License ) { write-host "License Problems detected cannot assign the Right ones " exit } $TeacherLicenseCount=(Get-MsolAccountSku | Where-Object {$_.AccountSkuId -eq $TeacherA3License}).ActiveUnits - (Get-MsolAccountSku | Where-Object {$_.AccountSkuId -eq $TeacherA3License}).ConsumedUnits $StudentLicenseCount=(Get-MsolAccountSku | Where-Object {$_.AccountSkuId -eq $StudentA3License}).ActiveUnits - (Get-MsolAccountSku | Where-Object {$_.AccountSkuId -eq $StudentA3License}).ConsumedUnits write-host "Available Teacher Licenses: $TeacherLicenseCount" write-host "Available Student Licenses: $StudentLicenseCount" #debug licenses available #Get-MsolAccountSku if(!$TeacherLicenseCount -And !$StudentLicenseCount) { write-host "No Licenses Left !" exit } #-All foreach ( $currentExternalUser in ( Get-MsolUser -All -Synchronized | Where-Object { $_.UserPrincipalName -NotLike "*#EXT#@*" -and $_.UserPrincipalName -Like "*@schule.at" } )) { #debugging is phun #$currentExternalUser | Get-Member #$currentExternalUser #$currentExternalUser.licenses | Get-Member #write-host "Foo: $foo" #exit if ( $($currentExternalUser.Department) -eq "Lehrer" -and -not ( $($currentExternalUser.Licenses.AccountSkuID) -like '*M365EDU_A3*' ) -and $TeacherLicenseCount -gt 0 ) { if(!$currentExternalUser.isLicensed) { Set-MsolUser -UserPrincipalName $currentExternalUser.UserPrincipalName -UsageLocation "AT" Set-MsolUserLicense -UserPrincipalName $currentExternalUser.UserPrincipalName -AddLicenses $TeacherA3License } else { Set-MsolUserLicense -UserPrincipalName $currentExternalUser.UserPrincipalName -AddLicenses $TeacherA3License -RemoveLicenses $($currentExternalUser.Licenses.AccountSkuId) } if( $? ) { write-host "SUCCESSFULLY replaced TEACHER License on $($currentExternalUser.UserPrincipalName)" } else { write-host "ERROR could not replace TEACHER License on $($currentExternalUser.UserPrincipalName)" } $TeacherLicenseCount=(Get-MsolAccountSku | Where-Object {$_.AccountSkuId -eq $TeacherA3License}).ActiveUnits - (Get-MsolAccountSku | Where-Object {$_.AccountSkuId -eq $TeacherA3License}).ConsumedUnits } else { if( -not ( $($currentExternalUser.Licenses.AccountSkuId) -like '*M365EDU_A3_*') -and $StudentLicenseCount -gt 0) { if(!$currentExternalUser.isLicensed) { Set-MsolUser -UserPrincipalName $currentExternalUser.UserPrincipalName -UsageLocation "AT" Set-MsolUserLicense -UserPrincipalName $currentExternalUser.UserPrincipalName -AddLicenses $StudentA3License } else { Set-MsolUserLicense -UserPrincipalName $currentExternalUser.UserPrincipalName -AddLicenses $StudentA3License -RemoveLicenses $($currentExternalUser.Licenses.AccountSkuId) } if( $? ) { write-host "SUCCESSFULLY replaced PUPILS License on $($currentExternalUser.UserPrincipalName)" } else { write-host "ERROR could not replace PUPILS License on $($currentExternalUser.UserPrincipalName)" } $StudentLicenseCount=(Get-MsolAccountSku | Where-Object {$_.AccountSkuId -eq $StudentA3License}).ActiveUnits - (Get-MsolAccountSku | Where-Object {$_.AccountSkuId -eq $StudentA3License}).ConsumedUnits } else { write-host "NOT replacing License on $($currentExternalUser.UserPrincipalName)" } } $countEntries++; } write-host "Entries: $countEntries" write-host "Available Teacher Licenses: $TeacherLicenseCount" write-host "Available Student Licenses: $StudentLicenseCount" Stop-Transcript ===== repair_ext_outlook.ps1 powershell ===== * Durch eine Verkettung unglücklicher Umstände kam es zu folgender Situation * Addressobjekte die Teil von Gruppenverteilern sind (durch die #EXT#@ Einträge in der Cloud ersichtlich) bekamen Lizenzen zugewiesen * Durch die Lizenzzuweisung wurde das proxy smtp:mailadresse Attribut der Einträge entfernt - beim Versand an die Gruppenverteiler kann der MS Mechanismus zum Auflösen die Mail Adressen nicht mehr "finden" * Dieser Fehler wird erst ersichtlich sobald die Gruppenverteiler im Outlook expandiert werden und eine Übermittlungsbestätigung angefordert wird ( 500er Fehler der MS Mail Server .. proxyAddresses primary Mail attribute missing ) * Dieses Skript entfernt die Lizenz und weist den Einträgen wieder die Mailadresse zu $365Logon = Get-Credential $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $365Logon -Authentication Basic -AllowRedirection Connect-MsolService Import-PSSession $Session -AllowClobber Start-Transcript -path repair-ext-outlook-logging.txt -NoClobber $countEntries=0 foreach ( $currentExternalUser in ( Get-MailUser -ResultSize unlimited | Where-Object { $_.UserPrincipalName -like "*#EXT#@*" -and $_.RecipientTypeDetails -eq "GuestMailUser"} )) { $currentExternalUserLicense=Get-MsolUser -UserPrincipalName $currentExternalUser.UserPrincipalName if ( $currentExternalUser.UserPrincipalName ) { if( $currentExternalUserLicense.isLicensed ) { Set-MsolUserLicense -UserPrincipalName $currentExternalUser.UserPrincipalName -RemoveLicenses "SCHULE:STANDARDWOFFPACK_IW_STUDENT" if( $? ) { write-host "Successfully removed License on $($currentExternalUser.UserPrincipalName)" } else { write-host "ERROR could not remove License on $($currentExternalUser.UserPrincipalName)" } } Set-Mailuser -Identity $currentExternalUser.UserPrincipalName -EmailAddresses $currentExternalUser.ExternalEmailAddress if( $? ) { write-host "Successfully set Email: $($currentExternalUser.ExternalEmailAddress) on $($currentExternalUser.UserPrincipalName)" } else { write-host "ERROR could not set Email Address on: $($currentExternalUser.UserPrincipalName)" } $countEntries++; } } write-host "Entries: $countEntries" Stop-Transcript Remove-PSSession $Session ===== fix-wds-workstations.ps1 powershell ===== * WDS und DHCP laufen auf selben Server * Um die Zuordnung von MAC Adresse der Maschine <-> zu Deployment AD Name zu fixieren param( [Parameter(Mandatory=$true)] [string]$searchCriteria ) $domainSuffix=".local-domain.local" foreach ($macAddress in Get-DhcpServerv4Scope | Get-DhcpServerv4Lease -AllLeases | Where-Object {$_.hostname -like $searchCriteria } ) { if ( $macAddress.hostname -like "*$domainSuffix" ) { $hostname=$macAddress.hostname.split(".")[0] echo "Setting WDS parameter : $($macAddress.clientid);$hostname" Set-WdsClient -DeviceName $hostname -DeviceId $macAddress.clientid } else { echo "Not a domain joined computer: $($macAddress.clientId);$($macAddress.hostname))" } } ===== cleanGroupsOffice365.ps1 powershell ===== * Getestet auf Windows 10 LTSC 2019 FIXME * **Achtung** zum löschen aller Gruppen die nicht durch AD Gruppenzugehörigkeit erstellt wurden (bei einer **Virtualschool** Installation * Mit dem letzten auskommentierten Eintrag ist es auch möglich alle Objekte aus dem Papierkorb zu löschen $adminUPN="admin@domain" Connect-MsolService Connect-AzureAD $countGroups=0 echo "OwnerName;;OwnerDepartment;;DisplayName;;CommonName;;E-Mail Address;;Description" > "Delete-Groups.csv" foreach ( $currentGroup in ( Get-MsolGroup -All | Where-Object { -not $_.GroupType -eq 'MailEnabledSecurity' } )) { $objectId=$currentGroup.objectId $objectOwner=Get-AzureADGroupOwner -ObjectId $objectId write-host "Remove: OwnerName: $($objectOwner.UserPrincipalName) ,OwnerDepartment: $($objectOwner.Department), DisplayName: $($currentGroup.DisplayName) , CommonName: $($currentGroup.CommonName) , E-Mail Address: $($currentGroup.EmailAddress) , Description: $($currentGroup.Description)" echo "$($objectOwner.UserPrincipalName);;$($objectOwner.Department);;$($currentGroup.DisplayName);;$($currentGroup.CommonName);;$($currentGroup.EmailAddress);;$($currentGroup.Description)" >> "Delete-Groups.csv" Remove-MsolGroup -ObjectId $currentGroup.objectId -Force $countGroups++; } write-host "Count all matching Groups: $countGroups" #Get-AzureADMSDeletedGroup | Remove-AzureADMSDeletedDirectoryObject ===== removeRemoved-office365.ps1 powershell ===== * Gelöschte Cloud Benutzer **endgültig** löschen (vor Ablauf der 30 Tages Frist) * **Achtung** Getestet mit Windows 10 LTSC 2019 * Windows 2012r2 erkennt den **-RemoveFromRecycleBin** - nach mehreren Stunden des erfolglosen Versuchs das Modul zu aktualisieren wurde es auf Windows 10 durchgeführt $adminUPN="admin@DOMAIN" $userCredential = Get-Credential -UserName $adminUPN -Message "Type the password" Connect-MsolService -Credential $userCredential Start-Transcript -path connect-office365-logging.txt -NoClobber foreach ( $currentUser in Get-MsolUser -ReturnDeletedUsers -All ) { $currentPrincipal = $currentUser.UserPrincipalName write-host "Soll User mit der UPN: $currentPrincipal gelöscht werden?" Remove-MsolUser -UserPrincipalName $currentUser.UserPrincipalName -RemoveFromRecycleBin } Stop-Transcript ===== manCreatePupils.ps1 powershell ===== * Quick and Dirty anlegen von AD User Accounts + Sync in die Cloud (proxyAddresses) * **PATH_FILE** im Format vorname.nachname@domain;Passwort max.mustermann@domain;PASSWORD_ACCOUNT * **manCreatePupils.ps1** $delim=";" $lines=Get-Content -Path PATH_FILE $ouPath="TARGET_OU_DISTINGUISHED_PATH" Foreach ($singleMail in $lines) { $userPassword=$singleMail.split($delim)[1] $singleMail=$singleMail.split($delim)[0] if([string]::IsNullOrEmpty($UserPassword)) { $userPassword="4598j56778" } $securePass = ConvertTo-SecureString $userPassword -AsPlainText -Force $fullName=$singleMail.split("@")[0] $forename=$fullName.split(".")[0] $lastname=$fullName.split(".")[1] write-host "Bearbeite: $singleMail , Forename: $forename , Lastname: $lastname , Password: $userPassword" if ( "$forename.$lastname".length -lt 20 ) { New-ADUser -Name "$forename.$lastname" -SamAccountName "$forename.$lastname" -UserPrincipalName $singleMail -Path $ouPath -Enabled $true -AccountPassword $securePass -OtherAttributes @{'proxyAddresses'="SMTP:$singleMail"} -EmailAddress $singleMail } else { New-ADUser -Name "$forename.$lastname" -SamAccountName ("$forename.$lastname").substring(0,20) -UserPrincipalName $singleMail -Path $ouPath -Enabled $true -AccountPassword $securePass -OtherAttributes @{'proxyAddresses'="SMTP:$singleMail"} -EmailAddress $singleMail } if( -not ( $? ) ) { echo "FEHLER - E-mail: $singleMail Vorname: $forename Nachname: $lastname Password: $userPassword" | Out-File -FilePath PATH_DEBUG_FILE -Append echo "FEHLER - E-mail: $singleMail Vorname: $forename Nachname: $lastname Password: $userPassword" } else { echo "OK - E-mail: $singleMail Vorname: $forename Nachname: $lastname Password: $userPassword" | Out-File -FilePath PATH_DEBUG_FILE -Append echo "OK - E-mail: $singleMail Vorname: $forename Nachname: $lastname Password: $userPassword" } } ===== countUnusedUsers powershell ===== * **countUnusedUsers.ps1** $countAll=0 $daysLastLogon=180 $timeThreshold=(Get-Date).Adddays(-($daysLastLogon)) $userObjects = Get-ADUser -Filter {LastLogonTimeStamp -lt $timeThreshold} -SearchBase 'LDAP_BASE' -Properties UserPrincipalName,LastLogonTimeStamp,whenChanged,whenCreated,lastLogon,objectGUID Start-Transcript -path unusedUserTrack.txt Foreach ($user in $userObjects) { $lastLogon=[datetime]::FromFileTime($user.lastLogon) write-host "$($user.UserPrincipalName) - last Logon: $lastLogon WhenChanged: $($user.whenChanged) WhenCreated: $($user.whenCreated) " #Disable-ADAccount -Identity $($user.objectGUID) if($? ) { write-host "SUCCESSFULLLY disabled $($user.userPrincipalName) " } else { write-host "ERROR could not disable $($user.userPrincipalName) " } $countAll+=1 } write-host "All Elements counted: $countAll" write-host "Days Logon Threshold: $daysLastLogon Days" Stop-Transcript ===== countAndCleanUnusedComputers powershell ===== * **countAndCleanUnusedComputers.ps1** * https://blog.netwrix.com/2017/07/20/how-to-find-inactive-computers-in-active-directory-using-powershell/ * https://www.it-zeugs.de/fehlermeldung-beim-loeschen-eines-active-directory-users.html $countAll=0 $daysLastLogon=180 $timeThreshold=(Get-Date).Adddays(-($daysLastLogon)) $ComputerObjects = Get-ADComputer -Filter {LastLogonTimeStamp -lt $timeThreshold} -SearchBase 'LDAP_BASE' -Properties Name,LastLogonTimeStamp,whenChanged,whenCreated,lastLogon Start-Transcript -path unusedComputerTrack.txt -NoClobber Foreach ($computer in $ComputerObjects) { $lastLogon=[datetime]::FromFileTime($computer.lastLogon) write-host "$($computer.Name) - last Logon: $lastLogon WhenChanged: $($computer.whenChanged) WhenCreated: $($computer.whenCreated) " Remove-ADObject -Identity $computer -Confirm -Recursive $countAll+=1 } write-host "All Elements counted: $countAll" write-host "Days Logon Threshold: $daysLastLogon Days" Stop-Transcript ===== countComputers powershell ===== * **countComputers.ps1** * https://www.powershellbros.com/get-computer-objects-from-ous/ * https://stackoverflow.com/questions/36574283/powershell-count-function-not-working-as-expected * https://blog.netwrix.com/2017/07/20/how-to-find-inactive-computers-in-active-directory-using-powershell/ $OUs = (Get-ADOrganizationalUnit -Filter * -SearchBase 'LDAP_BASE' -SearchScope Subtree) $countAll=0 $daysLastLogon=180 $timeThreshold=(Get-Date).Adddays(-($daysLastLogon)) Foreach ($item in $OUs){ $ComputerObjects = Get-ADComputer -Filter {LastLogonTimeStamp -gt $timeThreshold} -SearchBase $item.DistinguishedName -SearchScope OneLevel If($ComputerObjects){ $magicCount=($ComputerObjects | Measure-Object).Count write-host "$($item.Name) - $magicCount" $countAll+=$magicCount } } write-host "All Elements counted: $countAll" write-host "Days Logon Threshold: $daysLastLogon Days" ===== cloudUserDetails powershell ===== * **cloudUserDetails.ps1** * **.\cloudUserdetails.ps1 -searchUser christian** * Um herauszufinden ob die Ankerung der lokalen AD User in die Microsoft Cloud korrekt durchgeführt wird - bei Synchronisierungsproblemen sehr hilfreich param( [string]$searchUser="mustermann" ) $adminUPN="admin@DOMAIN" $userCredential = Get-Credential -UserName $adminUPN -Message "Type the password" Connect-MsolService -Credential $userCredential $incorrectID=0 $correctID=0 $incorrectAD=0 foreach ( $currentUser in Get-MsolUser -All -Search $searchUser) { $principalNameCloud=$currentUser.UserPrincipalName $immutableIdCloud=$currentUser.ImmutableId $guidCloud=[GUID][system.convert]::FromBase64String($immutableIdCloud) $username=$principalNameCloud $currentADUser=Get-ADUser -Filter "(UserPrincipalName -eq '$username')" -SearchBase "LDAP_SEARCH_BASE" $currentADUserCount=(Get-ADUser -Filter "(UserPrincipalName -eq '$username')" -SearchBase "LDAP_SEARCH_BASE").count write-host "---------------------------------------------------------" write-host "Current Cloud User: $principalNameCloud" write-host "Current Cloud GUID: $guidCloud" if(-not ($currentADUserCount -gt 1) -and -not ($currentADUserCount -eq 0) ) { $immutableIdAdUser= [system.convert]::ToBase64String(([GUID]$currentADUser.objectGUID).ToByteArray()) if($immutableIdAdUser -eq $immutableIdCloud) { write-host "UPN: $principalNameCloud has correct ImmutableID" $correctID++; } else { write-host "UPN: $principalNameCloud has incorrect ImmutableID" $incorrectID++; } } else { $guidUser=Get-ADUser -Filter "(objectGuid -eq '$guidCloud')" -SearchBase "LDAP_SEARCH_BASE" write-host "UPN: $principalNameCloud has not been found in AD!!" write-host "BUT Matching Guid: $guidUser" $incorrectAD++; } write-host "------------------------------------------------" } ===== clean-groups powershell ===== * **ACHTUNG** Um Gruppen zu löschen die keine Mitglieder haben * **clean_groups.ps1** param( [string]$searchFilter="*" ) $ldapBase="DISTINGUISHED_NAME_LDAP_BASE_OU" foreach ($adGroup in Get-ADGroup -SearchBase $ldapBase -Filter $searchFilter) { $groupCount= (Get-AdgroupMember -Identity $adGroup -recursive).count if( $groupCount -eq 0 ) { remove-adgroup -Confirm $adGroup } } ===== restart-workstations powershell ===== * **restart-workstations.ps1** * zB: **.\restart-workstations.ps1 -searchCriteria *EDV* ** param( [string]$searchCriteria="*" ) $ldapBase="OU=Workstations,OU=Ressourcen,DC=schule,DC=intern" $i=0 foreach ($domainComputer in Get-ADComputer -LDAPFilter "(name=$searchCriteria)" -SearchBase $ldapBase ) { echo "Restarting Computer: $($domainComputer.dnsHostname)" Restart-Computer -Force -ComputerName $($domainComputer.dnsHostname) 2> $null $i++ } echo "Computer Count: $i" ===== shutdown-workstations powershell ===== * **shutdown-workstations.ps1** * zB: **.\shutdown-workstations.ps1 -SearchCriteria *EDV* ** param( [string]$searchCriteria="*" ) $ldapBase="OU=Workstations,OU=Ressourcen,DC=schule,DC=intern" $i=0 foreach ($domainComputer in Get-ADComputer -LDAPFilter "(name=$searchCriteria)" -SearchBase $ldapBase ) { echo "Stopping Computer: $($domainComputer.dnsHostname)" Stop-Computer -Force -ComputerName $($domainComputer.dnsHostname) 2> $null $i++ } echo "Computer Count: $i" ===== wake-on-lan dhcp leases powershell ===== * **wake-on-lan.ps1** * zB: ** .\wake-on-lan.ps1 -SearchCriteria *EDV101* ** param( [string]$searchCriteria="*" ) #wake on lan https://gallery.technet.microsoft.com/scriptcenter/Send-WOL-packet-using-0638be7b #Begin wake on lan code function Send-WOL { <# .SYNOPSIS Send a WOL packet to a broadcast address .PARAMETER mac The MAC address of the device that need to wake up .PARAMETER ip The IP address where the WOL packet will be sent to .EXAMPLE Send-WOL -mac 00:11:32:21:2D:11 -ip 192.168.8.255 #> [CmdletBinding()] param( [Parameter(Mandatory=$True,Position=1)] [string]$mac, [string]$ip="255.255.255.255", [int]$port=9 ) $broadcast = [Net.IPAddress]::Parse($ip) $mac=(($mac.replace(":","")).replace("-","")).replace(".","") $target=0,2,4,6,8,10 | % {[convert]::ToByte($mac.substring($_,2),16)} $packet = (,[byte]255 * 6) + ($target * 16) $UDPclient = new-Object System.Net.Sockets.UdpClient $UDPclient.Connect($broadcast,$port) [void]$UDPclient.Send($packet, 102) } # End wake on lan Code foreach ($macAddress in Get-DhcpServerv4Scope | Get-DhcpServerv4Lease | Where-Object {$_.hostname -like $searchCriteria } ) { echo "Sending wol to : $($macAddress.clientid);$($macAddress.hostname)" Send-WOL -mac $($macAddress.clientId) } ====== rdp server zertifikat austauschen ====== * Für die Domäne , in diesem Beispiel schule.intern wird ein **Wildcard Zertifikat** von einer für das System gültigen CA ausgestellt die auf allen Servern ausgerollt wurde, auf die per RDP zugegriffen wird ***.schule.intern** * Im Linux wird das CA Zertifikat zum System hinzugefügt (dpkg-reconfigure ca-certificates - siehe Linux) * rdesktop (1.9.0) und xfreerdp (2.0.0-dev5 (2693389a+debian)) überprüfen nun das SSL Zertifikat und melden KEINE Fehlermeldung wenn das Zertifikat korrekt unterschrieben wurde und der Hostname als FQDN für den Zugriff richtig gesetzt {{:know-how:0_rdp_cert_import.png?400|}} {{:know-how:1_rdp_cert_import.png?400|}} {{:know-how:2_rdp_cert_import.png?400|}} {{:know-how:3_rdp_cert_import.png?400|}} {{:know-how:4_rdp_cert_import.png?400|}} {{:know-how:5_rdp_cert_import.png?400|}} {{:know-how:6_rdp_cert_import.png?400|}} {{:know-how:7_rdp_cert_import.png?400|}} * Zuweisen des Zertifikats zum RDP Dienst über Fingerprint - ohne Spaces und **ACHTUNG** ohne non printable Charakters wenn Copy&Paste über GUI passiert * https://social.technet.microsoft.com/Forums/windows/en-US/1806a272-6442-4872-a8ba-e30b25507f27/replace-the-remote-desktop-certificate-correctly wmic /namespace:\\root\cimv2\TerminalServices PATH Win32_TSGeneralSetting Set SSLCertificateSHA1Hash="5d969239c9de854cc3af8c3b16deb1ab85b4fcc2" ====== adconnect ====== ===== adconnect - Seamless SSO aktivieren ===== * FIXME / Einrichtung GPOs und Applikation adconnect https://docs.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-sso-quick-start * FIXME Smart Links für Seamless SSO: https://www.deyda.net/index.php/de/2019/07/18/aktivierung-von-azure-ad-seamless-single-sign-on/#Beispiel_Adressen_fuer_domain_hint_login_hint * adconnect (.NET) ignoriert zum Teil die System Proxy Einstellungen (!) - siehe https://www.msxfaq.de/cloud/identity/aadconnect_und_httpproxy.htm * Achtung zusätzliches Firewalling: #2022-09-06 cc: SSO activate / adconnect \.registration.msappproxy.net \.msappproxy.net ===== adconnect - troubleshoot Password Hash Synchronization ===== * Sollte er am magischen MS Portal anzeigen , dass die DIR Sync funktioniert die Password Synchronisation jedoch nicht - Powershell als Admin Starten auf dem Sync Gerät und die PasswordSync Diagnostik anwerfen **Invoke-ADSyncDiagnostics -PasswordSync** PS C:\WINDOWS\system32> Invoke-ADSyncDiagnostics -PasswordSync ======================================================================== = = = Password Hash Synchronization General Diagnostics = = = ======================================================================== AAD Tenant - GymnasiumNeusiedl.onmicrosoft.com Password Hash Synchronization cloud configuration is enabled False AD Connector - foo.intern Password Hash Synchronization is enabled False Password Hash Synchronization is NOT running for AD Connector: foo.intern Would you like to RESTART password hash synchronization for AD Connector: foo.intern? [y/n]: y Restarting... Password Hash Sync Configuration for source "foo.intern" updated. Password Hash Sync Configuration for source "foo.intern" updated. Password Hash Synchronization is successfully restarted for AD Connector: foo.intern Directory Partitions: ===================== Directory Partition - foo.intern False False False Last successful attempt to synchronize passwords from this directory partition started at: 11/21/2022 10:36:00 AM UTC and ended at: 11/21/2022 10:36:05 AM UTC Only Use Preferred Domain Controllers: False Checking connectivity to the domain... Domain "foo.intern" is reachable Did you find Password Hash Sync General Diagnostics helpful? [y/n]: ===== adconnect - Synchronization Errors - DeletingCloudOnlyObjectNotAllowed ===== * Benutzer die vom lokalen AD synchronisiert wurden , wurden gelöscht und wieder hergestellt um sie als "CloudOnly" Benutzer zu administrieren / Er versucht weiterhin den User zu löschen stellt jedoch fest, dass es sich nun ob ein CloudOnly Objekt handelt - und löscht es daher nicht * Objekte die ausschließlich in der Cloud erstellt wurden besitzen keine "ImmutableId" / daher auf $null setzen und die Synchronization Error verschwinden * Danke: https://learn.microsoft.com/en-us/answers/questions/905372/deletingcloudonlyobjectnotallowed.html / https://learn.microsoft.com/en-us/answers/questions/611870/azure-ad-connect-sync-error-114-after-removing-ad.html Install-Module -Name MSOnline Connect-MsolService Set-MsolUser -UserPrincipalName UPN_USER -ImmutableId "$null" echo $? true ====== office 365 powershell ====== * Return Random Password String (https://adamtheautomator.com/powershell-random-password/) $minLength = 5 ## characters $maxLength = 10 ## characters $length = Get-Random -Minimum $minLength -Maximum $maxLength $nonAlphaChars = 5 $password = [System.Web.Security.Membership]::GeneratePassword($length, $nonAlphaChars) * Office365 Set Password Set-MsolUserPassword -UserPrincipalName "davidchew@consoso.com" -NewPassword "pa$$word" * Office365 gelöschte User restoren als "alter UPN-restore" $adminUPN="admin@domain" $userCredential = Get-Credential -UserName $adminUPN -Message "Type the password" Connect-MsolService -Credential $userCredential foreach ( $currentUser in Get-MsolUser -ReturnDeletedUsers -All ) { $principalNameOld=$currentUser.UserPrincipalName $principalNameNew=$principalNameOld.split("@")[0]+"-restore@domain" write-Host "Original Name: $principalNameOld , New Name: $principalNameNew" Restore-MSolUser -UserPrincipalName $principalNameOld -NewUserPrincipalName $principcalNameNew -AutoReconcileProxyConflicts } * Gelöschte Sharepoint Seiten anzeigen Import-Module -Name Microsoft.Online.SharePoint.PowerShell $adminUPN="admin@domain" $userCredential = Get-Credential -UserName $adminUPN -Message "Type the password." Connect-SPOService -Url https://ORGANISATION-admin.sharepoint.com -Credential $userCredential Get-SPODeletedSite -IncludePersonalSite * Bulks Restore von gelöschten Usern - mit Mail Notification ihres Passworts für den Restore Account #office 365 administration specific $adminUPN="admin@pdomain" $userCredential = Get-Credential -UserName $adminUPN -Message "Type the password" Connect-MsolService -Credential $userCredential if(!$?) { write-Host "Could not Connect to Office 365 Service" exit 2 } #Mailserver and useraccount that will be abused for notification of the users e.g. Microsoft smtp $smtpServer="smtp.office365.com" $mailUsername="E-MAIL-ADDRESS" $mailPassword="E-MAIL-PASSWORD" $securePass = ConvertTo-SecureString $mailPassword -AsPlainText -Force $mailAuth = New-Object System.Management.Automation.PSCredential ($mailUsername, $securePass) $successRestore="false" $successPassword="false" $successMail="false" $simplePassword="false" foreach ( $currentUser in Get-MsolUser -ReturnDeletedUsers -All -Search "SEARCH_PATTERN_NAME_TESTING" ) { #Get the old UserPrincipal Name that conains an e-mail $principalNameOld=$currentUser.UserPrincipalName #Construct the new UserPrincipal Name $principalNameNew=$principalNameOld.split("@")[0]+"-restore@domain" $mailSubject="Alter Account: "+$principalNameNew Restore-MSolUser -UserPrincipalName $principalNameOld -NewUserPrincipalName $principalNameNew -AutoReconcileProxyConflicts if($?) { $successRestore="true" #OK User could be restore with new Principal Name - Let's create a SIMPLE password for him $simplePassword = "AcD!"+(Get-Random -Minimum 1000000 -Maximum 9999999) Set-MsolUserPassword -UserPrincipalName $principalNameNew -NewPassword $simplePassword if($?) { $successPassword="true" $mailBody="Hallo, `r`n deine alten Daten wie Mail/OneDrive erreichst du folgendermaßen:`r`n Login https://login.microsoftonline.com `r`n Benutzername: "+$principalNameNew+"`r`n Passwort: "+$simplePassword+"`r`n LG Das IT Team" Send-MailMessage -smtpserver $smtpServer -Subject $mailSubject -From $mailUsername -Body $mailBody -Credential $mailAuth -to $principalNameOld -UseSsl if($?) { $successMail="true" } else { $successMail="false" } } else { $successPassword="false" } #Lets pause the process we don't know if we can send that many mails without being marked as Spam or something else Start-Sleep -seconds (Get-Random -Minimum 2 -Maximum 10 ) } else { $successRestore="false" } write-Output "$principalNameOld;$principalNameNew;$simplePassword;$successRestore;$successPassword;$successMail" | Tee-Object -Append -FilePath "C:\Scripts\restore.txt" } * Delete Deleted - für den Fall dass die User innerhalb der 30 Tage Frist gelöscht werden müssen Install-Module MSOnline $adminUPN="adminUPNt" $userCredential = Get-Credential -UserName $adminUPN -Message "Type the password" Connect-MsolService -Credential $userCredential foreach ( $currentUser in Get-MsolUser -ReturnDeletedUsers -All ) { $currentPrincipal = $currentUser.UserPrincipalName write-host "Remove Principal: $currentPrincipal" Remove-MsolUser -UserPrincipalName $currentUser.UserPrincipalName -RemoveFromRecycleBin -Force if ($?) { write-host "Successfully removed $currentPrincipal " } else { write-host "ERROR removing $currentPrincipal " } } ====== poor mans windows advanced threat protection - intune ====== * Getestet mit Windows 10 Pro (1909) / Windows 10 LTSC 2019 * Intune **vollverwaltet** und **teilverwaltete** Geräte * Über Intune wird über die **"Skripts"** Funktionalität ein Mechanismus deployed der analog zur Variante mit E-Mail / Kerberos Notifikationen eine Notifikation über einen Web Endpunkt triggered sobald ein Virus durch den Windows Defender gefunden wird ===== Server - Intune ===== * Bei **Geräte** - **Skripts** - Hier werden alle Skripte angezeigt: {{:know-how:0_skripts_overview.png?400|}} * Das bereits hochgeladene Skript wurde **ATP-Deploy** benannt - nach einiger Zeit (nach 2 Tagen wieder überprüft) erscheint eine Statistik mit "Gerätestatus" , "Benutzerstatus" {{:know-how:1_skripts_overview_monitor.png?400|}} * Das bereits hochgeladene Powershell Skript könnte nun wieder hochgeladen werden / **Achtung** in diesem Beispiel läuft es mit **SYSTEM** aka. **root** Berechtigungen / Das Powershell Skript wird nur für Mitglieder der Gruppe **ATP-Geräte** angewandt {{:know-how:2_skripts_properties.png?400|}} * In diesem Punkt könnte es nochmals hochgeladen oder geändert werden / **Achtung** nach dem Upload ist es nicht mehr möglich (ich habs noch nicht debugged) herauszufinden was eigentlich ausgeführt wird :) / Beim Hinzufügen handelt es sich um das gleiche User Interface / In meinem Fall möchte ich das Skript als **SYSTEM** ausführen auf **64 Bit Maschinen** / Bei Überprüfen lässt sich noch die Gruppe angeben für die das Skript Gültigkeit hat - **ATP-Geräte** / Bei erneutem Hochladen eines geändert Skripts wird das Powershell Skript nochmals ausgeführt / Sonst wird es laut MS Doku nur **einmal** ausgeführt / Skriptbeispiel: {{ :know-how:atp-deploy-system.ps1.zip |}} {{:know-how:3_skripts_properties_deployment.png?400|}} * Wie kommt es zur Zuweisung zur Gruppe der **ATP-Geräte** / über Umwege - die **Gerätekategorie** {{:know-how:4_skripts_devices_category.png?400|}} {{:know-how:6_skripts_devices_categories_names.png?400|}} * Die Sicherheitsgruppe **ATP-Geräte** enthält Devices denen die Gerätekategorie **ATP-Prototyping** zugewiesen wurde {{:know-how:5_skripts_groups_dynamic_membership.png?400|}} * Skripte für **HOSTNAME** Webserver d.h. wohin notified werden soll: {{ :know-how:intune_atp_server.zip |}} ===== Endgerät - Workstations ===== * Debugging auf dem Endgerät * Die **Intune Management Extension** muss auf dem Gerät **automatisch** installiert werden damit die Powershell Skripte ausgeführt werden * Überprüfung ob das Gerät im Intune registriert wurde {{:know-how:0_workstation_intune_info.png?400|}} * Informationen zur Registrierung / **Microsoft Intune Management Extension** muss nach einiger Zeit (Testraum Check 2 Tage) erscheinen {{:know-how:1_workstation_intune_management_extensions.png?400|}} * Synchronisierung kann auch **manuell** nochmals angeworfen werden / Laut MS Docs wird sie auch bei Neustart und erneutem Login angestoßen / Es war nicht ersichtlich wodurch die **Microsoft Intune Management Extension** getriggered wird {{:know-how:2_workstation_synchronize_manually.png?400|}} * Sobald installiert befinden sich einige Logfiles in diesem Verzeichnis **C:\ProgramData\Microsoft\IntuneManagementExtension\** {{:know-how:3_workstation_intunemanagement_extension_logfiles.png?400|}} ====== Microsoft 365 Defender - ATP ====== * Offenbar bekommen Bundesschulen aktuell der Anzahl der Lehrer A3 Lizenzen entsprechend für die ATP/MS 365 Defender Lizenzen * Geräte muss "geboarded" werden d.h. Logik muss auf dem jeweiligen Client installiert werden * **Keine** MSI Datei sondern good old fashioned magic *.cmd / Batch File für Deployment von Microsoft * **Anforderungen**: Ich möchte ein Notification Mail bekommen wenn zB: Viren gefunden werden mit Gerätename und Virenfund/Malware Fund Info * Grundsätzliche Schritte und erste Erfahrungen: * https://security.microsoft.com - Login - Geräte einbinden {{:know-how:0-ms365-defender-atp-einstellungen-onboarding.png?400|}} {{:know-how:0-ms365-defender-atp.png?400|}} {{:know-how:1-ms365-defender-atp-notify-mail.png?400|}} {{:know-how:2-ms365-defender-atp-notify-mail.png?400|}} {{:know-how:3-ms365-defender-atp-mail.png?400|}} {{:know-how:4-ms365-defender-atp-mail.png?400|}} * Manuelles Deployment der CMD Datei: **PsExec.exe \\rechner -c " \\UNC_PATH\WindowsDefenderATPLocalOnboardingScript.cmd" ** - vorher in CMD Datei das Heading mit der User Eingabe entfernen und die "pause" ====== poor mans windows advanced threat protection - lokal ====== * Getestet auf Windows LTSB 2016 64Bit / LTSC 2019 * Es soll bei Virus/Malware Fund durch Windows Defender eine Notifikation an eine zentrale Stelle erfolgen * Wenn das Event **"Malware gefunden"** (event ID 1116 siehe https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-defender-antivirus/troubleshoot-windows-defender-antivirus ) vom **"Windows Defender"** (https://docs.microsoft.com/en-us/powershell/module/defender/?view=win10-ps ) getriggered wird löst der Task Planer ein Powershell Skript aus - in dem Beispiel befinden sich 2 , eines um per Mail zu Notifizieren , das Andere um zB: einen POST HTTP Request abzusetzen * Task Definition und Scripts für **C:\Scripts\** , **Achtung** Berechtigungen bei E-Mail Versand für Standard- User entfernen {{ :know-how:poor-mans-windows-atp.zip |}} * **Deployment** könnte als Computer GPO - im Startup als batch Datei gesetzt werden zB: {{ :know-how:deploy_malware_trigger.bat.zip |}} * **Regelmäßiges Scannen** auf einem Server könnte zB: folgendermaßen gelöst werden , im folgenden Beispiel wird das Laufwerk G:\ gescannt -> speichern als .ps1 und in Task Planer aufnehmen zB: **wöchentlich** * **ScanStorage.ps1** Update-MpSignature Start-MpScan -ScanType CustomScan -ScanPath G:\ ====== poor mans harddisk notification check - lokal ====== * In Kombination mit Poor Mans Support System - https://doku.pannoniait.at/doku.php?id=know-how:linux#sso_-_apache_mit_kerberos_poor_mans_ticket_system * Aus aktuellem Anlass - da 200GB SSD Platten / NVMEs im Schulbereich zu klein sind / Wenn lokale Profile verwendet werden und zahlreiche User sich auf dem Gerät einloggen * Enthält ein Powershell Skript (C:\Scripts\*.ps1) , das beim Start (Aufgabe *.xml) ausgeführt wird / Durch das Batch file (*.bat) kann es als Computerrichtlinie deployed werden * Wenn die Geräte unter 16GB frei haben oder ein Festplattenproblem / Dateisystem Problem festgestellt wird , wird ein POST Request an das Support System getriggered, das eine Mail an den zuständigen Betreuer versendet * {{ :know-how:harddisk_notification.zip |}} * Beispiel Mail: {{:know-how:harddisk-troubles.png?400|}} ====== poor mans updates available check - lokal ====== * In Kombination mit Poor Mans Support System - https://doku.pannoniait.at/doku.php?id=know-how:linux#sso_-_apache_mit_kerberos_poor_mans_ticket_system * Aus aktuellem Anlass da bei manchen Endgeräten die Updates nicht installiert werden / WSUS wurde aufgrund zu vieler Fehler entfernt und ich möchte die Notifikationen per E-Mail pro Gerät erhalten ggf. wird ein Mail Filter eingerichtet * Deployment von Startup Skript über GPO ; {{ :know-how:updatesavailable.zip |}} * Beispiel Mail: {{:know-how:poor_mans_update_available_notification.png?400|}} ====== APC-USB-USV remote server shutdown ====== * Gesetzt folgendem Fall - eine APC USV hängt per USB an einem Server und es wird ein Zweiter hinzugefügt und an der USV angehängt / Für diese USV Reihe existiert jedoch keine Management Interface Karte , daher weiß der "remote" Server nicht wann die USV aktiv wird bei Stromausfall * Auf dem "Host" Server der per USB mit der USV verbunden ist werden in der Aufgabenplanung Tasks (batch Files) gestartet um den zweiten Server bei Bedarf herunterzufahren * Getestet auf Host Server **Windows 2012r2 Standard** und Remote Server **Windows 2016 Standard** * Konfiguration "Host" Server der mit USV verbunden ist * **Achtung** USV wird als "Akku" angezeigt - das Skript liest die aktuelle Akku Ladung raus, fällt das Ladeniveau unter einen bestimmten threshold zB: 30% wird ein event getriggered , das beim zweiten Job dazu führt dass das Shutdown Skript ausgeführt wird * XML Konfigurationen für die Tasks {{ :know-how:shutdown_server_on_low_battery.xml.gz |}} ,{{ :know-how:check_battery.xml.gz |}} * Batch Dateien für die Skripte: {{ :know-how:scripts.zip |}} , Check Battery stammt von https://superuser.com/questions/1162575/windows-event-id-for-battery-level-change - "the fixed one" * In {{ :know-how:scripts.zip |}} befindet sich auch eine **powershell** Variante zum Herunterfahren - hier müsste bei der zu startenden Applikation **powershell.exe** gewählt werden + Parametern könnte Ausführung zB: folgendermaßen sein ** powershell.exe -ExecutionPolicy Bypass c:\scripts_shutdown\shutdown-server.ps1 ** * Konfiguration "Remote Server" der durch Windows Boardmittel **shutdown** vom "Host" Server heruntergefahren wird * Lokalen Standard User anlegen: {{:know-how:00_local_shutdown_user.png?400|}} {{:know-how:11_local_shutdown_user_group.png?400|}} * Lokalen Standard User **Herunterfahren von Remote** erlauben * **gpedit.msc** {{:know-how:0_local_gpo_path.png?400|}} {{:know-how:1_force_shutdown_from_remote.png?400|}} * Netzwerkkonfiguration **Datei und Druckerfreigabe** damit psshutdown connecten kann {{:know-how:22_network_configuration.png?400|}} ====== Software RAID1 mit Windows Boardmitteln ====== * Getestet auf Windows 2012r2 mit Hp Microserver gen8 und 2 SSD Platten / MBR Boot * Ausgezeichnete Anleitung unter: https://www.windowspro.de/wolfgang-sommergut/plattenspiegelung-raid-1-einrichten-fuer-windows-8x-server-2012-r2 * Im Wesentlichen über die GUI: * Computerverwaltung * Datenträger auswählen -> konvertieren in Dynamischen * zB: Wenn Datenträger 0 gespiegelt werden soll auf Datenträger 1 * Datenträger 1 vollständig löschen alle Volumes falls vorhanden * Datenträger 0 rechtsklick auf Partition Spiegelung hinzufügen -> Datenträger1 auswählen * Sollte **"Die Synchronisation wird wiederholt"** - ohne Prozentanzeige stehen - klick in betroffene Spiegelung und einmal F5 drücken und er aktualisiert die Anzeige mit Prozentangabe ====== Boot Treiber auf AHCI stellen ====== * Getestet auf Windows 2012r2 / HP Microserver gen 8 B120I Software RAID * Umstellung von B120I RAID auf AHCI Modus * Nach der Umstellung im abgesichterten Modus starten & aus dem abgesicherten Modus neu booten und funktioniert :) * Quote von: https://hetmanrecovery.com/recovery_news/how-to-enable-ahci-mode-for-sata-in-the-bios-without-reinstalling-windows.htm Run Registry Editor. To do it, press Win + R and type in the command regedit. Go to the section HKEY_LOCAL_MACHINE\ SYSTEM\ CurrentControlSet\ Services\ iaStorV Regedit. Go to the section HKEY_LOCAL_MACHINE\ SYSTEM\ CurrentControlSet\ Services\ iaStorV Double-click on Start element and set its value to 0 (zero). Regedit. Double-click on Start element and set its value to 0 (zero). In the next section, HKEY_LOCAL_MACHINE\ SYSTEM\ CurrentControlSet\ Services\ iaStorAV\ StartOverride set the zero value for the element 0. Regedit. HKEY_LOCAL_MACHINE\ SYSTEM\ CurrentControlSet\ Services\ iaStorAV\ StartOverride set the zero value for the element 0 In the section HKEY_LOCAL_MACHINE\ SYSTEM\ CurrentControlSet\ Services\ storahci set the value to 0 (zero) for Start element. Regedit. HKEY_LOCAL_MACHINE\ SYSTEM\ CurrentControlSet\ Services\ storahci set the value to 0 (zero) for Start element. In the subsection, HKEY_LOCAL_MACHINE\ SYSTEM\ CurrentControlSet\ Services\ storahci\ StartOverride set the zero value for the element 0. In our case, there is nothing to see, but you will see it, if AHCI has not been enabled yet. Close Registry Editor. ====== Fileserver Deduplizierung ====== * Wenn ausreichend I/O und CPU Power vorhanden kann die Deduplizierung genutzt werden um Speicher zu gewinnen / **Achtung** Wenn das Dateisystem fehlerhaft wird oder einzelne Dateien beschädigt werden in Folge **alle** betroffenen beschädigt da die Deduplizierung die redundanten Daten nur **einmal** speichert - daher auch der Speichergewinn - you have been warned :) * In der Praxis konnte ich auf einem Fileserver mit >1.5 Mio Dateien von 800GB auf 2TB (!) Speicher gewinnen * Getestet auf einem Windows 2016 (hyper V Hostsystem mit 2CPUs u. RAID10 4TB SSDs / hyper v Gast / Generation 2 / 2 CPUs / dynamischen RAM bis zu 8GB) {{:know-how:0-dedup-install.png?400|}} {{:know-how:1-dedup-configure.png?400|}} {{:know-how:2-dedup-activate.png?400|}} {{:know-how:3-dedup-rate.png?400|}} ====== Fileserver Migration von Shares ====== * Achtung Share Permissions beachten (https://blogs.technet.microsoft.com/askds/2008/11/24/how-to-back-up-and-restore-ntfs-and-share-permissions/) Backup and Restore of Share Permissions To backup share permissions, export the Shares registry key. Open Regedit to the following location: HKLMSYSTEMCurrentControlSetServicesLanmanServerShares Right-click the Shares registry key and select Export. Give it a file name such as shareperms.reg. When you want to restore the permissions, double-click shareperms.reg to import it back into the registry. Use the Reg tool to backup the registry key from the command line: reg export HKLMSYSTEMCurrentControlSetServicesLanmanServerShares shareperms.reg If you need to restore it at some point, just run: reg import shareperms.reg Backup and Restore of NTFS Permissions Use this command to backup NTFS permissions: icacls d:data /save ntfsperms.txt /t /c The /T switch allows it to get subfolder permissions too. The /C switch allows it to continue even if errors are encountered (although errors will still be displayed). Use this command to restore them: icacls d: /restore ntfsperms.txt Note that in the command to save the permissions, I specified the target folder D:Data, but when I restored them, I specified just D: as the target. Icacls is a little funky like that, and here’s why. If you open the text file with the exported permissions (ntfsperms.txt in the above example), you’ll see that Icacls uses relative paths (in bold below). Underneath the relative paths are the permissions for the folders in Security Descriptor Definition Language (SDDL) format. data D:AI(A;ID;FA;;;BA)(A;OICIIOID;GA;;;BA)(A;ID;FA;;;SY)(A;OICIIOID;GA;;;SY)(A;OICIID;0x1200a9;;;BU)(A;ID;0x1301bf;;;AU)(A;OICIIOID;SDGXGWGR;;;AU) datafolder1 D:AI(A;ID;FA;;;BA)(A;OICIIOID;GA;;;BA)(A;ID;FA;;;SY)(A;OICIIOID;GA;;;SY)(A;OICIID;0x1200a9;;;BU)(A;ID;0x1301bf;;;AU)(A;OICIIOID;SDGXGWGR;;;AU) datafolder2 D:AI(A;ID;FA;;;BA)(A;OICIIOID;GA;;;BA)(A;ID;FA;;;SY)(A;OICIIOID;GA;;;SY)(A;OICIID;0x1200a9;;;BU)(A;ID;0x1301bf;;;AU)(A;OICIIOID;SDGXGWGR;;;AU) Had I specified D:Data in the command to restore the permissions, it would have failed looking for a D:DataData folder: D:>icacls d:data /restore perms.txt d:datadata: The system cannot find the file specified. Successfully processed 0 files; Failed processing 1 files You might think specifying D: as the target in the restore command may somehow mess up the permissions on other folders at that level, but as you can see from the ntfsperms.txt output file, it only has information about the Data folder and subfolders, so that is all it will change. – Craig Landis * Empfehlung nur NTFS Permissions verwenden dann reicht robocopy zum Kopieren aus und es müssen nur die entsprechenden Shares erstellt (**fsmgmt.msc**) werden mit Share Permission FULL für "Jeder" * d.h. **robocopy \\QUELLE\Share ZIELLAUFWERK:\Share /TEE /S /E /DCOPY:DA /COPY:DATS /SECFIX /PURGE /MIR /R:5 /W:30 /log:C:\TMP\Log-Kopieren.txt** Gestartet: Donnerstag, 17. Mai 2018 11:54:04 Quelle : \\QUELLE\Share Ziel : ZIELLAUFWERK:\Share Dateien : *.* Optionen: *.* /TEE /S /E /DCOPY:DA /COPY:DATS /SECFIX /PURGE /MIR /R:5 /W:30 ====== AD Datenbank Repair - Versuche ====== Microsoft : https://support.microsoft.com/de-at/help/258062. Datenbank ad repair https://www.tecchannel.de/a/active-directory-datenbank-pflegen-und-reparieren,435528,5 --- Datenbank repair https://www.tecchannel.de/a/active-directory-sichern-wiederherstellen-und-warten,2040204,6 Praxis für Windows Server 2012 und 2012 R2 Active Directory - sichern, wiederherstellen und warten Artikel empfehlen: Kommentare & Drucken: Autor: 08.04.2014Von Thomas Joos (Autor) Active-Directory-Datenbank reparieren Zuweilen kann es vorkommen, dass die Active-Directory-Datenbank nicht mehr funktioniert. Gehen Sie bei einem solchen Problem folgendermaßen vor: Starten Sie den Server im Verzeichnisdienstwiederherstellung-Modus, oder beenden Sie Active Directory mit net stop ntds. Öffnen Sie eine Befehlszeile und starten Ntdsutil.exe. Geben Sie anschließend den Befehl activate instance ntds ein. Geben Sie files ein, um zu file maintenance zu gelangen. Geben Sie integrity ein, um einen Integritätstest der Datenbank durchzuführen. Wenn dieser Test eine Fehlermeldung anzeigt, können Sie versuchen, die Datenbank in Ntdsutil.exe zu retten. Verlassen Sie mit quit die file maintenance, aber bleiben Sie in der Oberfläche von Ntdsutil.exe. Geben Sie den Befehl semantic database analysis ein. Geben Sie zunächst den Befehl verbose on ein, damit Sie detaillierte Informationen erhalten. Geben Sie als Nächstes den Befehl go fixup ein. ====== CSV - Bulk User Batch Import mit Passwort definiert für alle (create_user.bat) ====== * Analog zu **create_user_text_csv.bat** - nur Passwörter sind für alle gleich und definiert + SCRIPT Pfad wird angegeben + Passwort muss nach 1. Login geändert werden @echo off set pass=PASSWORD_ALLE_USER set scriptpath=SCRIPT.BAT set list_users=liste.txt set error_list=user-error.csv set success_list=user-success.csv echo accountUsername;gruppe;beschreibung> %error_list% echo accountUsername;gruppe;beschreibung> %success_list% for /f "tokens=1,2 delims=;" %%f in (%list_users%) DO ( net user %%f 1> nul 2>&1 if %ERRORLEVEL% EQU 2 ( net user %%f %pass% /add /active:yes /passwordchg:yes /scriptpath:%scriptpath% /Y /DOMAIN 1> nul 2>&1 if %ERRORLEVEL% EQU 2 ( echo Successfully created: %%f net group %%g 1> nul 2>&1 if %ERRORLEVEL% EQU 2 ( net group %%g /add /DOMAIN 1> nul 2>&1 ) net group %%g %%f /ADD /DOMAIN 1> nul 2>&1 if %ERRORLEVEL% EQU 2 ( echo Successfully added: %%f to group: %%g echo %%f;%%g;Complete Success >> %success_list% ) else ( echo FAIL: Couldn't add %%f to group %%g echo %%f;%%g;User created couldn't be added to group >> %error_list%) ) else ( echo FAIL: Couldn't add user %%f echo "%%f;%%g;User couldn't be added" >> %error_list% ) ) else ( echo FAIL: User: %%f already available manual intervention needed echo %%f;%%g;User already available >> %error_list% ) ) pause ====== CSV - Bulk Prüfungs User Batch import (create_user_test_csv.bat) ====== * Es existiert eine GPO die für User mit der Mitgliedschaft zu zB: pruefung aktiv wird * Achtung 2xMal ausführen - Vielleicht Environment beim 1. Mail Ausführung nicht korrekt / ERRORLEVEL ? * CSV Datei im gleichen verzeichnis - **user-liste-test.txt** mit Liste der zu erstellenden Benutzernamen und der Gruppenzugehörigkeit user01;pruefung user02;pruefung user03;pruefung * **create_user_test_csv.bat** @echo off set list_users=user-liste-test.txt set error_list=user-error.csv set success_list=user-success.csv echo accountUsername;gruppe;beschreibung > %error_list% echo accountUsername;gruppe;passwort;beschreibung > %success_list% for /f "tokens=1,2 delims=;" %%f in (%list_users%) DO ( net user %%f 1> nul 2>&1 if %ERRORLEVEL% EQU 2 ( setlocal EnableDelayedExpansion set /a pass="!RANDOM!+10000000+!RANDOM!*1000" net user %%f !pass! /add /active:yes /passwordchg:no /Y /DOMAIN 1> nul 2>&1 if %ERRORLEVEL% EQU 2 ( echo Successfully created: %%f net group %%g 1> nul 2>&1 if %ERRORLEVEL% EQU 2 ( net group %%g /add /DOMAIN 1> nul 2>&1 ) net group %%g %%f /ADD /DOMAIN 1> nul 2>&1 if %ERRORLEVEL% EQU 2 ( echo Successfully added: %%f to group: %%g echo %%f;%%g;!pass!;Complete Success >> %success_list% ) else ( echo FAIL: Couldn't add %%f to group %%g echo %%f;%%g;!pass!;User created couldn't be added to group >> %error_list%) ) else ( echo FAIL: Couldn't add user %%f echo "%%f;%%g;User couldn't be added" >> %error_list% ) ) else ( echo FAIL: User: %%f already available manual intervention needed echo %%f;%%g;User already available >> %error_list% ) ) pause * **user-error.csv** **user-success.csv** werden erstellt im gleichen Verzeichnis - in der success Datei befindet sich auch das "generierte" Passwort für die Prüfungsbenutzer * Die User selbst werden bei einem AD Server in der OU "USERS" abgelegt ====== Ordner kopieren (per GPO oder psexec) ====== * Beispielaufruf: **robocopy_copy.bat \\fileserver\Software-big\ C:\Software-big\ C:\copy_software_big.txt** * Kann auch als GPO (Computer Startup) genutzt werden / Parameter über Reiter "Parameter" hinzufügen * **Achtung** /mir spiegel alles vom Ursprung , die Parameter immer überprüfen!! * **robocopy_copy.bat** echo off set fromLocation=%1 set toLocation=%2 set toLogfile=%3 IF %1.==. GOTO Usage IF %2.==. GOTO Usage IF %3.==. GOTO Usage if exist "%toLogFile%" goto Ende if not exist "%toLocation%" mkdir %toLocation% robocopy /MIR /R:2 /W:2 %fromLocation% %toLocation% if %ERRORLEVEL% EQU 0 echo "finished_successfully" > %toLogfile% exit 0 :Usage echo "%0 fromLocation toLocation logFile echo --------------------------- echo Beispielaufruf: %0 \\file\Software\ C:\Software\ C:\copy_software.txt exit 2 :Ende exit 0 ====== NTFS Ownership ändern ====== * Getestet auf **Windows 2012r2 Standard** als **Domain Administrator** der eine User Ownership vergibt https://stackoverflow.com/questions/20673599/change-owner-and-permissions-on-folder#20676221 To make an addition to permissions and: icacls.exe d:\test /setowner domain\username To set ownership. Other options of interest from icacls /?: /T indicates that this operation is performed on all matching files/directories below the directories specified in the name. /C indicates that this operation will continue on all file errors. Error messages will still be displayed. ====== NTFS Volume verkleinern ====== * Gegeben: 1.5TB Volume das auf 500GB verkleinert werden soll und bereits seit Jahren existiert * **FAIL**: * Restore Punkte deaktivieren & löschen - hat nichts gebracht * SWAP Speicher Konfiguration ändern - auf manuell gestellt und auf dem Volume gibts keinen SWAP - hat nichts gebracht * Windows internes defrag zahlreiche Male ausgeführt - hat nichts gebracht - offenbar nicht verschiebbare Dateien die nicht identifizierbar sind * Möchte kein neues Volume per SCSI hinzufügen und alle Shares neu definieren müssen bzw. nicht genug Speicherplatz für Kopie verfügbar * Windows Ansatz zum verkleinern: * https://docs.microsoft.com/en-us/windows-server/storage/disk-management/shrink-a-basic-volume#addcon To shrink a basic volume using a command line Open a command prompt and type diskpart. At the DISKPART prompt, type list volume. Note the number of the simple volume you want to shrink. At the DISKPART prompt, type select volume . Selects the simple volume volumenumber you want to shrink. At the DISKPART prompt, type shrink [desired=] [minimum=]. Shrinks the selected volume to desiredsize in megabytes (MB) if possible, or to minimumsize if desiredsize is too large. * **LÖSUNG** * Server wurde heruntergefahren / Volume an virtuelle Win10 LTSB 2016 Maschine per SCSI angehängt * Partitionierungsprogramm , das Verkleinerung "gratis" anbietet: https://www.disk-partition.com/de/free-partition-manager.html - hat funktioniert ! ====== DHCP Server auslesen ohne powershell ====== * http://andrewmorgan.ie/2008/05/export-dhcp-reservations-with-mac-addresses/ Once i had the file in csv, i simply imported it into an excel sheet using spaces as the delimiter and hey presto a lovely little reservation report: Same rules as always, dont run it from a UNC path, copy it local to the DHCP server and run it there. netsh dhcp server dump >> reservationdump.txt find “Add reservedip” reservationdump.txt >> reservations.csv You can download the script as is here: * Aktuelle Leases für einen "Scope":# * https://serverfault.com/questions/378839/query-a-windows-dhcp-server-find-mac-from-hostname This script almost works as well. It currently lists extra clients. Some regex magic with the find command parameters could fix this. Save to to a .cmd file and specify your dhcppserver and a valid scope. for /f "skip=4 delims=: tokens=2" %%a in ('nslookup %1') do set IP=%%a netsh dhcp server \\ourdhcpsvr scope 192.168.1.0 show clients|findstr "%IP%" Output should look like this 172.16.19.78 - 255.255.248.0 - c6-33-5f-cb-a7-a5 -4/25/2017 8:26:07 AM -D ====== Computer Liste auslesen aus AD dsquery ====== * https://4sysops.com/archives/get-adcomputer-display-computers-in-ou-or-ad-group-with-powershell/ Say you want to find out which computers will be affected if you link a GPO to a certain OU. You could run the following dsquery command: dsquery computer "OU=IT,DC=contoso,DC=com" -o rdn 1 dsquery computer "OU=IT,DC=contoso,DC=com" -o rdn The result would be a list of computer names. If you omit the -o switch with the rdn value, you receive a list of Distinguished Names. ====== Windows generell Dateien löschen ====== * zB: in einem Verzeichnis mehr als 1Mio Dateien * Löschen über Explorer shift -> ENTF * Er schafft es nicht die korrekte Anzahl der Dateien zu berechnen und auch nicht die Dauer des Löschvorgangs * Löschen über cli: The best I've found is a two line batch file with a first pass to delete files and outputs to nul to avoid the overhead of writing to screen for every singe file. A second pass then cleans up the remaining directory structure: del /f/s/q foldername > nul rmdir /s/q foldername ====== Windows home-verzeichnisse erstellen ====== * Falls auf home verzeichnisse verwiesen wird die nicht existieren / mit diesem Skript können Sie unter angabe der entsprechenden OU / und Domain Servers angelegt werden ##################################################################### # AUTHOR : Victor Ashiedu # DATE : 01-10-2014 # WEB : iTechguides.com # BLOG : iTechguides.com/blog # COMMENT : This PowerShell script creates a home folder for all users in Active Directory # (Accessed only by the user) If this script was helpful to you, # please take time to rate it at: http://gallery.technet.microsoft.com/PowerShell-script-to-832e08ed ##################################################################### ############################VERY IMPORTANT:########################## #before you run this script enure that you read the ReadMe text file ###################################################################### #This script has the following functionalities:####################### #1 Creates a persoanl (home folder) for all AD users #2 Provides option to create users folders as DisplayName or sAMAccountname (Log on name) #3 Grants each users "Full Control" to his or her folder #4 Maps the users folder as drive 'H' (Configured via AD Users property, #5 Ensures that users canot access another user's folder ####################################################################### ####################################################################### #BEGIN SCRIPT #Define variable for a server to use with query. #This might be necessary if you operate in a Windows Server 2003 Domain # and have AD web services installed in a particular DC $ADServer = ad.schule.intern' #Get Admin accountb credential $GetAdminact = Get-Credential #Import Active Directory Module Import-Module ActiveDirectory #define search base - the OU where you want to # search for users to modify. you can define the #domain as your searchbase #add OU in the format OU=OU 1,Users OU,DC=domain,DC=com $searchbase = "OU=Benutzer,DC=DOMAIN,DC=COM" #Search for AD users to modify $ADUsers = Get-ADUser -server $ADServer -Filter * -Credential $GetAdminact -searchbase $searchbase -Properties * ForEach ($ADUser in $ADUsers) { #$ADUser -properties SamAccountName | Format-List #$ADUser | Select-Object -Property SamAccountName,homedirectory | Format-List [string]$pathHomeDirectory = $( $ADUser.homedirectory ) if ( -not ( Test-Path $pathHomeDirectory ) ) { write-host("--------"); write-host("Home Directory not found: "+$path); write-host("AccountName: "+$ADUser.samAccountName); #Create Missing directory $homeShare = New-Item -path $pathHomeDirectory -ItemType Directory -force -ea Stop $acl = Get-Acl $homeShare $FileSystemRights = [System.Security.AccessControl.FileSystemRights]“Modify“ $AccessControlType = [System.Security.AccessControl.AccessControlType]::Allow $InheritanceFlags = [System.Security.AccessControl.InheritanceFlags]“ContainerInherit, ObjectInherit“ $PropagationFlags = [System.Security.AccessControl.PropagationFlags]“InheritOnly“ $AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule ($ADUser.SID, $FileSystemRights, $InheritanceFlags, $PropagationFlags, $AccessControlType) $acl.AddAccessRule($AccessRule) Set-Acl -Path $homeShare -AclObject $acl -ea Stop Write-Host („HomeDirectory created at {0}“ -f $homeShare) write-host("--------"); } } #END SCRIPT ====== Windows 2016 Ressourcen Manager f. Quotas ====== * Installation auf Dateiserver über damischen ServerManager {{:know-how:ressourcen-manager-windows-dateisserver.png?200|}} * Link zum Ressourcen Manager: ** %windir%\system32\mmc.exe %windir%\system32\fsrm.msc ** * zB: Harte Grenze mit 2TB auf ganzes Laufwerk mit E-Mail Notifikation ( SMTP Server kann über Rechtsklick - Ressourcen-Manager - Optionen konfigurieren eingestellt werden / natürlich ohne user auth zumindests in GUI) {{:know-how:ressourcen-manager-kontingente-uebersicht.png?200|}} {{:know-how:ressourcen-manager-eigenschaften-kontingent.png?200|}} * **Achtung: ** er benötigt einige Zeit um das Kontingent zu berechnen und den Verbrauch in der Zeit "stimmt" der freie und verbrauchte Speicher NICHT ====== Windows 2012r2 to Windows 2016 Upgrade ===== * Hardware: **HP ML350 Gen9** * Specials: Hyper-V Server - Rolle * Alle Hyper-V Gastsysteme **herunter fahren** / Nach Reboot manuell einzeln Hochfahren / Netzwerkkonfiguration sichern zum Vergleichen ala. ipconfig /all > C:\network_config.txt / Konfiguration der Hyper-V Switches sichern zum Vergleichen nach dem Upgrade * Vor dem Upgrade aktuellen **Smart Array P440ar** Treiber installieren - nochmals in Windows 2012r2 reinbooten * Windows 2016 Server ISO entpacken & setup.exe ausführen / Microsoft Recommendations zur Kenntnis nehmen mit Hinweisen für komplette Neuinstallation * **Upgrades** für 2016 erst nach der Installation durchführen * Hyper-V Gastsysteme herunter fahren & Konfigurations - Versionen upgraden ====== Windows 2012r2 to Windows 2019 Upgrade ===== * **Achtung** wird nicht empfohlen ABER dieser Upgrade Pfad wird grundsätzlich **unterstützt** * Getestet auf/mit: Restore Offline Backup von Altaro auf hyper-v Server, Betroffener 2012r2 Server mit folgenden Rollen: AD/DNS/DHCP/WDS / 2. AD Server wurde **hart** entfernt für den Test des Offline Upgrades * **setup.exe** des 2019er ISOS aufrufen {{:know-how:issues.png?400|}} {{:know-how:1-ad_prep.png?400|}} {{:know-how:2-remove-identity.png?400|}} * **Achtung** Adconnect V1.x läuft nicht mehr auf 2019 / WDS startet nicht mehr - Verzeichnisse für ARM anlegen dann funktionierts * **Achtung** Update hängt bei 91% bei minimaler IO Tätigkeit und minimaler CPU Auslastung / nach >1 Stunde wurde das Upgrade trotzdem fertig gestellt * **Achtung** nach Bereinigung dieser Issues kommt noch eine Überprüfung der vorhandenen Programme auf Kompatiblität - sollten hier Programme auftauchen die **nicht** kompatibel sind **müssen** die Programme entfernt bzw. bereinigt werden sonst ist das Setup stuck / Mit **https://docs.microsoft.com/en-us/sysinternals/downloads/procmon** lässt sich überprüfen welche Checks durchgeführt werden - Microsoft ruttelt hier alle Laufwerke durch und sucht nach "hardcoded" Verzeichnisnamen zB: "Update Services" ====== Windows 2012r2 Powershell TLS troubles ===== * ein besonders tolles Schmankerl / Diverse Versuche "NuGet" Provider zu installieren schlugen fehl - Kontrolle auf dem Proxy ergab verdächtige Paketgrößen bei CONNECT Analyse * Wireshark Dump des TLS Hanshakes zeigte, dass Microsoft die Unterstützung für TLS1 (oder auch 1.1 FIXME) deaktiviert hat - es muss mit zumindest TLS 1.2 zugegriffen werden Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force WARNUNG: MSG:UnableToDownload «https://go.microsoft.com/fwlink/?LinkID=627338&clcid=0x409» «» WARNUNG: Die Liste der verfügbaren Anbieter kann nicht heruntergeladen werden. Überprüfen Sie Ihre Internetverbindung. WARNUNG: Es kann kein Download von URI "https://go.microsoft.com/fwlink/?LinkID=627338&clcid=0x409" nach "" durchgeführt werden. Install-PackageProvider : Für die angegebenen Suchkriterien für Anbieter "NuGet" wurde keine Übereinstimmung gefunden. Der Paketanbieter erfordert das TLS V1 Alert Errors - Wireshark PS C:\Users\administrator.SCHULE.000> [System.Net.ServicePointManager]::Security Protocol = [System.Net.SecurityProtocolType]::Tls12 PS C:\Users\administrator.SCHULE.000> Install-PackageProvider -Name NuGet -Minim umVersion 2.8.5.201 -Force Name Version Source Summary ---- ------- ------ ------- nuget 2.8.5.208 https://onege... NuGet provi... ====== Forefront 2010 ===== * Lässt sich nicht löschen / da aktuelle Version nicht unterstützt www.jodrik.nl/uninstalling-forefront-2010-from-server-2012-after-server-upgrade/ -> Forefront 2010 deinstallieren - Kompatiblität für Windows 7 bei setup.exe aktivieren in den Attributen -> C:\Program Files\Microsoft Security Client>setup.exe /x ====== Windows 2012r2 Azure AD High Load ===== * https://www.tecklyfe.com/how-to-fix-microsoft-online-reporting-monitoringagent-startup-high-cpu/ * microsoft.online.reporting.monitoringagent.startup High CPU Load - frisst die CPU beim Task Manager * Mittlerweile Hotfix verfügbar für Azure AD COnnect Stop the Azure AD Connect Health Sync Monitor Service The first option is to stop the Azure AD Connect Health Sync Monitor service and set it to manual until the updated utility is released. Click on Start and search for Services Find the Azure AD Connect Health Sync Monitor service Right click on it and click Stop Right click on the same service and go to Properties Change the Startup Type to Manual ====== GPO 1607 - Templates Problem ===== * Blabla Geo Location error "Fehler „‚Microsoft.Policies.Sensors.WindowsLocationProvider‘ ist bereits definiert“" https://support.microsoft.com/de-at/help/3077013/microsoft-policies-sensors-windowslocationprovider-is-already-defined Methode 2 Löschen Sie die Dateien „LocationProviderADM.admx“ und „LocationProviderADM.adml“, und ändern Sie „Microsoft-Windows-Geolocation-WLPAdm.admx“ und „Microsoft-Windows-Geolocation-WLPAdm.adml“ in die richtigen Namen. Szenario 1 Löschen Sie die Dateien „LocationProviderADM.admx“und „LocationProviderADM.adml“ aus dem zentralen Speicher. Benennen Sie „Microsoft-Windows-Geolocation-WLPAdm.admx“ um in „LocationProviderADM.admx“. Benennen Sie „Microsoft-Windows-Geolocation-WLPAdm.adml“um in „LocationProviderADM.adml“. Szenario 2 Löschen Sie die Datei „Microsoft-Windows-Geolocation-WLPAdm.admx“ aus dem lokalen Speicher. Der Pfad zum lokalen Richtlinienspeicher lautet „C:\Windows\PolicyDefinitions“. ====== Windows Update Cli ===== * Cli wuauclt /DetectNow Jetzt nach Updates suchen. wuauclt /ReportNow Nicht berichtete Probleme an Microsoft melden. wuauclt /ShowSettingsDialog Windows-Update-Einstellungen anzeigen. wuauclt /ResetAuthorization Update-Komponenten zurücksetzen. wuauclt /ResetEulas Bestätigung der Lizenzverträge erneut einholen. wuauclt /ShowWU Windows-Update anzeigen. wuauclt /ShowWindowsUpdate Windows-Update anzeigen. wuauclt /SelfUpdateManaged wuauclt /SelfUpdateUnmanaged wuauclt /UpdateNow Verfügbare Updates installieren. wuauclt /ShowWUAutoScan wuauclt /ShowFeaturedUpdates wuauclt /ShowOptions wuauclt /ShowFeaturedOptInDialog wuauclt /DemoUI * Windows 10 Windows Update Logs oho natürlich net mehr windowsUpdate.log Happy Powershell C:\Users\christian.czeczil>powershell Windows PowerShell Copyright (C) 2016 Microsoft Corporation. Alle Rechte vorbehalten. PS C:\Users\christian.czeczil> Get-WindowsUpdateLog Converting C:\Windows\logs\WindowsUpdate into C:\Users\christian.czeczil\Desktop\WindowsUpdate.log ... Verzeichnis: C:\Users\CHRIST~1.CZE\AppData\Local\Temp\WindowsUpdateLog Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 04.07.2018 11:31 SymCache Eingabe ---------------- Datei(en): C:\Windows\logs\WindowsUpdate\WindowsUpdate.20180626.173314.738.1.etl C:\Windows\logs\WindowsUpdate\WindowsUpdate.20180626.190715.973.1.etl C:\Windows\logs\WindowsUpdate\WindowsUpdate.20180626.204114.477.1.etl C:\Windows\logs\WindowsUpdate\WindowsUpdate.20180626.221514.107.1.etl * Logging des Clients (https://support.microsoft.com/de-at/help/902093/how-to-read-the-windowsupdate-log-file) Standardmäßig verzeichnet der Windows Update-Client sämtliche Transaktionsinformationen in folgender Protokolldatei: %windir%\Windowsupdate.log Wenn auf der Microsoft Windows Update-Website oder vom Dienst für automatische Updates eine Fehlermeldung ausgegeben wird, können Sie das Problem mithilfe der in der Protokolldatei "Windowsupdate.log" enthaltenen Informationen beheben. * Windows Updates Hack - neu intialisieren am Client CMD (als Admin) net stop wuauserv net stop bits rd /s /q %windir%\SoftwareDistribution del %windir%\WindowsUpdate.log net start wuauserv net start bits wuauclt /resetauthorization /detectnow wuauclt /reportnow * Seit Windows 10 usoclient (https://www.borncity.com/blog/2018/07/05/windows-10-und-der-usoclient/) UsoClient.exe StartScan StartDownload StartInstall RestartDevice ====== GPO - interaktives Batch Skript ===== * Sollten die User bei einem User Skript befragt werden müssen d.h. **interaktiv** * In diesem Zweig befinden sich die entsprechenden GPO Einstellungen um batch Skript sichtbar zu machen **Anweisungen in Anmeldeskripts während der Ausführung anzeigen** {{:know-how:gpo_skripts_interaktiv.png?400|}} * Batch Abfragebeispiel (https://administrator.de/forum/abfrage-batchdatei-integrieren-118820.html) echo Hast du die Lizenz eingegeben und sie wurde akzeptiert ? ( j/n ) :Frage SET /p wahl= if /i not '%wahl%' == 'n' (if /i '%wahl%' == 'j' (goto Ja ) ) else goto Nein if defined wahl ECHO Bitte mit j fuer Ja oder n fuer Nein. antworten. Vielen Dank & goto Frage :Nein goto Ende :Ja echo success > C:\license.log :Ende ====== GPO für bestimmte Windows Versionen (WMI) ===== * https://docs.microsoft.com/en-us/windows/security/identity-protection/windows-firewall/create-wmi-filters-for-the-gpo To create a WMI filter that queries for a specified version of Windows Open the Group Policy Management console. In the navigation pane, expand Forest: YourForestName, expand Domains, expand YourDomainName, and then click WMI Filters. Click Action, and then click New. In the Name text box, type the name of the WMI filter. Note: Be sure to use a name that clearly indicates the purpose of the filter. Check to see if your organization has a naming convention. In the Description text box, type a description for the WMI filter. For example, if the filter excludes domain controllers, you might consider stating that in the description. Click Add. Leave the Namespace value set to root\CIMv2. In the Query text box, type: syntax select * from Win32_OperatingSystem where Version like "6.%" This query will return true for devices running at least Windows Vista and Windows Server 2008. To set a filter for just Windows 8 and Windows Server 2012, use "6.2%". For Windows 10 and Windows Server 2016, use "10.%". To specify multiple versions, combine them with or, as shown in the following: syntax ... where Version like "6.1%" or Version like "6.2%" To restrict the query to only clients or only servers, add a clause that includes the ProductType parameter. To filter for client operating systems only, such as Windows 8 or Windows 7, use only ProductType="1". For server operating systems that are not domain controllers, use ProductType="3". For domain controllers only, use ProductType="2". This is a useful distinction, because you often want to prevent your GPOs from being applied to the domain controllers on your network. The following clause returns true for all devices that are not domain controllers: syntax ... where ProductType="1" or ProductType="3" The following complete query returns true for all devices running Windows 10, and returns false for any server operating system or any other client operating system. syntax select * from Win32_OperatingSystem where Version like "10.%" and ProductType="1" The following query returns true for any device running Windows Server 2016, except domain controllers: syntax select * from Win32_OperatingSystem where Version like "10.%" and ProductType="3" Click OK to save the query to the filter. Click Save to save your completed filter. ====== Hyper-V Storage Offline ===== * Besonders erfreulich wenn der Server (2012r2) neu bootet und das Storage Volume nicht online nimmt obwohl es ein lokales RAID Controller Volume ist / auf dem alle virtuellen Maschinen liegen * SAN Policy wurde auf "OnlineAll" geändert https://support.purestorage.com/Solutions/Microsoft_Platform_Guide/aaa_Quick_Setup_Steps/Step_04 Microsoft DiskPart-Version 6.3.9600 Copyright (C) 1999-2013 Microsoft Corporation. Auf Computer: FOO DISKPART> san SAN-Richtlinie : Offline - Freigegeben DISKPART> SAN Policy=OnlineAll Die SAN-Richtlinie für das aktuelle Betriebssystem wurde erfolgreich geändert. DISKPART> ====== Hyper-V Storage Migration ===== * Getestet auf Win2012r2 von einem SAS RAID Volume auf ein SSD RAID Volume im **laufenden Betrieb** {{:know-how:0_move_virtual_machine_storage.png?400|}} {{:know-how:1_move_virtual_machine_storage.png?400|}} {{:know-how:2_move_virtual_machine_storage.png?400|}} {{:know-how:3_move_virtual_machine_storage.png?400|}} {{:know-how:4_move_virtual_machine_storage.png?400|}} ====== Hyper-V Replikation ===== https://www.andysblog.de/windows-hyper-v-replikat-uebersicht-anleitung-fuer-den-arbeitsgruppenbetrieb * Achtung CRL Check deaktivieren !!! * Achtung kann auch sein KEIN FQDN Name sondern nur über hostname replizieren !!! * Aktivieren der Replikation über Powershell cli: Enable-VMReplication -VmName VM_NAME -ReplicaServerName FOFOFOFO -ReplicaServerPort fofofo -AuthenticationType Certificate -CertificateFingerprint FINGERPRINT * Anleitung vom Blog - des is a Bursch: Anleitung zu Hyper-V-Replikat in Arbeitsgruppen oder bei stand-alone Servern Diese Anleitung bezieht sich auf zwei stand-alone Hyper-V Server 2012. Jeder Host ist in einer anderen Arbeitsgruppe. Für die Replikation kommt in dieser Konstellation nur die Authentifizierung mit Zertifikaten in Frage. Der Einfachheit halber werden selbstsignierte Zertifikate verwendet. Neben den zwei Hyper-V Servern wird eine Windows 8 Arbeitsstation für die Einrichtung und Verwaltung benötigt. Windows 8 Windows Software Development Kit (SDK) for Windows 8 herunterladen und installieren. Aus dem SDK wird das Tool „makecert.exe“ benötigt um die Zertifikate für die Hyper-V Hosts erstellen zu können. Dieses Tool auf die Hyper-V Hosts kopieren. Unter „Systemsteuerung – Programme und Funktionen – Windows-Funktionen aktivieren und deaktivieren – Hyper-V“ die „Hyper-V-Verwaltungstools“ aktivieren. HVRemote herunterladen. In einer Eingabeaufforderung mit erhöhten Rechten folgende Befehle ausführen: cscript hvremote.wsf /anondcom:grant cmdkey /add:HYPER-V-COMPUTERNAME /user:HYPER-V-COMPUTERNAME\Administrator /pass Der cmdkey-Befehl muss für jeden Hyper-V angepasst und ausgeführt werden. Hyper-V Server 2012 Auf allen Hyper-V Hosts muss die Remoteverwaltung aktiviert sein. Ferner sollten statische IP-Adressen konfiguriert werden. Damit die Firewall den Replikationsverkehr durchlässt muss folgender Befehl pro Host ausgeführt werden: netsh advfirewall firewall set rule group="Hyper-V-Replikat - HTTPS" new enable=yes Nachfolgend wird von einem primären und einem recovery Host ausgegangen. Bei den Befehlen muss „“ pro Host angepasst werden, z.B. „host1.test.local“. Auf dem primären Host folgende Befehle ausführen: makecert -pe -n "CN=PrimaryTestRootCA" -ss root -sr LocalMachine -sky signature -r "PrimaryTestRootCA.cer" makecert -pe -n "CN=" -ss my -sr LocalMachine -sky exchange -eku 1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2 -in "PrimaryTestRootCA" -is root -ir LocalMachine -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 PrimaryTestCert.cer Auf dem recovery Host folgende Befehle ausführen: makecert -pe -n "CN=RecoveryTestRootCA" -ss root -sr LocalMachine -sky signature -r "RecoveryTestRootCA.cer" makecert -pe -n "CN=" -ss my -sr LocalMachine -sky exchange -eku 1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2 -in "RecoveryTestRootCA" -is root -ir LocalMachine -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 RecoveryTestCert.cer Nun muss die „*.CA.cer“-Datei auf den jeweils anderen Host kopiert werden. Auf dem primären Host wird das Zertifikat mit dem Befehl certutil -addstore -f Root "RecoveryTestRootCA.cer" importiert. Auf dem recovery Host wird das Zertifikat mit dem Befehl certutil -addstore -f Root "PrimaryTestRootCA.cer" importiert. Abschließend muss auf beiden Hosts der Befehl reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\Replication" /v DisableCertRevocationCheck /d 1 /t REG_DWORD /f ausgeführt werden. Damit sind die Voraussetzungen für Hyper-V-Replikat erfüllt. Nun kann für alle gewünschten virtuellen Maschinen die Replikation konfiguriert werden. Dazu den Hyper-V-Manager auf der Windows 8 Arbeitsstation starten, beide Hyper-V Hosts hinzufügen und die jeweilige virtuelle Maschine mit der rechten Maustaste anklicken. Anschließend „Replikation aktivieren…“ auswählen und dem Assistenten folgen. Wichtig dabei ist, das bei der Angabe des Replikatserver der FQDN verwendet wird, der NetBIOS-Name reicht nicht aus und führt zu einer Fehlermeldung! ====== Hyper-V Nested Virtualization ===== * Auch bei Hyper-V gibts die nasty virtualization :) * https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/nested-virtualization * **powershell** Set-VMProcessor -VMName -ExposeVirtualizationExtensions $true ====== Hyper-V Server 2019 ===== * Nach Replikation von 2012r2 auf 2019 Server * **Achtung** zur Migration von Hyper V Hosts die **NICHT** in einer Domäne sind - Replikation mit Zertifikaten nutzen * **Generation 2** Maschinen können nicht mehr starten * Fehlermeldung: {{:know-how:hyper_v_2019_cpu_fehler.png?400|}} * **Lösung** ** MAC Adresse** der Maschine auf neuem Server ** ändern ** ===== Hyper-V VLAN ===== * Getestet auf Ubuntu 18.04 und Windows 2019 Host * Wollte VLANs direkt nativ im Linux konfigurieren / Es ist leider nur möglich entweder **tagged** (**trunk**) Pakete oder **untagged** (**access**) Pakete über den Host auf den Switch zu bringen * **NativeVlanId **bedeutet Pakete die von der linux Maschine untagged sind werden durch den Host mit der VLAN Id getagged d.h. am Switch nur **tagged** Pakete / **Untagged** ist die Default Konfiguration PS C:\Users\Administrator> Set-VMNetworkAdapterVLAN -VMName PLAY -Trunk -AllowedVlanIDList 1-500 -NativeVlanId 1 PS C:\Users\Administrator> Set-VMNetworkAdapterVLAN -VMName PLAY -Untagged * Gezielt gewisse Tagged VLANs an den Switch weiter geben zB: VLAN10 am Switch / wird als eigene "Netzwerkkarte" hinzugefügt mit Identifikation des VLAN's - Linux sieht eine "normale" Netzwerkkarte das Tagging übernimmt das Hostsystem {{:know-how:hyper-v-vlans.png?400|}} ===== Hyper-V Powershell ===== * Recovery Snapshots zB: von Altaro löschen sollte ein Reboot erfolgt sein PS > Get-VMCheckpoint -VMName Fileserver VMName Name SnapshotType CreationTime ParentSnapshot Name ------ ---- ------------ ------------ -------------- Fileserver Altaro Temp Checkpoint:-Fileserver - (24.10.2023 - 20:00:17) Recovery 24.10.2023 20:00:18 PS > Remove-VMCheckpoint -VMName Fileserver ====== KMS Server ===== * Getestet auf **Windows 2019 Standard** * **Achtung** für die Office 2019 Professional Plus KMS Lizenzen muss **office2019volumelicensepack_x64** installiert werden damit die Keys vom KMS Server erkannt werden * Installation KMS Dienst: {{:know-how:0-kms-installation-all-powershell.png?400|}} {{:know-how:1-kms-server-direkt.png?400|}} * Wenn der Eintrag nicht im DNS veröffentlicht werden soll (fürs auto lookup der Clients/Server) muss dies manuell erfolgen - es handelt sich hier um einen **SRV** Eintrag zB: {{:know-how:2-kms-no-propagate-in-dns.png?400|}} {{:know-how:3-kms-srv-dns-eintrag.png?400|}} * Key hinzufügen zB: Windows 2019 Standard KMS Key: {{:know-how:4-kms-key-add-kms-host.png?400|}} * Key bei Microsoft aktivieren: {{:know-how:5-kms-key-added-activate.png?400|}} * Offizielle Infos & interessantes Debugging: Firewalling: x.x.x.x - - [18/Jan/2023:11:51:07 +0100] "CONNECT sls.update.microsoft.com:443 HTTP/1.1" 200 4405 "-" "-" TCP_TUNNEL:HIER_DIRECT 52.152.110.14 - - x.x.x.x - - [18/Jan/2023:11:51:08 +0100] "GET http://ocsp.digicert.com/MFEwTzBNMEswSTAJBgUrDgMCGgUABBSAUQYBMq2awn1Rh6Doh%2FsBYgFV7gQUA95QNVbRTLtm8KPiGxvDl7I90VUCEAJ0LqoXyo4hxxe7H%2Fz9DKA%3D HTTP/1.1" 200 892 "-" "Microsoft-CryptoAPI/10.0" TCP_MISS:HIER_DIRECT 93.184.220.29 application/ocsp-response - x.x.x.x - - [18/Jan/2023:11:51:08 +0100] "CONNECT login.live.com:443 HTTP/1.1" 200 16349 "-" "-" TCP_TUNNEL:HIER_DIRECT 40.126.32.67 - - x.x.x.x - - [18/Jan/2023:11:51:09 +0100] "CONNECT licensing.mp.microsoft.com:443 HTTP/1.1" 200 5297 "-" "-" TCP_TUNNEL:HIER_DIRECT 20.123.104.105 - - x.x.x.x - - [18/Jan/2023:11:51:10 +0100] "CONNECT activation-v2.sls.microsoft.com:443 HTTP/1.1" 200 21030 "-" "-" TCP_TUNNEL:HIER_DIRECT 40.91.76.224 - - x.x.x.x - - [18/Jan/2023:11:51:12 +0100] "CONNECT validation-v2.sls.microsoft.com:443 HTTP/1.1" 200 58569 "-" "-" TCP_TUNNEL:HIER_DIRECT 20.83.72.98 - - x.x.x.x - - [18/Jan/2023:11:51:19 +0100] "CONNECT validation-v2.sls.microsoft.com:443 HTTP/1.1" 200 15113 "-" "-" TCP_TUNNEL:HIER_DIRECT 20.83.72.98 - - x.x.x.x - - [18/Jan/2023:11:51:21 +0100] "CONNECT login.live.com:443 HTTP/1.1" 200 22253 "-" "-" TCP_TUNNEL:HIER_DIRECT 40.126.32.67 - - x.x.x.x - - [18/Jan/2023:11:51:21 +0100] "CONNECT licensing.mp.microsoft.com:443 HTTP/1.1" 200 5297 "-" "-" TCP_TUNNEL:HIER_DIRECT 20.123.104.105 - - x.x.x.x - - [18/Jan/2023:11:51:39 +0100] "CONNECT licensing.mp.microsoft.com:443 HTTP/1.1" 200 5297 "-" "-" TCP_TUNNEL:HIER_DIRECT 20.123.104.105 - - x.x.x.x - - [18/Jan/2023:11:51:40 +0100] "CONNECT activation-v2.sls.microsoft.com:443 HTTP/1.1" 200 21030 "-" "-" TCP_TUNNEL:HIER_DIRECT 40.91.76.224 - - x.x.x.x - - [18/Jan/2023:11:51:42 +0100] "CONNECT validation-v2.sls.microsoft.com:443 HTTP/1.1" 200 58569 "-" "-" TCP_TUNNEL:HIER_DIRECT 20.83.72.98 - - x.x.x.x - - [18/Jan/2023:11:51:47 +0100] "CONNECT validation-v2.sls.microsoft.com:443 HTTP/1.1" 200 15113 "-" "-" TCP_TUNNEL:HIER_DIRECT 20.83.72.98 - - x.x.x.x - - [18/Jan/2023:11:51:50 +0100] "CONNECT login.live.com:443 HTTP/1.1" 200 22253 "-" "-" TCP_TUNNEL:HIER_DIRECT 40.126.32.67 - - x.x.x.x - - [18/Jan/2023:11:51:50 +0100] "CONNECT licensing.mp.microsoft.com:443 HTTP/1.1" 200 5297 "-" "-" TCP_TUNNEL:HIER_DIRECT 20.123.104.105 - - --- Keys anzeigen cmd: List KMS Keys in use by host-server itself cscript c:\windows\system32\slmgr.vbs /dlv List all installed KMS Keys: cscript C:\Windows\System32\slmgr.vbs /dli all Offizielles: https://learn.microsoft.com/de-de/windows-server/get-started/kms-create-host https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/dn502531(v=ws.11) ====== Storage Pools / Storage Spaces ===== * Eine Mehrzahl von Festplatten wird zu einem Storage Pool zusammen gefasst und aus dem Pool wird ein Storage Space / virtuelle Disk gebildet * Offizielles: https://learn.microsoft.com/en-us/windows-server/storage/storage-spaces/deploy-standalone-storage-spaces * **MIRROR** und **Thick Provisioning** (FIXME / welches Raid wird hier eigentlich gebaut ???) - ich hätte eigentlich gern RAID10 - mit 4x6TB SATA Platten {{:know-how:0-spaces-create-pool.png?400|}} {{:know-how:1-spaces-disks.png?400|}} {{:know-how:2-spaces-pool-erstellen.png?400|}} {{:know-how:3-spaces-name.png?400|}} {{:know-how:4-spaces-mirror.png?400|}} {{:know-how:5-spaces-thick-provisioning.png?400|}} {{:know-how:6-spaces-max-array.png?400|}} {{:know-how:7-spaces-choose-disk.png?400|}} * Dem Ergebnis kann ein Laufwerksbuchstabe zugeordnet oder ein Dateisystem installiert werden ====== Windows Proxy einstellungen ===== * Auto detection für aktuell eingeloggten Benutzer (mit zB: WPAD und PAC File per DHCP): You can do it with this: To Enable 'Automatically Detect Settings' REG ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v AutoDetect /t REG_DWORD /d 1 /f To Disable 'Automatically Detect Settings' REG ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v AutoDetect /t REG_DWORD /d 0 /f * WinHTTP Komponente: (zB: .NET Applikationen) The proxy settings for WinHTTP are not the proxy settings for Microsoft Internet Explorer. You cannot configure the proxy settings for WinHTTP in the Microsoft Windows Control Panel. Using the WinHTTP proxy configuration utility does not alter the settings you use for Internet Explorer. To configure a system wide proxy do netsh winhttp set proxy myproxy source: http://technet.microsoft.com/pt-br/library/cc731131(v=ws.10).aspx#BKMK_5 if you want to use IE proxy settings for all programs, try netsh winhttp import proxy source =ie source: http://technet.microsoft.com/pt-br/library/cc731131(v=ws.10).aspx#BKMK_2 more information here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa384069(v=vs.85).aspx ====== Windows 2012r2 Update Fehler ===== Am 06.08.2015 schrieb Woly: ein frisch installierter Server 2012 R2 Essentials meldet bei der Suche nach Updates den Fehler 80244019. Dieser Fehlercode scheint häufiger in Verbindung mit WSUS aufzutreten, aber weder führt dieser Server einen WSUS aus, noch hängt er an einem WSUS. Die Verbindung "nach draußen" wird durch einen handelsüblichen DSL-Router gewährleistet und auch nicht eingeschränkt. In einer administrativen Commandline diese Befehle ausführen und anschließend den Server komplett neu starten. net stop wuauserv rd /s /q %windir%\SoftwareDistribution del %windir%\WindowsUpdate.log net start wuauserv Nach dem Neustart auf Windows Update manuell nach Updates suchen lassen. Das kann beim ersten Mal auch etwas länger dauern. ====== Windows DNS Server - Linux dig formErr ===== https://kevinlocke.name/bits/2017/01/20/formerr-from-microsoft-dns-server-for-dig/ DIG requested kevinlocke.name and received FORMERR. After some trial and error, I determined that the issue results from DIG 9.11 sending the DNS COOKIE option. This option was enabled by default in BIND 9.11. Unfortunately, adding this option causes DNS Server to treat the request as malformed. This behavior appears to violate “Any OPTION-CODE values not understood by a responder or requestor MUST be ignored.” from Section 6.1.2 of RFC 6891, but that is of small consolation for a non-working system. -> As a workaround, pass the +nocookie option (or +noedns to disable all EDNS options) as in ====== Windows DNS Server Blacklist ===== Removing WPAD from DNS block list The DNS Server role in Windows Server 2008 introduces a global query block list to reduce vulnerability associated with dynamic DNS updates. For more information, see About implementing WPAD. If you want to use WPAD with DNS, note the following: If WPAD entries are configured in DNS before the DNS server is upgraded in Windows Server 2008, no action is required. If you configure or remove WPAD after you deploy the DNS server role on a server running Windows Server 2008, you must update the block list on all DNS servers that host the zones affected by the change. The affected zones are those where you registered the WPAD servers. Updating the block list Use the dnscmd command-line tool to manage the global query block list. Open a command line prompt, and then do the following: To check whether the global query block is enabled, type the following: dnscmd /info /enableglobalqueryblocklist To display the host names in the current block list, type the following: dnscmd /info /globalqueryblocklist To disable the block list and ensure that the DNS Server service does not ignore queries for names in the block list, type the following: dnscmd /config /enableglobalqueryblocklist 0 To enable the block list and ensure that the DNS Server service ignores queries for names in the block list, type the following: dnscmd /config /enableglobalqueryblocklist 0 To remove all names from the block list, type the following: dnscmd /config /globalqueryblocklist To replace the current block list with a list of the names that you specify, type the following: dnscmd /config /globalqueryblocklist name [name]… For more information and instructions, see the document "DNS Server Global Query Block List", available for download from Domain Name System at Microsoft TechNet. ====== VHD into WIM konvertieren ===== 19 down vote accepted Absolutely, let's post a prim and proper answer for Google. This is a simple 2 command Powershell execution, using the dism module. The dism can be copied to earlier versions of Windows, provided you have the appropriate version of the windows management framework. First, mount the vhd using Mount-WindowsImage -ImagePath C:\VHDs\BigHomies.vhdx -Path C:\VHDMount -Index 1 Then, capture it into a wim with New-WindowsImage -CapturePath C:\VHDMount -Name Win7Image -ImagePath C:\CapturedWIMs\Win7.wim -Description "Yet another Windows 7 Image" -Verify And let it do it's thing. When you are done you can unmount the vhd and discard any changes using: Dismount-WindowsImage -Path C:\VHDMount -Discard ====== VHD dynamic in fixed konvertieren ===== https://hyper-v-backup.backupchain.com/how-to-convert-from-dynamic-vhdvhdx-disk-format-to-from-fixed-in-hyper-v/ Convert-VHD –Path c:\VM\my-vhdx.vhdx –DestinationPath c:\New-VM\new-vhdx.vhdx –VHDType Dynamic ====== Windows Dienste f. User ===== * Service für normalen user nutzbar machen Beispiele: * Programm: {{ :know-how:subinacl.zip |}} * Good Read mit Alternativen: http://woshub.com/set-permissions-on-windows-service/ C:\Program Files (x86)\Windows Resource Kits\Tools>subinacl /SERVICE \\PLAY-PC-2 \joomlaApache /GRANT=schule.intern\Lehrer=F subinacl /SERVICE \\PLAY-PC-2\joomlaApache /GRANT=schule.intern\Schueler=F C:\Users\Administrator>subinacl /service joomlaApache /grant="schule.intern\Dom�nen-Benutzer=F" C:\Program Files (x86)\Windows Resource Kits\Tools ====== DHCP Server ====== ===== UEFI/LEGACY PXE BOOT WDS Options ===== * Getestet auf Windows 2022 * Vielen Dank an ** https://rdr-it.com/en/wds-dhcp-configuration-for-uefi/ ** für den Artikel * Sollten sich DHCP und WDS Server auf der **gleichen** Maschine befinden setzt der WDS Dienst unter dem Häckchen **DHCP-Optionen konfigurieren** alle notwendigen Optionen (DHCP Option 60) für den DHCP Server die für PXE Booten sowohl Legacy als auch UEFI notwendig sind {{:know-how:wds-option-60-for-dhcp.png?400|}} {{:know-how:pxe-option-60-same-server-dhcp-wds.png?400|}} * Sollte sich der DHCP Server auf einem anderen Server befinden kann mit folgenden Optionen zum Windows WDS Server verwiesen werden - in diesem Beispiel befindet sich der WDS Server auf dem Server **10.0.0.2** (Option 66 und Option 67) - LEGACY Boot {{:know-how:pxe-wds-options-legacy-mbr-boot-wds-windows.png?400|}} * Für den Verweis über UEFI PXE Boot ist der Aufwand schon größer - es muss eine eigene Herstellerklasse definiert werden und bei einem Match werden die Optionen 66 und 67 mit geändertem Inhalt an den Client verschickt: * bei den DHCP Einstellungen unter IPV4 Herstellerklassen - **Hinzufügen**: {{:know-how:0-uefi-class-match-correct.png?400|}} {{:know-how:1-uefi-richtlinie-erstellen.png?400|}} {{:know-how:2-uefi-class-match.png?400|}} {{:know-how:3-uefi-send-match-66-pxe-server.png?400|}} {{:know-how:3-uefi-send-match-67-pxe-server.png?400|}} {{:know-how:4-uefi-ip-bereich.png?400|}} {{:know-how:5-uefi-send-match-summary.png?400|}} ===== UEFI ipxe MENÜ Option ===== * Im **Default** Binary , das herunter geladen werden kann fragt das ipxe EFI Binary nach dem Menüpfad um ihn als DHCP Antwort zu erhalten {{:know-how:0-ipxe-custom.png?400|}} {{:know-how:1-ipxe-custom-path-menue.png?400|}} {{:know-how:2-ipxe-conditions.png?400|}} {{:know-how:3-ipxe-user-class.png?400|}} {{:know-how:4-ipxe-benutzerklasse.png?400|}} {{:know-how:5-ipxe-benutzerklasse-ascii.png?400|}} ====== WDS/Windows/WSUS Server ====== * Bei sysprep Fehler: https://social.technet.microsoft.com/Forums/windows/en-US/c469805c-98af-4bb2-9655-c86c294470a9/sysprep-failure-occurred-while-executing-drmv2cltdll-fix?forum=w7itproinstall: Click Start > Run, type Services.msc to open the Services applet. Scroll down to Windows Media Player Network Sharing Service, double click it, change the Startup type to Disabled. Click OK. Reboot the PC * WDS Treiberproblem Fehler 30 bei nivida: Bei Fehler 30 nvidia treiber: expand *.* .\test\ -> dann kommt wurde vergrößert xy prozent und dann gehts im test verzeichnis siehe WDS deadaffebeef magic darunter für treiber hinzufügen * WDS am Server - Image mounten & gucken http://deadaffebeef.com/blog/wds-windows-updates-treiber-zu-wim-abbild-hinzufugen/ 1) Das Installationsabbild, welchem weitere Pakete hinzugefügt werden sollen, muss zu allererst exportiert werden: CMD (als Administrator ausführen!): wdsutil -Export-Image -Image:”Win7 x86 ENT” -ImageType:Install -ImageGroup:Win7 -DestinationImage -FilePath:D:\Win7x86ENT.wim -Overwrite:Yes 2) Als nächstes muss die WIM-Datei gemountet werden: dism -Mount-Wim -WimFile:D:\Win7x86ENT.wim -Index:1 -MountDir:D:\Mount 3) Nun können die Update- (CAB oder MSU) bzw. Treiber-Pakete dem gemounteten Image hinzugefügt werden: Windows Updates: dism -Image:D:\Mount -Add-Package -PackagePath: /Recurse Treiber: dism -Image:D:\Mount -Add-Driver -Driver: 4) Die vorgenommenen Änderungen am Image müssen gespeichert werden: dism -Commit-Wim -MountDir:D:\Mount 5) Bevor das neue Image im WDS eingebunden werden kann, muss es zunächst unmountet werden: dism -Unmount-Wim -Commit -MountDir:D:\Mount 6) Jetzt noch das ursprüngliche Installationsabbild durch das angepasste ersetzen und wir sind fertig: wdsutil -Replace-Image -Image:”Win7 x86 ENT” -ImageType:Install -ImageGroup:Win7 -ReplacementImage -ImageFile:D:\Win7x86ENT.wim Alternativ kann das geänderte Image als neues Abbild im WDS eingebunden werden: wdsutil -Add-Image -ImageType:Install -ImageGroup:Win7 -ImageFile:D:\Win7x86ENT.wim -SingleImage:”Win7 x86 Enterprise” -Name:”Win7 x86 ENT” -Description:”Win7 x86 ENT Image – neu” * Netzwerk Konnektivität überprüfen: **links shift + F10** in WDS Boot Umgebung * Achtung bei tftp timeout: https://support.microsoft.com/en-us/kb/977512 (DNS Server nimmmt alle Ports von WDS) * Zeit reparieren NTP: http://blogs.technet.com/b/nepapfe/archive/2013/03/01/it-s-simple-time-configuration-in-active-directory.aspx AT Pool: server 0.at.pool.ntp.org server 1.at.pool.ntp.org server 2.at.pool.ntp.org server 3.at.pool.ntp.org zB: llten Sie eine neuere Version von Windows einsetzten, können Sie den NTP-Client nutzen, der in das System integriert ist. Führen Sie dazu folgendes Kommando als Administrator aus: w32tm /config /syncfromflags:manual /manualpeerlist:"0.pool.ntp.org 1.pool.ntp.org 2.pool.ntp.org 3.pool.ntp.org" Status: C:\Users\administrator.SCHULE.000>w32tm /query /status Sprungindikator: 0(keine Warnung) Stratum: 2 (Sekundärreferenz - synchr. über (S)NTP) Präzision: -6 (15.625ms pro Tick) Stammverzögerung: 0.0000000s Stammabweichung: 0.0100000s Referenz-ID: 0x564D5450 (Quell-IP: 86.77.84.80) Letzte erfolgr. Synchronisierungszeit: 24.06.2015 11:07:00 Quelle: VM IC Time Synchronization Provider Abrufintervall: 6 (64s) Befehl: w32tm /config /syncfromflags:manual /manualpeerlist:"0.at.pool.ntp.org 1.at.pool.ntp.org 2.at.pool.ntp.org "/update /reliable:yes w32tm /resync Time gschichtln hyper v: http://blogs.msdn.com/b/robertvi/archive/2011/05/11/time-synchronization-and-domain-controller-vm-s.aspx https://support.microsoft.com/en-us/kb/816042 https://technet.microsoft.com/en-us/library/virtual_active_directory_domain_controller_virtualization_hyperv(WS.10).aspx Time Set Session: C:\Users\Administrator>w32tm /query /status Sprungindikator: 0(keine Warnung) Stratum: 4 (Sekundärreferenz - synchr. über (S)NTP) Präzision: -23 (119.209ns pro Tick) Stammverzögerung: 0.0358491s Stammabweichung: 0.0479295s Referenz-ID: 0x3369D0AD (Quell-IP: 51.105.208.173) Letzte erfolgr. Synchronisierungszeit: 14.05.2021 19:05:41 Quelle: time.windows.com,0x8 Abrufintervall: 10 (1024s) C:\Users\Administrator>w32tm /config /manualpeerlist:"at.pool.ntp.org,0x8" /syncfromflags:manual /reliable:yes /update Der Befehl wurde erfolgreich ausgeführt. C:\Users\Administrator>net stop w32time && net start w32time Windows-Zeitgeber wird beendet. Windows-Zeitgeber wurde erfolgreich beendet. Windows-Zeitgeber wird gestartet. Windows-Zeitgeber wurde erfolgreich gestartet. C:\Users\Administrator>w32tm /resync Befehl zum erneuten Synchronisieren wird an den lokalen Computer gesendet. Der Befehl wurde erfolgreich ausgeführt. C:\Users\Administrator>w32tm /query /status Sprungindikator: 0(keine Warnung) Stratum: 3 (Sekundärreferenz - synchr. über (S)NTP) Präzision: -23 (119.209ns pro Tick) Stammverzögerung: 0.0123271s Stammabweichung: 7.8446831s Referenz-ID: 0x563B50AA (Quell-IP: 86.59.80.170) Letzte erfolgr. Synchronisierungszeit: 14.05.2021 19:17:02 Quelle: at.pool.ntp.org Abrufintervall: 6 (64s) * Keyserver auf clients bestimmen: slmgr.vbs /ckms slmgr.vbs /skms KMS_SERVER_ADRESSE slmgr.vbs /ato * WSUS Illegaler Pfad Error: It's not about root partition, it's about trailing slash. E:\WSUS\ will give you the same error. E:\WSUS will work. kein "\" suffix * WSUS Laufzeitfehler - blabla unterschiedliche Laufzeitversionen (.NET schaß) * inetmgr ausführen * WSUS Pool auf .NET 4 umstellen von 2 {{:know-how:wsus-pool-umstellen.png?100|}} ====== Druckserver neu starten ====== @echo off net stop spooler del %SystemRoot%\spool\PRINTERS\*.tmp net start spooler ====== Drucker per Cli hinzufügen ====== * https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/rundll32-printui Examples: Examples To add a new remote printer, printer1, for a computer, Client1, which is visible for the user account where this command is run, type: rundll32 printui.dll PrintUIEntry /in /n\\client1\printer1 To add a printer using the add printer wizard and using an .inf file, InfFile.inf, located on drive c: at Infpath, type: rundll32 printui.dll PrintUIEntry /ii /f c:\Infpath\InfFile.inf To delete an existing printer, printer1, on a computer, Client1, type: rundll32 printui.dll PrintUIEntry /dn /n\\client1\printer1 To add a per computer printer connection, printer2, for all users of a computer, Client2, type (the connection will be applied when a user logs on): rundll32 printui.dll PrintUIEntry /ga /n\\client2\printer2 To delete a per computer printer connection, printer2, for all users of a computer, Client2, type (the connection will be deleted when a user logs on): rundll32 printui.dll PrintUIEntry /gd /n\\client2\printer2 To view the properties of the print server, printServer1, type: rundll32 printui.dll PrintUIEntry /s /t1 /c\\printserver1 To view the properties of a printer, printer3, type: rundll32 printui.dll PrintUIEntry /p /n\\printer3 * https://www.der-windows-papst.de/2015/05/14/netzwerkdrucker-per-kommandozeile-einrichten/ Druckerinstallation per Kommandozeile. Das Einrichten eines Netzwerkdrucker per CMD mit folgendem Befehl: rundll32.exe printui.dll,PrintUIEntry /in /n “\\printsvr\KonicaMinolta 240f” Der Parameter /in bedeutet > install network printer Der Parameter /n gibt den Freigabenamen des Druckers an. In diesem Beispiel mit Pfadnamen zum Printserver. ====== Office 2013/Office 365 ====== * **Office nimmt nicht die User Crendentials:** * Achtung: https://technet.microsoft.com/en-us/library/jj683102.aspx#Bkmk_4_DeleteCreds To delete an Office profile that may still be cached From Registry Editor, browse to: HKEY_CURRENT_USER\Software\Microsoft\Office\15.0\Common\Identity\Identities Choose the Office profile that you want to delete, and then choose Delete. From the Identity hive, navigate to the Profiles node, choose that same identity, open the shortcut menu (right-click), and then choose Delete. * Office 2013 aktivieren: @echo off if not EXIST "C:\Program Files (x86)\Microsoft Office\Office15\" GOTO End if EXIST "C:\activated.txt" GOTO End cd "C:\Program Files (x86)\Microsoft Office\Office15\" cscript ospp.vbs /act > C:\activated.txt :End * Clutter überall deaktivieren: 1. Powershell administrative Berechtingungen 2. Set-ExecutionPolicy Unrestricted –force 3. $UserCredential = Get-Credential 4. $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic –AllowRedirection 5. Import-PSSession $Session 6. Get-Mailbox -ResultSize Unlimited | Set-Clutter -Enable $False ====== Windows Aktivierungsstatus ====== So überprüfst Du, ob der KMS Server aktiviert Slmgr.vbs /ckms Slmgr.vbs /skms KMS_SERVER Du kannst mit dem folgenden Befehl im Commandprompt überprüfen, ob die Aktivierung erfolgreich durchgeführt wird: slmgr.vbs –ato * am DNS Server: Using DNS Manager, in the appropriate forwarding lookup zone, create a new SRV RR using the appropriate information for the location. By default, KMS listens on TCP port 1688, and the service is _VLMCS. Table 2 contains example settings for a SRV RR. Table 2 SRV Resource Record Name Setting Service _VLMCS Protocol _TCP Port number 1688 Host offering the service FQDN of KMS Host ====== Windows PE Boot Environment ====== * Windows 7 : shift + F10 -> Konsole ipconfig /all -> ip check drvload Pfad/*.inf -> Treiber laden ====== Zugriff auf lokale Gruppenrichtlinien ====== * start - ausführen -> mmc.exe -> Kontext der lokalen Gruppenrichtlinien des Computers importieren * Ohne diese Maßnahmen lassen sich die Windows Updates auf einem lokalen Server der nicht Mitglied einer Domäne ist nicht sinnvoll konfigurieren * zB: Updates konfigurieren falls betroffener Server kein Mitglied der Domäne ist / möchte täglich nach Updates suchen / Treiberupdates ausschließen / um 01:00 soll er installieren und auch automatisch neu starten wenn notwendig * Getestet auf Windows 2019 Standard {{:know-how:0-local-gpo-mmc-local-computer.png?400|}} {{:know-how:1-local-gpo-automatic-updates-configuration.png?400|}} {{:know-how:2-local-gpo-activate-deactivated.png?400|}} ====== WSUS ====== * Application Pool WSUS stürzt immerwieder ab: * https://blogs.msdn.microsoft.com/the_secure_infrastructure_guy/2015/09/02/windows-server-2012-r2-wsus-issue-clients-cause-the-wsus-app-pool-to-become-unresponsive-with-http-503/ * Application Pool Größe erhöhen über IIS Manager -> WSUS * Bereinigung ausführen: # Variablen $DateFormat = Get-Date -format yyyyMMdd-HH-mm $Logfile = "D:\Logs\wsus-bereinigung-$DateFormat.log" # WSUS Bereinigung durchführen Invoke-WsusServerCleanup -CleanupObsoleteUpdates -CleanupUnneededContentFiles -CompressUpdates -DeclineExpiredUpdates -DeclineSupersededUpdates | Out-File $Logfile * Speicherort für die Updates verschieben (https://mntechblog.de/wsus-speicherort-updates-verschieben/) * zB: Nach F:\WSUS verschieben und Logfile erstellen * C:\Program Files\Update Services\Tools\WsusUtil.exe movecontent F:\WSUS F:\WSUS.log [-skipcontent] * Mit skipcontent ändert er offenbar nur die Config und versucht keinen Kopiervorgang * Achtung er schreibt es passt aber er ändert das VZ nicht !!! * Bei Erfolg und das alte Datenverzeichnis LÖSCHEN sonst ein lock!! 2018-08-27T08:23:57 Successfully stopped WsusService. 2018-08-27T08:23:57 Beginning content file location change to F:\WSUS\ 2018-08-27T08:23:57 Did not copy files due to -skipcopy flag. 2018-08-27T08:23:57 Successfully changed WUS configuration. 2018-08-27T08:23:59 Successfully changed IIS virtual directory path. 2018-08-27T08:23:59 Successfully removed existing local content network shares. 2018-08-27T08:23:59 Successfully created local content network shares. 2018-08-27T08:23:59 Successfully changed registry value for content store directory. 2018-08-27T08:23:59 Successfully changed content file location. 2018-08-27T08:24:01 Successfully started WsusService. 2018-08-27T08:24:01 Content integrity check and repair... 2018-08-27T08:24:01 Initiated content integrity check and repair. ====== Office 365 Online World of Microsoft ====== ===== Regelwerke für Nachrichten / Message Flows ===== * Regelwerk um Nachrichten mit bestimmten Eigenschaften abzulehnen zB: DLP {{:know-how:dlp-regeln-microsoft.png?200|}} * Regelwerk um Nachrichten an Verteiler abzulehnen die folgende Charakteristik aufweisen / Absender ist außerhalb der Organisation und die Empfangsemail ist zB: 1a@domain.foo oder 1ab@domain.foo ^[1-9]{1}[a-zA-Z]{1,2}@domain.foo$ * Wenn es sich hier um Gruppenverteiler handelt (zB: security enabled) ist es **NICHT** möglich auf den Recipient zu matchen (danke Microsoft, richtig gute Idee :)) / Offenbar werden nur folgende Regex für meinen use case unterstützt: https://learn.microsoft.com/de-de/exchange/mail-flow-best-practices/regular-expressions-usage-transport-rules / Es wird auf **to** Header gematched mit folgenden patterns 'To' header matches the following patterns: '^\d\S@domain.foo$' or '^\d\S\S@domain.foo$' {{:know-how:dlp_distribution_list.png?400|}} * Alternative Variante mit dem Setzen von **msExchRequireAuthToSendTo = TRUE** für die betroffenen Gruppen / Achtung hier braucht es die Exchange LDAP Attribute - Untested - **https://www.reddit.com/r/exchangeserver/comments/t0mi80/msexchrequireauthtosendto_on_synced_exchange/** Von deucalion75 bei Reddit With all of that said, you'll definitely want to download the latest UR of Exchange (2016 typically works best, but any should do) and extract it to your schema master. Then, in an elevated powershell, run the following to expand your attributes: .\Setup /PrepareSchema /IAcceptExchangeServerLicenseTerms .\Setup /PrepareAD /OrganizationName:FirstOrganization /IAcceptExchangeServerLicenseTerms .\Setup /PrepareAllDomains /IAcceptExchangeServerLicenseTerms User avatar level 2 justinb19 · /IAcceptExchangeServerLicenseTerms_DiagnosticDataON ===== Weiterleitung aktivieren ===== * Falls es erforderlich wird "Weiterleitungen" zu aktivieren - Achtung Microsoft hat hier gegen Ende November/Dezember 2020 die Policy geändert - dass per **default** **keine Weiterleitungen mehr erlaubt sind** * Bei **Filterrichtlinie für ausgehendes Spam ‎(immer EIN)‎ - Richtlinie bearbeiten** * https://protection.office.com/antispam {{:know-how:2_weiterleitungen_filterrichtlinie_fuer_ausgehenden_spam.png?400|}} ===== Whitelist Absender ===== * **Achtung** Befindet sich aktuell (2024) unter: https://security.microsoft.com/antispam , keine Exchange Regel mehr * **Antispam-Eingangsrichtlinie** -> dort lassen sich Absendeadressen hinzufügen {{:know-how:0-antispam-whitelist-sender-address.png?400|}} ===== Spam in Junk-Mail ===== * Teilweise werden Mails von MS zum Frühstück verspeist und der Sender weiß nicht , dass die Mail nicht zugestellt wurde , wenn die Option Spam auf **"Nachricht löschen"** steht - mit **"Nachricht in Junk-E-Mail verschieben"** wird sie zumindest zum Empfänger zugestellt * https://security.microsoft.com/antispam : {{:know-how:spam-in-junkmail.png?400|}} ====== Powershell - nice to know ====== * Wird ein Powershell Skript aufgerufen , das mehrere Ausgaben enthält zB: mit write-host kann nicht einfach "redirected" werden - sondern zB: mit Start-Transcript und Stop-Transcript kann die Ausgabe aufgezeichnet werden * https://ss64.com/ps/syntax-redirection.html PS C:\> Start-Transcript -path c:\docs\Text3.txt .\YOUR-SCRIPT.ps1 PS C:\> Stop-Transcript ====== Windows Server 2019 ====== ===== Domain Controller hinzufügen ===== * Debugging mit dcdiag * Empfehlung Resolver "überkreuzen" dc1 resolved zuerst über dc2 und dc2 zuerst über dc1 * Zuerst Server installieren mit lokalem Benutzer - ins AD setzen und dann die Rolle hinzufügen * DHCP Server Konfiguration aktualisieren für weiteren DNS Server * Domäne: **schule.intern** Server **dc2.schule.intern** {{:know-how:0_controller_add_rollen_hinzufuegen_domain_dienste.png?400|}} {{:know-how:1_controller_add_installation_starten.png?400|}} {{:know-how:2_controller_add_taskmanager.png?400|}} {{:know-how:3_controller_add_server_heraufstufen_domain_controller.png?400|}} {{:know-how:4_controller_add_domaincontroller_hinzufuegen_vorhanden.png?400|}} {{:know-how:5_controller_add_full_provisioning_domain_controller.png?400|}} {{:know-how:6_controller_add_dns_fehler_ok.png?400|}} {{:know-how:7_controller_add_beliebige_domain_controller.png?400|}} {{:know-how:8_controller_add_standard_pfade.png?400|}} {{:know-how:9_controller_add_warnings_ok_dns.png?400|}} {{:know-how:10_controller_add_alles_ok.png?400|}} ===== MAK Key Fehler Aktivierung ===== * https://www.ugg.li/windows-server-2019-aktivierung-der-eingegebene-produkt-key-funktioniert-nicht-0x80070490/ * Key definieren über cli: **slmgr /ipk KEY** {{:know-how:windows_2019_mak_key_troubles.png?400|}} {{:know-how:windows_2019_key_cmd.png?400|}} ====== Windows 10 ====== ===== Unattended XML File erstellen ===== * Vielen Dank: * https://learn.microsoft.com/en-us/windows-hardware/get-started/adk-install * https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-vista/cc722029(v=ws.10) * https://learn.microsoft.com/de-de/previous-versions/windows/it-pro/windows-8.1-and-8/hh825702(v=win.10) * https://learn.microsoft.com/de-de/windows-hardware/customize/desktop/unattend/microsoft-windows-international-core-winpe-uilanguage * https://www.windowscentral.com/how-create-unattended-media-do-automated-installation-windows-10#uefi_partition_setup * https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/automate-windows-setup?view=windows-11 * https://superuser.com/questions/715368/how-to-bypass-the-os-edition-selection-page-in-a-windows-unattended-setup * https://learn.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-pnpcustomizationsnonwinpe-driverpaths * Ziel war es ein unattended XML File zu erstellen , das die Festplatte partitioniert (**UEFI**) und eine Workgroup setzt - sonst soll **alles** Default sein damit der User das Windows 10 Professional Setup klicki feeling bekommt und in **Eigenverantwortung** die Fragen beantwortet * Es wurde eine Windows 10 Pro/Enterprise ISO genutzt die von den Microsoft VSLC Servern herunter geladen wurde * Das XML File kann sowohl am WDS Server für eine install.wim (zB: aus der ISO extrahiert und dem WDS Server hinzugefügt) als auch für eine USB Stick Installation verwendet werden - oder überhaupt per /unattend:XML_FILE definiert werden :) * XML am WDS Server (hier wurde bereits Windows 10 Pro ausgewählt beim install.wim Import) **unattended-uefi.xml**: de-DE de-DE de-DE de-DE 0407:00000407 1 300 Primary 2 100 EFI 3 128 MSR 4 Primary true NTFS 1 1 DE94BBA4-06D1-4D40-A16A-BFD50179D6AC C 4 4 NTFS 3 3 2 2 FAT32 0 true 0 4 OnError true Private * XML in Kombination mit iPXE - großes ISO Image **unattended-uefi.xml**: de-DE de-DE de-DE de-DE 0407:00000407 1 300 Primary 2 100 EFI 3 128 MSR 4 Primary true NTFS 1 1 DE94BBA4-06D1-4D40-A16A-BFD50179D6AC C 4 4 NTFS 3 3 2 2 FAT32 0 true 0 4 OnError /IMAGE/NAME Windows 10 Pro true * Auf und mit **USB Stick** **Boot** mit **vmd** treibern unter STICK_ROOT\driver\vmd , **Autounattend.xml** - bei Lenovo F12 und Boot USB Stick de-DE de-DE de-DE de-DE 0407:00000407 C:\driver\vmd\ 1 300 Primary 2 100 EFI 3 128 MSR 4 Primary true NTFS 1 1 DE94BBA4-06D1-4D40-A16A-BFD50179D6AC C 4 4 NTFS 3 3 2 2 FAT32 1 true 1 4 OnError /IMAGE/NAME Windows 10 Pro true * Aber wie kommt es zu den lustigen XML Dateien und wie können sie validiert werden ? * ADK installieren: https://learn.microsoft.com/en-us/windows-hardware/get-started/adk-install * Programm aus ADK: **"Windows System Image Manager"** * Links unten bei **Windows-Image** **install.wim** importieren und Katalog herunterladen lassen / dauert initial **sehr** lang {{:know-how:0-windows-image-manager.png?400|}} ===== Aktivieren d. Keys aus BIOS ===== * Sollte das Notebook zurück gesetzt worden sein und das Gerät mit dem Produktschlüssel ausgeliefert worden sein {{:know-how:aktivierung_1.png?400|}} {{:know-how:aktivierung_2.png?400|}} {{:know-how:aktivierung_3.png?400|}} {{:know-how:aktivierung_4.png?400|}} {{:know-how:aktivierung_5.png?400|}} ===== MBR to UEFI ===== * Konvertieren bestehender MBR basierender Systeme auf UEFI * Getestet mit Windows 10 LTSC 2019 (1809) - bestehendes System von MBR auf UEFI migrieren (Hyper-V Generation 1 -> Generation 2 Maschine) / Gebootet wurde von LTSC 2021 Windows 10 ISO {{:know-how:0_convert_mbr_to_gpt.png?400|}} {{:know-how:1_convert_mbr_to_gpt.png?400|}} ===== Microsoft Store auf LTSC 2019 ===== * Folgendes Problem: es werden Applikationen im msix Format benötigt https://its.bitmedia.at/ecdl-at/kandidatin/ - Software * Offiziell nicht supported - aber wo ein Wille ist findet sich ein Weg 8-) * **Update:** Die Pakete gibts doch offiziell zB: "Windows 10 Enterprise LTSC 2019 Inbox Apps" - wer zB: Zugriff auf das VLSC Center von Microsoft hat / **Achtung** SHA1 Summen der Originaldateien von Microsoft unterscheiden sich zum Teil von **LTSC-Add-MicrosoftStore** - es können natürlich unterschiedliche Versionen sein * **Update 2:** Es **reicht Add-AppxPackage 'PFAD\*.msix' ** aktueller User - Pfad zur msix Datei für die Installation von zB: Bitmedia msix File - und das Querladen muss aktiviert sein per GPO - es muss kein Store zwingend installiert sein ! - danke an Christoph Adl für den Tipp * Danke: https://github.com/kkkgo/LTSC-Add-MicrosoftStore , https://woshub.com/how-to-download-appx-installation-file-for-any-windows-store-app/ , https://apps.microsoft.com/store/detail/app-installer/9NBLGGH4NNS1 , https://store.rg-adguard.net/ , Georg Bernold für den Hinweis, dass es hier auch offizielle Pakete gibt * Zuerst wird der Microsoft Store auf den Geräten installiert / Nach erfolgter Installation wird für den jeweilige Benutzer, der sich einloggt der **App-Installer** installiert / MSIX Dateien können nun geöffnet und gestartet werden (entsprechene GPO für das Querladen von Apps muss aktiviert werden - sonst können nur Apps direkt aus dem Store installiet und gestartet werden * 1. ListenpunktMicrosoft Store installieren - Computer Startup GPO für betroffene Geräte: * \\server\freigabe\LTSCStore\ enthält den Content von: {{ :know-how:ltscstore.tar.gz |}} (https://github.com/kkkgo/LTSC-Add-MicrosoftStore , Appx/MSIX von: https://apps.microsoft.com/store/detail/app-installer über https://store.rg-adguard.net/ ) * **ltsc_store.bat** robocopy /E /R:2 \\server\freigabe\LTSCStore\ C:\TMP\ if %ERRORLEVEL% EQU 16 goto end if %ERRORLEVEL% EQU 15 goto end if %ERRORLEVEL% EQU 14 goto end if %ERRORLEVEL% EQU 13 goto end if %ERRORLEVEL% EQU 12 goto end if %ERRORLEVEL% EQU 11 goto end if %ERRORLEVEL% EQU 10 goto end if %ERRORLEVEL% EQU 9 goto end if %ERRORLEVEL% EQU 8 goto end if %ERRORLEVEL% EQU 7 goto install if %ERRORLEVEL% EQU 6 goto install if %ERRORLEVEL% EQU 5 goto install if %ERRORLEVEL% EQU 4 goto install if %ERRORLEVEL% EQU 3 goto install if %ERRORLEVEL% EQU 2 goto install if %ERRORLEVEL% EQU 1 goto install if %ERRORLEVEL% EQU 0 goto install :install if exist "C:\store_installed.txt" goto end cd C:\TMP\LTSC-Add-MicrosoftStore-2019 start /wait .\Add-Store.cmd if %ERRORLEVEL% EQU 0 echo success > C:\store_installed.txt :end * 2. User GPO Login / Powershell **App-installer** Installieren und die ITS Bitmedia App , die zuvor herunter geladen wurde im MSIX Format / **Achtung** wird in den jeweiligen User Profilen einmalig beim Login abgelegt und installiert * **install_itsr.ps1** if ( -not ( Test-Path $env:userprofile\AppData\Local\itsr3_0_2_installed.txt )) { if (Test-Path "C:\store_installed.txt") { if ( -not ( Test-Path $env:userprofile\AppData\Local\app_installer_installed.txt ) ) { Add-AppxPackage "C:\tmp\LTSC-Add-MicrosoftStore-2019\App-installer\Microsoft.UI.Xaml.2.7_7.2208.15002.0_x64__8wekyb3d8bbwe.Appx" Add-AppxPackage "C:\tmp\LTSC-Add-MicrosoftStore-2019\App-installer\Microsoft.VCLibs.140.00.UWPDesktop_14.0.30704.0_x64__8wekyb3d8bbwe.Appx" Add-AppxPackage "C:\tmp\LTSC-Add-MicrosoftStore-2019\App-installer\Microsoft.DesktopAppInstaller_2023.118.406.0_neutral_~_8wekyb3d8bbwe.Msixbundle" if($?) { echo "installed" > $env:userprofile\AppData\Local\app_installer_installed.txt } } } Add-AppxPackage "\\server\freigabe\ITS-Organizer\itsr3-3.0.2.msix" if($?) { echo "installed" > $env:userprofile\AppData\Local\itsr3_0_2_installed.txt } } ===== MS-Intune Nice-to-Know Bug Features / powershell ===== * FIXME - restart abbrechen mit shutdown -a / Azure integrierter Rechner / Nicht integrierter Rechner Unterschiede * Factory Reset mit -> **cmd (als Administrator) -> systemreset** * Infos zum Umgang mit MS Graph Intune Powershell / Installation PS C:\Windows\system32> Install-Module -Name Microsoft.Graph.Intune Der NuGet-Anbieter ist erforderlich, um den Vorgang fortzusetzen. PowerShellGet erfordert die NuGet-Anbieterversion 2.8.5.201 oder höher für die Interaktion mit NuGet-basierten Repositorys. Der NuGet-Anbieter muss in "C:\Program Files\PackageManagement\ProviderAssemblies" oder "C:\Users\christian.CZECZIL\AppData\Local\PackageManagement\ProviderAssemblies" verfügbar sein. Sie können den NuGet-Anbieter auch durch Ausführen von 'Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force' installieren. Möchten Sie den NuGet-Anbieter jetzt durch PowerShellGet installieren und importieren lassen? [J] Ja [N] Nein [H] Anhalten [?] Hilfe (Standard ist "J"): j Nicht vertrauenswürdiges Repository Sie installieren die Module aus einem nicht vertrauenswürdigen Repository. Wenn Sie diesem Repository vertrauen, ändern Sie dessen InstallationPolicy-Wert, indem Sie das Set-PSRepository-Cmdlet ausführen. Möchten Sie die Module von 'PSGallery' wirklich installieren? [J] Ja [A] Ja, alle [N] Nein [K] Nein, keine [H] Anhalten [?] Hilfe (Standard ist "N"): j PS C:\Windows\system32> Get-Command -Module Microsoft.Graph.Intune PS C:\Windows\system32> Install-Module -Name Microsoft.Graph.Intune PS C:\Windows\system32> echo $? ----- PS C:\Windows\system32> Set-ExecutionPolicy Bypass PS C:\Windows\system32> Connect-MSGraph -AdminConsent Get-IntuneManagedDevice PS C:\Windows\system32> Get-Command -Module Microsoft.Graph.Intune CommandType Name Version Source ----------- ---- ------- ------ Alias Get-AADGroup 6.1907.1.0 Microsoft.Graph.Intune Alias Get-AADGroupCreatedOnBehalfOf 6.1907.1.0 Microsoft.Graph.Intune Alias Get-AADGroupCreatedOnBehalfOfReference 6.1907.1.0 Microsoft.Graph.Intune Alias Get-AADGroupGroupLifecyclePolicy 6.1907.1.0 Microsoft.Graph.Intune Alias Get-AADGroupMember 6.1907.1.0 Microsoft.Graph.Intune Alias Get-AADGroupMemberOf 6.1907.1.0 Microsoft.Graph.Intune Alias Get-AADGroupMemberOfReferenceSet 6.1907.1.0 Microsoft.Graph.Intune Alias Get-AADGroupMemberReferenceSet 6.1907.1.0 Microsoft.Graph.Intune Alias Get-AADGroupOwner 6.1907.1.0 Microsoft.Graph.Intune Alias Get-AADGroupOwnerReferenceSet 6.1907.1.0 Microsoft.Graph.Intune Alias Get-AADGroupPhoto 6.1907.1.0 Microsoft.Graph.Intune Alias Get-AADGroupPhotoDataData 6.1907.1.0 Microsoft.Graph.Intune Alias Get-AADGroupPhotoSet 6.1907.1.0 Microsoft.Graph.Intune Alias Get-AADGroupPhotoSetDataData 6.1907.1.0 Microsoft.Graph.Intune Alias Get-AADGroupSetting 6.1907.1.0 Microsoft.Graph.Intune Alias Get-IntuneAppConfigurationPolicyTargeted 6.1907.1.0 Microsoft.Graph.Intune Alias Get-IntuneAppConfigurationPolicyTargetedApp 6.1907.1.0 Microsoft.Graph.Intune Alias Get-IntuneAppConfigurationPolicyTargetedAssignment 6.1907.1.0 Microsoft.Graph.Intune Alias Get-IntuneAppConfigurationPolicyTargetedDeploym... 6.1907.1.0 Microsoft.Graph.Intune Alias Get-IntuneApplePushNotificationCertificate 6.1907.1.0 Microsoft.Graph.Intune Alias Get-IntuneAppProtectionPolicy 6.1907.1.0 Microsoft.Graph.Intune Alias Get-IntuneAppProtectionPolicyAndroid 6.1907.1.0 Microsoft.Graph.Intune Alias Get-IntuneAppProtectionPolicyAndroidApp 6.1907.1.0 Microsoft.Graph.Intune Alias Get-IntuneAppProtectionPolicyAndroidAssignment 6.1907.1.0 Microsoft.Graph.Intune Alias Get-IntuneAppProtectionPolicyAndroidDeploymentS... 6.1907.1.0 Microsoft.Graph.Intune ----- Discovering available commands Get the full list of available cmdlets: Get-Command -Module Microsoft.Graph.Intune Get documentation on a particular cmdlet: Get-Help Use a UI to see the parameter sets more easily: Show-Command .... ===== MS-Intune BYOD ===== * BYOD Enrollment für MS Intune / Getestet auf Windows 10 LTSC 2019 {{:know-how:0-ms-intune-byod.png?400|}} * MDM Enrollment URL wenns in der Microsoft Cloud liegt: * https://enrollment.manage.microsoft.com/enrollmentserver/discovery.svc * Für Auto Configuration müssen folgende DNS Einträge gesetzt werden ( https://techcommunity.microsoft.com/t5/intune-customer-success/which-cnames-to-use-for-auto-discovery-during-mdm-enrollment/ba-p/279952 ) Type Host name Points to TTL CNAME EnterpriseEnrollment. company_domain.com EnterpriseEnrollment-s.manage.microsoft.com 1 hour The company_domain in the FQDN should be the registered domain name(s) you are using for single sign on with the UPN. For example if users at Contoso use name@contoso.com as their email/UPN, the Contoso DNS admin would need to create the following CNAMEs. Type Host name Points to TTL CNAME EnterpriseEnrollment. contoso.com EnterpriseEnrollment-s.manage.microsoft.com 1 hour If you have more than one UPN suffix, you need to create one CNAME for each domain name and point each one to EnterpriseEnrollment-s.manage.microsoft.com. For example if users at Contoso use name@contoso.com, but also use name@us.contoso.com, and name@eu.constoso.com as their email/UPN, the Contoso DNS admin would need to create the following CNAMEs. Type Host name Points to TTL CNAME EnterpriseEnrollment. contoso.com EnterpriseEnrollment-s.manage.microsoft.com 1 hour CNAME EnterpriseEnrollment. us.contoso.com EnterpriseEnrollment-s.manage.microsoft.com 1 hour CNAME EnterpriseEnrollment. eu.contoso.com EnterpriseEnrollment-s.manage.microsoft.com 1 hour Registration vs Enrollment CNAMEs Azure Active Directory has a different CNAME that it uses for device registration for iOS, Android, and Windows devices. Intune conditional access requires devices to be registered, also called “workplace joined”. If you plan to use conditional access, you should also configure the EnterpriseRegistration CNAME for each company name you have. Type Host name Points to TTL CNAME EnterpriseRegistration. company_domain.com EnterpriseRegistration.windows.net 1 hour ===== Remotehilfe ===== * Getestet auf Windows 10 LTSC2019 / Windows 10 Pro 1909 * **Anforderung:** Eine Windows built in Möglichkeit finden um Benutzern Remote Unterstützung geben zu können - **Remotehilfe** * Technische Infos: Pfad: %SystemRoot%\system32\quickassist.exe Installation Powershell zB: auf LTSC 2019 Add-WindowsCapability -Online -Name "App.Support.QuickAssist~~~~0.0.1.0" Traffic Firewall: -funktioniert mit Proxy Server (getestet mit Ubuntu 18.04 / Squid) -Einer der Einstiegspunkte zB: zum Blockieren - remoteassistance.support.services.microsoft.com Port 443 Kommunikation läuft grundsätzlich über TLS 1.2 siehe hiefür https://docs.microsoft.com/en-us/windows/client-management/quick-assist -Laufende Kommunikation: x.x.x.x - - [06/Apr/2021:14:06:54 +0200] "CONNECT webpooldm20r04.infra.lync.com:443 HTTP/1.0" 200 7690 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; Win64; x64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)" TCP_TUNNEL:HIER_DIRECT 52.112.81.29 - - x.x.x.x x.x.x.x - - [06/Apr/2021:14:06:54 +0200] "CONNECT browser.pipe.aria.microsoft.com:443 HTTP/1.0" 200 6824 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; Win64; x64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)" TCP_TUNNEL:HIER_DIRECT 40.78.128.150 - - x.x.x.x x.x.x.x - - [06/Apr/2021:14:06:54 +0200] "CONNECT web.vortex.data.microsoft.com:443 HTTP/1.0" 200 6873 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; Win64; x64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)" TCP_TUNNEL:HIER_DIRECT 40.77.226.250 - - x.x.x.x x.x.x.x - - [06/Apr/2021:14:06:54 +0200] "CONNECT web.vortex.data.microsoft.com:443 HTTP/1.0" 200 6452 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; Win64; x64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)" TCP_TUNNEL:HIER_DIRECT 40.77.226.250 - - x.x.x.x x.x.x.x - - [06/Apr/2021:14:06:57 +0200] "CONNECT webpooldm20r04.infra.lync.com:443 HTTP/1.0" 200 7706 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; Win64; x64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)" TCP_TUNNEL:HIER_DIRECT 52.112.81.29 - - x.x.x.x x.x.x.x - - [06/Apr/2021:14:06:57 +0200] "CONNECT browser.pipe.aria.microsoft.com:443 HTTP/1.0" 200 7249 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; Win64; x64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)" TCP_TUNNEL:HIER_DIRECT 40.78.128.150 - - x.x.x.x x.x.x.x - - [06/Apr/2021:14:06:57 +0200] "CONNECT webpooldm20r04.infra.lync.com:443 HTTP/1.0" 200 14541 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; Win64; x64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)" TCP_TUNNEL:HIER_DIRECT 52.112.81.29 - - x.x.x.x x.x.x.x - - [06/Apr/2021:14:06:57 +0200] "CONNECT web.vortex.data.microsoft.com:443 HTTP/1.0" 200 8557 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; Win64; x64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)" TCP_TUNNEL:HIER_DIRECT 40.77.226.250 - - x.x.x.x x.x.x.x - - [06/Apr/2021:14:06:57 +0200] "CONNECT web.vortex.data.microsoft.com:443 HTTP/1.0" 200 6031 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; Win64; x64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)" TCP_TUNNEL:HIER_DIRECT 40.77.226.250 - - x.x.x.x * Ablauf Sitzung * Programm auf beiden Maschinen starten d.h. derjenige der Support braucht (Support Nehmer) und derjenige der Support gibt (Support Geber) {{:know-how:0-remote-hilfe.png?400|}} * Support Geber geht auf "Unterstützung gewähren" und Support Nehmer braucht die ID des Support Gebers {{:know-how:1-remote-hilfe.png?400|}} * Support geben d.h. unterstützung gewähren (erfordert Microsoft Account) {{:know-how:2-remote-hilfe-support-geben.png?400|}} * Support Geber erhält ID die dem Support Nehmer mitgeteilt werden muss {{:know-how:3-remote-hilfe-support-geben-id.png?400|}} * Support Nehmer trägt ID des Gebers ein {{:know-how:4-remote-hilfe-support-anfordern-id.png?400|}} * Support Geber wählt ob er Vollzugriff oder nur Bildschirm anzeigen möchte (eigentlich sollte dies der Support Nehmer bestimmen .. :)) {{:know-how:5-remote-hilfe-support-full-access.png?400|}} * Support Nehmer muss Zugriff erlauben {{:know-how:6-remote-hilfe-freigeben.png?400|}} * Sitzung wird aufgebaut {{:know-how:7-remote-hilfe-access.png?400|}} * Grundsätzlich können GPO's definiert werden ob auf Maschinen zugegriffen werden darf oder nicht / Funktioniert bei LTSC 2019 offenbar nicht, Einstellung wird vom System ignoriert **FIXME** ===== Administrator Account Hinzufügen / Resetten / Aktivieren ===== * Schöne Lösung: http://www.top-password.com/blog/4-ways-to-enable-built-in-administrator-account-on-windows/ * Booten von externem Datenträger zB: Windows live DVD/ USB Stick / shift + F10 für command prompt * utilman.exe durch cmd.exe austauschen im system32 vom Produktiv - System * Wenn das System noch bootet Links neben Power Icon drücken -> Command Prompt öffnet sich mit Admin Berechtigungen * Administrator Account aktivieren und Passwort zurück setzen: net user Administrator Administrator /active:yes /expires:never * Interessant bei zB: Ungarisch herauszufinden wie der Administrator User heißt , siehe hierzu https://social.technet.microsoft.com/wiki/contents/articles/13813.localized-names-for-administrator-account-in-windows.aspx ===== Lokale Benutzer Startup ===== * Pfad für lokale Startup Skripten: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup * Ablage von zB: bat Files möglich ===== Upgrade LTSB 2016 to LTSC2019 ===== * Geht über LTSC2019 ISO obwohl offiziell nicht supported - über reguläres Setup Programm * Nach Upgrade ist **sysprep** nicht mehr möglich (Microsoft.Windows.SecondaryTileExperience_10.0.0.0_netral_cw5n1h2txyewy) Offenbar verweist das System auf diese App die jedoch bereits gelöscht wurde durch das Upgrade (Errors: **0x3cf2** , **0x80073cf2**) * sysprep hat wieder funktioniert nach folgenden Schritten FIXME 1. Systemplatte räumen lassen / inklusive Systemdateien 2. Benutzerprofile löschen über Win GUI , die sich löschen lassen / Erweiterte Einstellungen / Benutzerprofile 3. Installation kb4476976 https://support.microsoft.com/en-us/topic/january-22-2019-kb4476976-os-build-17763-292-21eea485-af3a-2d1e-e3e5-f48ba53def26 (?) 4. Rechner aus dem AD nehmen / wieder Workstation wie bei Erstmaligem sysprep 5. AppXDB Editor für Pakete - https://github.com/SoftSonic83/AppxDBEditor Microsoft.Windows.SecondaryTileExperience=0 Windows.MiracastView=0 Microsoft.LanguageExperiencePackde-DE=0 6. AppxDBEditor cmd -> so lange bis keine Fehlermeldung kommt / Status ändern auf "löschbar" 7. Admin Powershell Get-AppxPackage -AllUser -Name Microsoft.Windows.SecondaryTileExperience | Remove-AppxPackage -AllUsers Get-AppxPackage -AllUser -Name Windows.MiracastView | Remove-AppxPackage -AllUsers Get-AppxPackage -AllUser -Name Microsoft.LanguageExperiencePackde-DE | Remove-AppxPackage -AllUsers 8. Reboot 9. Sysprep hakerl setzen / oobe Experience / herunterfahren ===== Upgrade Windows 7 to Windows 10 ===== * Mit Windows Update Assistent * Sollte bei "Updates suchen" bei 46% stecken bleiben folgende Schritte durchführen - Stop vom Windows Update Dienst - er startet ihn ndanach wieder automatisch Administrator CMD.exe -> net stop wuauserv to stop ===== Windows - Telemetrie für die Firewall zum blocken ===== * Achtung aggregierte Portale die zB: bei akamai liegen bei ipset blocks vortex.data.microsoft.com vortex-win.data.microsoft.com telecommand.telemetry.microsoft.com telecommand.telemetry.microsoft.com.nsatc.net oca.telemetry.microsoft.com oca.telemetry.microsoft.com.nsatc.net sqm.telemetry.microsoft.com sqm.telemetry.microsoft.com.nsatc.net watson.telemetry.microsoft.com watson.telemetry.microsoft.com.nsatc.net redir.metaservices.microsoft.com choice.microsoft.com choice.microsoft.com.nsatc.net df.telemetry.microsoft.com reports.wes.df.telemetry.microsoft.com wes.df.telemetry.microsoft.com services.wes.df.telemetry.microsoft.com sqm.df.telemetry.microsoft.com telemetry.microsoft.com watson.ppe.telemetry.microsoft.com telemetry.appex.bing.net telemetry.urs.microsoft.com telemetry.appex.bing.net settings-sandbox.data.microsoft.com vortex-sandbox.data.microsoft.com survey.watson.microsoft.com watson.live.com watson.microsoft.com statsfe2.ws.microsoft.com corpext.msitadfs.glbdns2.microsoft.com compatexchange.cloudapp.net cs1.wpc.v0cdn.net a-0001.a-msedge.net statsfe2.update.microsoft.com.akadns.net sls.update.microsoft.com.akadns.net fe2.update.microsoft.com.akadns.net diagnostics.support.microsoft.com corp.sts.microsoft.com statsfe1.ws.microsoft.com pre.footprintpredict.com i1.services.social.microsoft.com i1.services.social.microsoft.com.nsatc.net feedback.windows.com feedback.microsoft-hohm.com feedback.search.microsoft.com adnexus.net adnxs.com az361816.vo.msecnd.net az512334.vo.msecnd.net vortex-bn2.metron.live.com.nsatc.net vortex-cy2.metron.live.com.nsatc.net dmd.metaservices.microsoft.com ===== Systemsteuerung direkt ausführen als -> ms-setting ===== https://www.deskmodder.de/blog/2015/06/03/windows-10-einstellungen-direkt-aufrufen-ausfuehren-dialog/ Einstellungsseite Befehl Startseite ms-settings: Energiesparmodus ms-settings:batterysaver Energiesparmodus (Einstellungen) ms-settings:batterysaver-settings Akkuverbrauch (Nutzung) ms-settings:batterysaver-usagedetails Bluetooth-Geräte verwalten ms-settings:bluetooth Farben ms-settings:colors Datennutzung ms-settings:datausage Datum und Zeit ms-settings:dateandtime Untertitel für Hörgeschädigte ms-settings:easeofaccess-closedcaptioning Hoher Kontrast ms-settings:easeofaccess-highcontrast Bildschirmlupe ms-settings:easeofaccess-magnifier Sprachausgabe ms-settings:easeofaccess-narrator Tastatur ms-settings:easeofaccess-keyboard Maus ms-settings:easeofaccess-mouse Erleichterte Bedienung (Weitere Optionen) ms-settings:easeofaccess-otheroptions Sperrbildschirm ms-settings:lockscreen Offline Navigation (Karten) ms-settings:maps Flugzeugmodus ms-settings:network-airplanemode Proxy ms-settings:network-proxy VPN ms-settings:network-vpn Benachrichtigungen und Aktionen ms-settings:notifications Konto-Information ms-settings:privacy-accountinfo Kalender ms-settings:privacy-calendar Kontakte ms-settings:privacy-contacts Weitere Geräte ms-settings:privacy-customdevices Feedback ms-settings:privacy-feedback Position (Ortung) ms-settings:privacy-location Nachrichten ms-settings:privacy-messaging Mikrofon ms-settings:privacy-microphone Bewegungsdaten ms-settings:privacy-motion Funkempfang ms-settings:privacy-radios Spracherkennung, Freihand, Eingabe (Cortana) ms-settings:privacy-speechtyping Kamera ms-settings:privacy-webcam Region und Sprache ms-settings:regionlanguage Sprache (Ein- und Ausgabe) ms-settings:speech Windows Update ms-settings:windowsupdate Arbeitsplatzzugriff ms-settings:workplace Angeschlossene Geräte ms-settings:connecteddevices Für Entwickler ms-settings:developers Bildschirm ms-settings:display Maus und Touchpad ms-settings:mousetouchpad Mobilfunk ms-settings:network-cellular Einwahlverbindung (DFÜ) ms-settings:network-dialup DirectAccess ms-settings:network-directaccess Ethernet ms-settings:network-ethernet mobiler Hotspot ms-settings:network-mobilehotspot Wi-Fi ms-settings:network-wifi Wi-Fi (Einstellungen) ms-settings:network-wifisettings Optionale Funktionen ms-settings:optionalfeatures Familie und weitere Benutzer ms-settings:otherusers Personalisierung ms-settings:personalization Hintergrund ms-settings:personalization-background Farben ms-settings:personalization-colors Start ms-settings:personalization-start Netzbetrieb und Energiesparen ms-settings:powersleep Annäherungssensor ms-settings:proximity Display-Rotation ms-settings:screenrotation Anmeldeoptionen ms-settings:signinoptions Speicher (Verbrauch) ms-settings:storagesense Themes ms-settings:themes Eingabe (Rechtschreibung) ms-settings:typing Tablet-Modus ms-settings:tabletmode Datenschutzoptionen ms-settings:privacy ===== Windows RAM Belegung auslesen ===== f you don't mind using the command line, WMI can do this and is native with Windows XP and newer. Simply run wmic MEMORYCHIP get BankLabel,DeviceLocator,Capacity,Tag >wmic MEMORYCHIP get BankLabel,DeviceLocator,Capacity,Tag BankLabel Capacity DeviceLocator Tag BANK 0 2147483648 Bottom - Slot 1 (top) Physical Memory 0 BANK 1 4294967296 Bottom - Slot 2 (under) Physical Memory 1 (DeviceLocator will likely give you DIMM numbers on a desktop machine - the top/under slots are because I'm on a laptop. Both BankLabel and DeviceLocator formats may vary by machine.) ===== Startmenü anpassen ===== Step 1: Design your start menu Remove / add tiles and apps to and from your start menu ready for the layout to be exported Step 2: Run Windows PowerShell as administrator Run the PowerShell as administrator and run the command: Export-StartLayout –path .xml Should look like this: export-startlayout -path C:\startlayout.xml Step 3: Open Group policy management console (gpmc.msc) and create new GPO Create a new GPO Go to User Configuration or Computer Configuration > Policies > Administrative Templates >Start Menu and Taskbar Right-click Start Layout in the right pane, and click Edit. This opens the Start Layout policy settings (Please note you will need the Windows 10 GPO add in downloaded to do this, I have a How-to on my page on how to get them, or Windows server 2016.) Link: https://community.spiceworks.com/how_to/139795-add-windows-10-group-policy-objects-to-windows-server-2012-r2 Step 4: Configure the GPO Enter the following settings, and then click OK: Select Enabled Under Options, specify the path to the .xml file that contains the Start layout. For example, type C:\Users\Test01\StartScreen.xml or \\ShareName\StartScreen.xml. Optionally, enter a comment to identify the Start layout. Step 5: Roll out the GPO Open CMD on the server and type: gpupdate /force And get everyone to restart their work stations ===== AppAssoc exportieren - Achtung Fehler 0x80004002 ===== Microsoft Windows [Version 10.0.16299.309] (c) 2017 Microsoft Corporation. Alle Rechte vorbehalten. C:\Users\Administrator.RESERVE-PC01>cd Desktop C:\Users\Administrator.RESERVE-PC01\Desktop>dism /online /Export-DefaultAppAssociations:assoc-adobe.xml Tool zur Imageverwaltung für die Bereitstellung Version: 10.0.16299.15 Abbildversion: 10.0.16299.309 Fehler: 0x80004002 Die aktuellen Benutzerzuordnungen konnten nicht in die Datei "assoc-adobe.xml" exportiert werden. Weitere Informationen finden Sie in der Hilfe. Die DISM-Protokolldatei befindet sich unter "C:\Windows\Logs\DISM\dism.log". C:\Users\Administrator.RESERVE-PC01\Desktop> What the fuck :( https://social.technet.microsoft.com/Forums/en-US/5161bd23-733e-4e2f-a500-d652fc23b81d/the-current-user-associations-could-not-be-exported-to-file-error-0x80004002?forum=win10itprosetup wusa /uninstall /kb:4088776 what the fuck ² deinstall takes >45 minutes.. ---- dism /online /Export-DefaultAppAssociations:assoc-adobe.xml --- C:\Users\Administrator.RESERVE-PC01\Desktop>cd C:\TMP C:\TMP>dism /online /Export-DefaultAppAssociations:assoc-adobe.xml Tool zur Imageverwaltung für die Bereitstellung Version: 10.0.16299.15 Abbildversion: 10.0.16299.125 Der Vorgang wurde erfolgreich beendet. ===== batch driver installation ===== Speaking of newer versions of Windows. In Hyper-V Server 2012 r1 & r2, the command-line is: pnputil – Granger Sep 29 '16 at 3:48 ===== batch subdirectory search and delete ===== for /d /r "c:\" %%a in (temp\) do if exist "%%a" echo rmdir /s /q "%%a" For each folder (/d), recursively (/r) under c:\ test for the presence of a temp folder and if it exist, remove it directory removal command is only echoed to console. If the output is correct, remove the echo command ===== DISM magic commands ===== * dism magic (image mounted: -Image:D:\Mount) DISM /Online /Cleanup-Image /CheckHealth * Lenovo G2 ITL - Disk nicht gefunden bei WDS - Von **VMD** auf **AHCI** umstellen * WDS Fehler - Imagegröße ändert sich nicht in der GUI - Treiber werden NICHT hinzugefügt obwohl alles OK scheint * **Lösung** -> INDEX:2 * **Wie finde ich den INDEX** -> dism /Get-WimInfo /WimFile:File_image.wim * **Wie kann ich das gleiche Image wieder mounten nach FAIL** -> dism /cleanup-wim E:\TMP\dism-windows-10>.\Dism.exe -Mount-Wim -WimFile:E:\TMP\Windows10_1607_64Bi t_verteilen.wim -Index:2 -MountDir:E:\TMP-Mount Deployment Image Servicing and Management tool Version: 10.0.16299.15 Abbild wird bereitgestellt [==========================100.0%==========================] The operation completed successfully. E:\TMP\dism-windows-10>.\dism -Image:E:\TMP-Mount -Add-Driver -Driver:E:\Treiber \HP-800-G4-SFF\hp-800-g4-intel-nic-sp98256\src /Recurse Deployment Image Servicing and Management tool Version: 10.0.16299.15 Image Version: 10.0.14393.0 Suche nach zu installierenden Treiberpaketen... Anzahl der zu installierenden Treiberpakete: 2. 1 von 2 - E:\Treiber\HP-800-G4-SFF\hp-800-g4-intel-nic-sp98256\src\E1D\e1d68x64. inf wird installiert: INFO: DISM hat die Überprüfung der Treibersignatur übersprungen, weil die Versio nen des ausgeführten Betriebssystems und des Zielbetriebssystems nicht übereinst immen. Das Treiberpaket wurde erfolgreich installiert. 2 von 2 - E:\Treiber\HP-800-G4-SFF\hp-800-g4-intel-nic-sp98256\src\E1R\e1r68x64. inf wird installiert: INFO: DISM hat die Überprüfung der Treibersignatur übersprungen, weil die Versio nen des ausgeführten Betriebssystems und des Zielbetriebssystems nicht übereinst immen. Das Treiberpaket wurde erfolgreich installiert. The operation completed successfully. E:\TMP\dism-windows-10>.\Dism -Commit-Wim -MountDir:E:\TMP-Mount Deployment Image Servicing and Management tool Version: 10.0.16299.15 Abbild wird gespeichert [==========================100.0%==========================] The operation completed successfully. E:\TMP\dism-windows-10>.\Dism -Unmount-Wim -Commit -MOuntDir:E:\TMP-Mount Deployment Image Servicing and Management tool Version: 10.0.16299.15 Abbilddatei: E:\TMP\Windows10_1607_64Bit_verteilen.wim Abbildindex: 2 Abbild wird gespeichert [==========================100.0%==========================] Bereitstellung des Abbilds wird aufgehoben [==========================100.0%==========================] The operation completed successfully. * WDS Fehler bei Treiber hinzufügen - "Wird nicht unterstützt" * Auf aktuelle **dism** Client Version achten!! * https://docs.microsoft.com/de-at/windows-hardware/manufacture/desktop/dism-supported-platforms ===== wol geht net ===== * wol geht nixda mehr / Gerätemanager wurscht / Hybrid Boot ist deaktiviert! Bios Remote Server HP 800 G1 64Bit Windows 10 16xx * Original Intel 64Bit Windows Treiber von der Intel Seite runterladen!! Da muss ein Bug im Microsoft Treiber sein ===== Default Programme spezifizieren ===== * Standardprogramme festlegen bzw. exportieren * GPO Key: Computerkonfiguration\Richtlinien\Administrative Vorlagen\Windows-Komponenten\Datei-Explorer\Konfigurationsdatei für Standardzuordnungen festlegen * Details: https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/export-or-import-default-application-associations Dism /Online /Export-DefaultAppAssociations:\\Server\Share\AppAssoc.xml ====== Windows 7 ====== ===== urbackup restore/windows bare metal restore - boot auf IDE setzen ===== * Sollte bei Windows 7/XP nach einem Hardwareumzug oder Restore von AHCI auf IDE umgestellt worden sein und der entsprechende Bluescreen mit Auto Reboot erscheinen * Dieser Fall tritt ein wenn zB: der Restore auf einem Hyper-V (getestet Windows 2016 Hyper-V) durchgeführt wird d.h. die Hardware ausgetauscht * **Hirens Boot CD** (Achtung legacy Version einsetzen https://www.hirensbootcd.org/files/Hirens.BootCD.15.2.zip) * Tool: **fix_hdc.cmd** <-> editiert die Registry entsprechend - leider gibt es einen Bug der es **nicht** zulässt Hirens Boot CD auf **Hyper-V** zu starten (er bleibt nach der Auswahl des Mini XP hängen) * Schritte für Hyper-V Restore: * ISO mit **fix_hdc für Windows 7 als VB Skript**: {{ :know-how:boot-driver-fix.iso.gz |}} (https://github.com/DotSlashNatalie/fix-7hdc/blob/master/fix_7hdc.vbs) und fixide (https://www.d7xtech.com/free-software/fixide/) {{:know-how:0-windows-7-restore-hyper-v-settings.png?400|}} {{:know-how:1-windows-7-restore-boot-win7-cd.png?400|}} {{:know-how:2-windows-7-restore-boot-win7-cd.png?400|}} {{:know-how:3-windows-7-restore-boot-win7-cd-abort.png?400|}} {{:know-how:4-windows-7-restore-boot-cd-win7-cd-cmd.png?400|}} {{:know-how:5-windows-7-restore-boot-win7-cd-fix7hdc.png?400|}} {{:know-how:6-windows-7-restore-boot-win7-cd-fixhdc.png?400|}} {{:know-how:7-windows-7-restore-boot-win7-cd-success-boot.png?400|}} ===== psexec Batch command ausführen - netzwerkdrucker löschen ===== for /F %%f in (DV2.txt.txt) do ( psexec \\%%f -u Administrator -p PASSWORD C:\Windows\System32\cmd.exe /C rundll32 printui.dll,PrintUIEntry /dn /n \\schulserver\EDV2 ) pause ===== Sprachsteuerung ===== Du klickst auf Start -> Systemsteuerung -> Center für erleichterte Bedienung -> Computer ohne einen Bildschirm verwenden. Dort kannst du die Hakerl rausnehmen wie im Bild angeführt und OK klicken damit er die Einstellungen übernimmt. ===== Display klonen über cmd ===== Displayswitch.exe also has command line parameters that allow you to create a shortcut that will set a specific display mode. /internal /clone /extend /external – JJS Jun 15 '12 at 22:41 ===== Windows Gruppenrichtlinien ====== * Achtung Bei Proxy Einstellungen F5/F6 zum Aktivieren drücken IE 10 Win2012r2 !! ====== Drucker ====== ===== HP2055dn ===== * Wenn er gleich nach dem Starten einen Hex Error anzeigt mit Boot foo -> Firmware beschädigt * Drucker via USB an Endgerät <-> PLC6 Treiber installieren lokal <-> Tool aus ZIP öffnen HP Firmware rescue * Beim Starten von Drucker abbrechen u. Ok gleichzeitig <--> bootcode Anzeige auf Display <--> Tool von HP * Rescue Firmware: {{:know-how:hp2055-boot-rescue.zip|}} ====== Windows PXE Server + Linux Bootserver mit NFS ===== * Infomaterialien bezüglich PXE Boot mit syslinux über einen WDS Deployment Server (2012r2) + NFS Bootserver * Exports am NFS Server e.g: #PXE boots /srv/grml96 10.0.0.0/8(ro,sync,insecure,no_subtree_check) 192.168.0.0/16(ro,sync,insecure,no_root_squash,no_subtree_check) /srv/mint18 10.0.0.0/8(ro,sync,insecure,no_root_squash,no_subtree_check) 192.168.0.0/16(ro,sync,insecure,no_root_squash,no_subtree_check) /srv/avira 10.0.0.0/8(ro,sync,insecure,no_root_squash,no_subtree_check) 192.168.0.0/16(ro,sync,insecure,no_root_squash,no_subtree_check) /srv/wipe 10.0.0.0/8(ro,sync,insecure,no_root_squash,no_subtree_check) 192.168.0.0/16(ro,sync,insecure,no_root_squash,no_subtree_check) Keywords: WDS , Deployment, PXE , PXE-Boot, boot, Network Boot, wds , deployment , pxe * Unterlagen: {{ :know-how:wds-pxe-deployment.tar.gz |}} ===== dhcp-server pxe bios boot optionen ===== * Getestet auf DHCP Server von Windows 2012r2 * **Achtung** funktioniert nur auf legacy boot systemen die kein UEFI brauchen * Zeichenfolgewert <=> IP des TFTP Servers * pxelinux.0 wenn zB: syslinux verwendet wird https://mirrors.edge.kernel.org/pub/linux/utils/boot/syslinux/ {{:know-how:0_dhcp_pxe_option.png?400|}} {{:know-how:1_dhcp_pxe_name_file.png?400|}} * bei dnsmasq: dhcp-boot=pxelinux.0,HOSTNAME_SERVER,IP_SERVER ====== Applikationen/GPOs ====== ===== TINspire CX CAS Student ===== * Schullizenz kann jährlich verlängert werden / Gleichzeitige Ausführung von zB: 5 Instanzen * Problem - er kann keine Verbindung mit dem Lizenzserver herstellen * Auf dem Lizenzserver läuft **lservnt.exe** auf **UDP Port 5093** {{:know-how:0-ti-nspire-cas.png?400|}} * **Achtung:** Windows Firewall auf Lizenzserver muss UDP Port 5093 zulassen - beim Start versucht der Client den definierten lizenzserver zu kontaktieren (wird von TI dokumentiert wie dies konfiguriert werden muss) - dies muss eine 2 Wege Kommunikation sein ===== Profile automatisiert löschen bei Speichermangel ===== * Es sollen die Profile auf der lokalen Maschine gelöscht werden wenn der verfügbare Speicher unter ein definierten Threshold fällt zB: 10GB / Als Computer Startup GPO -> Powershell Skripte * Vielen Dank: delprof2.exe - https://helgeklein.com/free-tools/delprof2-user-profile-deletion-tool/ * **Check_Harddisk_Notification.ps1** $driveCheck="C" $threshold=10 #2022-03-10 cc: Thanks https://stackoverflow.com/questions/12159341/how-to-get-disk-capacity-and-free-space-of-remote-computer $foo=Get-PSDrive C $foo=$($foo.Free) $message = "" if( ($foo/ 1GB) -lt $threshold ) { $message = "Disk Space is NOT good - Drive: "+$driveCheck+" / GB free: "+($foo/1GB)+" / Computer: "+$env:computername+" / Threshold GB: "+$threshold+"`r`n" $message += . '\\DOMAIN\SysVol\DOMAIN\Policies\POL_ID\Machine\Scripts\Startup\delprof2.exe' /u } else { $message = "Disk Space is good - Drive: "+$driveCheck+" / GB free: "+($foo/1GB)+" / Computer: "+$env:computername+" / Threshold GB: "+$threshold } write-Output ($message) > C:\harddisk_check.txt ===== Shutdown if 2.5 hours idle ===== * Computer GPO -> Starten * Offensichtlich existiert ein Bug im Windows 10 (Getestet auf LTSB 2016) , der dazu führt dass der "Computer Idle" Trigger **aber** erst nach x Stunden nicht funktioniert - nach ~10 Minuten wird das Programm ausgeführt egal wie die Idle Wait Werte gesetzt sind * **Workaround** nach 10 Minuten wird shutdown.bat gestartet die 9000 Sekunden darauf wartet ein Shutdown durchzuführen / Wird innerhalb von 9000 Sekunden der Rechner aus dem IDLE State unterbrochen wird die Batch Datei beendet * **deploy_shutdown_trigger.bat** if exist "C:\trigger_shutdownifidle_success.txt" goto ENDE if exist "C:\Scripts" goto Copy_BAT mkdir C:\Scripts icacls C:\Scripts /grant Administratoren:F /grant SYSTEM:F /grant Administrator@schule.intern:F /inheritance:r :Copy_BAT icacls C:\Scripts /grant Administratoren:(CI)(OI)(F) /grant SYSTEM:(CI)(OI)(F) /grant Administrator@schule.intern:(CI)(OI)(F) /inheritance:r copy /Y \\DOMAIN\SysVol\DOMAIN\Policies\PATH_POLICY\Machine\Scripts\Startup\shutdown.bat C:\Scripts\shutdown.bat schtasks /create /xml "\\DOMAIN\SysVol\DOMAIN\Policies\PATH_POLICY\Machine\Scripts\Startup\\ShutdownIdle.xml" /tn "Trigger_Shutdown_If_Idle" if %ERRORLEVEL% EQU 0 ( echo "success" > C:\trigger_shutdownifidle_success.txt ) :ENDE * **ShutdownIdle.xml** 2020-11-12T10:57:39.9973789 SCHULE\christian.czeczil \Trigger_Shutdown_If_Idle true S-1-5-18 HighestAvailable IgnoreNew false true false false false PT10M PT0S true false true true false true false true false PT0S 7 C:\Scripts\shutdown.bat * **shutdown.bat** timeout 9000 /nobreak shutdown /a shutdown /f /s /t 0 * **enable_shutdown_if_idle.bat** if not exist C:\trigger_shutdownifidle_success.txt goto Ende schtasks /change /ENABLE /tn "Trigger_Shutdown_If_Idle" > C:\trigger_Shutdown_If_Idle_ENABLE.txt 2>&1 :Ende * **disable_shutdown_if_idle.bat** if not exist C:\trigger_shutdownifidle_success.txt goto Ende schtasks /change /DISABLE /tn "Trigger_Shutdown_If_Idle" > C:\trigger_Shutdown_If_Idle_DISABLE.txt 2>&1 :Ende ===== Office 2021 Professinal Plus LTS - MAK/KMS Key Installation ===== * Vorher das Office Deployment Tool runter laden / es geht um die aktuelle **setup.exe** die auch den Produkt Code kennt / vorher Programminhalt download mit **.\setup.exe /download setup.xml** * **Achtung** in dieser Variante zum manuellen installieren rechtsklick -> als Administrator ausführen / Zuerst wird Office 2019 deinstalliert und ggf. Office 2016 wenn es per **msi** installiert wurde * Bei KMS Keyserver siehe Generic Volume Keys: https://learn.microsoft.com/en-us/deployoffice/vlactivation/gvlks * **install_office2021ltsc.bat** if exist C:\office2021ltsc_success.txt goto Ende \\server\share\Office2021LTSC\setup.exe /configure \\server\share\Office2021LTSC\remove-2019.xml \\server\share\Office2021LTSC\setup.exe /configure \\server\share\Office2021LTSC\setup.xml if %ERRORLEVEL% EQU 0 ( echo "success" > C:\office2021ltsc_success.txt ) :Ende * **remove-2019.xml** * **setup.xml** ===== Office 2019 Professinal Plus - MAK Key Installation ===== * Office 2019 Professional Plus nicht als *.iso runterladbar , diese Version nimmt den MAK Key nicht: https://officecdn.microsoft.com/pr/492350f6-3a01-4f97-b9c0-c7c6ddf67d60/media/de-de/ProPlus2019Retail.img * Man braucht das Office Deployment Tool: https://www.microsoft.com/en-us/download/details.aspx?id=49117 * Das ODT - lädt eine **setup.exe** herunter die Click-to-Run Version von Office * Vor dem Einsatz der Batch Datei Programmdateien herunter laden mit **setup.exe /download setup.xml** * Bei **PIDKEY** kann gleich der MAK Key eingetragen werden für die Installation * Ich möchte in dieser Variante die Installation bzw. Deinstallation **manuell anstoßen** können umd die betroffenen User sollen den Forstschritt sehen können ("Full") * **setup.xml** * **uninstall_office.xml** * Deinstalliert ein vorhandene Office 2016 MAK Installation die noch per ISO installiert wurde * **Install_Office_2019.bat** if exist "C:\Program Files (x86)\Microsoft Office\root\Office16" goto Ende if exist "C:\Program Files (x86)\Common Files\microsoft shared\OFFICE16\Office Setup Controller\setup.exe" goto Remove goto Install :Remove "C:\Program Files (x86)\Common Files\microsoft shared\OFFICE16\Office Setup Controller\setup.exe" /uninstall ProPlus /config \\schulserver\windows10-programme$\Office2019\uninstall_office.xml :Wait timeout 10 /nobreak if exist "C:\Program Files (x86)\Common Files\microsoft shared\OFFICE16\Office Setup Controller\setup.exe" goto Wait :Install \\schulserver\windows10-programme$\Office2019\setup.exe /configure \\schulserver\windows10-programme$\Office2019\setup.xml echo "installed_office2019" > C:\Office2019_installed.txt :Ende echo finished pause ===== Windows Auto Login deaktivieren ===== {{:know-how:gpo_windows_auto_login_deaktivieren.png?400|}} ===== Windows Auto Login aktivieren für Benutzer ===== * Kann sich auch um AD Benutzer handeln / Computer Richtlinie Startup * **ACHTUNG** GPOS für Computer sind für alle authentifizierten Benutzer im AD lesbar {{:know-how:gpo_windows_auto_login_aktivieren.png?400|}} ===== Windows Upgrade LTSB2016 auf LTSC (2019) ===== * hat als Computerrichtlinie nicht geklappt :( * **Achtung als Benutzerrichtlinie** startup d.h. es wird ein Benutzer mit lokalen Administratorrechten gebraucht ggf. diverse Reboots * In Kombination mit Auto Login für Upgrade User mit lokalen Administrator Rechten / Falls bereits auf LTSC 2019 aktualisiert wurde wird wieder ausgeloggt echo off FOR /F "tokens=4 USEBACKQ" %%F IN (`ver`) DO ( SET var=%%F ) #Windows 10 LTSC (2019) if %var% == 10.0.17763.107] goto Ausloggen \\schulserver\windows10-programme$\LTSC2019\setup.exe /auto upgrade /dynamicupdate disable /compat ignorewarning :Ende exit :Ausloggen logoff exit ===== Windows Updates deaktivieren ===== * Getestet auf Windows 10 2016 LTSB echo > C:\disable_updates.txt sc config wuauserv start= disabled > C:\disable_updates.txt 2>&1 sc config usosvc start= disabled >> C:\disable_updates.txt 2>&1 net stop wuauserv >> C:\disable_updates.txt 2>&1 net stop usosvc >> C:\disable_updates.txt 2>&1 ===== Windows Updates aktivieren ===== * Getestet auf Windows 10 2016 LTSB echo > C:\enable_updates.txt sc config wuauserv start= demand > C:\enable_updates.txt 2>&1 sc config usosvc start= demand >> C:\enable_updates.txt 2>&1 net start wuauserv >> C:\enable_updates.txt 2>&1 net start usosvc >> C:\enable_updates.txt 2>&1 ===== Windows Updates durchführen ===== * Getestet auf Windows 10 2016 LTSB / LTSC 2019 * Funktioniert **nicht mehr** mit LTSC 2021 %SystemRoot%\system32\usoclient.exe ScanInstallWait %SystemRoot%\system32\timeout.exe /T 300 /NOBREAK %SystemRoot%\system32\usoclient.exe StartInstall echo > C:\update_durchfueren.txt ===== Windows Updates manuell planen u. installieren ===== * Getestet mit LTSC 2019 * Nachdem der Update Plan (Stand 18.05.2022) ignoriert wird und keine Updates mehr entsprechend der Gruppenrichtlinien installiert werden muss wieder eine manuelle Lösung her * Die Microsoft native Art und Weise die Updates über powershell zu installieren funktioniert **nicht** wird einmal entfernt oder wieder hinzugefügt * **Achtung** bei LTSC 2016 verwendet die Maschine per Default NICHT TLS1.2 - FAIL * **Achtung** ggf. Asynchron ausführen (Computerrichtlinien-> System -> Skripts) und **NICHT** auf Netzwerk warten * Danke an den Entwickler von PSWindowsUpdate / GPO Rechner Start / Powershell Modul auf Rechnern installieren**install_ps_windowsupdate.ps1** if ( -not ( Get-Module -ListAvailable -Name PSWindowsUpdate ) ) { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force > C:\install_ps_windowsupdate_log.txt Install-Module -Name PSWindowsUpdate -Force >> C:\install_ps_windowsupdate_log.txt } else { write-host "PSWindows Update already installed" } * Updates an einem bestimmten Tag zu einer bestimmten Uhrzeit installieren - am **Mittwoch** vor **07:00** (Rechner werden zB: um 06:50 geweckt) / GPO Rechner Start **install_on_day_updates.ps1** #%A Day of the week - full name Monday #%u Numeric day of the week (1-7) Monday = 1, Sunday = 7 $current_day=(Get-Date -UFormat "%u").toString() $current_hour=(Get-Date -UFormat "%H") #write-host $current_day if ($current_day -eq "3" -and ([int]$current_hour -lt 7)) { if(Get-Module -ListAvailable -Name PSWindowsUpdate) { Get-WindowsUpdate > C:\Windows_update.txt Install-WindowsUpdate -MicrosoftUpdate -IgnoreReboot -AcceptAll >> C:\windows_update.txt } } ===== Microsoft Teams Installation ===== * MSI Datei von https://docs.microsoft.com/de-de/microsoftteams/msi-deployment (Commercial) * Möchte **nicht** dass Teams bei jedem Login gleich geladen wird if exist C:\teams_installed.txt goto Ende msiexec /i \\SERVER_PATH_TRUSTED\Teams_windows_x64.msi OPTIONS="noAutoStart=true" ALLUSERS=1 echo foo > C:\teams_installed.txt :Ende ===== Microsoft Teams Upgrade Installation ===== * Da die Version in X tagen nicht mehr verwendbar ist * Neue MSI Datei saugen -> alte MSI Datei behalten und umbenennen if exist C:\teams_installed_1.txt goto Ende if exist C:\teams_installed.txt goto Deinstallieren if not exist C:\teams_installed.txt goto Installieren :Deinstallieren msiexec /x \\SERVER_PATH_TRUSTED\Teams_windows_x64_old.msi /quiet :Installieren msiexec /i \\SERVER_PATH_TRUSTED\Teams_windows_x64.msi OPTIONS="noAutoStart=true" ALLUSERS=1 echo foo > C:\teams_installed_1.txt :Ende ===== Immunet silent Deinstallation ===== * **ImmunetSetup.exe muss noch vorhanden sein ggf. runterladen** * **delete_immunet.bat** if exist "C:\immunet_deinstalled.txt" goto ENDE \\share_network\ImmunetSetup.exe /S /remove 1 echo "deinstalled" > C:\immunet_deinstalled.txt" :ENDE ===== Archicad Education 24 verteilen ===== * Version 19 deinstallieren - Achtung Reboot direkt nach Deinstallation - Archicad24 daraufhin installieren if exist "C:\Program Files\GRAPHISOFT\ArchiCAD 19\ArchiCAD.exe" goto Uninstall19 if exist "C:\archicad24_installed.txt" goto Ende "\\share_network\ArchiCad24\ARCHICAD-24-AUT-3008-1.7.exe" --mode unattended --enableautomaticupdate 0 --eduSerialNumber SERIAL_NUMBER --eduUserID USER_ID echo > C:\archicad24_installed.txt goto Ende :Uninstall19 start "" /wait "C:\Program Files\GRAPHISOFT\ArchiCAD 19\Uninstall.AC\uninstaller.exe" -silent shutdown /r /t 60 :Ende ===== PrinterNightmare nightmare ===== * **Well done** Microsoft - drucken funktioniert nicht mehr, wenn der Drucker nicht bereits hinzugefügt wurde - Stand 2021-09-20 - LTSC2019 Workstations u. 2012r2 Druckserver * Genau dieser Bug hat zugeschlagen: https://docs.microsoft.com/en-us/answers/questions/517533/pint-server-and-print-nightmare-update.html * Computer GPO Startup Skript um einen Drucker direkt hinzuzufügen $printerName="HP-DRUCKER-DIREKT" $printerIP="IP-HP-DRUCKER" $printerCheck="C:\HP-DRUCKER-DIREKT-installed.txt" if ( -not (Test-Path "C:\HP-Printer-Drivers-installed.txt") ) { #Standort PCL6 Treiber von HP pnputil /add-driver \\SERVER\FREIGABE\*.inf /install /subdirs > C:\HP-Printer-Drivers-installed.txt } if ( -not (Test-Path $printerCheck )) { Add-PrinterDriver -Name "HP Universal Printing PCL 6" Add-PrinterPort -Name $printerIP"_Port_Manual" -PrinterHostAddress $printerIP Add-Printer -Name $printerName -PortName $printerIP"_Port_Manual" "HP Universal Printing PCL 6" if($?) { write-host "installed" > $printerCheck } } ===== Hardware Details erfassen ===== * Um wesentliche Hardwaredetails der Rechner zu erfassen wie Hersteller des Geräts / Seriennummern / Prozessor / RAM / Festplatte - mit **Get-WmiObject -List** erhält man eine Liste mit allen Möglichkeiten * Als **Startup - Computer Richtlinie geeignet** , am Share ausschließlich Schreib-Zugriff auf "Domänencomputer" geben * **hardwareDetails.ps1** #Get-WmiObject -List $checkFile="\\SERVER\HWDETAILS$\$env:computername.log" if ( -not (Test-Path $checkFile)) { Get-WmiObject -Class Win32_Bios | Format-List -Property * | Out-File $checkFile Get-WmiObject -Class Win32_Processor | Format-List -Property * | Out-File -Append $checkFile Get-WmiObject -Class Win32_DiskDrive | Format-List -Property * | Out-File -Append $checkFile Get-WmiObject -Class Win32_PhysicalMemory | Format-List -Property * | Out-File -Append $checkFile } ===== Archicad 24 Education Lizenz verteilen ===== * Sollte Lizenz abgelaufen sein auf Referenzmaschine erneuern u. **education.lic** verteilen auf andere Maschinen * **deploy_archicad_license.bat** @echo off if exist "C:\archicad_license_2019.txt" goto Ende copy /Y \\share_network\education.lic "C:\ProgramData\ARCHICAD\AC_24_AUT" if %errorlevel% equ 0 ( echo "success" > C:\archicad_license_2019.txt ) :Ende ===== Google Sketchup 8 deinstallieren ===== * Falls Installations **.msi** Datei noch vorhanden if exist C:\sketchup8_deinstalled.txt goto Ende msiexec.exe /x "\\LOCATION\Sketchup_8\GoogleSketchUp8.msi" /q echo > C:\sketchup8_deinstalled.txt :Ende ===== MSDT Diagnose deaktivieren ===== * Aktuell noch immer nicht gefixed: https://www.borncity.com/blog/2022/06/01/follina-schwachstelle-cve-2022-30190-warnungen-erste-angriffe-der-status/ * Empfohlener Microsoft Workaround + GPOs um die Diagnosefunktionalität zu deaktivieren - Soweit noch keine Nebeneffekte auf >300 Rechnern {{:know-how:0-mstd-disable-gpo.png?400|}} * **disable_msdt.bat** if exist C:\ms-msdt.reg goto Ende reg export HKEY_CLASSES_ROOT\ms-msdt C:\ms-msdt.reg reg delete HKEY_CLASSES_ROOT\ms-msdt /f :Ende * **Update** Es ist ebenfalls möglich auf einer lokalen Maschine die msdt.exe im System32\ Ordner umzubenennen oder zu löschen - zB: über eine Konsolen Rescue Sitzung - als Prozess im SYSTEM Kontext während des Betriebs lässt Windows das Verschieben oder Löschen **nicht** zu ===== Power BI Desktop installieren ===== * msi ist deprecated / zumindest laut einer Microsoft Seite / **\\vboxsrv\tmp** entsprechend anpassen if exist C:\PowerBI_installed.txt goto Ende start /wait \\vboxsrv\tmp\PBIDesktopSetup_x64.exe /s ACCEPT_EULA=1 if %ERRORLEVEL% EQU 0 echo > C:\PowerBI_installed.txt :Ende * Deinstallation mit: \\vboxsrv\tmp\PBIDesktopSetup_x64.exe /s /uninstall ===== Krita installieren ===== * **\\vboxsrv\tmp** entsprechend anpassen / Version von **https://download.kde.org/stable/krita/5.1.1/krita-x64-5.1.1-setup.exe** if exist C:\Krita_installed.txt goto Ende start /wait \\vboxsrv\tmp\krita-x64-5.1.1-setup.exe /S if %ERRORLEVEL% EQU 0 echo > C:\Krita_installed.txt :Ende * Deinstallation mit: if not exist "C:\Program Files\Krita (x64)\uninstall.exe" goto Ende "C:\Program Files\Krita (x64)\uninstall.exe" /S :Ende