Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ Biçim [Keep a Changelog](https://keepachangelog.com/) esas alınmıştır.

## [Unreleased]

### Eklendi
- **Kontrol makinesi saatiyle bağımsız karşılaştırma.** Gerçek VM bulgusu: snapshot/rollback sonrası sunucu saati 13 gün geride iken `chronyc tracking` ("0.000000155 seconds slow", Ref time sunucunun kendi yanlış saatinde) ve `sources` sapmayı göstermedi; 0.1.1 `durum` `ntp_senkron=yes sapma_ms=0.0` dedi, plan `saat` içermedi. Artık sunucunun `date +%s` değeri Ansible kontrol makinesininkiyle karşılaştırılır (chrony'den bağımsız): fark > 300 sn ise `durum` `saat_sapma_kontrolcuye_gore_sn=N` verir ve `ntp_senkron=no` olur, `preview`/`apply` plana `saat` ekler ve uyarır. `apply` önce chrony'yi yeniden başlatıp (bayat ölçümü atar) `makestep` dener; fark sürerse ve `utility_ntp_clock_from_controller=true` ise (varsayılan `false`, açık seçenek) `date -s` ile kontrol makinesinin saatine ayarlar. Chrony yeniden başlatma sonrası taze kaynakla saati doğruluyorsa kontrolcü saatine DOKUNULMAZ (kontrol makinesi yanlış olabilir) ve uyarılır.
- LAB testleri 21-27 (SAHTE `date` ve `chronyc`).

### Denenmedi
- Gerçek VM'de: chrony yeniden başlatma + `makestep` ile bayat durumun düzelmesi ve `date -s` yolu. Bayat chrony nedeni varsayımdır (aşağıya bakın), LAB'da gerçek chronyd yok.

### Değişti
- `scripts/release-publish.sh`: Release ve özet doğrulamasından sonra paket indeksini günceller (`sshpocket-index/scripts/index-publish.sh`, `SSHPOCKET_INDEX_DIR`); betik yoksa etiketten önce durur; indeks hatası yayımlanmış Release'i geçersiz kılmaz. Normal sürümde `components.lock` PR'ı gerekmez. Paket içeriği değişmedi (sürüm gerektirmez). Gerçek `index-publish.sh` ile DENENMEDİ (atrap betikle test edildi).

Expand Down
9 changes: 6 additions & 3 deletions component.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
"effects": [],
"requires_sudo": false,
"confirm": "none",
"warnings": ["Salt okunur: saat dilimi, LANG, chrony durumu, ofseti ve gerçek sapmayı (seçili kaynak yoksa erişilebilir kaynakların farkı) okur; hiçbir şeyi değiştirmez. ntp_senkron=yes için chrony çalışırken seçili kaynak ve sapma <= 1 sn gerekir. chrony kurulu değilse ntp_servis=inactive/unknown, ofset ve sapma unknown görünür."],
"outputs": { "format": "keyvalue-line", "prefix": "SSHPOCKET_RESULT utility.durum", "keys": ["timezone", "locale", "ntp_servis", "ntp_senkron", "offset_ms", "kaynak_sayisi", "sapma_ms", "secili_kaynak"] }
"warnings": ["Salt okunur: saat dilimi, LANG, chrony durumu, ofseti ve gerçek sapmayı (seçili kaynak yoksa erişilebilir kaynakların farkı) okur; hiçbir şeyi değiştirmez. ntp_senkron=yes için chrony çalışırken seçili kaynak ve sapma <= 1 sn, ayrıca sunucu saatinin kontrol makinesinden en çok 300 sn farklı olması gerekir (saat_sapma_kontrolcuye_gore_sn; chrony snapshot/rollback sonrası bayat ve yanıltıcı olabilir). chrony kurulu değilse ntp_servis=inactive/unknown, ofset ve sapma unknown görünür."],
"outputs": { "format": "keyvalue-line", "prefix": "SSHPOCKET_RESULT utility.durum", "keys": ["timezone", "locale", "ntp_servis", "ntp_senkron", "offset_ms", "kaynak_sayisi", "sapma_ms", "secili_kaynak", "saat_sapma_kontrolcuye_gore_sn"] }
},
"preview": {
"cmd": "ansible-playbook playbooks/preview.yml --check --diff",
Expand All @@ -28,7 +28,8 @@
"warnings": [
"Önizleme yalnızca dosya farkını ve plan adlarını gösterir: timedatectl, locale-gen, paket kurulumu ve chrony yeniden başlatması --check'te çalışmaz, gösterilmez.",
"Boş bırakılan utility_timezone / utility_locale / utility_ntp_servers o alana hiç dokunulmayacağı anlamına gelir.",
"chrony çalışıyorsa ve saat 1 sn'den fazla sapmışsa plana 'saat' girer: apply tek seferlik adımlar. chrony bu koşuda kurulacaksa sapma önizlemede ölçülemez."
"chrony çalışıyorsa ve saat 1 sn'den fazla sapmışsa plana 'saat' girer: apply tek seferlik adımlar. chrony bu koşuda kurulacaksa sapma önizlemede ölçülemez. Sunucu saati kontrol makinesine göre 300 sn'den fazla farklıysa (chrony göstermese de) plana yine 'saat' girer.",
"Kontrol makinesi saati referans alınır: o yanlışsa karşılaştırma da yanlış uyarır."
],
"outputs": { "format": "keyvalue-line", "prefix": "SSHPOCKET_RESULT utility.preview", "keys": ["degisen", "plan"] }
},
Expand All @@ -45,6 +46,7 @@
"auditd açıksa saat dilimi değişimi 'time-change' kaydı üretir (beklenen). ufw giden trafiği reddediyorsa (hardening_ufw_outgoing_deny) NTP için 123/udp çıkışı gerekir.",
"locale-gen ve chrony kurulumu gerekirse apt ile paket kurar (locales, chrony); geri_yukle paketleri kaldırmaz.",
"Saat 1 sn'den fazla sapmışsa (chrony çalışıyorken ölçülür) apply kaynaklar erişilebilir olunca TEK SEFERLİK `chronyc makestep` yapar (en çok 60 sn bekler; kalıcı makestep ayarı yazılmaz). Adımlama zaman sıçramasıdır: log damgaları, cron işleri, auditd 'time-change' kaydı, ssh/TOTP/sertifika geçerliliği etkilenebilir. Kapatmak için utility_ntp_makestep=false.",
"Sunucu saati kontrol makinesinden 300 sn'den fazla farklıysa chrony önce yeniden başlatılır, makestep denenir; fark sürerse ve utility_ntp_clock_from_controller=true ise 'date -s' ile kontrol makinesinin saatine ayarlanır (chrony taze kaynakla doğruluyorsa dokunulmaz).",
"Saat dilimi değişince systemd-timedated yeniden başlatılır (timedatectl önbelleği eski değeri tutmasın)."
],
"outputs": { "format": "keyvalue-line", "prefix": "SSHPOCKET_RESULT utility.apply", "keys": ["degisen", "plan", "yedek"] }
Expand All @@ -67,6 +69,7 @@
{ "name": "utility_timezone", "type": "string", "default": "", "group": "Zaman", "description": "Saat dilimi (örn. Europe/Istanbul). Boş = saat dilimine dokunma. /usr/share/zoneinfo altında var olmalı." },
{ "name": "utility_locale", "type": "string", "default": "", "group": "Dil", "description": "Sistem dili: yalnızca LANG (örn. en_US.UTF-8). Boş = dokunma. LC_* yönetilmez. Gerekirse locales kurulur ve locale üretilir." },
{ "name": "utility_ntp_servers", "type": "list[string]", "default": [], "group": "NTP", "description": "NTP kaynakları (en çok 8): 'host', 'server host' ya da 'pool host'; iburst otomatik eklenir. Boş = dağıtım varsayılanı (dosya yazılmaz, chrony kurulmaz). Dağıtımın varsayılan kaynakları kalır." },
{ "name": "utility_ntp_clock_from_controller", "type": "bool", "default": false, "group": "NTP", "description": "Sunucu saati kontrol makinesine göre 300 sn'den fazla farklıysa ve chrony saati bir kaynakla doğrulayamıyorsa apply saati KONTROL MAKİNESİNİN saatine 'date -s' ile ayarlar. Kontrol makinesinin saati yanlışsa sunucu da yanlış olur. false = yalnız chrony." },
{ "name": "utility_ntp_makestep", "type": "bool", "default": true, "group": "NTP", "description": "Saat 1 sn'den fazla sapmışsa apply chrony çalışırken TEK SEFERLİK 'chronyc makestep' yapar (kalıcı ayar yazılmaz). false = sapmaya dokunma." },
{ "name": "utility_backup", "type": "bool", "default": true, "group": "Yedek", "description": "Değiştirmeden önce /var/backups/utility/<tarih>/ altına yedek al. false = yedek alınmaz ve geri_yukle yeni değişikliği geri alamaz." },
{ "name": "utility_restore_from", "type": "string", "default": "", "group": "Yedek", "description": "geri_yukle için yedek adı (örn. 20261105T101500Z). Boş = en son yedek." }
Expand Down
9 changes: 7 additions & 2 deletions playbooks/durum.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Salt okunur durum: saat dilimi, LANG, NTP servisi/senkron/ofset/kaynak sayısı. Hiçbir şey değiştirmez, sudo gerektirmez.
# Sonuç satırı: SSHPOCKET_RESULT utility.durum timezone=… locale=… ntp_servis=… ntp_senkron=yes|no offset_ms=… kaynak_sayisi=… sapma_ms=… secili_kaynak=yes|no
# Sonuç satırı: SSHPOCKET_RESULT utility.durum timezone=… locale=… ntp_servis=… ntp_senkron=yes|no offset_ms=… kaynak_sayisi=… sapma_ms=… secili_kaynak=yes|no saat_sapma_kontrolcuye_gore_sn=<N|unknown>
- name: utility durum (salt okunur)
hosts: utility
gather_facts: false
Expand Down Expand Up @@ -56,13 +56,17 @@
- name: Read clock drift
ansible.builtin.include_role: {name: ntp, tasks_from: drift}

