---
title: 'Kullanıcılar ve İzinler'
source: 'https://academia.sh/tr/kurslar/konteynerler/kullanicilar-ve-izinler'
course: Konteynerler
language: tr
updated: '2026-08-17T18:09:04+00:00'
license: 'CC BY-SA 4.0'
---

# Kullanıcılar ve İzinler

Köksüz çalışmanın üç ölçüsü: ayrıcalıklı kimliğe on beş girdinin kaçının açık kaldığı, köksüz kimliğe geçişin kaç girdide sahiplik düzeltmesi istediği ve düzeltmeden sonra bağlama takmasında kaç yolun ortamdan gelen sahiplikle kapalı kaldığı.

Önceki ders ağ ayrımını kurdu: hangi adın hangi adrese çözüldüğü, hangi bağlantı noktasının dışarı
açıldığı ve açılmayanın erişilemez kaldığı sayıldı. O ölçümlerin hepsi sürecin **ne yaptığını**
sayıyordu. İçeride **kimin** çalıştığı hiç sorulmadı ve sorulmadığı için varsayılan yürürlükte
kaldı: bir imaj derlenirken içine yazılan her dosyanın sahibi derlemeyi yürüten ayrıcalıklı
kimliktir, süreç de aynı kimlikle başlar. Bölgesel ölçüm ağının okuma toplayıcı servisi — sayaç
verisini toplayan, doğrulayan ve faturalamaya devreden kurgu yazılım — bu dersin ölçüm nesnesidir.

Uygulama düzeyindeki yetki soruları bu dersin dışındadır. Gizli değerin nerede durduğu, kaç yerde
tekrarlandığı ve döndürülürken ne kırdığı Gizli Değer Yönetimi dersinde ölçülmüştü. Buradaki soru
bir sınır aşağısındadır: o değerin **dosyasına** hangi kimliğin ulaşabildiği ve bu ulaşmanın
imaj tanımından mı yoksa ortamdan mı geldiği.

**CZ25 — servisin imajı on beş girdiden oluşur** (dosya ve dizin) ve servis çalışırken bunların
üzerinde on iki işlem yapar: okuma, yazma, çalıştırma. **CZ26 — derleme sırasında yazılan her girdi
ayrıcalıklı kimliğin (`0:0`) sahipliğine geçer.** **CZ27 — köksüz düzende süreç kimliği
`10001:10001`'dir.** **CZ28 — bağlanan konak dizini içeride `501:20` sahipliğiyle görünür**; bu
sahiplik imajdan değil, takmanın geldiği yerden okunur. **CZ29 — ayrıcalıklı kimlik isteğe bağlı
erişim denetimini atlar**, kip bitlerine bakılmaz. **CZ30 — kullanıcı ad alanı eşlemesi yoksa
konteyner içindeki sayısal kimlik konaktaki aynı sayıdır.**

## İzin Matrisi

Aşağıdaki koşum dosyaları gerçekten diske yazar, kip bitlerini `chmod` ile kurar ve `statSync` ile
geri okur; tablodaki kip sütunu diskten gelir. Sahiplik ise bir **modeldir**: sahiplik değiştirmek
ayrıcalık istediğinden sahip ve grup numaraları tabloda tutulur, erişim kararı bu numaralarla
gerçek kip bitleri üzerinden hesaplanır. Bir yola erişimin bütün ata dizinlerinde çalıştırma biti
istemesi de hesaba katılır.

