0Pricing
DevOps Bootcamp · Ders

En Az Ayrıcalıklı Çalıştırma ve sudo Disiplini

Ayrıcalıkları düşürün, sudo kurallarının kapsamını sıkı tutun ve riskli işlemlerden önce etkin UID değerini doğrulayın.

En Az Ayrıcalıklı Çalıştırma ve sudo Disiplini, CoddyKit'te ücretsiz bir DevOps Bootcamp dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, DevOps Bootcamp öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. DevOps Bootcamp kursu toplamda 4 dersten oluşur.

Kabuk Betiklerinde En Az Ayrıcalık Neden Önemlidir

Otomasyondaki güvenlik ihlallerinin çoğu karmaşık açıklardan değil, betiklerin gerektiğinden daha fazla ayrıcalıkla çalışmasından kaynaklanır. Yalnızca bir günlük dosyasını döndürmesi gereken root olarak çalışan bir cron işi, gerçekleşmesi beklenen bir kazadır.

En az ayrıcalık ilkesi şunu belirtir: her işlem, işini yapmak için gereken izinleri ve yalnızca bunları kullanarak çalışmalıdır. Bash betiklerinde bu şu anlama gelir:

  • Mümkün olduğunda ayrıcalıksız bir kullanıcı olarak çalıştırmak
  • root yetkisine yalnızca bunu gerektiren belirli komutlar için yükselmek
  • Yükseltilmiş işlem tamamlanır tamamlanmaz ayrıcalıkları bırakmak
  • Kimlik bilgilerini kapsamlarının ötesinde asla saklamamak veya devralmamak

Bu derste somut teknikler ele alınır: sudo kapsamlandırması, su ile ayrıcalık bırakma, UID doğrulama korumaları ve sudoers güçlendirmesi; böylece üretim betikleri için disiplinli bir ayrıcalık modeli oluşturulur.

Riskli İşlemlerden Önce Etkin UID'yi Denetleme

Gerçekten root gerektiren herhangi bir kod bloğundan önce betiğiniz, beklenen etkin UID ile çalıştığını doğrulamalıdır. Varsaymayın; her zaman doğrulayın.

$EUID, geçerli işlemin etkin kullanıcı kimliğini tutan özel bir Bash değişkenidir. Root'un EUID değeri her zaman 0'dır. Betiğin başında veya ayrıcalıklı bir bloğun çevresinde bunu denetlemek, yanlış kimlikle yanlışlıkla çalıştırılmayı önler.

Şu koruma kalıbını kullanın:

#!/usr/bin/env bash
set -euo pipefail

# Guard: this script must NOT run as root.
if [[ "$EUID" -eq 0 ]]; then
  echo "ERROR: Do not run this script as root. Use a normal user account." >&2
  exit 1
fi

echo "Running as UID $EUID — proceeding safely."

Yalnızca Gerektiğinde Root Olduğunu Doğrulama

Bazı betiklerin gerçekten root yetkisine ihtiyacı vardır. Bu durumda koruma tersine çevrilir: betiğin ayrıcalıklı bir sistem çağrısına ulaşıp çalışma sırasında kafa karıştırıcı bir izin hatası üretmesini beklemek yerine, root yoksa erkenden başarısız olun.

Erken çıkışı yararlı bir kullanım mesajıyla birleştirmek, betiklerin kendi belgelerini içermesini sağlar:

#!/usr/bin/env bash
set -euo pipefail

require_root() {
  if [[ "$EUID" -ne 0 ]]; then
    echo "ERROR: $(basename "$0") must be run as root." >&2
    echo "  Try: sudo $(basename "$0") $*" >&2
    exit 1
  fi
}

require_root "$@"

echo "Root confirmed (EUID=0). Starting privileged work..."

sudo'yu Tek Komutla Sınırlandırma

En yaygın hata, bir betiğin en üstüne sudo koyup ardından her şeyi root olarak çalıştırmaktır. Bunun yerine sudo'yu yalnızca ona ihtiyaç duyan tam komuta uygulayın; diğer her şey normal kullanıcınız olarak çalışır.

