Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c737bd3192 |
@@ -50,6 +50,7 @@ Operational documentation:
|
||||
- [Broker location, health, timeout, and recovery](docs/broker-operations.md)
|
||||
- [Windows domain join and remote-access onboarding](docs/windows-client-onboarding.md)
|
||||
- [Required Credential Provider client enrollment](docs/client-enrollment.md)
|
||||
- [Linux client enrollment with realmd and SSSD](docs/linux-client-enrollment.md)
|
||||
- [Domain monitoring, usage reports, and six-month retention](docs/monitoring.md)
|
||||
- [Decision: do not persist password verifiers in Redis](docs/decisions/0001-no-password-cache.md)
|
||||
|
||||
@@ -106,6 +107,13 @@ Start-SguServerBootstrap.cmd 192.168.50.10
|
||||
Start-SguClientEnrollment.cmd 192.168.50.10
|
||||
```
|
||||
|
||||
Linux clients are enrolled through their native PAM/SSSD stack instead of the
|
||||
Windows Credential Provider:
|
||||
|
||||
```bash
|
||||
sudo bash ./Enroll-SguLinuxDomainClient.sh --domain-controller 192.168.50.10
|
||||
```
|
||||
|
||||
The server command creates a new forest and resumes by itself after its required
|
||||
restart. The client command registers a unique non-exportable mTLS certificate,
|
||||
installs and validates SGU before domain join, then enables the managed remote
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Recuperación desde cero y alta en una sola ejecución
|
||||
|
||||
Los releases entregan dos ZIP independientes. Cada uno contiene sus binarios,
|
||||
Los releases entregan tres ZIP independientes. Cada uno contiene sus binarios,
|
||||
scripts, instalador offline requerido y un manifiesto SHA-256 interno. No contienen
|
||||
contraseñas, claves privadas ni certificados reutilizables.
|
||||
|
||||
@@ -131,6 +131,30 @@ bosque modificar el dominio. Para la operación soportada, el script aplica una
|
||||
transacción proveedor-primero y se niega a unir un equipo que no haya pasado las
|
||||
validaciones.
|
||||
|
||||
## Cliente Linux nuevo
|
||||
|
||||
El ZIP `sgu-linux-client-bootstrap-VERSION.zip` usa el mecanismo nativo de
|
||||
Linux: `realmd`, Kerberos, SSSD, NSS y PAM. No distribuye ni instala el
|
||||
Credential Provider de Windows.
|
||||
|
||||
En una VM con Internet por `Default Switch` y una NIC privada conectada a
|
||||
`Laboratorio AD`, ejecutar como administrador:
|
||||
|
||||
```bash
|
||||
sudo bash ./Enroll-SguLinuxDomainClient.sh \
|
||||
--domain-controller 192.168.50.10 \
|
||||
--domain-interface eth0 \
|
||||
--domain-address 192.168.50.12/24 \
|
||||
--enable-ssh
|
||||
```
|
||||
|
||||
La contraseña de la cuenta autorizada para la unión se solicita de forma
|
||||
interactiva por `realmd`; no se incluye en la línea de comandos. El script
|
||||
configura DNS de AD en la NIC privada, preserva la ruta de Internet, crea la
|
||||
cuenta de equipo en `OU=Laboratorio`, habilita creación de directorio personal
|
||||
mediante PAM y valida la cuenta de equipo con `adcli testjoin`. La documentación
|
||||
de operación completa está en [linux-client-enrollment.md](linux-client-enrollment.md).
|
||||
|
||||
## Crear y publicar un release
|
||||
|
||||
Desde el repositorio y con el SDK fijado en `global.json`:
|
||||
@@ -150,4 +174,4 @@ la línea de comandos. Para empaquetar recursos institucionales adicionales:
|
||||
-ServerContentPath C:\Preparacion\Packages
|
||||
```
|
||||
|
||||
`SHA256SUMS-VERSION.txt` permite comprobar ambos ZIP antes de usarlos.
|
||||
`SHA256SUMS-VERSION.txt` permite comprobar los tres ZIP antes de usarlos.
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
# Enrolamiento de clientes Linux
|
||||
|
||||
El enrolador Linux incorpora una estación Debian/Ubuntu o RHEL/Fedora/Rocky/AlmaLinux a `lci.lasalle.mx` mediante `realmd`, `adcli`, Kerberos y SSSD. No instala el Credential Provider de Windows: Linux conserva su propio inicio de sesión PAM/SSSD.
|
||||
|
||||
La contraseña de la cuenta autorizada para unir equipos se solicita directamente por `realmd`. Nunca se acepta como argumento, ni se escribe en archivos, registros o la línea de comandos.
|
||||
|
||||
## Requisitos de red
|
||||
|
||||
El equipo debe alcanzar por una interfaz privada al controlador de dominio, DNS y Kerberos. En el laboratorio:
|
||||
|
||||
| Servicio | Destino |
|
||||
| --- | --- |
|
||||
| Controlador y DNS | `192.168.50.10` |
|
||||
| Dominio | `lci.lasalle.mx` |
|
||||
| OU de equipos | `OU=Laboratorio,DC=lci,DC=lasalle,DC=mx` |
|
||||
|
||||
Para una VM Hyper-V con dos NIC, mantén el Internet en `Default Switch` y conecta una segunda NIC a `Laboratorio AD`. El enrolador puede configurar la segunda NIC sin modificar la ruta predeterminada:
|
||||
|
||||
```bash
|
||||
sudo bash ./Enroll-SguLinuxDomainClient.sh \
|
||||
--domain-controller 192.168.50.10 \
|
||||
--domain-interface eth0 \
|
||||
--domain-address 192.168.50.12/24 \
|
||||
--enable-ssh
|
||||
```
|
||||
|
||||
`--domain-interface` y `--domain-address` son opcionales como pareja. Si ya se aprovisionó la red privada mediante cloud-init, DHCP o gestión de configuración, omítelos y conserva únicamente `--domain-controller`.
|
||||
|
||||
El script se niega a reconfigurar una interfaz que posea la ruta predeterminada; así no deja a la máquina sin salida a Internet al agregar AD.
|
||||
|
||||
## Qué instala y configura
|
||||
|
||||
1. Instala `realmd`, `adcli`, SSSD, Kerberos y los módulos NSS/PAM adecuados para la familia de distribución.
|
||||
2. Comprueba el registro DNS SRV de Active Directory y sincronización de hora ya existente.
|
||||
3. Establece el nombre de host `NOMBRE.lci.lasalle.mx` antes de crear la cuenta de equipo.
|
||||
4. Une el equipo con `adcli` en `OU=Laboratorio`.
|
||||
5. Activa SSSD, creación de directorio personal mediante PAM y valida la contraseña de la cuenta de equipo con `adcli testjoin`.
|
||||
6. Cuando se proporcionó la NIC privada, activa actualizaciones DNS dinámicas de SSSD en esa interfaz.
|
||||
7. Con `--enable-ssh`, instala y habilita OpenSSH y abre únicamente el servicio SSH cuando el firewall local ya está activo.
|
||||
|
||||
El objeto de equipo aparece como `NOMBRE` en `OU=Laboratorio`. SSSD registra su registro A cuando la actualización DNS dinámica está activada.
|
||||
|
||||
## Inicio de sesión de dominio
|
||||
|
||||
Después de la unión, el formato explícito es:
|
||||
|
||||
```text
|
||||
usuario@lci.lasalle.mx
|
||||
```
|
||||
|
||||
La primera sesión crea `/home/usuario@lci.lasalle.mx`. El valor predeterminado de SSSD conserva credenciales para desconexiones breves de la red; las contraseñas no son administradas ni almacenadas por el Auth Broker.
|
||||
|
||||
Para limitar quién puede iniciar sesión, incluye un grupo de AD:
|
||||
|
||||
```bash
|
||||
sudo bash ./Enroll-SguLinuxDomainClient.sh \
|
||||
--domain-controller 192.168.50.10 \
|
||||
--allow-group 'SG-Laboratorio-Linux-Users'
|
||||
```
|
||||
|
||||
Ese modo ejecuta `realm deny --all` seguido de `realm permit --groups`; crea y administra el grupo antes de usarlo.
|
||||
|
||||
## Verificación y salida controlada
|
||||
|
||||
```bash
|
||||
realm list
|
||||
sudo adcli testjoin --domain=lci.lasalle.mx
|
||||
getent passwd 'usuario@lci.lasalle.mx'
|
||||
sudo sssctl domain-status lci.lasalle.mx
|
||||
```
|
||||
|
||||
Para sacar un equipo del dominio de forma explícita:
|
||||
|
||||
```bash
|
||||
sudo realm leave lci.lasalle.mx
|
||||
```
|
||||
|
||||
Esta última acción elimina la relación de confianza local; debe ejecutarse sólo durante baja o reconstrucción del equipo.
|
||||
Executable
+233
@@ -0,0 +1,233 @@
|
||||
#!/usr/bin/env bash
|
||||
# Enroll-SguLinuxDomainClient.sh
|
||||
#
|
||||
# Idempotently joins a Debian/Ubuntu or RHEL-family Linux workstation to the
|
||||
# SGU Active Directory laboratory. The join password is always requested by
|
||||
# realmd; this script never accepts, logs, or stores it.
|
||||
|
||||
set -Eeuo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
DOMAIN_NAME='lci.lasalle.mx'
|
||||
DOMAIN_CONTROLLER=''
|
||||
DOMAIN_DNS=''
|
||||
COMPUTER_OU='OU=Laboratorio,DC=lci,DC=lasalle,DC=mx'
|
||||
JOIN_USER='Administrator'
|
||||
DOMAIN_INTERFACE=''
|
||||
DOMAIN_ADDRESS=''
|
||||
COMPUTER_NAME=''
|
||||
ALLOW_GROUP=''
|
||||
ENABLE_SSH=false
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
sudo ./Enroll-SguLinuxDomainClient.sh --domain-controller <IPv4-or-FQDN> [options]
|
||||
|
||||
Required:
|
||||
--domain-controller VALUE Fixed IPv4 address or DNS name of the AD controller.
|
||||
|
||||
Options:
|
||||
--domain-name VALUE AD DNS domain (default: lci.lasalle.mx).
|
||||
--domain-dns VALUE DNS server for the AD network (default: domain controller).
|
||||
--computer-ou DN Destination computer OU.
|
||||
--join-user USER AD account permitted to join computers (default: Administrator).
|
||||
--computer-name NAME NetBIOS host name; its FQDN becomes NAME.DOMAIN.
|
||||
--domain-interface IFACE Private NIC connected to the AD network.
|
||||
--domain-address CIDR Static IPv4 address for --domain-interface, e.g. 192.168.50.12/24.
|
||||
--allow-group GROUP Restrict Linux sign-in to this AD group after joining.
|
||||
--enable-ssh Install, enable, and (when active) permit OpenSSH in the local firewall.
|
||||
--help Show this help.
|
||||
|
||||
Network safety:
|
||||
--domain-interface and --domain-address must be supplied together. The selected
|
||||
interface must not own the default route, so the command cannot replace the
|
||||
Internet route while attaching a private AD NIC.
|
||||
|
||||
The AD password is requested interactively by realmd. It is never accepted as an
|
||||
argument or written to a file, log, or command line.
|
||||
EOF
|
||||
}
|
||||
|
||||
fail() {
|
||||
printf 'ERROR: %s\n' "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
need_command() {
|
||||
command -v "$1" >/dev/null 2>&1 || fail "Required command is unavailable: $1"
|
||||
}
|
||||
|
||||
while (($#)); do
|
||||
case "$1" in
|
||||
--domain-controller) DOMAIN_CONTROLLER=${2:?Missing value for --domain-controller}; shift 2 ;;
|
||||
--domain-name) DOMAIN_NAME=${2:?Missing value for --domain-name}; shift 2 ;;
|
||||
--domain-dns) DOMAIN_DNS=${2:?Missing value for --domain-dns}; shift 2 ;;
|
||||
--computer-ou) COMPUTER_OU=${2:?Missing value for --computer-ou}; shift 2 ;;
|
||||
--join-user) JOIN_USER=${2:?Missing value for --join-user}; shift 2 ;;
|
||||
--computer-name) COMPUTER_NAME=${2:?Missing value for --computer-name}; shift 2 ;;
|
||||
--domain-interface) DOMAIN_INTERFACE=${2:?Missing value for --domain-interface}; shift 2 ;;
|
||||
--domain-address) DOMAIN_ADDRESS=${2:?Missing value for --domain-address}; shift 2 ;;
|
||||
--allow-group) ALLOW_GROUP=${2:?Missing value for --allow-group}; shift 2 ;;
|
||||
--enable-ssh) ENABLE_SSH=true; shift ;;
|
||||
--help|-h) usage; exit 0 ;;
|
||||
*) fail "Unknown argument: $1. Use --help for usage." ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ ${EUID} -eq 0 ]] || fail 'Run this command with sudo or as root.'
|
||||
[[ -n $DOMAIN_CONTROLLER ]] || fail '--domain-controller is required.'
|
||||
|
||||
if [[ -z $DOMAIN_DNS ]]; then
|
||||
DOMAIN_DNS=$DOMAIN_CONTROLLER
|
||||
fi
|
||||
|
||||
if [[ -n $DOMAIN_INTERFACE || -n $DOMAIN_ADDRESS ]]; then
|
||||
[[ -n $DOMAIN_INTERFACE && -n $DOMAIN_ADDRESS ]] || \
|
||||
fail '--domain-interface and --domain-address must be supplied together.'
|
||||
fi
|
||||
|
||||
if [[ -z $COMPUTER_NAME ]]; then
|
||||
COMPUTER_NAME=$(hostname -s)
|
||||
fi
|
||||
COMPUTER_NAME=${COMPUTER_NAME^^}
|
||||
HOST_FQDN="${COMPUTER_NAME,,}.${DOMAIN_NAME,,}"
|
||||
|
||||
install_prerequisites() {
|
||||
local -a packages=()
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
packages=(realmd sssd sssd-tools adcli libnss-sss libpam-sss krb5-user packagekit samba-common-bin)
|
||||
if [[ $ENABLE_SSH == true ]]; then
|
||||
packages+=(openssh-server)
|
||||
fi
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update
|
||||
apt-get install -y "${packages[@]}"
|
||||
pam-auth-update --enable mkhomedir --force
|
||||
return
|
||||
fi
|
||||
|
||||
if command -v dnf >/dev/null 2>&1; then
|
||||
packages=(realmd sssd sssd-tools adcli oddjob oddjob-mkhomedir samba-common-tools krb5-workstation)
|
||||
if [[ $ENABLE_SSH == true ]]; then
|
||||
packages+=(openssh-server)
|
||||
fi
|
||||
dnf install -y "${packages[@]}"
|
||||
authselect select sssd with-mkhomedir --force
|
||||
return
|
||||
fi
|
||||
|
||||
fail 'Supported package managers are apt-get (Debian/Ubuntu) and dnf (RHEL/Fedora/Rocky/AlmaLinux).'
|
||||
}
|
||||
|
||||
configure_private_ad_interface() {
|
||||
[[ -n $DOMAIN_INTERFACE ]] || return
|
||||
need_command nmcli
|
||||
ip link show "$DOMAIN_INTERFACE" >/dev/null 2>&1 || \
|
||||
fail "Network interface does not exist: $DOMAIN_INTERFACE"
|
||||
|
||||
local default_interface
|
||||
default_interface=$(ip route show default | awk 'NR == 1 { print $5 }')
|
||||
if [[ $default_interface == "$DOMAIN_INTERFACE" ]]; then
|
||||
fail "Refusing to reconfigure $DOMAIN_INTERFACE because it owns the default route. Use the private AD NIC."
|
||||
fi
|
||||
|
||||
local connection_name="SGU-Lab-AD-${DOMAIN_INTERFACE}"
|
||||
if ! nmcli -t -f NAME connection show | grep -Fxq "$connection_name"; then
|
||||
nmcli connection add type ethernet ifname "$DOMAIN_INTERFACE" con-name "$connection_name"
|
||||
fi
|
||||
nmcli connection modify "$connection_name" \
|
||||
connection.autoconnect yes \
|
||||
ipv4.method manual \
|
||||
ipv4.addresses "$DOMAIN_ADDRESS" \
|
||||
ipv4.dns "$DOMAIN_DNS" \
|
||||
ipv4.dns-search "$DOMAIN_NAME" \
|
||||
ipv4.never-default yes \
|
||||
ipv6.method ignore
|
||||
nmcli connection up "$connection_name"
|
||||
}
|
||||
|
||||
enable_sssd_dyndns() {
|
||||
[[ -n $DOMAIN_INTERFACE ]] || return
|
||||
local configuration_directory='/etc/sssd/conf.d'
|
||||
local configuration_path="${configuration_directory}/90-sgu-dyndns.conf"
|
||||
local temporary_path
|
||||
temporary_path=$(mktemp)
|
||||
printf '%s\n' \
|
||||
"[domain/${DOMAIN_NAME,,}]" \
|
||||
"ad_hostname = ${HOST_FQDN}" \
|
||||
'dyndns_update = True' \
|
||||
'dyndns_update_ptr = True' \
|
||||
"dyndns_iface = ${DOMAIN_INTERFACE}" \
|
||||
'dyndns_refresh_interval = 43200' >"$temporary_path"
|
||||
install -d -o root -g root -m 700 "$configuration_directory"
|
||||
install -o root -g root -m 600 "$temporary_path" "$configuration_path"
|
||||
rm -f "$temporary_path"
|
||||
}
|
||||
|
||||
enable_ssh() {
|
||||
[[ $ENABLE_SSH == true ]] || return
|
||||
local service_name='sshd'
|
||||
if systemctl list-unit-files ssh.service >/dev/null 2>&1; then
|
||||
service_name='ssh'
|
||||
fi
|
||||
systemctl enable --now "$service_name"
|
||||
if command -v ufw >/dev/null 2>&1 && ufw status | grep -q '^Status: active'; then
|
||||
ufw allow OpenSSH
|
||||
elif command -v firewall-cmd >/dev/null 2>&1 && systemctl is-active --quiet firewalld; then
|
||||
firewall-cmd --permanent --add-service=ssh
|
||||
firewall-cmd --reload
|
||||
fi
|
||||
}
|
||||
|
||||
verify_domain_connectivity() {
|
||||
need_command getent
|
||||
getent ahostsv4 "$DOMAIN_CONTROLLER" >/dev/null || \
|
||||
fail "Could not resolve the domain controller: $DOMAIN_CONTROLLER"
|
||||
if command -v resolvectl >/dev/null 2>&1; then
|
||||
resolvectl query --type=SRV "_ldap._tcp.dc._msdcs.${DOMAIN_NAME}" >/dev/null || \
|
||||
fail "AD DNS does not provide _ldap._tcp.dc._msdcs.${DOMAIN_NAME}."
|
||||
fi
|
||||
}
|
||||
|
||||
configure_private_ad_interface
|
||||
install_prerequisites
|
||||
verify_domain_connectivity
|
||||
|
||||
# Establish a canonical host name before adcli creates or refreshes the
|
||||
# computer object, SPNs, and keytab entries.
|
||||
hostnamectl set-hostname "$HOST_FQDN"
|
||||
|
||||
if realm list --name-only 2>/dev/null | grep -Fxqi "$DOMAIN_NAME"; then
|
||||
printf 'Computer is already joined to %s; validating and refreshing configuration.\n' "$DOMAIN_NAME"
|
||||
else
|
||||
realm discover "$DOMAIN_NAME" >/dev/null
|
||||
printf 'Joining %s. realmd will request the password for %s interactively.\n' "$DOMAIN_NAME" "$JOIN_USER"
|
||||
realm join \
|
||||
--membership-software=adcli \
|
||||
--client-software=sssd \
|
||||
--computer-ou="$COMPUTER_OU" \
|
||||
--user="$JOIN_USER" \
|
||||
"$DOMAIN_NAME"
|
||||
fi
|
||||
|
||||
enable_sssd_dyndns
|
||||
systemctl enable --now sssd
|
||||
sssctl config-check
|
||||
systemctl restart sssd
|
||||
adcli update --domain="$DOMAIN_NAME" --host-fqdn="$HOST_FQDN" --computer-name="$COMPUTER_NAME"
|
||||
adcli testjoin --domain="$DOMAIN_NAME"
|
||||
|
||||
if [[ -n $ALLOW_GROUP ]]; then
|
||||
realm deny --all
|
||||
realm permit --groups "$ALLOW_GROUP"
|
||||
fi
|
||||
|
||||
enable_ssh
|
||||
|
||||
printf '\nLinux enrollment completed.\n'
|
||||
printf ' Host: %s\n' "$HOST_FQDN"
|
||||
printf ' Domain: %s\n' "$DOMAIN_NAME"
|
||||
printf ' OU: %s\n' "$COMPUTER_OU"
|
||||
printf ' Login format: %%U@%s\n' "$DOMAIN_NAME"
|
||||
realm list
|
||||
@@ -80,15 +80,17 @@ if (-not $runtimeInstaller) {
|
||||
New-Item -ItemType Directory -Path $resolvedOutputRoot -Force | Out-Null
|
||||
$clientRoot = Join-Path $resolvedOutputRoot "sgu-client-bootstrap-$Version"
|
||||
$serverRoot = Join-Path $resolvedOutputRoot "sgu-server-bootstrap-$Version"
|
||||
$linuxClientRoot = Join-Path $resolvedOutputRoot "sgu-linux-client-bootstrap-$Version"
|
||||
$clientZip = "$clientRoot.zip"
|
||||
$serverZip = "$serverRoot.zip"
|
||||
foreach ($target in @($clientRoot,$serverRoot,$clientZip,$serverZip)) {
|
||||
$linuxClientZip = "$linuxClientRoot.zip"
|
||||
foreach ($target in @($clientRoot,$serverRoot,$linuxClientRoot,$clientZip,$serverZip,$linuxClientZip)) {
|
||||
if (Test-Path -LiteralPath $target) {
|
||||
throw "Release target already exists: $target"
|
||||
}
|
||||
}
|
||||
|
||||
New-Item -ItemType Directory -Path $clientRoot,$serverRoot -Force | Out-Null
|
||||
New-Item -ItemType Directory -Path $clientRoot,$serverRoot,$linuxClientRoot -Force | Out-Null
|
||||
|
||||
Copy-RequiredFile -Source (Join-Path $PSScriptRoot 'Invoke-SguClientBootstrap.ps1') `
|
||||
-Destination (Join-Path $clientRoot 'Invoke-SguClientBootstrap.ps1')
|
||||
@@ -120,6 +122,17 @@ Write-PackageManifest -PackageRoot $clientRoot -PackageVersion $Version -Package
|
||||
Compress-Archive -Path (Join-Path $clientRoot '*') -DestinationPath $clientZip `
|
||||
-CompressionLevel Optimal
|
||||
|
||||
# Linux clients use their native PAM/SSSD sign-in stack rather than the Windows
|
||||
# Credential Provider. Keep their self-contained bootstrap independent so a
|
||||
# Linux administrator never receives Windows binaries or certificate material.
|
||||
Copy-RequiredFile -Source (Join-Path $PSScriptRoot 'Enroll-SguLinuxDomainClient.sh') `
|
||||
-Destination (Join-Path $linuxClientRoot 'Enroll-SguLinuxDomainClient.sh')
|
||||
Copy-RequiredFile -Source (Join-Path $repositoryRoot 'docs\linux-client-enrollment.md') `
|
||||
-Destination (Join-Path $linuxClientRoot 'README.md')
|
||||
Write-PackageManifest -PackageRoot $linuxClientRoot -PackageVersion $Version -PackageKind LinuxClient
|
||||
Compress-Archive -Path (Join-Path $linuxClientRoot '*') -DestinationPath $linuxClientZip `
|
||||
-CompressionLevel Optimal
|
||||
|
||||
Copy-RequiredFile -Source (Join-Path $PSScriptRoot 'Initialize-SguDomainController.ps1') `
|
||||
-Destination (Join-Path $serverRoot 'Initialize-SguDomainController.ps1')
|
||||
Copy-RequiredFile -Source (Join-Path $PSScriptRoot 'Start-SguServerBootstrap.cmd') `
|
||||
@@ -161,6 +174,7 @@ Compress-Archive -Path (Join-Path $serverRoot '*') -DestinationPath $serverZip `
|
||||
$checksums = @(
|
||||
("{0} {1}" -f (Get-FileHash -LiteralPath $clientZip -Algorithm SHA256).Hash, (Split-Path $clientZip -Leaf))
|
||||
("{0} {1}" -f (Get-FileHash -LiteralPath $serverZip -Algorithm SHA256).Hash, (Split-Path $serverZip -Leaf))
|
||||
("{0} {1}" -f (Get-FileHash -LiteralPath $linuxClientZip -Algorithm SHA256).Hash, (Split-Path $linuxClientZip -Leaf))
|
||||
)
|
||||
$checksumsPath = Join-Path $resolvedOutputRoot "SHA256SUMS-$Version.txt"
|
||||
[IO.File]::WriteAllLines($checksumsPath, $checksums, [Text.UTF8Encoding]::new($false))
|
||||
@@ -169,6 +183,8 @@ $checksumsPath = Join-Path $resolvedOutputRoot "SHA256SUMS-$Version.txt"
|
||||
Version = $Version
|
||||
ClientPackage = $clientZip
|
||||
ClientSha256 = (Get-FileHash -LiteralPath $clientZip -Algorithm SHA256).Hash
|
||||
LinuxClientPackage = $linuxClientZip
|
||||
LinuxClientSha256 = (Get-FileHash -LiteralPath $linuxClientZip -Algorithm SHA256).Hash
|
||||
ServerPackage = $serverZip
|
||||
ServerSha256 = (Get-FileHash -LiteralPath $serverZip -Algorithm SHA256).Hash
|
||||
Checksums = $checksumsPath
|
||||
|
||||
@@ -17,6 +17,7 @@ $tagName = "v$Version"
|
||||
$assetPaths = @(
|
||||
(Join-Path $ReleaseDirectory "sgu-client-bootstrap-$Version.zip"),
|
||||
(Join-Path $ReleaseDirectory "sgu-server-bootstrap-$Version.zip"),
|
||||
(Join-Path $ReleaseDirectory "sgu-linux-client-bootstrap-$Version.zip"),
|
||||
(Join-Path $ReleaseDirectory "SHA256SUMS-$Version.txt")
|
||||
)
|
||||
foreach ($assetPath in $assetPaths) {
|
||||
@@ -100,6 +101,7 @@ Bootstrap reproducible para el laboratorio SGU.
|
||||
- **Advertencia:** el bootstrap de servidor crea un bosque nuevo. No restaura los SID, contraseñas ni relaciones de confianza del bosque anterior; para conservarlos se requiere una recuperación de bosque desde una copia de estado del sistema.
|
||||
- `sgu-server-bootstrap-$Version.zip`: crea el bosque AD/DNS, OUs, grupo RDP, GPO, recurso `Packages`, broker mTLS y administración remota; se reanuda solo después del reinicio.
|
||||
- `sgu-client-bootstrap-$Version.zip`: registra un certificado mTLS único, instala y valida el Credential Provider antes de unir el equipo al dominio, habilita RDP/WinRM y se repara al arranque.
|
||||
- `sgu-linux-client-bootstrap-$Version.zip`: une clientes Debian/Ubuntu o RHEL/Fedora/Rocky/AlmaLinux con realmd, Kerberos y SSSD. Solicita interactivamente la contraseña de unión y no instala el Credential Provider de Windows.
|
||||
- El servidor configura WEF/WEC para registrar sesiones y fallos, inventariar el estado alcanzable de las máquinas cada cinco minutos y conservar durante 183 días tanto esos eventos como el diagnóstico estructurado del Auth Broker.
|
||||
- Windows Home se detecta y se rechaza con una explicación, ya que no admite unión a Active Directory ni RDP host.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user