```js
// agac.mjs — kurgu okuma toplayici servisinin dosya agaci.
// Dosyalar ve kip bitleri GERCEK: diske yazilir, chmod ile kurulur, statSync ile geri okunur.
// Sahiplik bir MODELDIR: chown ayricalik ister, bu yuzden sahip/grup tabloda tutulur.
import { mkdirSync, writeFileSync, chmodSync, statSync, rmSync } from 'node:fs';

export const AYRICALIKLI = { ad: 'ayricalikli', uid: 0, gid: 0 };      // CZ26
export const KOKSUZ = { ad: 'koksuz', uid: 10001, gid: 10001 };        // CZ27
export const KONAK = { uid: 501, gid: 20 };                            // CZ28

// [yol, tur, kip, sahip, grup] — bagli/ altindakiler konak sahipligiyle gorunur.
export const IMAJ = [
  ['uygulama', 'd', 0o755, 0, 0],
  ['uygulama/baslat.mjs', 'f', 0o755, 0, 0],
  ['uygulama/toplayici.mjs', 'f', 0o644, 0, 0],
  ['uygulama/dogrulayici.mjs', 'f', 0o644, 0, 0],
  ['ayar', 'd', 0o755, 0, 0],
  ['ayar/servis.json', 'f', 0o644, 0, 0],
  ['ayar/imza-anahtari', 'f', 0o600, 0, 0],
  ['durum', 'd', 0o755, 0, 0],
  ['durum/kuyruk.veri', 'f', 0o644, 0, 0],
  ['durum/kilit', 'f', 0o644, 0, 0],
  ['gecici', 'd', 0o777, 0, 0],
  ['bagli', 'd', 0o755, KONAK.uid, KONAK.gid],
  ['bagli/olcum-01.csv', 'f', 0o644, KONAK.uid, KONAK.gid],
  ['bagli/olcum-02.csv', 'f', 0o640, KONAK.uid, KONAK.gid],
  ['bagli/cikti', 'd', 0o755, KONAK.uid, KONAK.gid],
];

export function kur(kok, dugumler) {
  rmSync(kok, { recursive: true, force: true });
  mkdirSync(kok, { recursive: true });
  for (const [yol, tur, kip] of dugumler) {
    const tam = `${kok}/${yol}`;
    if (tur === 'd') mkdirSync(tam); else writeFileSync(tam, `# ${yol}\n`);
    chmodSync(tam, kip);
  }
  return dugumler.map(([yol, tur, , uid, gid]) => ({
    yol, tur, uid, gid, kip: statSync(`${kok}/${yol}`).mode & 0o777,
  }));
}

// Istege bagli erisim denetimi: sahip / grup / diger uclusunden biri secilir.
// CZ29: ayricalikli kimlik ucluyu atlar; calistirma icin yine de bir x biti arar.
export function izin(dugum, kimlik) {
  const { kip } = dugum;
  if (kimlik.uid === 0) return { r: true, w: true, x: (kip & 0o111) !== 0 };
  const u = kimlik.uid === dugum.uid ? kip >> 6 : kimlik.gid === dugum.gid ? kip >> 3 : kip;
  return { r: (u & 4) !== 0, w: (u & 2) !== 0, x: (u & 1) !== 0 };
}

// Bir yola erisim, butun ata dizinlerinde x bitini de ister.
export function erisim(agac, yol, kimlik) {
  const p = yol.split('/');
  for (let i = 1; i < p.length; i += 1) {
    const ata = agac.find((d) => d.yol === p.slice(0, i).join('/'));
    if (ata && !izin(ata, kimlik).x) return { r: false, w: false, x: false };
  }
  return izin(agac.find((d) => d.yol === yol), kimlik);
}

export const bicim = (e) => `${e.r ? 'r' : '-'}${e.w ? 'w' : '-'}${e.x ? 'x' : '-'}`;

