# dsa-pc-setup.ps1

Первичная настройка клиентского Windows-ПК «из коробки» в инфраструктуре DSA.

## Что делает

1. **Edition upgrade** — если на ПК Windows Home/Core (10 или 11), апгрейдит до Pro через `changepk.exe /productkey` с generic Microsoft-ключом. После апгрейда ПК уходит в перезагрузку, скрипт сам продолжается после первого логина админа.
2. **Поиск имени в AD** — запросом LDAP к домену клиента находит минимальный свободный номер `XXX-CNNN` (например `ABS-C037`).
3. **Список локальных юзеров с выбором** — показывает все SAM-аккаунты с `RID >= 1000` (кроме текущей сессии), даёт инженеру выбрать кого конвертировать. Поддерживает массовый выбор (`1,3,5`), все (`all`) и никого (`none`). Невыбранные юзера остаются как есть.
4. **Доменный юзер — новый или существующий** — для каждого выбранного локального аккаунта инженер выбирает режим:
   - `[N] новый`: спрашиваем ФИО на русском, скрипт создаёт юзера в AD (CN = `Имя Фамилия`, sAMAccountName = `n.familiya` по транслиту ГОСТ 7.79-Б, UPN = `n.familiya@<domain>`, пароль из 4 классов в 16 символов).
   - `[E] существующий`: спрашиваем sAMAccountName, скрипт находит юзера в AD, подтягивает displayName из объекта, **пароль не трогает**. Полезно когда у сотрудника уже есть доменный аккаунт и нужно просто пересадить его профиль на новый ПК.
5. **Rename + Domain Join** — одной операцией `Add-Computer -NewName` переименовывает ПК и присоединяет к домену (без отдельного промежуточного ребута).
6. **Миграция профиля каждого выбранного локального юзера** (в цикле):
   - logoff его сессии, выгрузка хайва из HKU;
   - переименование `C:\Users\OldUser` → `C:\Users\n.familiya`;
   - копирование ключа `HKLM\...\ProfileList\<OldSid>` → `<NewSid>` с правкой `ProfileImagePath`;
   - выставление ACL по голому SID (`icacls /grant *S-1-5-...`);
   - правка `NTUSER.DAT` и `UsrClass.dat` — поиск и замена всех вхождений старого SID на новый;
   - удаление локального пользователя (`Remove-LocalUser`).
7. **Reset built-in Administrator (RID 500)** — независимо от языка ОС (русский «Администратор» / английский «Administrator» — определяется по SID `*-500`). Генерирует новый 20-символьный пароль, применяет через `Set-LocalUser`, если аккаунт был disabled — активирует через `Enable-LocalUser`. Старый пароль теряется, новый выводится в консоль.
8. **Карточка ПК на DC** — сохраняет архивный файл `\\<DC>\C$\_Payload\Workstations\<ИМЯПК>.txt` (UTF-8 with BOM). Папка `Workstations\` зеркалит OU=Workstations в AD; если её нет на диске — создаётся. Внутри файла — имя ПК, дата, инженер, пароль Administrator, все созданные/подцепленные доменные юзеры с паролями (для существующих юзеров пароль не записывается, потому что мы его не меняли). Сохраняется через `New-PSDrive` + UNC `C$` с теми же доменными кредами что для AD-операций. Если DC недоступен — fallback на локальный `C:\ProgramData\DSA\<ИМЯПК>.card.txt`, об этом в консоли warning.
9. **Финальный ребут** через 90 секунд — после него ПК загружается с новым именем, в домене, доменные юзера логинятся в перенесённые профили.

## Чего скрипт НЕ делает

- **Не активирует Pro retail-ключом.** `changepk` ставит edition, для активации нужен реальный ключ (retail/MAK/KMS) — отдельный шаг.
- **Не настраивает GPO-привязку.** ПК попадает в OU указанную инженером, дальше GPO применятся стандартно.
- **Не устанавливает софт** (Office, антивирус, choco-пакеты) — этим занимаются другие плейбуки/скрипты.
- **Не настраивает OneDrive/Outlook.** После смены профиля они перезапросят авторизацию — это нормально.
- **Не сохраняет пароль никуда, кроме консоли.** Запишите его в Notion-страницу клиента до того как закроете окно.
- **Не делает atomic claim имени ПК.** Если два инженера одновременно настраивают ПК у одного клиента — могут занять один номер; второй `Add-Computer` упадёт с «name already exists», перезапустить.

## Требования

- Windows 10 / 11 любой edition.
- Запуск **из-под локального админа, который НЕ конвертируется**. Например, есть `Administrator` и `User1` — скрипт запускается под `Administrator`, конвертирует `User1`. (Себя конвертировать нельзя — скрипт упадёт на старте.)
- Сетевой доступ к контроллеру домена клиента (LDAP/389 и LDAPS/636 если SetPassword падает).
- Креды доменного админа (нужны для создания юзера и Add-Computer).
- ПК ещё не в домене.

## Запуск

На свежем ПК открываешь PowerShell **как администратор** и:

Команда одной строкой (в PowerShell разделитель команд — `;`, а не пробел — без них `&` будет интерпретироваться как часть предыдущей команды и упадёт с `AmpersandNotAllowed`):

```powershell
Set-ExecutionPolicy -Scope Process Bypass -Force; iwr https://d.dsa.one/dsa/scripts/dsa-pc-setup.ps1 -OutFile $env:TEMP\dsa-pc-setup.ps1; & $env:TEMP\dsa-pc-setup.ps1
```

Если удобнее тремя строками — копируй и вставляй построчно (после каждой `Enter`):

```powershell
Set-ExecutionPolicy -Scope Process Bypass -Force
iwr https://d.dsa.one/dsa/scripts/dsa-pc-setup.ps1 -OutFile $env:TEMP\dsa-pc-setup.ps1
& $env:TEMP\dsa-pc-setup.ps1
```

Дальше отвечаешь на вопросы:

```
FQDN домена (например abs.dsa.one): abs.dsa.one
Код клиента для префикса имени ПК [по умолчанию 'ABS']: <Enter>

