Mundarija (28)
- Bu darsda
- 1. Nega bu kerak?
- 2. Sir qayerlardan sizadi
- 2.1 Xarita
- 2.2 Kanon: sir xato xabariga tushmaydi
- 3. Git tarixi
- 3.1 Kanon tajribasi
- 3.2 Tarixni tozalash — ikkinchi qadam
- 4. Sizib chiqqanda nima qilish
- 5. Oldini olish: skanerlar
- 5.1 Skaner qanday ishlaydi
- 6. Sirni qayerda saqlash
- 6.1 Darajalar
- 6.2 *_FILE konvensiyasi
- 6.3 Secret manager'lar
- 6.4 SOPS + age
- 7. Rotatsiya — kodda qanday ko'rinadi
- 8. Hujumchi nigohi
- 9. API qadami: sirlar gigiyenasi (holat 40, 5-qism)
- 10. Ko'p uchraydigan xatolar
- 11. Mashqlar
- 1-mashq (oson): to'g'ri tartib
- 2-mashq (o'rta): maskalash
- 3-mashq (qiyin): .env ni tarixda qidirish
- 4-mashq: API qadami
- 12. Real ishda
- Xulosa
- Manbalar
Sirlarni boshqarish: .env, git tarixi, rotatsiya va secret manager'lar
Qisqacha: Sir — parol, API kalit, token, ichida parol bor baza manzili.
.envfaylni git'dan saqlaydi, lekin sirni himoya qilmaydi: u diskda ochiq matn, jarayon muhitida, ba'zan logda. Eng xavfli xato — sirni bir marta commit qilish: keyingi commit'da o'chirsangiz ham, u tarixda qoladi (kanongit log -Sbilan ikkala commit'ni topdi). Sizib chiqqan sirning yagona davosi — rotatsiya: eski kalitni bekor qilib, yangisini berish. Jamoa va serverlar ko'payganda sirlar maxsus omborga (Vault, Doppler, Infisical, bulut secret manager) yoki shifrlangan faylga (SOPS + age) ko'chadi.
Bu darsda
- Sir nima va u qayerlardan sizib chiqishini sanab bera olasiz.
- Git tarixidagi sirni topasiz va nega o'chirish yetmasligini tushuntira olasiz.
- Sir sizib chiqqanda qadamlar tartibini bilasiz.
- Ikki kalitli rotatsiyani (eski va yangi bir vaqtda) kodda yozasiz.
- Sir saqlash usullarini (env, fayl, secret manager, SOPS) solishtira olasiz.
Oldin bilishingiz kerak: Environment o'zgaruvchilar va .env, Env validatsiyasi va tipli config, crypto 1: hash va HMAC, .gitignore: to'liq qo'llanma.
1. Nega bu kerak?
Jasur kechqurun xorijiy mijoz uchun Stripe to'lov tizimini ulayapti. Tezroq sinash uchun kalitni to'g'ridan kodga yozdi: const KALIT = "sk_live_…" (Stripe'ning haqiqiy, pul yechadigan kalitlari shu prefiks bilan boshlanadi). Ishladi, commit qildi, push qildi. Ertalab esladi va kalitni .env ga ko'chirib, yangi commit qildi: "kalit olib tashlandi". Hammasi tozadek.
Lekin repo ochiq. Kalit tunda 9 soat tarixda turdi. GitHub'dagi ochiq kodni avtomatik skanerlaydigan botlar bor — ular bunday kalitni tez topadi. Kalit esa haqiqiy pul yechishi mumkin.
env darsida sozlamani koddan chiqardik, tipli config darsida xato xabarida qiymatni yashirdik. Bu dars sirlarning butun hayotini yopadi: qayerda saqlanadi, qanday sizib chiqadi, sizsa nima qilinadi.
O'xshatish: uy kaliti. Kalitni eshik ostidagi gilam tagiga qo'yish (.env) — ko'chadagi odamdan yashiradi, lekin uyga kirgan har kishi topadi. Kalitni yo'qotsangiz, "topilmasa kerak" deb kutmaysiz — qulfni almashtirasiz. Bu — rotatsiya.
2. Sir qayerlardan sizadi
2.1 Xarita
| Joy | Qanday | Kim ko'radi |
|---|---|---|
| Git tarixi | Bir marta commit | Repo'ga kirgan har kim, abadiy |
| Log | console.log(config), xato xabari |
Log tizimiga kirganlar |
| Xato javobi | Stack, detail |
Mijoz (global ishlovchi darsi) |
| Frontend build | VITE_…, NEXT_PUBLIC_… |
Har foydalanuvchi |
| Jarayon muhiti | Bola jarayon, crash dump, docker inspect |
Server foydalanuvchilari |
| Chat, skrinshot, AI yordamchi | "Mana kalit, nega ishlamayapti?" | Suhbat ishtirokchilari va xizmat |
| CI logi | echo $KALIT |
Repo'ga kirganlar |
Oxirgi qatorlar texnik emas, lekin eng ko'p uchraydi. AI yordamchiga kod bilan birga .env ni yuborish — sirni uchinchi tomonga berish demak (AI bilan ishlash darsi).
2.2 Kanon: sir xato xabariga tushmaydi
vazifalar-api da hozircha haqiqiy sir yo'q (auth — 28-qismda). Lekin himoya allaqachon bor:
configYuklaxatosida qiymatlar yo'q — testassert.doesNotMatch(x.message, /maxfiy-qiymat/)(tipli config darsi).- 500 javobida ichki xabar yo'q — test
/parol|maxfiy|…/(global ishlovchi darsi). .env.exampleda faqat namuna — "haqiqiy parol/kalit YO'Q va bo'lmasligi kerak".- Loglarda
authorization,cookie,*.parol,*.token— yashiriladi (Pino darsida).
3. Git tarixi
3.1 Kanon tajribasi
Kanon vaqtinchalik repo yaratdi va Jasurning xatosini takrorladi (t39-sirlar.txt; kalit — soxta sk_test_SOXTA_…): config.js ga kalit yozildi va commit qilindi, keyingi commit'da olib tashlandi. Chiqishda har qator — bitta git buyrug'i va uning natijasi. Asosiy savol: kalit hozirgi fayllarda yo'q bo'lsa ham, tarixda topiladimi?
git status --short (.gitignore'da .env): "?? .env.example\n?? .gitignore"
git check-ignore -v .env: .gitignore:1:.env .env
joriy fayllarda: ".env.example\n.gitignore"
git log -p -S "<kalit>" --oneline (kalit TARIXDA):
a9042b6 kalit olib tashlandi
411a5c3 tolov qo'shildi
git grep (barcha commitlarda): 1 ta mosO'qiymiz:
.env—.gitignoretufayli umuman ko'rinmaydi. Yaxshi.- Joriy fayllarda kalit yo'q —
config.jstozalangan. git log -S "<kalit>"— "shu matn qo'shilgan yoki olib tashlangan commit'lar": ikkalasi topildi.-pbilan har birining farqi (diff) ham ko'rinadi — kalit to'liq.
git log -S ni "pickaxe" (cho'kich) deyishadi — u tarixdan matnni qazib chiqaradi. Hujumchi ham aynan shuni qiladi. Kanon xulosasi: o'chirish yetmaydi — kalit almashtiriladi (rotatsiya), keyin kerak bo'lsa tarix tozalanadi.
3.2 Tarixni tozalash — ikkinchi qadam
Tarixdan sirni olib tashlash mumkin (git filter-repo, BFG). Lekin:
- Repo'ni klonlagan har kishida eski tarix qoladi.
- GitHub fork'lari, keshlar, CI artefaktlari — sizning nazoratingizdan tashqarida.
- Tarixni qayta yozish butun jamoaga
force pushva qayta klon degani.
Shuning uchun tartib qat'iy: avval rotatsiya, keyin (ixtiyoriy) tozalash. Tozalash usullari — 32-qismda.
Tekshirib ko'ring: Kalit
.envda edi, lekin.gitignorega.envqatorini kalit commit qilingandan keyin qo'shdingiz..envendi himoyalanganmi?
Javob
Yo'q. .gitignore faqat kuzatilmayotgan fayllarga ta'sir qiladi. .env allaqachon kuzatuvda — keyingi o'zgarishlar ham commit'ga tushaveradi. Kerak: git rm --cached .env (faylni diskda qoldirib kuzatuvdan chiqarish), keyin commit. Va tarixdagi kalit uchun — rotatsiya.
4. Sizib chiqqanda nima qilish
flowchart TD
A[Sir sizdi] --> B["1. Bekor qilish / rotatsiya<br/>(daqiqalar ichida)"]
B --> C["2. Ishlatilganmi?<br/>provayder loglari"]
C --> D["3. Koddan olib tashlash<br/>to'g'ri joyga ko'chirish"]
D --> E["4. Tarixni tozalash<br/>(ixtiyoriy)"]
E --> F["5. Sabab va oldini olish<br/>skaner, hook"]Diagrammadagi tartib muhim: rotatsiya birinchi, hatto kod hali tuzatilmagan bo'lsa ham. Har daqiqa hisobda.
| Qadam | Amalda |
|---|---|
| 1. Bekor qilish | Provayder panelida kalitni o'chirish, yangisini yaratish; serverga yangisini berish |
| 2. Tekshirish | To'lov tizimi, bulut yoki API'ning faollik logi: noma'lum IP, g'alati so'rovlar |
| 3. Tuzatish | Kod → env/sir ombori; .gitignore; testlar |
| 4. Tozalash | git filter-repo, jamoaga xabar |
| 5. Oldini olish | Secret scanning, pre-commit hook (har commit'dan oldin avtomatik ishlaydigan tekshiruv skripti), kod ko'rib chiqish |
Uyalib yashirish — eng yomon reaksiya. Jamoada "sir sizdi" deyish oson bo'lishi kerak: tez aytilgan sizish — kichik hodisa, yashirilgani — katta.
5. Oldini olish: skanerlar
Sirlarni avtomatik qidiradigan vositalar:
| Vosita | Qayerda ishlaydi | Holat |
|---|---|---|
| GitHub secret scanning + push protection | GitHub serveri: ma'lum formatdagi kalitli push'ni rad etadi | Ochiq repolarda bepul (GitHub hujjati) |
| gitleaks | Lokal, pre-commit hook, CI | Ochiq kodli |
| trufflehog | Lokal, CI; topilgan kalitni provayderda tekshiradi | Ochiq kodli |
Halol: kanon mashinasida gitleaks yo'q — sinalmagan; trufflehog va push protection ham sinalmagan. Bu yerda ularning g'oyasini o'z skanerimiz bilan ko'ramiz.
5.1 Skaner qanday ishlaydi
Ko'p provayderlar kalitlariga prefiks qo'yadi — aynan skanerlar topishi uchun: GitHub tokeni ghp_, Stripe sk_live_, AWS AKIA. Qolganini — "qiymati uzun va tasodifiy" belgisi bilan topishadi:
const QOIDALAR = [
["GitHub token", /\bghp_[A-Za-z0-9]{36}\b/],
["Stripe live kalit", /\bsk_live_[A-Za-z0-9]{16,}\b/],
["AWS kalit ID", /\bAKIA[0-9A-Z]{16}\b/],
["Parolli URL", /\b\w+:\/\/[^\s:/]+:[^\s@/]+@/],
];
function skanerla(matn) {
const topildi = [];
matn.split("\n").forEach((qator, i) => {
for (const [nom, re] of QOIDALAR) {
if (re.test(qator)) topildi.push(`${i + 1}-qator: ${nom}`);
}
});
return topildi;
}
const fayl = [
'const port = 3000;',
'const url = "postgres://ali:Maxfiy123@db.example.com/app";',
`const k = "sk_live_${"x".repeat(24)}";`,
"// ghp_ — bu shunchaki izoh",
].join("\n");
console.log(skanerla(fayl));Konsolda:
[ '2-qator: Parolli URL', '3-qator: Stripe live kalit' ]To'rtinchi qator — faqat prefiks, kalit uzunligi yo'q: skaner jim. Kalitni "x".repeat(24) bilan yasadik — dars matnining o'zi ham skanerlarni "bezovta qilmasin". Haqiqiy vositalarda yuzlab qoidalar va entropiya (tasodiflik) o'lchovi bor.
6. Sirni qayerda saqlash
6.1 Darajalar
| Usul | Qachon | Kamchilik |
|---|---|---|
.env (lokal) |
Dasturchi kompyuteri | Diskda ochiq; jamoaga tarqatish — chat orqali (yomon) |
Server env (systemd, Docker environment) |
Bitta server, kichik jamoa | docker inspect va jarayon muhitida ko'rinadi |
Fayl (/run/secrets/…, *_FILE) |
Docker/Compose secrets, Kubernetes | Fayl huquqlari to'g'ri bo'lishi kerak |
| SOPS + age | Shifrlangan fayl git'da | Kalit boshqaruvi o'zingizda |
| Secret manager (Vault, Doppler, Infisical, AWS/GCP) | Ko'p server, ko'p odam | Yana bir xizmat; narx |
Kanon bularning hech birini sinamagan (Docker — 33-qism, CI secrets — 34-qism). Quyida — har birining g'oyasi.
6.2 *_FILE konvensiyasi
Docker va Kubernetes sirni fayl sifatida beradi (/run/secrets/db_parol) — u docker inspect va jarayon muhitida ko'rinmaydi. Ko'p rasmiy image'lar (masalan, postgres) POSTGRES_PASSWORD_FILE kabi o'zgaruvchini qo'llaydi: "qiymat emas, faylning yo'li". O'z ilovangizda ham shunday qilish mumkin:
import { readFileSync, writeFileSync, mkdtempSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
function sirOqi(env, nom) {
const yol = env[`${nom}_FILE`];
if (yol !== undefined) return readFileSync(yol, "utf8").trim();
return env[nom];
}
const papka = mkdtempSync(join(tmpdir(), "sir-"));
const fayl = join(papka, "db_parol");
writeFileSync(fayl, "namuna-parol-emas\n", { mode: 0o600 });
console.log(sirOqi({ DB_PAROL_FILE: fayl }, "DB_PAROL"));
console.log(sirOqi({ DB_PAROL: "env-dan" }, "DB_PAROL"));
console.log(sirOqi({}, "DB_PAROL"));Konsolda:
namuna-parol-emas
env-dan
undefinedtrim() — fayl oxiridagi yangi qatorni olib tashlaydi (aks holda parol "…\n" bo'lib, baza "parol noto'g'ri" deydi — klassik tuzoq). mode: 0o600 — faqat egasi o'qiy oladi (Linux'da; Windows bu bitlarni deyarli e'tiborsiz qoldiradi). Kanondagi FaylOmbori ham ma'lumot faylini 0o600 bilan yozadi.
6.3 Secret manager'lar
- HashiCorp Vault — o'z serveringizda; sirlarni so'rov bo'yicha beradi, hatto dinamik sir yaratadi (har ishga tushganda yangi, qisqa muddatli baza paroli).
- Doppler, Infisical — bulut (Infisical — ochiq kodli, o'zingiz ham joylashtirasiz): veb panel, CLI
doppler run -- npm startsirlarni jarayon muhitiga quyadi. - AWS Secrets Manager, GCP Secret Manager — bulut provayderining o'zi; avtomatik rotatsiya.
Umumiy g'oya: sirning bitta haqiqiy manbai, kim qachon o'qiganining logi, va rotatsiya — bir joyda. Ilova kodi uchun farqi kam: oxir-oqibat qiymat process.env yoki faylga keladi — configYukla o'zgarmaydi.
6.4 SOPS + age
SOPS — YAML/JSON/env faylning qiymatlarini shifrlaydi, kalitlarni ochiq qoldiradi: git diff'da "qaysi sir o'zgardi" ko'rinadi, nima ga o'zgargani — yo'q. age — zamonaviy, oddiy shifrlash vositasi (kalit — bitta qator). Shifrlangan fayl git'da yashaydi, ochish kaliti — faqat serverda va mas'ul odamlarda. Kichik jamoa uchun secret manager'siz yaxshi yo'l. Kamchiligi — boshqa vositalar darsidagi .env.vault bilan bir xil: kalit sizsa, tarixdagi hamma versiya ochiladi.
7. Rotatsiya — kodda qanday ko'rinadi
Kalitni almashtirish bir lahzada bo'lmaydi: 3 ta server bor, birinchisiga yangi kalit berildi, qolgan ikkitasi hali eskisida. Agar kalit imzo uchun bo'lsa (webhook, cookie), server bir muddat ikkala kalitni qabul qilishi kerak. crypto darsidagi HMAC bilan:
const kodla = new TextEncoder();
const hex = (b) =>
[...new Uint8Array(b)].map((x) => x.toString(16).padStart(2, "0"))
.join("");
async function imzola(kalit, xabar) {
const k = await crypto.subtle.importKey("raw", kodla.encode(kalit),
{ name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
const b = kodla.encode(xabar);
const imzo = await crypto.subtle.sign("HMAC", k, b);
return hex(imzo);
}
/** kalitlar[0] — joriy, qolganlari — hali qabul qilinadigan */
async function imzoKimniki(kalitlar, xabar, imzo) {
for (const [i, kalit] of kalitlar.entries()) {
if ((await imzola(kalit, xabar)) === imzo) return i;
}
return -1;
}
const xabar = '{"hodisa":"vazifa.bajarildi","id":7}';
const eski = await imzola("eski-namuna-kalit", xabar);
const yangi = await imzola("yangi-namuna-kalit", xabar);
const kalitlar = ["yangi-namuna-kalit", "eski-namuna-kalit"];
console.log(await imzoKimniki(kalitlar, xabar, yangi)); // 0
console.log(await imzoKimniki(kalitlar, xabar, eski)); // 1
const faqatYangi = ["yangi-namuna-kalit"];
console.log(await imzoKimniki(faqatYangi, xabar, eski)); // -1Konsolda:
0
1
-1Rotatsiya bosqichlari: (1) hamma serverga [yangi, eski]; (2) imzolash faqat yangisi bilan; (3) eski bilan kelayotgan so'rovlar tugagach — [yangi]. Natija 1 (eski kalit) kelsa — logga yozing: kim hali yangilanmagani ko'rinadi.
Haqiqiy kodda === o'rniga vaqtga chidamli solishtirish kerak (crypto.timingSafeEqual — Node, crypto darsi), aks holda hujumchi javob vaqtidan imzoni bayt-bayt taxmin qilishi mumkin.
Tekshirib ko'ring: Nega rotatsiya uchun
KALITni bitta qiymat emas, ro'yxat (KALITLAR=yangi,eski) qilish kerak?
Javob
Bitta qiymat bilan kalitni almashtirish — "hamma joyda bir vaqtda" degani. Bunday lahza yo'q: serverlar ketma-ket yangilanadi, mijozlar eski kalit bilan imzolagan so'rovlarni hali yuborayotgan bo'ladi. Ro'yxat bilan o'tish davri bor — hech kim uzilmaydi.
8. Hujumchi nigohi
- Ochiq repo skaneri. Hujumchi GitHub'dagi yangi commit'larni avtomatik skanerlaydi va
sk_live_,AKIA, parolli URL'larni qidiradi. Himoya: sir hech qachon commit'ga tushmasin (.gitignore, push protection, pre-commit skaner); tushsa — darhol rotatsiya. git log -S. "Olib tashlangan" kalit tarixdan bir buyruq bilan chiqadi. Himoya: rotatsiya, keyin tarix tozalash.- Xato xabari va log. Buzuq so'rov bilan stack yoki config qiymatini chiqartirishga urinish. Himoya: kanondagi uch test — 500 yashirin, config xatosi qiymatsiz, log redact.
- Frontend build.
VITE_STRIPE_SECRET— build'da JS faylga yoziladi, "Sahifa kodini ko'rish" bilan ochiladi. Himoya: frontend'da faqat ochiq kalit (publishable), sir — faqat server env'ida. - Ortiqcha huquq. Sizgan kalitning zarari uning huquqlariga teng. Himoya: har xizmatga alohida, minimal huquqli kalit (faqat o'qish, faqat bitta bucket — bulutdagi bitta fayl ombori).
9. API qadami: sirlar gigiyenasi (holat 40, 5-qism)
Hali commit qilmang — commit keyingi darsda. vazifalar-api da yangi kod yo'q — tekshiruv ro'yxati:
git check-ignore -v .env
git log --all -p -S "sk_" --oneline
git grep -n -E "(parol|token|secret|_KEY)\s*=" -- ':!*.example'.enve'tiborsiz qolyaptimi (check-ignorechiqishi bor)?- Tarixda kalitga o'xshash narsa bormi (
-Sbo'sh bo'lishi kerak)? - Kodda sir qiymati bormi (
git grepfaqat nomlarni ko'rsatishi kerak, qiymatlarni emas)? .env.exampleda faqat namuna qiymatlar.test/config.test.tsvatest/xato.test.tsdagi "qiymat yo'q" tekshiruvlari o'tadi.
Kanon .gitignore (holat 40):
node_modules/
dist/
.env
*.log
coverage/
data/data/ — SAQLASH=fayl dagi vazifalar fayli; unda foydalanuvchi ma'lumoti bor, u ham git'ga tushmasligi kerak. *.log — loglarda tasodifan sir bo'lishi mumkin.
10. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
| Kalit "o'chirildi", lekin ishlatildi | Faqat yangi commit, rotatsiya yo'q | Avval rotatsiya |
.env git'da, garchi .gitignore da bo'lsa ham |
Avval commit qilingan | git rm --cached .env + rotatsiya |
| Baza "parol noto'g'ri", parol to'g'ri | Fayldagi \n |
.trim() |
| CI logida sir | echo, set -x, xato xabarida qiymat |
CI maskalash, qiymatsiz xabarlar |
| Kalit almashtirildi — yarim serverlar ishlamayapti | Bir lahzada almashtirish | Ikki kalitli o'tish davri |
| Frontend'da maxfiy kalit | VITE_/NEXT_PUBLIC_ prefiksi |
Faqat serverda |
| Sir chatda yuborildi | "Tezroq" | Secret manager yoki bir martalik havola |
11. Mashqlar
Yechimlar kurs/mashqlar/25/39-sirlar/ da.
1-mashq (oson): to'g'ri tartib
Stripe live kaliti ochiq repo'ga push qilindi. Qadamlarni tartiblang: (a) git filter-repo; (b) Stripe panelida kalitni bekor qilish; (c) kodni env'ga o'tkazish; (d) Stripe logida noma'lum to'lovlarni tekshirish.
Tartib: [:b], [:d], [:c], [:a]
Yechim
b → d → c → a. Bekor qilish birinchi — u zararni to'xtatadi. Keyin zarar bo'lganmi — tekshirish. Keyin kodni tuzatish (yangi kalit endi env'da). Tarixni tozalash oxirida va ixtiyoriy: kalit allaqachon yaroqsiz.
2-mashq (o'rta): maskalash
maskala(qiymat) yozing: 8 belgidan qisqa bo'lsa — butunlay ***; aks holda birinchi 4 belgi + … + uzunlik (sk_l…(32)). Keyin configniLogla(config, sirlar) — obyektni nusxalab, sirlar ro'yxatidagi kalitlarni maskalasin.
Yechim
function maskala(qiymat) {
const s = String(qiymat);
if (s.length < 8) return "***";
return `${s.slice(0, 4)}…(${s.length})`;
}
function configniLogla(config, sirlar) {
const nusxa = { ...config };
for (const k of sirlar) {
if (nusxa[k] !== undefined) nusxa[k] = maskala(nusxa[k]);
}
return nusxa;
}
const config = {
PORT: 3000,
WEBHOOK_URL: "https://example.com/hook?token=abc123def456",
DB_PAROL: "qisqa",
};
console.log(configniLogla(config, ["WEBHOOK_URL", "DB_PAROL"]));Konsolda:
{ PORT: 3000, WEBHOOK_URL: 'http…(43)', DB_PAROL: '***' }Uzunlikni ko'rsatish foydali: "parol bo'sh keldimi yoki to'liqmi?" degan savolga qiymatni ochmasdan javob beradi. Qisqa qiymatda boshini ham ko'rsatmaymiz — 4 belgi uning yarmi bo'lardi.
3-mashq (qiyin): .env ni tarixda qidirish
Commit'lar ro'yxati berilgan: [{ id, fayllar: { "yo'l": "matn" } }] (har commit — o'sha paytdagi to'liq holat). pickaxe(commitlar, matn) yozing: git log -S kabi — matn soni o'zgargan commit'larni qaytarsin (qo'shilgan yoki olib tashlangan).
Yechim
function sana(fayllar, matn) {
let n = 0;
for (const t of Object.values(fayllar)) {
n += t.split(matn).length - 1;
}
return n;
}
function pickaxe(commitlar, matn) {
const natija = [];
let oldingi = 0;
for (const c of commitlar) {
const hozir = sana(c.fayllar, matn);
if (hozir !== oldingi) {
natija.push(`${c.id} ${hozir > oldingi ? "+" : "-"}`);
}
oldingi = hozir;
}
return natija;
}
const KALIT = "sk_test_SOXTA_123";
const commitlar = [
{ id: "a1", fayllar: { "app.js": "port = 3000" } },
{ id: "b2", fayllar: { "app.js": `kalit = "${KALIT}"` } },
{ id: "c3", fayllar: { "app.js": `kalit = "${KALIT}"; x = 1` } },
{ id: "d4", fayllar: { "app.js": "kalit = process.env.K" } },
];
console.log(pickaxe(commitlar, KALIT));Konsolda:
[ 'b2 +', 'd4 -' ]c3 da kalit bor, lekin soni o'zgarmagan — -S uni ko'rsatmaydi (haqiqiy git ham shunday). Kanon tajribasidagi ikki commit — aynan "+" va "−".
4-mashq: API qadami
«API qadami» bo'limidagi uch buyruqni o'z vazifalar-api repo'ngizda bajaring va besh banddan iborat ro'yxatni tekshiring. Qo'shimcha: configYukla ga WEBHOOK_URL xato bo'lganda qiymat chiqmasligini tekshiradigan test yozing. Commit qilmang.
Yechim
Test: assert.throws(() => configYukla({ WEBHOOK_URL: "token-bor-yaroqsiz" }), (x) => x instanceof ConfigXatosi && !x.message.includes("token-bor")). prettifyError faqat xato turini va → at WEBHOOK_URL ni yozadi — test o'tadi. git log -S "sk_" bo'sh bo'lishi kerak; agar biror narsa chiqsa — bu mashq emas, haqiqiy hodisa: «Sizib chiqqanda» bo'limidagi tartib bilan.
12. Real ishda
- Jamoaga kelgan birinchi haftada so'raladigan savol: "sirlar qayerda?" Javob odatda: secret manager (Doppler/Vault/bulut) yoki CI secrets + server env.
- Kompaniyalarda sizish hodisasi uchun yozma tartib (runbook) bo'ladi — yuqoridagi besh qadam uning asosi.
- Intervyu savollari: "Kalitni commit qilib qo'ysangiz nima qilasiz?", "
.envni nega xavfsiz deb bo'lmaydi?", "Kalit rotatsiyasini uzilishsiz qanday qilasiz?"
Xulosa
- Sir sizadigan joylar: git tarixi, log, xato javobi, frontend build, jarayon muhiti, chat.
- Commit qilingan sir o'chirilgandan keyin ham tarixda (
git log -S) — davosi rotatsiya, tozalash — ikkinchi. - Tartib: bekor qilish → ishlatilganmi → kodni tuzatish → tarix → oldini olish.
- Saqlash darajalari:
.env(lokal) → server env → fayl (*_FILE) → SOPS → secret manager. - Rotatsiya — ikki kalitli o'tish davri; skanerlar (push protection, gitleaks, trufflehog) — oldini olish.
Keyingi dars: Backend'da sana va vaqt — UTC'da saqlash, Toshkent kuni bo'yicha filtr va holat 40 ning commit'i.
Manbalar
- The Twelve-Factor App — Config: https://12factor.net/config
- GitHub hujjati — Secret scanning va push protection: https://docs.github.com/en/code-security/secret-scanning
- OWASP Secrets Management Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html
- gitleaks: https://github.com/gitleaks/gitleaks ; trufflehog: https://github.com/trufflesecurity/trufflehog ; SOPS: https://github.com/getsops/sops ; age: https://github.com/FiloSottile/age
- HashiCorp Vault: https://developer.hashicorp.com/vault ; Infisical: https://infisical.com/docs ; Docker secrets: https://docs.docker.com/engine/swarm/secrets/
- Kanon:
natijalar/tajriba/t39-sirlar.txt(soxta kalit,git check-ignore,git log -S,git grep);vazifalar-apiholat 40 (.gitignore,.env.example,test/config.test.ts). gitleaks, trufflehog, push protection, Vault, Doppler, Infisical, SOPS — sinalmagan (hujjat bo'yicha).
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!