Bu, saldırının etkisini sınırlar: Bir saldırgan betiğinize kod enjekte ederse root izinleriyle yalnızca önünde sudo bulunan bölümleri çalıştırabilir.

Aşağıdaki iki kalıbı karşılaştırın. İkincisi çok daha güvenlidir:

#!/usr/bin/env bash
set -euo pipefail

# BAD: escalate early, do everything as root (avoid this)
# sudo bash -c '
#   cp config.conf /etc/app/config.conf
#   chown app:app /etc/app/config.conf
#   systemctl restart app
# '

# GOOD: escalate only for the commands that require it
LOCAL_CONF="./config.conf"
DEST="/etc/app/config.conf"

# Unprivileged: validate the config before touching anything as root
if ! grep -q '^[[:space:]]*\[main\]' "$LOCAL_CONF"; then
  echo "ERROR: config.conf is missing [main] section" >&2
  exit 1
fi

# Privileged: only these three commands run under sudo
sudo cp "$LOCAL_CONF" "$DEST"
sudo chown app:app "$DEST"
sudo systemctl restart app

echo "Config deployed and service restarted."

Sıkı sudoers Kuralları Yazma

Bir betikte sudo somecommand çağrısı, yalnızca sudoers dosyası tam olarak o komuta ve başka hiçbir şeye izin verecek şekilde yapılandırılmışsa güvenli çalışır. Hizmet hesapları için ALL=(ALL) NOPASSWD: ALL gibi kurallardan kaçının.

Bunun yerine, visudo için güvenli sözdizimini kullanarak kuralları belirli bağımsız değişkenlere sahip belirli komutlarla sınırlandırın. Bir sudoers kuralındaki temel alanlar:

  • Kullanıcı — sudo'yu kimin çağırabileceği
  • Makine — hangi makinede (taşınabilirlik için ALL kullanın)
  • RunAs — hangi kimliğin üstlenileceği (neredeyse her zaman root)
  • Komut — isteğe bağlı olarak gerçek bağımsız değişkenlerle birlikte tam mutlak yol

Bir dağıtım hizmet hesabı (deployer) için sıkı kural örnekleri:

# /etc/sudoers.d/deployer  (edit with: sudo visudo -f /etc/sudoers.d/deployer)
#
# Allow 'deployer' to restart exactly one service — nothing else
deployer ALL=(root) NOPASSWD: /usr/bin/systemctl restart app

# Allow copying a config file to a fixed destination only
deployer ALL=(root) NOPASSWD: /usr/bin/cp /home/deployer/staging/config.conf /etc/app/config.conf

# Allow chown of that specific file only
deployer ALL=(root) NOPASSWD: /usr/bin/chown app\:app /etc/app/config.conf

# NEVER do this — gives full root shell:
# deployer ALL=(ALL) NOPASSWD: ALL

su ve runuser ile Ayrıcalıkları Bırakma

Bir betik root olarak başladığında (örneğin root olarak çalışan bir sistem başlatıcısı veya cron tarafından başlatıldığında), ancak işlerin çoğunun ayrıcalıksız bir kullanıcı olarak yapılması gerektiğinde, tüm betiği root olarak çalıştırmak yerine ayrıcalıkları açıkça bırakın.

Bunun için iki araç vardır:

  • su -s /bin/bash -c 'command' username — username olarak bir kabuk başlatır ve komutu çalıştırır
  • runuser -u username -- command args — root sahipli betiklerde geçiş yapmak için Linux'ta tercih edilir; su'dan daha temizdir

Aşağıdaki kalıp, gerçek uygulama mantığı için app kullanıcısına geçen root sahipli bir dağıtım sarmalayıcısını gösterir:

#!/usr/bin/env bash
# This script is called by systemd as root during pre-deployment
set -euo pipefail

APP_USER="app"
DEPLOY_DIR="/opt/myapp"

# Step 1: privileged — fix ownership of deploy directory
chown -R "${APP_USER}:${APP_USER}" "$DEPLOY_DIR"

# Step 2: drop to app user for the actual migration/startup logic
# runuser is available on most modern Linux systems
runuser -u "$APP_USER" -- bash -c "
  cd $DEPLOY_DIR
  ./bin/migrate.sh
  ./bin/start.sh
"

