Arşivleme İşlemlerinde SELinux ve AppArmor Etiketlerini Koruma: Güvenlik Bağlamlarıyla Birlikte Yedekleme

Üretim ortamında bir gün, SELinux aktifken alınan bir yedekten geri dönüş yaptınız ve her şey yerli yerinde görünüyor ama Apache çalışmıyor. Loglar izin hatasıyla dolu. Dosyalar var, içerikler tam, ama güvenlik bağlamları kaybolmuş. İşte bu yazı tam olarak o anı yaşamamanız için.

SELinux ve AppArmor, Linux güvenlik modelinin en kritik katmanlarından ikisi. Ama arşivleme ve yedekleme süreçlerinde bu güvenlik etiketlerinin nasıl davrandığını bilmeden yapılan işlemler, tam anlamıyla zaman bombası yerleştiriyor sisteminize. Dosyaları yedeklediniz, geri yüklediniz, her şey “tamam” görünüyor. Ta ki bir servis çöküp incelemeye başlayana kadar.

Güvenlik Bağlamları Neden Kaybolur?

Standart tar, cp veya rsync komutlarıyla yapılan kopyalama ve arşivleme işlemleri, varsayılan davranışlarıyla dosyaların SELinux güvenlik bağlamlarını (security context) korumaz. Bağlam bilgisi, dosya sisteminin genişletilmiş öznitelikleri (xattr) içinde saklanır. Özellikle security.selinux adlı xattr alanı, o dosyanın kim tarafından, hangi servis tarafından erişilebileceğini belirler.

Örneğin /var/www/html/ altındaki bir dosya httpd_sys_content_t etiketiyle işaretlenmiştir. Bu etiketi olmadan Apache, SELinux politikası gereği o dosyayı okuyamaz. Geri yükleme sonrasında dosya fiziksel olarak orada durur ama SELinux açısından yabancıdır.

AppArmor tarafında ise durum biraz farklıdır. AppArmor profil tabanlı çalışır ve xattr kullanımı daha sınırlıdır, ancak bazı senaryolarda security.apparmor etiketleri de taşınması gereken metadata içerir.

Önce mevcut durumu görmek için basit bir kontrol yapalım:

# Bir dosyanın SELinux bağlamını görüntüle
ls -Z /var/www/html/index.html

# Çıktı şuna benzer:
# -rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/html/index.html

# Genişletilmiş özniteliklerin tamamını görüntüle
getfattr -n security.selinux /var/www/html/index.html

tar ile Güvenlik Bağlamlarını Koruma

tar komutu, --selinux ve --xattrs bayraklarıyla birlikte kullanıldığında güvenlik bağlamlarını arşive dahil eder. GNU tar 1.27 ve sonrasında bu özellik stabil hale gelmiştir. Çoğu modern RHEL, CentOS, Rocky Linux ve AlmaLinux kurulumunda bu sürüm bulunur.

# SELinux bağlamlarıyla birlikte arşiv oluşturma
tar --selinux --xattrs --acls -czpf /backup/webapp_backup.tar.gz /var/www/html/

# Parametreler:
# --selinux: SELinux güvenlik bağlamlarını dahil et
# --xattrs: Tüm genişletilmiş öznitelikleri koru
# --acls: POSIX ACL bilgilerini de sakla
# -c: Yeni arşiv oluştur
# -z: gzip sıkıştırma uygula
# -p: İzinleri koru
# -f: Dosya adını belirt

Geri yükleme sırasında da aynı bayrakların kullanılması gerekir, yoksa arşivde saklanan bağlam bilgisi kullanılmaz:

# SELinux bağlamlarıyla birlikte geri yükleme
tar --selinux --xattrs --acls -xzpf /backup/webapp_backup.tar.gz -C /

# Geri yüklemenin doğruluğunu kontrol et
ls -Z /var/www/html/index.html
getfattr -d /var/www/html/index.html

Burada dikkat edilmesi gereken bir nokta var: Eğer hedef dosya sistemi xattr desteklemiyorsa (örneğin bazı eski NFS bağlantıları veya FAT32 tabanlı medyalar), bu öznitelikler sessizce düşer. Yedekleme ortamınızın xattr desteklediğinden her zaman emin olun.

rsync ile Genişletilmiş Öznitelikleri Taşıma

rsync için durum biraz daha nüanslı. rsync 3.0.6 ve sonrasında -X (xattrs) ve -A (ACLs) bayrakları mevcuttur. Ancak varsayılan olarak security.* namespace’i dahil edilmez, çünkü bu özniteliklerin taşınması root yetkisi gerektirir ve güvenlik açısından hassastır.

# SELinux xattr'larıyla rsync yedekleme
rsync -aAXHv --numeric-ids /var/www/html/ /backup/html_mirror/