if (import.meta.url === `file://${process.argv[1]}`) {
  const agac = kur('./kok', IMAJ);
  const s = (x, n) => String(x).padStart(n);
  console.log(`${'yol'.padEnd(24)}${s('kip', 5)}${s('sahip', 8)}${s('ayricalikli', 13)}${s('koksuz', 9)}`);
  for (const d of agac) {
    console.log(`${(d.tur === 'd' ? `${d.yol}/` : d.yol).padEnd(24)}${s(d.kip.toString(8), 5)}`
      + `${s(`${d.uid}:${d.gid}`, 8)}${s(bicim(erisim(agac, d.yol, AYRICALIKLI)), 13)}`
      + `${s(bicim(erisim(agac, d.yol, KOKSUZ)), 9)}`);
  }
  for (const k of [AYRICALIKLI, KOKSUZ]) {
    const e = agac.map((d) => erisim(agac, d.yol, k));
    console.log(`${k.ad.padEnd(13)} okunabilir ${s(e.filter((x) => x.r).length, 2)}/${agac.length}`
      + `  yazilabilir ${s(e.filter((x) => x.w).length, 2)}/${agac.length}`
      + `  calistirilabilir ${s(e.filter((x) => x.x).length, 2)}/${agac.length}`);
  }
}
```

```
yol                       kip   sahip  ayricalikli   koksuz
uygulama/                 755     0:0          rwx      r-x
uygulama/baslat.mjs       755     0:0          rwx      r-x
uygulama/toplayici.mjs    644     0:0          rw-      r--
uygulama/dogrulayici.mjs  644     0:0          rw-      r--
ayar/                     755     0:0          rwx      r-x
ayar/servis.json          644     0:0          rw-      r--
ayar/imza-anahtari        600     0:0          rw-      ---
durum/                    755     0:0          rwx      r-x
durum/kuyruk.veri         644     0:0          rw-      r--
durum/kilit               644     0:0          rw-      r--
gecici/                   777     0:0          rwx      rwx
bagli/                    755  501:20          rwx      r-x
bagli/olcum-01.csv        644  501:20          rw-      r--
bagli/olcum-02.csv        640  501:20          rw-      ---
bagli/cikti/              755  501:20          rwx      r-x
ayricalikli   okunabilir 15/15  yazilabilir 15/15  calistirilabilir  7/15
koksuz        okunabilir 13/15  yazilabilir  1/15  calistirilabilir  7/15
```

İki sütun arasındaki fark, kip bitlerinin ne kadarının karar taşıdığını gösteriyor. Ayrıcalıklı
kimlik için on beş girdinin on beşi okunabilir ve on beşi yazılabilir; `600` kipiyle korunan imza
anahtarı da, konak sahipliğiyle gelen ölçüm dosyası da açıktır. O sütunda kip bitleri **karar
taşımaz**, yalnızca kayıt tutar. Köksüz sütununda ise aynı bitler kararı verir: okunabilir on üç,
yazılabilir bir. Yazılabilir tek girdi `gecici/` dizinidir ve nedeni kipinin `777` olmasıdır.

Çalıştırma sütununun iki kimlikte de yedi çıkması ayrı bir ayrımdır. Ayrıcalıklı kimlik izin
denetimini atlar ama olmayan bir çalıştırma bitini uyduramaz; dosyanın çalıştırılabilir olması
yetkiden değil, kipten gelir. Bu dersin bütün sayıları içinde ayrıcalığın değiştirmediği tek sütun
budur.

## Köksüz Çalışmaya Geçişin Bedeli

Matris tek başına bir karar vermez; hangi erişimin **gerektiği** bilinmeden "kapalı" bir sayı
değildir. İkinci koşum servisin gerçekten yaptığı on iki işlemi listeler, iki kimlikle koşturur ve
düşen işlemleri ayırır: imaj içinde düzeltilebilenler ile takmadan gelenler.

```js
// matris.mjs — koksuz calismaya gecisin bedeli ve konak tarafinda birakilan yuzey.
import { kur, izin, erisim, bicim, IMAJ, AYRICALIKLI, KOKSUZ } from './agac.mjs';

// Servisin gercekten yaptigi islemler: [yol, islem]
const GEREKLI = [
  ['uygulama/baslat.mjs', 'x'], ['uygulama/toplayici.mjs', 'r'],
  ['uygulama/dogrulayici.mjs', 'r'], ['ayar/servis.json', 'r'],
  ['ayar/imza-anahtari', 'r'], ['durum', 'w'], ['durum/kuyruk.veri', 'w'],
  ['durum/kilit', 'w'], ['gecici', 'w'], ['bagli/olcum-01.csv', 'r'],
  ['bagli/olcum-02.csv', 'r'], ['bagli/cikti', 'w'],
];

const dusen = (agac, kimlik) => GEREKLI.filter(([y, i]) => !erisim(agac, y, kimlik)[i]);
const yuzey = (agac, kimlik) => agac.filter((d) => izin(d, kimlik).w).length;

const agac = kur('./kok', IMAJ);
const s = (x, n) => String(x).padStart(n);
console.log(`ayricalikli: dusen islem ${dusen(agac, AYRICALIKLI).length}/${GEREKLI.length}`
  + `, yazilabilir girdi ${yuzey(agac, AYRICALIKLI)}/${agac.length}`);