Локальные пользователи (RID >= 1000, кроме текущей сессии Administrator):
   1. User1                    enabled    SID=S-1-5-21-...-1001
   2. TestUser                 disabled   SID=S-1-5-21-...-1002
   3. ivanov.local             enabled    SID=S-1-5-21-...-1003

Кого конвертировать в доменных? (номера через запятую, 'all' — все, 'none' — никого): 1,3
ФИО на русском для 'User1' (например 'Иван Петров'): Сидор Петров
   → логин: s.petrov
ФИО на русском для 'ivanov.local' (например 'Иван Петров'): Иван Иванов
   → логин: i.ivanov

Пробую найти OU _Payload (DSA-конвенция)...
  ✓ найдено OU=Workstations,OU=_Payload,DC=abs,DC=dsa,DC=one
  ✓ найдено OU=Users,OU=_Payload,DC=abs,DC=dsa,DC=one

OU для компьютера [по умолчанию 'OU=Workstations,OU=_Payload,...']: <Enter или своя>
OU для пользователей [по умолчанию 'OU=Users,OU=_Payload,...']: <Enter или своя>

Креды доменного администратора (например ABS\dsa_zabaluev)
PowerShell credential request:
User: ABS\dsa_zabaluev
Password: ****
```

В summary в конце получишь пароли для всех конвертированных юзеров + новый пароль built-in Administrator. Перепиши их в Notion ДО того как закроешь окно — на диск пароли не пишутся.

Если edition был Home — скрипт ребутнётся после edition upgrade и сам продолжится после логина. Если уже Pro — всё происходит в одной сессии, один ребут в конце.

### Особые случаи

- **Никого не конвертировать** (`none`) — скрипт сделает только rename+join домена и reset built-in Administrator. Локальные юзера останутся как есть.
- **Нет локальных юзеров с `RID >= 1000`** (только текущая сессия) — скрипт выводит warning и продолжает без конвертаций.
- **Текущая сессия — built-in Administrator** — скрипт предупредит и поменяет пароль самой себя. Новый пароль выведется в консоль; после ребута логиниться нужно будет уже новым.
- **Built-in admin не найден** (RID 500 удалён или скрыт) — reset пропускается с warning.

### Дефолты OU и `_Payload`

После ввода кредов скрипт лезет LDAP-ом в домен клиента и пытается найти DSA-конвенциональную структуру:

- `OU=Workstations,OU=_Payload,DC=<domain>` — для компьютеров
- `OU=Users,OU=_Payload,DC=<domain>` — для пользователей

Если найдены — они становятся дефолтами (Enter подтверждает). Если нет — fallback на стандартные `CN=Computers` и `CN=Users` в корне домена. В любом случае ввести свой DN можно вручную в ответе на prompt.

## Параметры командной строки

| Параметр | Назначение |
|---|---|
| `-Resume` | Внутренний флаг (выставляет Scheduled Task после ребута). Вручную обычно не нужен. |
| `-SkipEditionUpgrade` | Не делать апгрейд edition даже если Home (если, например, надо вручную позже). |
| `-SkipHiveRewrite` | Не править NTUSER.DAT/UsrClass.dat. Безопаснее (нет риска handle-залипания), но в реестре пользователя останутся «orphan SID»-вхождения. |
| `-StatePath` | Альтернативный путь к state-файлу. По умолчанию `C:\ProgramData\DSA\pc-setup.state.json`. |

## Файлы которые скрипт создаёт

| Путь | Что |
|---|---|
| `C:\ProgramData\DSA\pc-setup.ps1` | Копия скрипта для авторезюма после ребута |
| `C:\ProgramData\DSA\pc-setup.state.json` | State между фазами (значения зашифрованы DPAPI LocalMachine). Архивируется после успешного завершения. |
| `C:\ProgramData\DSA\pc-setup.log` | Лог всех действий |
| `Scheduled Task: DSA-PC-Setup-Resume` | Триггер `AtLogOn` для группы Administrators. Снимается автоматически при успехе. |

## Откат / разбор полётов

**Если упало посередине** — лог в `C:\ProgramData\DSA\pc-setup.log`. State в `pc-setup.state.json`. Можно перезапустить:

```powershell
& C:\ProgramData\DSA\pc-setup.ps1 -Resume
```

**Если ПК уже в домене но юзер не сконвертирован** — можно удалить state и Scheduled Task вручную и доделать ручными командами (см. лог чтобы понять докуда дошли).

**Если папка профиля переименована но реестр не правился** — войти доменным юзером не получится (Windows создаст новый профиль). Лечится правкой `HKLM\...\ProfileList\<новый_SID>\ProfileImagePath`.

**Если правка хайвов оставила handle** — `reg unload` не падает критично, хайв выгрузится при ребуте. После ребута старые SID-вхождения уже неактивны.

## Грабли

1. **EFS-зашифрованные файлы.** После смены SID они станут недоступны. Скрипт перед миграцией грепает `cipher /S` и спрашивает подтверждение если что-то нашёл.
2. **BitLocker.** Не ломаем, но recovery key должен быть сохранён до прогона.
3. **Антивирус.** Если стоит сторонний AV — может заблокировать takeown/icacls. Лучше выключить realtime до прогона.
4. **OneDrive/Outlook.** После миграции перезапросят логин — это нормально, не баг.
5. **Тестирование.** Это не dry-run. Первый прогон обязательно на тестовой ВМ со снапшотом перед запуском.

## Транслит логина — система Б (упрощённая)

| Кириллица | Транслит | Пример |
|---|---|---|
| Ё | yo | Ёлкин → yo.yolkin |
| Ж | zh | Жуков → zh.zhukov (если имя на Ж) |
| Й | j | Иосиф → i.iosif, Йорик → j.jorik |
| Х | x | Хохлов → x.xoxlov (если имя на Х) |
| Ц | cz | Цой → c.czoj (имя на Ц редко) |
| Ч | ch | Чернов → ch.chernov |
| Ш | sh | Шумилов → sh.shumilov |
| Щ | shh | Щукин → shh.shhukin |
| Ы | y | (в начале не встречается) |
| Э | e | Эдуард → e.eduard |
| Ю | yu | Юлия → yu.yuliya (если имя на Ю) |
| Я | ya | Яков → ya.yakov |
| Ъ, Ь | (пусто) | Подъячий → p.podyachij |

Первая буква имени — это **полный транслит первой кириллической буквы**, поэтому `Юлия Петрова` → `yu.petrova`, а не `y.petrova`. Это сохраняет однозначность обратного преобразования глазами.