# Parametreler:
# -a: Arşiv modu (sembolik linkler, izinler, zaman damgaları dahil)
# -A: ACL bilgilerini koru
# -X: Genişletilmiş öznitelikleri koru (security.selinux dahil)
# -H: Hard linkleri koru
# -v: Verbose çıktı
# --numeric-ids: Kullanıcı/grup ID'lerini isim yerine sayı olarak kullan

Uzak sunucuya rsync yaparken xattr desteğinin her iki tarafta da aktif olduğunu doğrulamak önemlidir:

# Uzak sunucuya SELinux bağlamlarıyla rsync
rsync -aAXHv --numeric-ids 
  -e "ssh -i /root/.ssh/backup_key" 
  /var/www/html/ 
  [email protected]:/backup/html/

# Rsync'in xattr desteğini kontrol et
rsync --version | grep "xattrs"

star: tar’ın Daha Az Bilinen Alternatifi

Sistem yöneticilerinin büyük çoğunluğunun adını bile duymadığı star komutu (Schily TAR), SELinux desteği açısından GNU tar’dan bile daha güvenilir sonuçlar verebilir. Özellikle RHEL ekosisteminde bazı kritik yedekleme senaryolarında tercih edilir.

# star kurulumu (RHEL/Rocky/AlmaLinux)
dnf install star -y

# star ile SELinux bağlamlarını koruyarak arşivleme
star -c -z -p -xattr -selinux -acl 
  -f /backup/webapp_star.tar.gz 
  /var/www/html/

# star ile geri yükleme
star -x -z -p -xattr -selinux -acl 
  -f /backup/webapp_star.tar.gz 
  -C /

star komutunun avantajı, SELinux desteğinin daha erken sürümlerde entegre edilmiş olması ve bazı edge case’lerde GNU tar’ın kaçırdığı bağlamları başarıyla taşıyabilmesidir.

Geri Yükleme Sonrası Doğrulama ve Onarım

İyi bir yedekleme prosedürünün en önemli parçası doğrulama adımıdır. Geri yükleme yaptıktan sonra güvenlik bağlamlarının sağlıklı olup olmadığını otomatik olarak kontrol eden bir script hazırlayalım:

#!/bin/bash
# selinux_verify.sh - Geri yükleme sonrası SELinux bağlam doğrulama

TARGET_DIR="${1:-/var/www/html}"
LOG_FILE="/var/log/selinux_restore_verify.log"
ISSUES_FOUND=0

echo "=== SELinux Bağlam Doğrulama: $(date) ===" | tee -a "$LOG_FILE"
echo "Dizin: $TARGET_DIR" | tee -a "$LOG_FILE"

# matchpathcon ile beklenen bağlamı karşılaştır
while IFS= read -r -d '' file; do
    expected=$(matchpathcon -n "$file" 2>/dev/null)
    current=$(stat -c "%C" "$file" 2>/dev/null)
    
    if [ "$expected" != "$current" ]; then
        echo "[UYARI] Bağlam uyuşmazlığı: $file" | tee -a "$LOG_FILE"
        echo "  Beklenen: $expected" | tee -a "$LOG_FILE"
        echo "  Mevcut  : $current" | tee -a "$LOG_FILE"
        ISSUES_FOUND=$((ISSUES_FOUND + 1))
    fi
done < <(find "$TARGET_DIR" -print0)

if [ "$ISSUES_FOUND" -gt 0 ]; then
    echo "[SONUC] $ISSUES_FOUND adet bağlam uyuşmazlığı bulundu." | tee -a "$LOG_FILE"
    echo "Otomatik düzeltme için: restorecon -Rv $TARGET_DIR"
else
    echo "[SONUC] Tüm bağlamlar doğru." | tee -a "$LOG_FILE"
fi

Eğer bağlamlar bozulmuşsa ve politika dosyaları sistemde sağlıklı durumda ise restorecon komutu kurtarıcınız olur:

# Dizin ve alt dizinlerdeki bağlamları politikaya göre sıfırla
restorecon -Rv /var/www/html/

# Parametreler:
# -R: Özyinelemeli uygula
# -v: Her değişikliği ekrana yaz

# Sadece değişenleri görmek için önce simüle et
restorecon -Rvn /var/www/html/
# -n: Gerçek değişiklik yapma, sadece ne yapılacağını göster

Önemli uyarı: restorecon komutu, sisteminizde kurulu SELinux politikasına göre bağlamları yeniden atar. Eğer özel bağlamlar tanımladıysanız ve bu tanımları politikaya yansıtmadıysanız, restorecon bu özel bağlamların üzerine yazar. Bu yüzden özel bağlamları her zaman semanage fcontext ile kalıcı hale getirin.

AppArmor Senaryoları: Ubuntu ve Debian Tarafı