# chrony'den bağımsız ikinci ölçüm: hedef saati - kontrol makinesi saati
- name: Compare with the controller clock
ansible.builtin.include_role: {name: ntp, tasks_from: skew}

# chronyc -c tracking alanları: 1 ref-id, 2 ad, 3 katman, 4 ref zamanı, 5 sistem saati farkı (saniye, işaretli) ...
- name: Result line
vars:
utility_d_clock: "{{ utility_clock }}"
# chrony çalışıyorsa 'senkron' = timedatectl yes + seçili kaynak + sapma <= 1 sn; çalışmıyorsa (timesyncd) timedatectl'e bakılır
utility_d_synced: >-
{{ (utility_d_sync.stdout | default('') | trim == 'yes') and
{{ (utility_d_sync.stdout | default('') | trim == 'yes') and not (utility_ctrl_skew_big | bool) and
(not (utility_d_clock.up | default(false)) or
(utility_d_clock.selected | default(false) and utility_d_clock.drift_s | default(none) is not none and utility_d_clock.drift_s | float <= 1.0)) }}
utility_d_offset: >-
Expand All @@ -78,3 +82,4 @@
kaynak_sayisi={{ (utility_d_sources.stdout_lines | default([]) | length) if utility_d_sources.rc == 0 else 0 }}
sapma_ms={{ ((utility_d_clock.drift_s | float * 1000) | round(1)) if utility_d_clock.drift_s | default(none) is not none else 'unknown' }}
secili_kaynak={{ 'yes' if utility_d_clock.selected | default(false) else 'no' }}
saat_sapma_kontrolcuye_gore_sn={{ utility_ctrl_skew_s if utility_ctrl_skew_s | string != '' else 'unknown' }}
1 change: 1 addition & 0 deletions roles/common/tasks/preflight.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
- (utility_ntp_servers | default([])) | length <= 8
- utility_backup | bool in [true, false]
- utility_ntp_makestep | default(true) | bool in [true, false]
- utility_ntp_clock_from_controller | default(false) | bool in [true, false]
- (utility_timezone | default('')) == '' or (utility_timezone | default('')) is match('^[A-Za-z0-9_+-]+(/[A-Za-z0-9_+-]+){0,2}$')
- (utility_locale | default('')) == '' or (utility_locale | default('')) is match('^(C|POSIX|C\.UTF-8|[a-z]{2,3}_[A-Z]{2}\.(UTF-8|ISO-8859-[0-9]{1,2}))$')
- >-
Expand Down
14 changes: 13 additions & 1 deletion roles/common/tasks/warnings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,19 @@
UYARI (utility): saat {{ utility_clock.drift_s }} sn sapmalı (ölçüm: {{ utility_clock.source }}); apply chrony ile TEK SEFERLİK adımlayacak (`chronyc makestep`).
Adımlama zaman sıçraması demektir: log zaman damgaları, cron işleri, auditd 'time-change' kaydı, ssh/TOTP/sertifika geçerliliği etkilenebilir.
Sapma kalıcı bir sorunsa (kaynak yok, snapshot'tan açılış) önce kaynakları kontrol edin. Kalıcı 'makestep' ayarı YAZILMAZ.
when: "'saat' in utility_plan and utility_clock is defined"
when: >-
'saat' in utility_plan and utility_clock is defined and utility_ntp_makestep | default(true) | bool and
utility_clock.drift_s | default(none) is not none and utility_clock.drift_s | float > utility_ntp_step_threshold_s | default(1.0) | float

- name: Warn about the controller clock difference
ansible.builtin.debug:
msg: >-
UYARI (utility): sunucu saati kontrol makinesine göre {{ utility_ctrl_skew_s }} sn farklı (negatif = sunucu geride); chrony'nin kendi ölçümü
bunu göstermese de (snapshot/rollback sonrası bayat durum). apply önce chrony'yi yeniden başlatıp `makestep` dener;
{{ 'utility_ntp_clock_from_controller=true: chrony doğrulayamazsa saat kontrol makinesinin saatine ayarlanacak (`date -s`; kontrol makinesinin saati yanlışsa sunucu da yanlış olur).'
if utility_ntp_clock_from_controller | default(false) | bool else 'kontrol makinesi saatine ayarlama kapalı (utility_ntp_clock_from_controller=false).' }}
Adımlama zaman sıçramasıdır: log zaman damgaları, cron, auditd 'time-change', ssh/TOTP/sertifika geçerliliği etkilenir.
when: utility_ctrl_skew_big | default(false) | bool

- name: Note chrony installation and clock drift
ansible.builtin.debug:
Expand Down
4 changes: 4 additions & 0 deletions roles/ntp/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
utility_ntp_servers: []
# saat sapması: eşikten büyükse apply TEK SEFERLİK `chronyc makestep` yapar (kalıcı makestep ayarı yazılmaz). false = sapmaya dokunma
utility_ntp_makestep: true
# chrony saati düzeltemezse (ya da doğrulayamazsa) apply saati KONTROL MAKİNESİNİN saatine `date -s` ile ayarlar. Kontrol makinesinin saati yanlışsa sunucu yanlışlanır; varsayılan false
utility_ntp_clock_from_controller: false
# iç sabitler (manifest değişkeni değil)
utility_ntp_step_threshold_s: 1.0
utility_ntp_step_timeout_s: 60
# hedef-kontrolcü saat farkı bu değeri (sn) aşarsa chrony ne derse desin sapma sayılır
utility_ntp_ctrl_threshold_s: 300
10 changes: 7 additions & 3 deletions roles/ntp/tasks/plan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,20 @@
utility_backup_paths: "{{ utility_backup_paths + (['/etc/chrony/sources.d/utility.sources'] if utility_ntp_need_file | bool else []) }}"
when: utility_ntp_need_pkg | bool or utility_ntp_need_file | bool or utility_ntp_need_service | bool

# SAAT SAPMASI (utility_ntp_servers'tan bağımsız): chrony çalışıyorsa ve sapma eşikten büyükse plana 'saat' girer; apply tek seferlik adımlar.
# SAAT SAPMASI (utility_ntp_servers'tan bağımsız): iki bağımsız ölçüm — chrony sapması ve hedef/kontrol makinesi saat farkı (skew.yml).
# Biri eşiği aşarsa plana 'saat' girer; apply düzeltir (chrony makestep ve/veya açık seçenekle kontrolcü saati).
- name: Plan clock step
when: utility_ntp_makestep | bool
block:
- name: Read the drift
ansible.builtin.include_tasks: drift.yml

- name: Compare with the controller clock
ansible.builtin.include_tasks: skew.yml

- name: Record the clock step plan
ansible.builtin.set_fact:
utility_plan: "{{ utility_plan + ['saat'] }}"
utility_ntp_need_step: true
when: >-
utility_clock.drift_s | default(none) is not none and utility_clock.drift_s | float > utility_ntp_step_threshold_s | float
(utility_ntp_makestep | bool and utility_clock.drift_s | default(none) is not none and utility_clock.drift_s | float > utility_ntp_step_threshold_s | float)
or (utility_ctrl_skew_big | bool and (utility_ntp_makestep | bool or utility_ntp_clock_from_controller | bool))
18 changes: 18 additions & 0 deletions roles/ntp/tasks/skew.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Hedef saatini KONTROL MAKİNESİNİN (Ansible controller) saatiyle karşılaştırır; chrony'den BAĞIMSIZ ikinci ölçüm (salt okunur; --check'te de çalışır).
# utility_ctrl_skew_s = hedef epoch - kontrolcü epoch (saniye; negatif = hedef geride), ölçülemezse ''. SSH gecikmesi (saniyeler) eşiğin (300 sn) yanında önemsiz.
# Neden: chrony'nin kendi sayıları (tracking/sources) VM snapshot/rollback sonrası bayat ama içten tutarlı olabilir ve sapmayı göstermeyebilir.
- name: Read the target clock
ansible.builtin.command: date +%s
register: utility_target_epoch
changed_when: false
failed_when: false
check_mode: false

- name: Compare with the controller clock
ansible.builtin.set_fact:
utility_ctrl_skew_s: >-
{{ (utility_target_epoch.stdout | trim | int - lookup('ansible.builtin.pipe', 'date +%s') | int)
if utility_target_epoch.rc == 0 and (utility_target_epoch.stdout | trim) is match('^[0-9]+$') else '' }}
utility_ctrl_skew_big: >-
{{ utility_target_epoch.rc == 0 and (utility_target_epoch.stdout | trim) is match('^[0-9]+$') and
((utility_target_epoch.stdout | trim | int - lookup('ansible.builtin.pipe', 'date +%s') | int) | abs) > (utility_ntp_ctrl_threshold_s | default(300) | int) }}
Loading