echo "Deploy complete. Privileged wrapper exiting."

Tek Bir Komutu Başka Bir Kullanıcı Olarak Çalıştırmak için sudo -u Kullanma

Her zaman tam bir kabuk oturumuna geçmeniz gerekmez. sudo -u username command, tek bir komutu belirtilen kullanıcı olarak çalıştırır ve ardından çağıran kimliğe döner. Bu, bir hizmet hesabına etkileşimli erişim izni vermeden o hesaba ait dosyalara dokunmak için kullanışlıdır.

Bunu, tam olarak o kullanıcı ve komut birleşimine izin veren bir sudoers kuralıyla birlikte kullanın:

#!/usr/bin/env bash
set -euo pipefail

# Scenario: deploy script runs as 'deployer'; DB migrations must run as 'postgres'
# sudoers entry needed:
#   deployer ALL=(postgres) NOPASSWD: /opt/app/bin/run_migrations.sh

DB_MIGRATION_SCRIPT="/opt/app/bin/run_migrations.sh"

if [[ ! -x "$DB_MIGRATION_SCRIPT" ]]; then
  echo "ERROR: migration script not found or not executable: $DB_MIGRATION_SCRIPT" >&2
  exit 1
fi

echo "Running DB migrations as postgres user..."
sudo -u postgres "$DB_MIGRATION_SCRIPT"

echo "Migrations done. Returning to deployer context (EUID=$EUID)."

Ortam Değişkenleri Yoluyla Ayrıcalık Yükseltmeyi Önleme

İnce bir saldırı yüzeyi: sudo oturumu tarafından devralınan ortam değişkenleri. Varsayılan olarak sudo ortamı sıfırlar; ancak yanlış yapılandırılmış env_keep veya env_reset geçersiz kılmaları, saldırganın denetimindeki LD_PRELOAD, PATH veya PYTHONPATH gibi değişkenleri ayrıcalıklı komutlara aktarabilir.

En iyi uygulamalar:

  • sudo altında çalışan betiklerde her zaman mutlak yollar kullanın — $PATH'e asla güvenmeyin
  • Yalnızca açıkça ihtiyaç duyduğunuz değişkenleri aktarın: sudo env VAR=value /path/to/cmd
  • sudoers içinde env_keep += PATH veya env_keep += LD_* kullanmaktan kaçının
  • Çağıran ortamı tamamen denetlediğinizden ve ona güvendiğinizden emin olmadıkça sudo -E kullanmayın
#!/usr/bin/env bash
set -euo pipefail

# BAD: relies on $PATH — attacker who controls PATH can hijack 'cp'
# sudo cp config.conf /etc/app/

# GOOD: absolute paths for every command called under elevated context
SUDO_BIN="/usr/bin/sudo"
CP_BIN="/usr/bin/cp"
CHOWN_BIN="/usr/bin/chown"
SYSTEMCTL_BIN="/usr/bin/systemctl"

"$SUDO_BIN" "$CP_BIN" ./config.conf /etc/app/config.conf
"$SUDO_BIN" "$CHOWN_BIN" app:app /etc/app/config.conf
"$SUDO_BIN" "$SYSTEMCTL_BIN" restart app

echo "Deployed with hardened absolute-path invocations."

Komut Bağımsız Değişkeni Doğrulamasıyla sudo'yu Sıkılaştırma

Bir sudoers kuralı belirli bir betiğe izin verse bile, kural bunları da sınırlandırmıyorsa betiğe rastgele bağımsız değişkenler aktarılabilir. Yaygın bir tuzak:

deployer ALL=(root) NOPASSWD: /opt/scripts/manage.sh

Bu, sudo /opt/scripts/manage.sh restart komutuna izin verir — ancak sudo /opt/scripts/manage.sh --arbitrary-flag komutuna da izin verir. manage.sh bağımsız değişkenleri ayrıcalıklı alt komutlara sorgulamadan aktarıyorsa bir sorun yaşarsınız.

Derinlemesine savunun: bağımsız değişkenleri sudoers'ta olduğu gibi ayrıcalıklı betiğin içinde de doğrulayın:

#!/usr/bin/env bash
# /opt/scripts/manage.sh — called via sudo; must validate its own args
set -euo pipefail