AppArmor kullanan sistemlerde (Ubuntu, Debian ve türevleri) tablo biraz farklıdır. AppArmor’ın profilleri /etc/apparmor.d/ altında saklanır ve asıl önemli olan dosya sistemi etiketleri değil, bu profil dosyalarının kendisidir. Yedekleme stratejinizde bu dizin mutlaka yer almalıdır.

Ancak bazı AppArmor konfigürasyonları security.apparmor xattr etiketini de kullanır. Özellikle hat state bazlı profillerde dosya seviyesinde etiketleme yapılabilir. Bu durumda yine tar --xattrs yaklaşımı gereklidir.

# AppArmor profilleri ve yedekleme
# Profil dizinini xattr'larla birlikte yedekle
tar --xattrs --acls -czpf /backup/apparmor_profiles.tar.gz 
    /etc/apparmor.d/ 
    /etc/apparmor/ 
    /var/lib/apparmor/

# Profilleri geri yükledikten sonra yeniden yükle
apparmor_parser -r /etc/apparmor.d/*

# Aktif profillerin durumunu kontrol et
aa-status

# Belirli bir profilin xattr durumunu kontrol et
getfattr -d /path/to/protected/file

Karmaşık bir Ubuntu sunucusunda veritabanı yedeklemesi yaparken AppArmor profillerini de sisteme dahil etmek kritiktir:

# MySQL/MariaDB verisi + AppArmor profili birlikte yedekleme
tar --xattrs --acls -czpf /backup/mysql_full_backup.tar.gz 
    /var/lib/mysql/ 
    /etc/mysql/ 
    /etc/apparmor.d/usr.sbin.mysqld

# Geri yükleme sonrası AppArmor profilini aktifleştir
tar --xattrs --acls -xzpf /backup/mysql_full_backup.tar.gz -C /
apparmor_parser -r /etc/apparmor.d/usr.sbin.mysqld
systemctl restart mysql

Üretim Senaryosu: Komple Sunucu Yedekleme Script’i

Şimdiye kadar anlattıklarımızı bir araya getiren, gerçek hayatta kullanılabilir kapsamlı bir yedekleme scripti hazırlayalım. Bu script hem SELinux hem de AppArmor ortamlarını algılar ve buna göre davranır:

#!/bin/bash
# secure_backup.sh - Güvenlik bağlamlarını koruyan yedekleme scripti

BACKUP_BASE="/backup/secure"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="${BACKUP_BASE}/${DATE}"
LOG_FILE="/var/log/secure_backup.log"

# Renk kodları
RED='33[0;31m'
GREEN='33[0;32m'
YELLOW='33[1;33m'
NC='33[0m'

log() {
    echo -e "${GREEN}[$(date '+%H:%M:%S')]${NC} $1" | tee -a "$LOG_FILE"
}

warn() {
    echo -e "${YELLOW}[UYARI]${NC} $1" | tee -a "$LOG_FILE"
}

error() {
    echo -e "${RED}[HATA]${NC} $1" | tee -a "$LOG_FILE"
    exit 1
}

# Root kontrolü
[ "$EUID" -ne 0 ] && error "Bu script root olarak çalıştırılmalıdır."

mkdir -p "$BACKUP_DIR"

# SELinux mi AppArmor mi kontrol et
detect_security_framework() {
    if command -v getenforce &>/dev/null && [ "$(getenforce)" != "Disabled" ]; then
        echo "selinux"
    elif command -v aa-status &>/dev/null && aa-status --enabled 2>/dev/null; then
        echo "apparmor"
    else
        echo "none"
    fi
}

SECURITY_FW=$(detect_security_framework)
log "Güvenlik çerçevesi algılandı: $SECURITY_FW"

# TAR parametrelerini belirle
build_tar_opts() {
    local opts="-czpf"
    opts+=" --xattrs --acls"
    
    if [ "$SECURITY_FW" = "selinux" ]; then
        opts+=" --selinux"
        log "SELinux bağlam desteği aktif"
    fi
    
    echo "$opts"
}

TAR_OPTS=$(build_tar_opts)

# Web dizinini yedekle
log "Web dizini yedekleniyor..."
tar $TAR_OPTS "${BACKUP_DIR}/webroot.tar.gz" /var/www/ 2>>"$LOG_FILE" 
    && log "Web dizini yedeklendi." 
    || warn "Web dizini yedeklemede sorun oluştu."

# Sistem konfigürasyonlarını yedekle
log "Sistem konfigürasyonları yedekleniyor..."
tar $TAR_OPTS "${BACKUP_DIR}/etc_backup.tar.gz" 
    /etc/selinux/ 
    /etc/apparmor.d/ 
    /etc/apparmor/ 
    /etc/ssh/ 
    /etc/nginx/ 
    /etc/apache2/ 
    /etc/mysql/ 
    2>>"$LOG_FILE" | grep -v "No such file" 
    && log "Konfigürasyonlar yedeklendi."

# SELinux politika ve etiket veritabanı
if [ "$SECURITY_FW" = "selinux" ]; then
    log "SELinux politika veritabanı yedekleniyor..."
    tar $TAR_OPTS "${BACKUP_DIR}/selinux_policy.tar.gz" 
        /etc/selinux/ 
        /var/lib/selinux/ 
        2>>"$LOG_FILE" 
        && log "SELinux politika yedeklendi."
    
    # Özel fcontext tanımlarını dışa aktar
    semanage fcontext -l > "${BACKUP_DIR}/semanage_fcontext.txt" 2>>"$LOG_FILE"
    semanage boolean -l > "${BACKUP_DIR}/semanage_boolean.txt" 2>>"$LOG_FILE"
    semanage port -l > "${BACKUP_DIR}/semanage_port.txt" 2>>"$LOG_FILE"
    log "SELinux özel tanımlar dışa aktarıldı."
fi

# Yedek manifest oluştur
find "$BACKUP_DIR" -type f | sort > "${BACKUP_DIR}/MANIFEST.txt"
sha256sum "${BACKUP_DIR}"/*.tar.gz > "${BACKUP_DIR}/CHECKSUMS.sha256"

log "Yedekleme tamamlandı: $BACKUP_DIR"
log "Toplam boyut: $(du -sh "$BACKUP_DIR" | cut -f1)"

SELinux Booleans ve Özel Politikaların Korunması

Çoğu zaman gözden kaçan kritik bir alan daha var: SELinux boolean değerleri ve semanage ile tanımlanmış özel kurallar. Bu bilgiler dosya sistemi xattr’larında değil, SELinux politika veritabanında saklanır. Bunları da yedeklemeniz gerekir.

# Mevcut tüm SELinux özelleştirmelerini dışa aktar
semanage export -f /backup/selinux_custom_policy.conf

# İçeriğini kontrol et
cat /backup/selinux_custom_policy.conf

# Yeni sistemde içe aktar
semanage import -f /backup/selinux_custom_policy.conf

# Kritik boolean değerlerini elle kaydet
getsebool -a | grep -E "(httpd|mysql|ftp|ssh)" > /backup/selinux_booleans_filtered.txt

# Tüm boolean değerlerini kaydet
getsebool -a > /backup/selinux_booleans_all.txt

Konteyner Ortamlarında Özel Durumlar

Podman veya Docker kullanan sistemlerde SELinux bağlamları daha da kritik hale gelir. Konteyner volume’larının host üzerindeki dizinleri, container_file_t veya özel etiketlerle işaretlenmelidir. Bu dizinleri yedeklerken bağlamların korunması, konteynerlerin yeniden başlatıldığında erişim sorunlarını önler.

# Podman volume dizinini SELinux bağlamlarıyla yedekle
VOLUME_PATH="/var/lib/containers/storage/volumes/myapp_data"

tar --selinux --xattrs --acls -czpf 
    /backup/container_volumes/myapp_data.tar.gz 
    "$VOLUME_PATH"

# Geri yükleme sonrası bağlamı doğrula
ls -Z "$VOLUME_PATH/_data/"

# Konteyner erişimi için doğru etiket
# svirt_sandbox_file_t veya container_file_t olmalı
chcon -Rt container_file_t "$VOLUME_PATH/_data/"

Sonuç

Güvenlik bağlamlarını göz ardı ederek yapılan yedeklemeler, sorun çıkmadığı sürece fark edilmez. Ta ki kritik bir an gelip geri yükleme yapılana kadar. O anda bir web servisi ayağa kalkmıyor, veritabanı kendi dosyalarına erişemiyor, SSH authorized_keys çalışmıyor. Hepsi SELinux veya AppArmor’ın “bu dosya benim bildiğim bağlamda değil, güvenmiyorum” demesinden kaynaklanıyor.

Pratik olarak yapılması gerekenler net:

  • tar kullanıyorsanız --selinux --xattrs --acls bayraklarını asla atlamayın
  • rsync kullanıyorsanız -AX bayraklarını ekleyin ve root olarak çalıştırın
  • Geri yükleme sonrası mutlaka bağlam doğrulaması yapın, gerekirse restorecon çalıştırın
  • semanage özelleştirmelerini semanage export ile ayrıca yedekleyin
  • AppArmor profil dizinini sistem yedeğine her zaman dahil edin

Yedeklemenin değeri, geri yüklemeyle ölçülür. Dosyalar orada duruyor ama sistem çalışmıyor olması, en kötü yedek senaryosudur. Güvenlik bağlamlarıyla birlikte alınan yedekler bu senaryoyu ortadan kaldırır.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir