test to integrate users
This commit is contained in:
parent
48afb5d0c8
commit
75828d8263
24
README.md
24
README.md
@ -81,6 +81,30 @@ Dieser Bereich muss von allen Entwicklern gelesen werden, bevor am Projekt gearb
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## PowerShell Integration (Benutzererstellung)
|
||||||
|
|
||||||
|
Die Weboberfläche nutzt PowerShell-Skripte, um Active Directory Benutzer anzulegen. Damit dies funktioniert, sind folgende Voraussetzungen erforderlich:
|
||||||
|
|
||||||
|
- Der Webserver läuft auf Windows und PHP kann PowerShell ausführen (`powershell` oder `pwsh`).
|
||||||
|
- Die PowerShell-Module `ActiveDirectory` müssen installiert (RSAT) und verfügbar sein.
|
||||||
|
- Der Benutzer, unter dem der Webserver läuft, muss ausreichende Rechte besitzen, um `New-ADUser` und `Add-ADGroupMember` auszuführen.
|
||||||
|
- Im `config/config.php` kann `powershell.dry_run` auf `true` gesetzt werden, um Tests ohne Änderungen durchzuführen.
|
||||||
|
|
||||||
|
Konfigurationsoptionen (in `config/config.php`):
|
||||||
|
- `powershell.exe`: Name oder Pfad zur PowerShell-Executable (standard `powershell`).
|
||||||
|
- `powershell.script_dir`: Pfad zu den PowerShell-Skripten (standard `scripts/powershell`).
|
||||||
|
- `powershell.execution_policy`: Auszuführende ExecutionPolicy (z. B. `Bypass`).
|
||||||
|
- `powershell.dry_run`: Wenn `true`, werden keine echten AD-Änderungen durchgeführt; das Skript meldet nur, was es tun würde.
|
||||||
|
|
||||||
|
Die grundlegende Funktionalität wurde mit folgenden Komponenten implementiert:
|
||||||
|
- `public/api/create_user.php`: API-Endpoint zur Erstellung eines einzelnen Benutzers.
|
||||||
|
- `public/api/create_users_csv.php`: API-Endpoint zur Erstellung mehrerer Benutzer aus CSV.
|
||||||
|
- `scripts/powershell/create_user.ps1`: PowerShell-Skript zum Erstellen eines einzelnen Benutzers.
|
||||||
|
- `scripts/powershell/create_users_csv.ps1`: PowerShell-Skript zum Erstellen mehrerer Benutzer aus CSV.
|
||||||
|
|
||||||
|
Bitte testen zuerst mit `powershell.dry_run = true` und prüfen sie die resultierenden Meldungen in UI.
|
||||||
|
|
||||||
|
|
||||||
## Mitwirken
|
## Mitwirken
|
||||||
|
|
||||||
Wer etwas ändern oder erweitern möchte:
|
Wer etwas ändern oder erweitern möchte:
|
||||||
|
|||||||
@ -110,12 +110,36 @@ class UserManagementController
|
|||||||
{
|
{
|
||||||
$viewPath = __DIR__ . '/../../public/views/createuser.php';
|
$viewPath = __DIR__ . '/../../public/views/createuser.php';
|
||||||
|
|
||||||
|
// Use session flash messages if available
|
||||||
|
$error = null;
|
||||||
|
$success = null;
|
||||||
|
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||||
|
@session_start();
|
||||||
|
}
|
||||||
|
if (isset($_SESSION['flash_error'])) {
|
||||||
|
$error = $_SESSION['flash_error'];
|
||||||
|
unset($_SESSION['flash_error']);
|
||||||
|
}
|
||||||
|
if (isset($_SESSION['flash_success'])) {
|
||||||
|
$success = $_SESSION['flash_success'];
|
||||||
|
unset($_SESSION['flash_success']);
|
||||||
|
}
|
||||||
|
$csvDetails = null;
|
||||||
|
if (isset($_SESSION['csv_details'])) {
|
||||||
|
$csvDetails = $_SESSION['csv_details'];
|
||||||
|
unset($_SESSION['csv_details']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$powershellDryRun = $this->config['powershell']['dry_run'] ?? false;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'view' => $viewPath,
|
'view' => $viewPath,
|
||||||
'data' => [
|
'data' => [
|
||||||
'error' => null,
|
'error' => $error,
|
||||||
'success' => null,
|
'success' => $success,
|
||||||
'loginPage' => false,
|
'loginPage' => false,
|
||||||
|
'csvDetails' => $csvDetails,
|
||||||
|
'powershellDryRun' => $powershellDryRun,
|
||||||
],
|
],
|
||||||
'pageTitle' => 'Benutzer erstellen',
|
'pageTitle' => 'Benutzer erstellen',
|
||||||
'activeMenu' => 'createuser',
|
'activeMenu' => 'createuser',
|
||||||
|
|||||||
@ -60,4 +60,14 @@ return [
|
|||||||
// Minimale Stufe: debug, info, warning, error
|
// Minimale Stufe: debug, info, warning, error
|
||||||
'min_level' => 'info',
|
'min_level' => 'info',
|
||||||
],
|
],
|
||||||
|
'powershell' => [
|
||||||
|
// Executable name: 'powershell' on Windows, 'pwsh' for PowerShell core.
|
||||||
|
'exe' => 'powershell',
|
||||||
|
// Script directory where the PS1 scripts live (relative to config dir)
|
||||||
|
'script_dir' => __DIR__ . '/../scripts/powershell',
|
||||||
|
// Execution policy to pass to the PowerShell invocation
|
||||||
|
'execution_policy' => 'Bypass',
|
||||||
|
// For testing; if true, the scripts will run in dry-run mode (no real AD changes)
|
||||||
|
'dry_run' => false,
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
109
public/api/create_user.php
Normal file
109
public/api/create_user.php
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
// Load config
|
||||||
|
$config = require __DIR__ . '/../../config/config.php';
|
||||||
|
|
||||||
|
// Simple login check (same as index.php)
|
||||||
|
$sessionKey = $config['security']['session_key_user'] ?? 'admin_user';
|
||||||
|
if (!isset($_SESSION[$sessionKey])) {
|
||||||
|
header('Location: ../index.php?route=login');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only accept POST
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
|
header('Location: ../index.php?route=createuser');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic input validation
|
||||||
|
$sam = trim((string)($_POST['samaccountname'] ?? ''));
|
||||||
|
$display = trim((string)($_POST['displayname'] ?? ''));
|
||||||
|
$mail = trim((string)($_POST['mail'] ?? ''));
|
||||||
|
$pass = (string)($_POST['password'] ?? '');
|
||||||
|
$ou = trim((string)($_POST['ou'] ?? ''));
|
||||||
|
$groups = trim((string)($_POST['groups'] ?? ''));
|
||||||
|
|
||||||
|
if ($sam === '' || $pass === '') {
|
||||||
|
$_SESSION['flash_error'] = 'Anmeldename und Passwort sind erforderlich.';
|
||||||
|
header('Location: ../index.php?route=createuser');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build payload
|
||||||
|
$payload = [
|
||||||
|
'samaccountname' => $sam,
|
||||||
|
'displayname' => $display,
|
||||||
|
'mail' => $mail,
|
||||||
|
'password' => $pass,
|
||||||
|
'ou' => $ou,
|
||||||
|
'groups' => $groups,
|
||||||
|
'dry_run' => (bool)($config['powershell']['dry_run'] ?? false),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Write payload to temp file
|
||||||
|
$tmpFile = tempnam(sys_get_temp_dir(), 'create_user_') . '.json';
|
||||||
|
file_put_contents($tmpFile, json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||||
|
|
||||||
|
// Build PS script path
|
||||||
|
$scriptDir = $config['powershell']['script_dir'] ?? __DIR__ . '/../../scripts/powershell';
|
||||||
|
$script = $scriptDir . DIRECTORY_SEPARATOR . 'create_user.ps1';
|
||||||
|
|
||||||
|
$exe = $config['powershell']['exe'] ?? 'powershell';
|
||||||
|
$executionPolicy = $config['powershell']['execution_policy'] ?? 'Bypass';
|
||||||
|
|
||||||
|
$cmd = sprintf(
|
||||||
|
'%s -NoProfile -NonInteractive -ExecutionPolicy %s -File "%s" -InputFile "%s"',
|
||||||
|
$exe,
|
||||||
|
$executionPolicy,
|
||||||
|
$script,
|
||||||
|
$tmpFile
|
||||||
|
);
|
||||||
|
|
||||||
|
// Execute and capture output and exit code
|
||||||
|
$output = [];
|
||||||
|
$returnVar = null;
|
||||||
|
if (!file_exists($script)) {
|
||||||
|
$_SESSION['flash_error'] = 'PowerShell-Skript nicht gefunden: ' . $script;
|
||||||
|
@unlink($tmpFile);
|
||||||
|
header('Location: ../index.php?route=createuser');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to locate the PowerShell executable
|
||||||
|
$exePathCheck = shell_exec(sprintf('where %s 2>NUL', escapeshellarg($exe)));
|
||||||
|
if ($exePathCheck === null) {
|
||||||
|
// 'where' returns null when command fails; continue anyways, exec will fail if not found
|
||||||
|
}
|
||||||
|
|
||||||
|
exec($cmd . ' 2>&1', $output, $returnVar);
|
||||||
|
$json = implode("\n", $output);
|
||||||
|
|
||||||
|
@unlink($tmpFile);
|
||||||
|
|
||||||
|
// Try to parse JSON output
|
||||||
|
$result = null;
|
||||||
|
if ($json !== '') {
|
||||||
|
$decoded = json_decode($json, true);
|
||||||
|
if (is_array($decoded)) {
|
||||||
|
$result = $decoded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result === null) {
|
||||||
|
$_SESSION['flash_error'] = 'Unbekannter Fehler beim Ausführen des PowerShell-Skripts: ' . ($json ?: 'Keine Ausgabe');
|
||||||
|
header('Location: ../index.php?route=createuser');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($result['success'])) {
|
||||||
|
$_SESSION['flash_success'] = $result['message'] ?? 'Benutzer erfolgreich erstellt.';
|
||||||
|
} else {
|
||||||
|
$_SESSION['flash_error'] = $result['message'] ?? 'Fehler beim Erstellen des Benutzers.';
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: ../index.php?route=createuser');
|
||||||
|
exit;
|
||||||
107
public/api/create_users_csv.php
Normal file
107
public/api/create_users_csv.php
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
// Load config
|
||||||
|
$config = require __DIR__ . '/../../config/config.php';
|
||||||
|
|
||||||
|
// Simple login check (same as index.php)
|
||||||
|
$sessionKey = $config['security']['session_key_user'] ?? 'admin_user';
|
||||||
|
if (!isset($_SESSION[$sessionKey])) {
|
||||||
|
header('Location: ../index.php?route=login');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
|
header('Location: ../index.php?route=createuser');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$delimiter = (string)($_POST['csvdelimiter'] ?? ',');
|
||||||
|
$hasHeader = (string)($_POST['hasHeader'] ?? '1');
|
||||||
|
|
||||||
|
// Two sources: uploaded file or csvcontent textarea
|
||||||
|
$csvContent = '';
|
||||||
|
if (!empty($_FILES['csvfile']['tmp_name']) && is_uploaded_file($_FILES['csvfile']['tmp_name'])) {
|
||||||
|
$csvContent = file_get_contents($_FILES['csvfile']['tmp_name']);
|
||||||
|
} else {
|
||||||
|
$csvContent = (string)($_POST['csvcontent'] ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trim($csvContent) === '') {
|
||||||
|
$_SESSION['flash_error'] = 'CSV ist leer. Bitte Datei auswählen oder Inhalt einfügen.';
|
||||||
|
header('Location: ../index.php?route=createuser');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write CSV to temp file
|
||||||
|
$tmpFile = tempnam(sys_get_temp_dir(), 'create_users_') . '.csv';
|
||||||
|
file_put_contents($tmpFile, $csvContent);
|
||||||
|
|
||||||
|
// Build payload with options
|
||||||
|
$payload = [
|
||||||
|
'input_file' => $tmpFile,
|
||||||
|
'delimiter' => $delimiter,
|
||||||
|
'has_header' => (bool)((int)$hasHeader),
|
||||||
|
'dry_run' => (bool)($config['powershell']['dry_run'] ?? false),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Save options as JSON as the input to the PS script
|
||||||
|
$metaFile = tempnam(sys_get_temp_dir(), 'create_users_meta_') . '.json';
|
||||||
|
file_put_contents($metaFile, json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||||
|
|
||||||
|
$scriptDir = $config['powershell']['script_dir'] ?? __DIR__ . '/../../scripts/powershell';
|
||||||
|
$script = $scriptDir . DIRECTORY_SEPARATOR . 'create_users_csv.ps1';
|
||||||
|
$exe = $config['powershell']['exe'] ?? 'powershell';
|
||||||
|
$executionPolicy = $config['powershell']['execution_policy'] ?? 'Bypass';
|
||||||
|
|
||||||
|
$cmd = sprintf(
|
||||||
|
'%s -NoProfile -NonInteractive -ExecutionPolicy %s -File "%s" -InputFile "%s"',
|
||||||
|
$exe,
|
||||||
|
$executionPolicy,
|
||||||
|
$script,
|
||||||
|
$metaFile
|
||||||
|
);
|
||||||
|
|
||||||
|
$output = [];
|
||||||
|
$returnVar = null;
|
||||||
|
if (!file_exists($script)) {
|
||||||
|
$_SESSION['flash_error'] = 'PowerShell-Skript nicht gefunden: ' . $script;
|
||||||
|
@unlink($tmpFile);
|
||||||
|
@unlink($metaFile);
|
||||||
|
header('Location: ../index.php?route=createuser');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
exec($cmd . ' 2>&1', $output, $returnVar);
|
||||||
|
$json = implode("\n", $output);
|
||||||
|
|
||||||
|
@unlink($tmpFile);
|
||||||
|
@unlink($metaFile);
|
||||||
|
|
||||||
|
$result = null;
|
||||||
|
if ($json !== '') {
|
||||||
|
$decoded = json_decode($json, true);
|
||||||
|
if (is_array($decoded)) {
|
||||||
|
$result = $decoded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result === null) {
|
||||||
|
$_SESSION['flash_error'] = 'Unbekannter Fehler beim Ausführen des PowerShell-Skripts: ' . ($json ?: 'Keine Ausgabe');
|
||||||
|
header('Location: ../index.php?route=createuser');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($result['success'])) {
|
||||||
|
$_SESSION['flash_success'] = $result['message'] ?? 'CSV verarbeitet.';
|
||||||
|
if (!empty($result['details'])) {
|
||||||
|
$_SESSION['csv_details'] = $result['details'];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$_SESSION['flash_error'] = $result['message'] ?? 'Fehler beim Verarbeiten der CSV.';
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: ../index.php?route=createuser');
|
||||||
|
exit;
|
||||||
@ -38,6 +38,12 @@ declare(strict_types=1);
|
|||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if (!empty($powershellDryRun) && $powershellDryRun === true): ?>
|
||||||
|
<div class="alert alert-warning" role="alert">
|
||||||
|
Die Anwendung ist im <strong>Dry-Run</strong>-Modus konfiguriert; PowerShell-Befehle werden nicht ausgeführt.
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<p class="mb-4">Hier können Sie einzelne Active-Directory-Benutzer anlegen oder eine CSV-Datei hochladen, um mehrere Benutzer gleichzeitig zu erstellen. Sie können die CSV in der Vorschau bearbeiten bevor Sie die Erstellung auslösen.</p>
|
<p class="mb-4">Hier können Sie einzelne Active-Directory-Benutzer anlegen oder eine CSV-Datei hochladen, um mehrere Benutzer gleichzeitig zu erstellen. Sie können die CSV in der Vorschau bearbeiten bevor Sie die Erstellung auslösen.</p>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -132,6 +138,40 @@ declare(strict_types=1);
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<?php if (!empty($csvDetails) && is_array($csvDetails)): ?>
|
||||||
|
<div class="row mt-4">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card shadow mb-4">
|
||||||
|
<div class="card-header py-3">
|
||||||
|
<h6 class="m-0 font-weight-bold text-secondary">CSV Verarbeitungsergebnisse</h6>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-sm table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Anmeldename</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Hinweis</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($csvDetails as $detail): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo htmlspecialchars((string)($detail['sam'] ?? ''), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
|
||||||
|
<td><?php echo (!empty($detail['success'])) ? 'OK' : 'FEHLER'; ?></td>
|
||||||
|
<td><?php echo htmlspecialchars((string)($detail['message'] ?? ''), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card shadow mb-4">
|
<div class="card shadow mb-4">
|
||||||
|
|||||||
86
scripts/powershell/create_user.ps1
Normal file
86
scripts/powershell/create_user.ps1
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$InputFile
|
||||||
|
)
|
||||||
|
|
||||||
|
# Read input JSON
|
||||||
|
try {
|
||||||
|
$json = Get-Content -Raw -Path $InputFile -ErrorAction Stop
|
||||||
|
$payload = $json | ConvertFrom-Json
|
||||||
|
} catch {
|
||||||
|
$err = $_.Exception.Message
|
||||||
|
Write-Output (@{ success = $false; message = "Failed to read/parse input JSON: $err" } | ConvertTo-Json -Compress)
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Default result
|
||||||
|
$result = @{ success = $false; message = "Unspecified error" }
|
||||||
|
|
||||||
|
# Validate
|
||||||
|
if (-not $payload.samaccountname -or -not $payload.password) {
|
||||||
|
$result.message = "Required fields: samaccountname and password"
|
||||||
|
Write-Output ($result | ConvertTo-Json -Compress)
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Convert to strings
|
||||||
|
$sam = [string]$payload.samaccountname
|
||||||
|
$display = [string]($payload.displayname)
|
||||||
|
$mail = [string]($payload.mail)
|
||||||
|
$pass = [string]$payload.password
|
||||||
|
$ou = [string]($payload.ou)
|
||||||
|
$groups = [string]($payload.groups)
|
||||||
|
$dryRun = [bool]($payload.dry_run -as [bool])
|
||||||
|
|
||||||
|
# Ensure ActiveDirectory module available
|
||||||
|
try {
|
||||||
|
Import-Module ActiveDirectory -ErrorAction Stop
|
||||||
|
} catch {
|
||||||
|
$result.message = "ActiveDirectory PowerShell module not available: $($_.Exception.Message)"
|
||||||
|
Write-Output ($result | ConvertTo-Json -Compress)
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build New-ADUser parameters
|
||||||
|
$props = @{
|
||||||
|
Name = if ($display -and $display -ne '') { $display } else { $sam }
|
||||||
|
SamAccountName = $sam
|
||||||
|
Enabled = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($mail -and $mail -ne '') { $props['EmailAddress'] = $mail }
|
||||||
|
if ($ou -and $ou -ne '') { $props['Path'] = $ou }
|
||||||
|
|
||||||
|
# Build secure password
|
||||||
|
$securePass = ConvertTo-SecureString $pass -AsPlainText -Force
|
||||||
|
$props['AccountPassword'] = $securePass
|
||||||
|
|
||||||
|
# Execute
|
||||||
|
if ($dryRun) {
|
||||||
|
$result.success = $true
|
||||||
|
$result.message = "DRY RUN: would create user $sam"
|
||||||
|
Write-Output ($result | ConvertTo-Json -Compress)
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
# Create the AD user
|
||||||
|
New-ADUser @props -ErrorAction Stop
|
||||||
|
|
||||||
|
# Add to groups, if provided
|
||||||
|
if ($groups -and $groups -ne '') {
|
||||||
|
$groupList = $groups -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' }
|
||||||
|
foreach ($g in $groupList) {
|
||||||
|
Add-ADGroupMember -Identity $g -Members $sam -ErrorAction Stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result.success = $true
|
||||||
|
$result.message = "User $sam created successfully"
|
||||||
|
Write-Output ($result | ConvertTo-Json -Compress)
|
||||||
|
exit 0
|
||||||
|
} catch {
|
||||||
|
$result.message = "Error creating user $sam: $($_.Exception.Message)"
|
||||||
|
Write-Output ($result | ConvertTo-Json -Compress)
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
97
scripts/powershell/create_users_csv.ps1
Normal file
97
scripts/powershell/create_users_csv.ps1
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$InputFile
|
||||||
|
)
|
||||||
|
|
||||||
|
# Read meta JSON
|
||||||
|
try {
|
||||||
|
$json = Get-Content -Raw -Path $InputFile -ErrorAction Stop
|
||||||
|
$meta = $json | ConvertFrom-Json
|
||||||
|
} catch {
|
||||||
|
Write-Output (@{ success = $false; message = "Failed to read/parse meta JSON: $($_.Exception.Message)" } | ConvertTo-Json -Compress)
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$csvFile = [string]$meta.input_file
|
||||||
|
$delimiter = [string]($meta.delimiter ?? ',')
|
||||||
|
$hasHeader = [bool]($meta.has_header -as [bool])
|
||||||
|
$dryRun = [bool]($meta.dry_run -as [bool])
|
||||||
|
|
||||||
|
if (-not (Test-Path -Path $csvFile)) {
|
||||||
|
Write-Output (@{ success = $false; message = "CSV file not found: $csvFile" } | ConvertTo-Json -Compress)
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure ActiveDirectory module is available
|
||||||
|
try {
|
||||||
|
Import-Module ActiveDirectory -ErrorAction Stop
|
||||||
|
} catch {
|
||||||
|
Write-Output (@{ success = $false; message = "ActiveDirectory PowerShell module not available: $($_.Exception.Message)" } | ConvertTo-Json -Compress)
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read CSV
|
||||||
|
try {
|
||||||
|
if ($hasHeader) {
|
||||||
|
$items = Import-Csv -Path $csvFile -Delimiter $delimiter -ErrorAction Stop
|
||||||
|
} else {
|
||||||
|
# Use default headers
|
||||||
|
$headers = 'samaccountname','displayname','mail','password','ou','groups'
|
||||||
|
$items = Import-Csv -Path $csvFile -Delimiter $delimiter -Header $headers -ErrorAction Stop
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Output (@{ success = $false; message = "Failed to parse CSV: $($_.Exception.Message)" } | ConvertTo-Json -Compress)
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$results = @()
|
||||||
|
$successCount = 0
|
||||||
|
$failCount = 0
|
||||||
|
|
||||||
|
foreach ($row in $items) {
|
||||||
|
$sam = $row.samaccountname
|
||||||
|
$display = $row.displayname
|
||||||
|
$mail = $row.mail
|
||||||
|
$pass = $row.password
|
||||||
|
$ou = $row.ou
|
||||||
|
$groups = $row.groups
|
||||||
|
|
||||||
|
if ([string]::IsNullOrWhiteSpace($sam) -or [string]::IsNullOrWhiteSpace($pass)) {
|
||||||
|
$results += @{ sam = $sam; success = $false; message = 'Missing samaccountname or password' }
|
||||||
|
$failCount++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($dryRun) {
|
||||||
|
$results += @{ sam = $sam; success = $true; message = 'DRY RUN: would create' }
|
||||||
|
$successCount++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$props = @{ Name = if ($display -and $display -ne '') { $display } else { $sam }; SamAccountName = $sam; Enabled = $true }
|
||||||
|
if ($mail -and $mail -ne '') { $props['EmailAddress'] = $mail }
|
||||||
|
if ($ou -and $ou -ne '') { $props['Path'] = $ou }
|
||||||
|
$securePass = ConvertTo-SecureString $pass -AsPlainText -Force
|
||||||
|
$props['AccountPassword'] = $securePass
|
||||||
|
|
||||||
|
New-ADUser @props -ErrorAction Stop
|
||||||
|
|
||||||
|
if ($groups -and $groups -ne '') {
|
||||||
|
$groupList = $groups -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' }
|
||||||
|
foreach ($g in $groupList) {
|
||||||
|
Add-ADGroupMember -Identity $g -Members $sam -ErrorAction Stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$results += @{ sam = $sam; success = $true; message = 'Created' }
|
||||||
|
$successCount++
|
||||||
|
} catch {
|
||||||
|
$results += @{ sam = $sam; success = $false; message = $_.Exception.Message }
|
||||||
|
$failCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$output = @{ success = $failCount -eq 0; message = "Created $successCount users, $failCount failures"; details = $results }
|
||||||
|
Write-Output ($output | ConvertTo-Json -Compress)
|
||||||
|
exit 0
|
||||||
Loading…
Reference in New Issue
Block a user