console.log(`koksuz     : dusen islem ${dusen(agac, KOKSUZ).length}/${GEREKLI.length}`
  + `, yazilabilir girdi ${yuzey(agac, KOKSUZ)}/${agac.length}`);
for (const [y, i] of dusen(agac, KOKSUZ)) {
  const d = agac.find((x) => x.yol === y);
  console.log(`  ${y.padEnd(22)} istenen ${i}  kip ${d.kip.toString(8)}  sahip ${d.uid}:${d.gid}`
    + `  ${d.yol.startsWith('bagli/') ? 'baglama takmasi — imajda duzeltilemez' : 'imaj icinde'}`);
}

// Iki duzeltme bicimi: sahipligi tasimak, ya da kip bitlerini gevsetmek.
// YABANCI: ayni bitlerden yararlanan ucuncu bir kimlik (baska bir surec ya da esleme yokken konak).
const YABANCI = { uid: 20002, gid: 20002 };
function duzelt(bicimAdi) {
  const t = kur('./kok', IMAJ);
  let dokunulan = 0;
  for (const [y] of dusen(t, KOKSUZ)) {
    const d = t.find((x) => x.yol === y);
    if (y.startsWith('bagli/')) continue;
    if (bicimAdi === 'sahiplik') { d.uid = KOKSUZ.uid; d.gid = KOKSUZ.gid; }
    else d.kip |= d.tur === 'd' ? 0o077 : 0o066;
    dokunulan += 1;
  }
  return { t, dokunulan, kalan: dusen(t, KOKSUZ) };
}
console.log(`\n${'duzeltme'.padEnd(16)}${s('dokunulan', 11)}${s('kalan dusen', 13)}`
  + `${s('koksuz yazar', 14)}${s('yabanci yazar', 15)}${s('yabanci okur', 14)}`);
let kalan = [];
for (const b of ['sahiplik', 'kip gevsetme']) {
  const r = duzelt(b);
  kalan = r.kalan;
  console.log(`${b.padEnd(16)}${s(r.dokunulan, 11)}${s(r.kalan.length, 13)}`
    + `${s(`${yuzey(r.t, KOKSUZ)}/${r.t.length}`, 14)}${s(`${yuzey(r.t, YABANCI)}/${r.t.length}`, 15)}`
    + `${s(`${r.t.filter((d) => izin(d, YABANCI).r).length}/${r.t.length}`, 14)}`);
}

// Konak yuzeyi: ayni sayisal kimligin konteyner disinda dokunabildigi girdiler (CZ30).
const KONAK_AGACI = [
  ['veri', 'd', 0o755, 0, 0], ['veri/olcum-arsiv', 'f', 0o644, 10001, 10001],
  ['veri/gunluk.log', 'f', 0o664, 0, 10001], ['ayar', 'd', 0o755, 0, 0],
  ['ayar/ag.json', 'f', 0o644, 0, 0], ['ev', 'd', 0o755, 10001, 10001],
  ['ev/anahtar', 'f', 0o600, 10001, 10001], ['ev/toplayici.mjs', 'f', 0o755, 10001, 10001],
];
const konak = kur('./konak', KONAK_AGACI);
const ESLEME = 100000;  // kullanici ad alani kaydirmasi
console.log(`\n${'konak kimligi'.padEnd(16)}${s('okunabilir', 12)}${s('yazilabilir', 13)}${s('ev/anahtar', 12)}`);
for (const k of [{ ad: 'eslemesiz 10001', uid: KOKSUZ.uid, gid: KOKSUZ.gid },
  { ad: `esleme +${ESLEME}`, uid: KOKSUZ.uid + ESLEME, gid: KOKSUZ.gid + ESLEME }]) {
  const e = konak.map((d) => erisim(konak, d.yol, k));
  console.log(`${k.ad.padEnd(16)}${s(`${e.filter((x) => x.r).length}/${konak.length}`, 12)}`
    + `${s(`${e.filter((x) => x.w).length}/${konak.length}`, 13)}`
    + `${s(bicim(erisim(konak, 'ev/anahtar', k)), 12)}`);
}
console.log(`baglama takmasindaki ${kalan.length} yol konak tarafinda duzeltilmeli;`
  + ` esleme acikken hedef kimlik ${KOKSUZ.uid} degil ${KOKSUZ.uid + ESLEME} olur`);