# Allowlist of valid actions
declare -A ALLOWED_ACTIONS=(
  [restart]=1
  [status]=1
  [reload]=1
)

ACTION="${1:-}"

if [[ -z "$ACTION" ]]; then
  echo "Usage: $(basename "$0") <restart|status|reload>" >&2
  exit 1
fi

if [[ -z "${ALLOWED_ACTIONS[$ACTION]:-}" ]]; then
  echo "ERROR: Unknown action '${ACTION}'. Allowed: ${!ALLOWED_ACTIONS[*]}" >&2
  exit 2
fi

/usr/bin/systemctl "$ACTION" app
echo "Action '$ACTION' executed successfully."

Temizleme Tuzağıyla Geçici Yetki Yükseltme

Bir betiğin ayrıcalıklı bir dosyaya, kimlik bilgisine veya kaynağa kısa süreliğine sahip olması gerektiğinde, hata ya da sinyal durumunda bile temizleme işleminin gerçekleşmesini sağlamak için Bash'in trap özelliğini kullanın. Bu, örneğin betik çökerse geride kalan geçici bir setuid ikili dosyasının veya root sahipliğindeki bir soketin neden olabileceği yetki sızıntısını önler.

Aşağıdaki kalıp root olarak geçici bir dosya oluşturur, dosyayı kullanır ve ardından siler; bu işlem EXIT üzerindeki bir trap tarafından garanti edilir:

#!/usr/bin/env bash
set -euo pipefail

# Must run as root for this demo
if [[ "$EUID" -ne 0 ]]; then
  echo "Run as root" >&2; exit 1
fi

TMP_SECRET=""

cleanup() {
  local exit_code=$?
  if [[ -n "$TMP_SECRET" && -f "$TMP_SECRET" ]]; then
    # Overwrite before deletion to reduce forensic recovery risk
    shred -u "$TMP_SECRET" 2>/dev/null || rm -f "$TMP_SECRET"
    echo "[cleanup] Removed privileged temp file." >&2
  fi
  exit "$exit_code"
}

trap cleanup EXIT INT TERM

# Create a root-owned temp file for a short-lived secret
TMP_SECRET="$(mktemp /tmp/deploy_secret.XXXXXXXX)"
chmod 600 "$TMP_SECRET"

# Simulate fetching a secret into the temp file
echo "super-secret-token" > "$TMP_SECRET"

# Use the secret (e.g., pass to a sub-command via file descriptor)
/usr/bin/some-privileged-tool --key-file "$TMP_SECRET"

echo "Privileged operation complete."

Ayrıcalıklı İşlemleri Denetleme ve Günlüğe Kaydetme

Her yetki yükseltme olayı bağlamıyla birlikte günlüğe kaydedildiğinde en az ayrıcalık ilkesini uygulamak daha kolaydır: işlemi kim, ne zaman ve neden çalıştırdı? İki katmanı birleştirin:

  1. sudo'nun kendisi — /var/log/auth.log (Debian/Ubuntu) veya /var/log/secure (RHEL), her sudo çağrısını otomatik olarak kaydeder
  2. Betiğe ait denetim günlüğü — amacın sistem günlüğüyle birlikte kaydedilmesi için her ayrıcalıklı işlevin başlangıcında yapılandırılmış bir kayıt yazın

Basit bir yapılandırılmış günlük işlevi kullanmak, denetim izlerini tutarlı ve grep ile aranabilir durumda tutar:

#!/usr/bin/env bash
set -euo pipefail

AUDIT_LOG="/var/log/app_deploy_audit.log"

log_privileged_action() {
  local action="$1"
  local reason="${2:-unspecified}"
  local ts
  ts="$(date -u '+%Y-%m-%dT%H:%M:%SZ')"
  printf '{"ts":"%s","user":"%s","euid":%d,"action":"%s","reason":"%s"}\n' \
    "$ts" "${SUDO_USER:-$USER}" "$EUID" "$action" "$reason" \
    | sudo tee -a "$AUDIT_LOG" > /dev/null
}

# Each privileged step is logged before execution
log_privileged_action "cp_config" "deploy release v2.4.1"
sudo /usr/bin/cp ./config.conf /etc/app/config.conf

