Maqolalar 7 daqiqa 212 ko‘rish
Token, parol, kalit: sirlar qayerda yashaydi va qayerda o'ladi
GitHub'ga tushib qolgan bot tokeni bir necha daqiqada topiladi — buni skanerlash botlari tinimsiz qilib turadi. Sirlarni to'g'ri saqlash tartibini quramiz: .env fayllar, ruxsatlar, sizib chiqqandagi harakatlar rejasi va commit'dan oldingi himoya.
Mundarija
Kiberxavfsizlik darslarimda talabalarga bitta tajribani aytib beraman: GitHub'ga ochiq repo bilan tasodifan yuklangan token o'rtacha bir necha daqiqa ichida birinchi marta sinab ko'riladi. Buni maxsus botlar qiladi — ular GitHub'ning yangi commit oqimini tinimsiz skanerlashadi va token naqshlarini (Telegram, AWS, Stripe...) avtomatik ushlashadi. Ya'ni "kim ham mening kichkina repomni ko'rardi" degan umid ishlamaydi: ko'radigan tomon odam emas, mashina.
Seriya davomida sirlarga oid qoidalar bo'lak-bo'lak uchrab keldi — systemd'da EnvironmentFile, CI'da Secrets. Yakuniy qismda hammasini bitta tizimga yig'amiz.
Asosiy qoida: sir kodda emas, muhitda#
Sirning kodda yashashiga birinchi qadam doim beg'ubor ko'rinadi: "hozircha shu yerga yozib turay, keyin olib tashlayman". Keyin u commit bo'ladi — va bo'ldi, endi u tarixda. Shuning uchun qoida murosasiz: token, parol, kalit — faqat muhit o'zgaruvchisida. Kod ularni nomi bilan so'raydi, qiymatini qayerdan kelishi bilan ishi yo'q:
# config/settings.py
import os
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"] # yo'q bo'lsa — ataylab yiqilsin
BOT_TOKEN = os.environ.get("BOT_TOKEN", "") # ixtiyoriy bo'lsa — bo'sh default
os.environ["..."] bilan os.environ.get("...") orasidagi tanlov ham
ongli: ilova ishlashi uchun majburiy sir yo'q bo'lsa, start paytida baland
ovozda yiqilgani yaxshi — jimgina bo'sh qiymat bilan ishlab, qayeridadir
g'alati xato berganidan ko'ra.
.env fayl va uning egizagi#
Muhit o'zgaruvchilarini qo'lda eksport qilib yurish noqulay, shuning uchun
ular .env faylga yig'iladi. Bu faylning ikkita temir qoidasi bor.
Birinchisi — .env repo'ga hech qachon tushmaydi. Buning uchun u loyihaning
birinchi kunidayoq .gitignore ga yoziladi:
.env
.gitignore faqat hali kuzatilmayotgan fayllarga ta'sir qiladi. Agar .env
allaqachon commit qilingan bo'lsa, qatorni qo'shishning o'zi yetmaydi — faylni
Git kuzatuvidan chiqarish kerak (diskdagi fayl o'chmaydi):
git rm --cached .env
git commit -m ".env ni Git kuzatuvidan chiqarish"
Lekin unutmang: bu faqat keyingi commit'larni himoya qiladi, tarixdagi sirlar joyida qoladi. Ular bilan nima qilish kerakligi pastdagi "Sizib chiqdi" bo'limida.
Ikkinchisi — .envning "egizagi": qiymatlarsiz, lekin to'liq ro'yxatli
.env.example fayli repo'da turadi:
# .env.example — bu fayl repo'da ochiq turadi, sirlar YO'Q
DJANGO_SECRET_KEY=
BOT_TOKEN=
DATABASE_URL=postgresql://user:password@127.0.0.1/dbname
TELEGRAM_ADMIN_CHAT_ID=
Bu kichik fayl ikki katta muammoni yechadi. Yangi muhit ko'targan odam
(yoki olti oydan keyingi siz) qaysi o'zgaruvchilar kerakligini kod ichini
titkilamasdan biladi. Va CI/CD qismida
aytilgan env drift — kodga yangi o'zgaruvchi qo'shilib, serverdagi .env
unutilishi — ushlanadigan bo'ladi: .env.example bilan serverdagi faylni
solishtirish kifoya. Qiymatlarni emas, faqat nomlarni solishtiramiz, shunda
sirlar ekranga chiqmaydi:
# serverda, loyiha papkasida
diff <(grep -o '^[A-Za-z_][A-Za-z0-9_]*=' .env.example | sort) \
<(grep -o '^[A-Za-z_][A-Za-z0-9_]*=' .env | sort)
Masalan, serverdagi .env ga TELEGRAM_ADMIN_CHAT_ID yozish unutilgan bo'lsa:
4d3
< TELEGRAM_ADMIN_CHAT_ID=
< belgili qator — .env.example da bor, lekin serverdagi .env da yo'q
o'zgaruvchi. Hech narsa chiqmasa, ikkala fayldagi nomlar bir xil.
Serverda .env ni kod o'zi o'qimaydi: uni systemd
qismida ko'rgan EnvironmentFile= qatori
xizmat ishga tushishidan oldin muhitga yuklaydi. Lokal kompyuterda esa bu
ishni kutubxona bajaradi — Django uchun qanday qilinishi alohida
maqolada bor. Busiz
python manage.py runserver KeyError: 'DJANGO_SECRET_KEY' bilan yiqiladi —
yuqorida aynan shuni xohlagan edik.
Serverda esa .env fayli o'z uy tartibiga ega:
sudo chown deploy:deploy /opt/mysite/.env
sudo chmod 600 /opt/mysite/.env # faqat egasi o'qiydi — boshqa hech kim
Sizib chiqdi: birinchi soat rejasi#
Ehtiyotkorlikka qaramay sir oshkor bo'lishi mumkin: commit'da ketdi, skrinshotda ko'rindi, chatga tashlab yuborildi. Bu vaziyatda ketma-ketlik oldindan ma'lum bo'lishi kerak, chunki o'ylab o'tirishga vaqt yo'q:
- Avval almashtiring, keyin tozalang. Birinchi harakat — sirni bekor
qilish: bot tokenini @BotFather'da
/revoke, API kalitni provayder panelida yangilash, parolni almashtirish. Repo'ni tozalash ikkinchi o'rinda — chunki sizdan oldin allaqachon nusxa olishgan deb hisoblang; - Yangi sirni joylang — serverdagi
.env, GitHub Secrets; - Tarixni tozalang — lekin illyuziyasiz.
git'da o'chirish — o'chirish emas
Keyingi commit'da sirni olib tashlash uni yashirmaydi: u tarixda, har
klonda, har fork'da qolgan. Tarixni git filter-repo yoki BFG bilan
qayta yozish mumkin, lekin bu ham faqat sizning repoingizni tozalaydi —
allaqachon tortib olingan nusxalarni emas. Shuning uchun tartib qat'iy:
sizib chiqqan sir — o'lgan sir, uni tozalash emas, almashtirish
qutqaradi.
Commit'dan oldingi himoya#
Eng yaxshi sizish — bo'lmagan sizish. Bir nechta bepul qatlamni yoqib qo'ying.
Birinchi qatlam — gitleaks. U fayllar va commit'lardan sir naqshlarini
qidiradi. O'rnatish: macOS'da brew install gitleaks, Linux va Windows uchun
tayyor fayl releases sahifasida.
# butun Git tarixini bir marta tekshirib chiqish
gitleaks git --redact .
--redact topilgan sirni ekranga chiqarmaydi — aks holda tekshiruvning o'zi
sirni terminal oynasida va CI loglarida ochiq ko'rsatib qo'yadi.
Qo'lda eslab yurmaslik uchun uni commit'dan oldin avtomatik ishlaydigan qilib
qo'yamiz. Loyiha papkasida .git/hooks/pre-commit faylini yarating:
#!/bin/sh
# faqat commit'ga tayyorlangan (staged) o'zgarishlarni tekshiradi
gitleaks git --pre-commit --staged --redact --no-banner .
chmod +x .git/hooks/pre-commit
Endi sir topilsa, gitleaks leaks found: 1 deb yozadi va commit
yaratilmaydi. Bu fayl .git ichida yotgani uchun repo bilan birga
tarqalmaydi — har bir kompyuterda alohida qo'yiladi.
Skaner — xavfsizlik to'ri, qoida emas
Gitleaks sirni naqsh va kalit so'z bo'yicha taniydi. Gitleaks 8.30
bilan tekshirilganda TELEGRAM_BOT_TOKEN = "..." va GitHub'ning ghp_... tokeni ushlandi,
lekin xuddi shu Telegram tokeni BOT_TOKEN = "..." nomi bilan yozilganda
ham, Django'ning SECRET_KEY qiymati ham o'tib ketdi. Shuning uchun
asosiy himoya — yuqoridagi qoida: sir kodga umuman yozilmaydi.
Ikkinchi qatlam — CI. Hook'ni o'rnatishni unutgan kompyuterdan kelgan
push'ni CI/CD qismidagi checks job'i
ushlaydi. Unga gitleaks qadamini qo'shamiz; butun tarixni ko'rishi uchun
checkout'ga fetch-depth: 0 kerak:
- uses: actions/checkout@v7
with:
fetch-depth: 0 # faqat oxirgi commit emas, butun tarix
- uses: gitleaks/gitleaks-action@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Shaxsiy akkauntdagi repo uchun shu yetarli. Repo tashkilot (organization)
akkauntiga tegishli bo'lsa, gitleaks sayti bepul beradigan GITLEAKS_LICENSE
kalitini ham Secrets'ga qo'shish kerak.
Uchinchi qatlam — GitHub push protection. Repo sahifasida Settings → Advanced Security → Push protection ni yoqing: GitHub tanigan naqshdagi sir push qilinsa, uni qabul qilmay qaytaradi. Ochiq repolarda bepul, yoqmaslikka sabab yo'q.
Nima .env'da, nima unda emas#
Oxirida bitta chegara masalasi. Hamma narsani ham sir deb yurmang — aksincha, konfiguratsiya bilan sirni ajratish tartib beradi:
| .env'da (sir) | Kodda/repo'da (konfiguratsiya) |
|---|---|
| SECRET_KEY, tokenlar, parollar | Port raqamlari, timeout'lar |
| Baza ulanish satri (paroli bilan) | ALLOWED_HOSTS ro'yxati |
| Tashqi API kalitlari | Kesh muddatlari, sahifa o'lchamlari |
Sir bo'lmagan narsani .envga olib o'tish teskari muammo tug'diradi:
konfiguratsiya ko'zdan yo'qoladi, muhitlar orasidagi farq esa hujjatsiz
qoladi.
Seriya yakuni#
To'qqiz qismlik yo'l shu yerda tugaydi. Yalang'och VPS'dan boshlagan edik — endi qo'lingizda to'liq tizim bor: SSH kalitli kirish va firewall, systemd ostidagi xizmatlar, nginx va TLS, timer'li zaxira, reboot'ga chidamlilik, o'zi deploy bo'ladigan pipeline, o'qiladigan loglar va joyida turgan sirlar. Bularning har biri alohida mayda ko'rinadi, birga esa "kechasi xotirjam uxlaydigan server" degan natijani beradi.
Savollar bo'lsa — bog'laning, qaysidir qadam o'z serveringizda boshqacha chiqqan bo'lsa, yozing: seriya jonli, real savollar asosida to'ldirilib boradi.