Adds the Blueforce Field OS provisioning stack on top of the existing fleet architecture, without rewriting the working systems (installer, diagnostics, Ansible, WireGuard/SSH/xRDP/RustDesk, Docker policies, monitoring, Docusaurus). ISO build (the previous builder was a skeleton that produced no medium): - boot layout is read from the base ISO at build time via `xorriso -report_el_torito as_mkisofs` and rebuilt with `-as mkisofs`; `-boot_image any replay` cannot work on Ubuntu live ISOs because the GRUB2 MBR lives in the source image's first 16 sectors and the EFI system partition is an appended partition, neither of which is a file in the ISO9660 tree - preflight now asserts El Torito boot metadata positively: xorriso exits 0 on a non-ISO input, which previously let an arbitrary file pass --check - artifact produced and verified: dist/Blueforce-Field-OS-1.0.0-amd64.iso, 6 481 917 952 bytes, SHA256 cb0cc56f...d431296, BIOS+UEFI entries preserved, /autoinstall.yaml at the media root, casper/minimal.squashfs byte-identical to the base - recorded baseline deviation: the verified medium on the build host is the Desktop flavour, so the manifest carries a baseline_deviation block instead of hiding it; Server remains one flag away Offline and identity: - offline APT contract with concrete package requirements, pin format and an audit table; builds fail closed while pins are UNPINNED - autoinstall keeps interactive-sections: [storage]: the operator confirms the target disk, and no automatic wipe is ever performed - firstboot terminal wizard for the 8-digit dealer id, three-state lifecycle (PROVISIONED_OFFLINE -> ENROLLED -> READY) with fail-closed gates, so a missing internet link or WireGuard handshake cannot fail provisioning but can never produce a false READY Fleet and migration: - five read-only Ansible playbooks for Field OS version, provisioning, enrollment, remote channels and offline readiness, all wave-scoped with a separate production override - Windows pre-migration inventory and data export extended to the full brief scope, read-only, never collecting credentials Tests: tests/run-all.sh -> 8/8 pass, exit 0. Boot acceptance (UEFI, Legacy BIOS, Secure Boot), air-gapped install, real enrollment endpoint and Windows rollback remain LAB work and are listed in IMPLEMENTATION-REPORT.md.
11 KiB
29 — Cihaz Enrollment
Kısa özet: Device enrollment, offline provision edilmiş cihazın merkezi envantere bir kez bağlanması ve merkezi kanallarca doğrulanmasıdır. Durum modeli tek yönlüdür:
PROVISIONED_OFFLINE → ENROLLED → READY; geri dönüş kenarı ve durum atlama yoktur (PROVISIONED_OFFLINE → READYdoğrudan olamaz). Tek kullanımlık tokenENROLLEDverir; yalnız WireGuard, erişim ve monitoring doğrulanıncaREADYverilir.READYsonrası kurtarma yolu yeniden provision'dır (27), durumu geri sarmak değil.
- Dosya:
docs/29-DEVICE-ENROLLMENT.md- İlgili kararlar:
24-DECISION-LOG.md#K-17(enrollment),#K-21(tek durum kaynağı ve ileri-yönlü geçişler),#K-12,#K-05,#K-07- Durum: [ ] Taslak
1. Amaç
Cihaz kimliğinin, ağ kaydının ve merkezi gözlemin sahada güvenli sırayla birleştirilmesini tanımlamak.
2. Kapsam
- Kapsam içi: durum makinesi, token özellikleri, merkezi kayıt, WG/remote/monitoring kapıları, token iptal kaydı.
- Kapsam dışı: offline işletim sistemi kurulumu (27), SSH anahtar yaşam döngüsü (06), release seçimi (30).
3. Kararlar
KARAR: Enrollment bir kez kullanılan, süreli ve cihaz kimliğine bağlı token ile yapılır. Durum modeli üç durumdur ve TEK YÖNLÜDÜR: PROVISIONED_OFFLINE → ENROLLED → READY. Geçişler ileri yönlüdür; **geri dönüş kenarı yoktur ve durum atlanamaz** (PROVISIONED_OFFLINE → READY doğrudan olamaz, READY → ENROLLED geri alınmaz). READY sonrası kurtarma yolu durumu geri sarmak değil, cihazı 27'ye göre YENİDEN PROVISION etmektir (yeni yaşam döngüsü: PROVISIONED_OFFLINE'dan başlar). Tek kaynak `/var/lib/blueforce/state.json` + `bf-enrollment-status` çıktısıdır.
GEREKÇE: Offline medya secret taşımaz; token yalnız bağlantı oluştuğunda kullanılır. READY, token kullanımından değil merkezi erişim ve health kanallarının gerçek doğrulamasından doğar. Geçmişi geri sarma kenarları "hangi cihaz ne zaman READY oldu" denetimini bulanıklaştırır ve yanlış teslim üretir; kurtarmayı yeniden provision'a bağlamak denetim izini tek yönlü ve kanıtlı tutar. Uygulanan kod bu sözleşmeyi zorlar: `bf-enrollment-status` yalnız üç durumu geçerli sayar, `bf-enroll` yalnız PROVISIONED_OFFLINE/ENROLLED fazından enrollment kabul eder.
ALTERNATİF: Kalıcı ortak bootstrap token — sızıntıda tüm filoyu etkiler; elendi. Geri alınabilir durum geçişleri (READY → ENROLLED) — denetim izini belirsizleştirir ve "READY gerçekten alındı mı" sorusunu cevapsız bırakır; reddedildi. Ayrı bir RETIRED/REVOKED durumu eklemek — açık soru olarak §13'te (bugünkü sözleşme `INVALID`/`PENDING` + exit≠0 ile fail-closed davranır).
RİSK: Token çalınması veya yanlış cihazda kullanılması; kısa TTL, tek kullanım, `BF-<no>` bağlama ve anlık iptal ile azaltılır. READY sonrası kurtarmanın yeniden provision gerektirmesi saha süresi maliyeti doğurur; azaltma: 17-RECOVERY kademeleri (L1→L9) önce denenir, yeniden provision son çare.
MALİYET: Ücretsiz.
LİSANS: OpenSSH — https://www.openssh.com/ ; WireGuard — https://www.wireguard.com/ ; token API davranışı kurum içi uygulama ve LAB doğrulamasıdır.
Güncelleme (2026-09-16, K-21): Bu dosyanın ek diyagramındaki iki geri dönüş kenarı (
ENROLLED → PROVISIONED_OFFLINE,READY → ENROLLED) uygulanan kuralla çelişiyordu ve kaldırılmıştır. Uygulanan kural: geçişler ileri yönlüdür; geri dönüş ve atlama yoktur. READY sonrası kurtarma yolu yeniden provision'dır (27) — ayrıntı §11 ve Ek'teki ikinci diyagram.
4. Neden Bu Karar?
İlk kurulumdaki cihaz, merkez açısından henüz bilinmeyen bir uçtur. Token yalnız kimlik bağlama yetkisi verir; merkezi kanalların gerçekten çalıştığını ispatlamaz. Bu ayrım yanlış READY teslimini engeller. Durumun tek yönlü olması da aynı amaca hizmet eder: "kuruldu → bağlandı → doğrulandı" sırası kanıt zinciridir; geri sarmalı kenarlar bu zinciri koparır ve denetimde hangi durumun ne zaman gerçek olduğunu belirsizleştirir. Bir cihaz READY'den düşürülmesi gerekiyorsa yapılan iş yeni bir provision + enrollment + READY kanıtı üretmektir (27), eski durumu geri yazmak değil.
5. Alternatifler
| Alternatif | Artı | Eksi | Sonuç |
|---|---|---|---|
| Tek-kullanımlık, TTL'li token | Küçük sızıntı alanı | Token üretim hizmeti gerekir | Seçildi |
| Ortak kalıcı token | Basit | Filo çapı sızıntı | Elendi |
| Manuel merkezi kayıt | Ek sistem yok | Hata/audit zayıf | Elendi |
6. Avantajlar
- Her kayıt hangi cihaz, kim ve ne zaman ile ilişkilidir.
- READY bağımsız sağlık kanıtına bağlıdır.
7. Dezavantajlar
- Cihazın internete kavuşması gerekir.
- Token hizmeti ve iptal kaydı işletilir.
8. Riskler
| Risk | Olasılık | Etki | Azaltma |
|---|---|---|---|
| Token tekrar kullanımı | Düşük | Yüksek | Atomik tüketim + audit |
| Kimlik çakışması | Düşük | Yüksek | Envanter benzersizlik kapısı |
| WG var ama health yok | Orta | Orta | READY için üç kanal şartı |
| READY sonrası kurtarma yolu yanlış modellenir (durum geri sarma denemesi) | Orta | Orta | Geçişler ileri yönlü; kurtarma = 27 yeniden provision; bf-enrollment-status yalnız üç durumu geçerli sayar, aksi halde INVALID/PENDING + exit≠0 |
central_verification alanları pending kalır, cihaz ENROLLED'da bekler |
Orta | Orta | Fail-closed READY kapısı + enrollment yanıt sözleşmesinin zorunlu alanları |
9. Uygulama Planı
- Merkezi admin, doğrulanmış bayi no için
BF-<no>bağlı, kısa ömürlü token üretir ve kayda açar. - Teknisyen tokenı yalnız cihaz ekranına girer; USB'ye, loga veya support bundle'a yazmaz.
- Başarılı yanıtın tamamı doğrulanır; yalnız bundan sonra WireGuard yapılandırması atomik kurulur ve servis etkin/aktif ise durum
ENROLLEDolur. bf-check-ready, kalıcıREADYdeğerini okumaz: güncel WG handshake, etkin xRDP, RustDesk yapılandırması, isteğe bağlı Mesh ajanı ve merkezden gelen doğrulama kanıtını bağımsız denetler. Tümü geçerse18-final-checkREADYyazar.- İleri-yönlü geçiş kuralı (uygulanan sözleşme): durumlar yalnız
PROVISIONED_OFFLINE → ENROLLED → READYsırasıyla ilerler.PROVISIONED_OFFLINE → READYdoğrudan geçiş yoktur (merkezi kanal kanıtı token olmadan üretilemez);ENROLLED → PROVISIONED_OFFLINEveyaREADY → ENROLLEDgeri dönüş kenarı yoktur. Bir cihaz READY'den çıkarılması gerekiyorsa:- önce 17-RECOVERY kademeleri (L1 servis restart → … → L8 USB ile sıfırdan imaj) denenir,
- kimlik/merkez kaydı ciddi biçimde bozuksa cihaz merkezi erişimden çekilir, token/peer iptal edilir ve 27'ye göre yeniden provision edilir; yeniden provision yeni bir yaşam döngüsü başlatır (
PROVISIONED_OFFLINE→ yeni token →ENROLLED→ yeni READY kanıtı). - Yani kurtarma "durumu geri sarmak" değil, "kanıtı yeniden üretmek"tir.
# BF_ENROLLMENT_ENDPOINT is supplied by the approved central control plane configuration.
printf '%s\n' '<tek-kullanimlik-token>' | sudo -E bf-enroll --token-stdin
bf-enrollment-status # yalnız PROVISIONED_OFFLINE | ENROLLED | READY; aksi halde INVALID/PENDING + exit≠0
bf-check-ready
10. Test Planı
| Test | Beklenen sonuç | Ortam |
|---|---|---|
| Geçerli token | PROVISIONED_OFFLINE → ENROLLED | LAB(2) |
| Aynı token ikinci kez | Reddedilir, audit kaydı | LAB(2) |
| Süresi geçmiş/yanlış cihaz tokenı | Reddedilir | LAB(2) |
| Merkezi kanallar eksik | ENROLLED kalır, READY olmaz | LAB(2) |
| Token olmadan READY denemesi | READY yazılmaz (atlama yok) | LAB(2) |
| READY sonrası kurtarma provası | Durum geri sarmak yerine 27 yeniden provision yolu çalışır | LAB(2) |
11. Rollback
- Token yanlış kullanılırsa merkezi admin tokenı iptal eder ve geçici kayıtları kapatır (cihaz ENROLLED'da kalır; READY'ye ilerlemez).
- Yanlış WireGuard peer/etiket,
ENROLLEDdurumunda düzeltilir ve yeniden doğrulanır. - READY sonrası ciddi kimlik sorunu varsa cihaz merkezi erişimden çekilir, token/peer iptal edilir ve 27'den yeniden provision edilir. Bu "rollback" bir durum geri alma değildir: yeni yaşam döngüsü PROVISIONED_OFFLINE'dan başlar ve READY yeniden kanıtlanır (geçişler ileri yönlüdür).
12. Kontrol Listesi
- Token tek kullanımlık, TTL'li ve
BF-<no>bağlı. - Token hiçbir medya/log/support bundle içinde yok.
- ENROLLED ve READY farklı, görünür durumlar.
- WG + remote + monitoring doğrulaması kayda bağlı.
- Merkez yanıtındaki
central_verificationkanıtı olmayan veyapendingolan cihaz READY olmaz. - Diyagramda/metinde geri dönüş kenarı ve durum atlama yok; READY sonrası kurtarma 27 yeniden provision olarak yazılı.
13. Açık Sorular
- Token TTL süresi ve yetkili üretici rolleri — sahibi: güvenlik yöneticisi.
- Enrollment API audit saklama süresi — sahibi: merkezi admin.
- Geri dönüşsüz modelde "cihaz işletmeden çekildi" durumu için ayrı bir kalıcı damga (ör.
retired) gerekir mi — karar sahibi: platform ekibi + 27 yazarı [K-21].
Ek: Merkezi doğrulama yanıt sözleşmesi ve güven sınırı
Enrollment yanıtı central_verification alanını zorunlu taşır. Alan secret, URL, erişim tokenı, RustDesk parolası veya WireGuard private key taşımaz; yalnız merkezde denetlenebilen referansları taşır:
{
"central_verification": {
"status": "pending | verified",
"verification_id": "merkez-kayit-referansi",
"monitoring": {"status": "pending | verified", "verification_id": "izleme-referansi"},
"remote": {"status": "pending | verified", "verification_id": "uzak-erisim-referansi"},
"management": {"status": "pending | verified", "verification_id": "yonetim-referansi"}
}
}
İstemci merkez URL'si veya kanıt uydurmaz. bf-remote-status yalnız imzalanmış/kimliği doğrulanmış enrollment yanıtından kalıcılaştırılan bu referansların tümü verified olduğunda merkezi kanıtı geçer; alan eksik, biçimsiz veya pending ise PENDING ile fail-closed olur. Yerel xRDP, RustDesk, isteğe bağlı Mesh ve güncel WG handshake bu merkez kanıtından ayrı olarak kontrol edilir.
Ek: Durum makinesi (tek yönlü — geri dönüş kenarı yok)
stateDiagram-v2
[*] --> PROVISIONED_OFFLINE
PROVISIONED_OFFLINE --> ENROLLED: tek kullanımlık token (ileri)
ENROLLED --> READY: WG + remote + monitoring kanıtı (ileri)
note right of READY
Geri dönüş kenarı YOKTUR ve durum atlanamaz
(PROVISIONED_OFFLINE -> READY doğrudan olamaz).
READY sonrası kurtarma: 27'ye göre yeniden provision.
end note
Ek: READY sonrası kurtarma yolu (yeni yaşam döngüsü)
flowchart LR
RDY["READY cihaz: kimlik/merkez kaydı ciddi biçimde bozuk"] --> CEK["Merkezi erişimden çek + token/peer iptal"]
CEK --> RP["27'ye göre YENİDEN PROVISION<br/>(yeni yaşam döngüsü başlar)"]
RP --> PO["PROVISIONED_OFFLINE"]
PO -->|yeni tek kullanımlık token| EN["ENROLLED"]
EN -->|yeni WG + remote + monitoring kanıtı| YENI["READY (yeniden kanıtlandı)"]
GERI["Durumu geri sarma (READY → ENROLLED vb.)"] -.->|"YASAK"| RDY