log_privileged_action "chown_config" "ensure app user owns config"
sudo /usr/bin/chown app:app /etc/app/config.conf

log_privileged_action "restart_service" "activate new config"
sudo /usr/bin/systemctl restart app

echo "Deployment complete. Audit entries written to $AUDIT_LOG"

Bilgi Yoklaması: sudo Kapsamı

Bash betiklerinde en az ayrıcalıkla yürütme konusundaki anlayışınızı sınayın.

Özet: En Az Ayrıcalıkla Yürütme ve sudo Disiplini

Bu derste, Bash betiklerini her adımda gereken en düşük ayrıcalıkla çalıştırma tekniklerinde ustalaştınız. Temel ilkelerin kısa bir özeti aşağıdadır:

  • $EUID ile koruma ekleyin — betik, root olmayı reddetmek veya root olmayı gerektirmek gibi durumlarda yanlış kimlikle çalışıyorsa hemen başarısız olun
  • sudo kapsamını tek tek komutlarla sınırlayın — hiçbir zaman betiğin tamamının yetkisini yükseltmeyin; sudoyu yalnızca gerçekten ihtiyaç duyan satırlara uygulayın
  • Sıkı sudoers kuralları yazın — tam mutlak yolları ve değişmez bağımsız değişkenleri belirtin; joker karakterlerden ve ALL'dan kaçının
  • runuser veya sudo -u ile ayrıcalıkları bırakın — root olarak başlayan bir betiğin ayrıcalıksız bir kullanıcıya devretmesi gerektiğinde, her şeyi root olarak çalıştırmak yerine doğru aracı kullanın
  • Mutlak yollar kullanın — ayrıcalıklı kod içinde hiçbir zaman $PATH'e güvenmeyin; ele geçirmeyi önlemek için ikili dosya yollarını doğrudan yazın
  • Ayrıcalıklı betiklerin içindeki bağımsız değişkenleri doğrulayın — sudoers kuralları ilk savunma hattıdır, tek savunma hattı değildir; izin verilenler listelerini kullanın
  • Yakalama ve temizleme yapın — hata durumunda bile geçici ayrıcalıklı kaynakların yok edilmesini garanti etmek için trap cleanup EXIT kullanın
  • Her yetki yükseltmesini günlüğe kaydedin — yapılandırılmış denetim kayıtları ile yerleşik sudo syslog'unu birleştirerek her ayrıcalıklı işlem için izlenebilirlik sağlayın

Tutarlı biçimde uygulandığında bu uygulamalar, otomasyonunuzun saldırı yüzeyini her zaman root olmaktan yalnızca kanıtlanabilir biçimde gerekli olduğunda root olmaya indirger; bu, güçlendirilmiş ve üretim kalitesinde Bash'in ayırt edici özelliğidir.

Sıkça Sorulan Sorular

“En Az Ayrıcalıklı Çalıştırma ve sudo Disiplini” dersi ücretsiz mi?

Evet — “En Az Ayrıcalıklı Çalıştırma ve sudo Disiplini” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve DevOps Bootcamp kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. DevOps Bootcamp kursu toplamda 4 dersten oluşur.

“En Az Ayrıcalıklı Çalıştırma ve sudo Disiplini” dersinde ne öğreneceğim?

Ayrıcalıkları düşürün, sudo kurallarının kapsamını sıkı tutun ve riskli işlemlerden önce etkin UID değerini doğrulayın. DevOps Bootcamp ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

DevOps Bootcamp öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te DevOps Bootcamp, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.

“En Az Ayrıcalıklı Çalıştırma ve sudo Disiplini” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu DevOps Bootcamp dersinde kod yazıp çalıştırabilir miyim?

Evet. Her DevOps Bootcamp dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. Komut ve Bağımsız Değişken Enjeksiyonunu Önleme
  2. Güvenli Gizli Bilgi Yönetimi ve Ortam Hijyeni
  3. En Az Ayrıcalıklı Çalıştırma ve sudo Disiplini
  4. ShellCheck ile Statik Analiz ve Denetim
← DevOps Bootcamp Sayfasına Dön