```

```
ayricalikli: dusen islem 0/12, yazilabilir girdi 15/15
koksuz     : dusen islem 6/12, yazilabilir girdi 1/15
  ayar/imza-anahtari     istenen r  kip 600  sahip 0:0  imaj icinde
  durum                  istenen w  kip 755  sahip 0:0  imaj icinde
  durum/kuyruk.veri      istenen w  kip 644  sahip 0:0  imaj icinde
  durum/kilit            istenen w  kip 644  sahip 0:0  imaj icinde
  bagli/olcum-02.csv     istenen r  kip 640  sahip 501:20  baglama takmasi — imajda duzeltilemez
  bagli/cikti            istenen w  kip 755  sahip 501:20  baglama takmasi — imajda duzeltilemez

duzeltme          dokunulan  kalan dusen  koksuz yazar  yabanci yazar  yabanci okur
sahiplik                  4            2          5/15           1/15         13/15
kip gevsetme              4            2          5/15           5/15         14/15

konak kimligi     okunabilir  yazilabilir  ev/anahtar
eslemesiz 10001          8/8          5/8         rw-
esleme +100000           7/8          0/8         ---
baglama takmasindaki 2 yol konak tarafinda duzeltilmeli; esleme acikken hedef kimlik 10001 degil 110001 olur
```

Ayrıcalıklı kimlikle on iki işlemin sıfırı düşer. Bu, ayrıcalıklı çalışmanın neden sürdüğünü tek
satırda açıklıyor: hiçbir şey kırılmaz, dolayısıyla hiçbir şey sorulmaz. Köksüz kimliğe geçildiğinde
on iki işlemin altısı düşer ve düşenlerin dağılımı asıl bilgidir — dördü imaj içindedir, ikisi
takmadan gelir.

İmaj içindeki dört düşük tek bir düzeltmeyle kapanır: o dört girdinin sahipliğinin köksüz kimliğe
geçirilmesi. Yalıtımın bu dersteki bedeli bu sayıdır — **dört girdide sahiplik düzeltmesi**, yani
imaj tanımına yazılacak dört yol. Bu yolların kod okunarak bulunamaması bedeli asıl ağırlaştıran
şeydir: hangi dosyanın yazıldığı ancak servis köksüz koşup düştüğünde ortaya çıkar, ve düşen her
işlem ayrı bir kırılmadır. Düzeltmeden sonra yazılabilir girdi sayısı ondan beşe değil, **on beşten
beşe** iner: ayrıcalıklı kimliğin yazabildiği on girdi kapanır. Kapanan on girdinin içinde imza
anahtarının yanındaki üç yapılandırma dosyası ve uygulama kodunun kendisi vardır; ele geçirilmiş bir
sürecin kendi kodunu değiştirip kalıcı olması bu on girdinin kapanmasıyla ortadan kalkar.

Aynı dört girdi iki ayrı yolla açılabilir ve tablo ikisini yan yana koyuyor. Sahipliği taşımak da
kip bitlerini gevşetmek de dört girdiye dokunur, ikisi de kalan düşük sayısını ikiye indirir ve
ikisinde de köksüz kimliğin yazabildiği girdi beştir. Servis her iki düzeltmeyle de aynı biçimde
ayağa kalkar. Fark tablonun son iki sütunundadır: sahiplik taşındığında üçüncü bir kimlik on beş
girdinin yalnız birine yazabilir, kip gevşetildiğinde beşine. Okuma sütunu farkı daha keskin
söylüyor — gevşetme imza anahtarının `600` kipini `666` yapar ve yabancı kimliğin okuyabildiği
girdi on üçten on dörde çıkar. İki düzeltme aynı hatayı susturur, imaj tanımına aynı sayıda satır
yazdırır ve **farklı bir yüzey bırakır**; hangisinin seçildiği ne hata iletisinden ne de servisin
davranışından okunur.

Kalan iki işlem imaj tanımına yazılarak kapanmaz. `bagli/olcum-02.csv` ve `bagli/cikti` takmadan
gelir; sahiplikleri imajın değil, takmanın geldiği yerin kaydındadır. **Yalıtımın delindiği birinci
yer budur:** on beş girdinin on birinin sahipliği çıktının içine alınabilir, dördününki çalışma
anında dışarıdan gelir ve o dördü için doğru sayı ancak iki tarafın anlaşmasıyla belirlenir.

## Sayısal Kimliğin Paylaşılması

Çıktının alt yarısı ikinci deliği ölçüyor. Köksüz kimlik `10001` bir addan değil bir sayıdan
ibarettir ve o sayı çekirdeğin tek bir tablosundan okunur. Konak tarafında sekiz girdilik kurgu bir
kümede aynı sayı beş girdiyi yazabilir; `ev/anahtar` dosyası `600` kipindedir, yani içeriden
erişilemeyen imza anahtarının konak eşdeğeri o kimliğe `rw-` açıktır. Köksüz çalışmak "yetkisiz
çalışmak" değildir; **başka bir sayının yetkisiyle çalışmaktır** ve o sayının konakta ne anlama
geldiği imajda yazmaz.

Kullanıcı ad alanı eşlemesi bu deliği kapatır: yüz bin kaydırmayla içerideki `10001` konakta
`110001` olur, hiçbir konak girdisinin sahibi ya da grubu değildir, yazılabilir sayısı beşten
**sıfıra** iner ve `ev/anahtar` okunamaz hâle gelir. Bedeli son satırdadır. Takmadaki iki yol için
konak tarafında yapılacak sahiplik düzeltmesinin hedefi artık `10001` değil `110001`'dir; içeriden
yazılan her yeni dosya da konakta o kimlikle görünür. Eşleme, dışarı taşan yetkiyi kapatırken
takmanın iki ucu arasındaki kimlik uyuşmazlığını büyütür. Yalıtım burada da tam olmaz, yalnızca
bedeli başka bir kaleme yazılır.

## Özet

- İzin matrisi ayrıcalıklı kimlik için karar taşımaz: on beş girdinin on beşi okunabilir, on beşi
  yazılabilir; `600` kipli imza anahtarı da açıktır. Kipin değiştirmediği tek sütun çalıştırmadır —
  iki kimlikte de yedi.
- Köksüz kimlikle on iki işlemin altısı düşer; dördü imaj içinde, ikisi bağlama takmasındadır.
- Geçişin bedeli dört girdide sahiplik düzeltmesidir ve bu dört yol koddan okunarak değil, servis
  düşerek bulunur; karşılığında yazılabilir girdi sayısı on beşten beşe iner. Aynı dördü kip
  gevşeterek açmak da servisi yürütür, ama yabancı bir kimliğe yazılabilir girdiyi birden beşe,
  okunabiliri on üçten on dörde çıkarır.
- On beş girdinin on birinin sahipliği çıktının içine alınabilir; dördü çalışma anında ortamdan
  gelir ve imaj tanımıyla düzeltilemez.
- Köksüz kimlik konakla aynı sayıdır: kurgu konak kümesinde sekiz girdinin beşini yazabilir ve
  `600` kipli konak anahtarını okuyabilir.
- Kullanıcı ad alanı eşlemesi konakta yazılabilir sayısını beşten sıfıra indirir; bedeli takmanın
  iki ucundaki kimlik uyuşmazlığının derinleşmesi, düzeltme hedefinin `110001`'e kaymasıdır.

## Sonraki Adım

Buraya kadarki bütün ölçümler tek bir konteyner üzerindeydi: bir dosya ağacı, bir kimlik, bir izin
matrisi. Oysa bölgesel ölçüm ağı tek süreç değildir — okuma toplayıcının yazdığı kuyruğu bir
doğrulayıcı okur, doğrulanan kayıt faturalamaya gider ve hepsinin altında bir kayıt deposu durur.
Bu servisleri elle başlatmak, her birinin ağını, birimini ve sırasını ayrı kararlarla kurmak
demektir; bir tanesi yeniden başladığında hangilerinin etkilendiği de o kararların içinde saklıdır.
Sonraki ders bu kurulumu bildirimsel bir bileşim dosyasına taşır ve iki biçimi sayıyla karşılaştırır:
dört servisli bir kurguda başlatma sırasının bağımlılık grafiğinden nasıl türetildiğini, hazır olma
denetimi olmadan kaç yarışın doğduğunu ve elle başlatmaya göre kaç komut ile kaç kararın ortadan
kalktığını ölçer.
