KEYCHAIN от терминала
Keychain Access GUI е само frontend. Реалната сила е в security командата — пълен CRUD на пароли, сертификати и ключове.
Как работи macOS Keychain
Keychain е encrypted database (SQLite + AES-256) в ~/Library/Keychains/. Има три вида items: generic passwords (app credentials), internet passwords (browser/URLs) и certificates/keys. security командата е официалният CLI за всичко.
# Намери internet password (браузър стил) $ security find-internet-password -s "github.com" -w # Намери generic password по service name $ security find-generic-password -s "MyApp" -w # Пълна информация за item-а (без паролата) $ security find-generic-password -s "MyApp"
# Добави generic password $ security add-generic-password \ -s "MyService" \ -a "myusername" \ -w "supersecretpassword" \ -T "" # -T "" = само текущия процес има достъп # Добави internet password $ security add-internet-password \ -s "api.example.com" \ -a "apiuser" \ -w "mytoken123" # Изтрий $ security delete-generic-password -s "MyService"
# Листни всички Keychain-и в системата $ security list-keychains # Dump всички items (без пароли) — за одит $ security dump-keychain | grep "svce\|acct\|srvr" # Провери кои apps имат достъп до конкретен item $ security dump-keychain -d | grep -A 5 "github" # Създай нов keychain (за CI/CD изолация) $ security create-keychain -p "keychainpassword" ci-build.keychain $ security unlock-keychain -p "keychainpassword" ci-build.keychain
SSH Config — отвъд basics
~/.ssh/config е най-подценяваният файл на sysadmin-а. Правилно настроен — спестява часове всяка седмица.
# ═══════════════════════════════════════ # ~/.ssh/config — Pro Setup # ═══════════════════════════════════════ # ── Глобални defaults за всички хостове Host * ServerAliveInterval 60 # keepalive всеки 60s ServerAliveCountMax 3 # 3 пъти, после disconnect AddKeysToAgent yes # автоматично в ssh-agent UseKeychain yes # macOS Keychain интеграция IdentityFile ~/.ssh/id_ed25519 Compression yes # компресия за бавни връзки ControlMaster auto # мултиплексиране — ControlPath ~/.ssh/cm_%r@%h:%p ControlPersist 10m # # пази конекцията 10 мин # ── Production сървър Host prod HostName 203.0.113.10 User deploy IdentityFile ~/.ssh/prod_ed25519 Port 2222 ForwardAgent no # НИКОГА на prod! # ── Dev сървър с jump host Host dev-internal HostName 10.0.0.50 User devuser ProxyJump bastion.example.com # ── Bastion / Jump сървър Host bastion.example.com User jumpuser IdentityFile ~/.ssh/bastion_ed25519 ForwardAgent yes # само на bastion е ОК # ── GitHub — без нужда от паролa Host github.com User git IdentityFile ~/.ssh/github_ed25519 IdentitiesOnly yes # само този ключ # ── Wildcard за цяла subnet Host 10.0.1.* User admin StrictHostKeyChecking no # за dev мрежи UserKnownHostsFile /dev/null
| Опция | Стойност | Защо е важна |
|---|---|---|
| UseKeychain | yes | SSH passphrase се пази в macOS Keychain — не я въвеждаш при всяка конекция |
| AddKeysToAgent | yes | Ключът се добавя в ssh-agent автоматично при първа употреба |
| ForwardAgent | no (prod) / yes (bastion) | Никога не forward-вай agent към production — компрометиран сървър може да го ползва |
| ProxyJump | bastion host | Замества ProxyCommand с по-прост синтаксис. SSH през jump host прозрачно. |
| IdentitiesOnly | yes | Без него ssh опитва всички ключове — може да trigger-не lockout при много опити |
| ControlPersist | 10m | Мултиплексирана конекция живее 10 минути след затваряне — последващите са instant |
# Ed25519 — съвременен, бърз, малък ключ (препоръчан) $ ssh-keygen -t ed25519 -C "work-laptop-2024" -f ~/.ssh/github_ed25519 # RSA 4096 ако сървърът не поддържа Ed25519 $ ssh-keygen -t rsa -b 4096 -C "legacy-server-key" # Провери fingerprint на ключ $ ssh-keygen -lf ~/.ssh/id_ed25519.pub 256 SHA256:abc123XYZ... work-laptop-2024 (ED25519) # Провери всички ключове в ssh-agent $ ssh-add -l # Добави ключ в macOS Keychain (запомня passphrase) $ ssh-add --apple-use-keychain ~/.ssh/id_ed25519 # Тествай конекция с verbose за дебъгване $ ssh -vvv git@github.com 2>&1 | grep "Offering\|Authenticated"
GPG — подписвай и криптирай
GPG на macOS с git commit подписване, файл криптиране и правилен agent setup. Изисква: brew install gnupg pinentry-mac
# Генерирай нов GPG ключ (интерактивно) $ gpg --full-generate-key # → Избери: RSA 4096 или Ed25519, 2-3 години валидност # Листни всички ключове $ gpg --list-keys --keyid-format LONG pub ed25519/3AA5C34371567BD2 2024-01-15 [SC] [expires: 2026-01-15] 4B2C4A1F5E8D9F2A1B3C4D5E6F7G8H9I0J1K2L3M uid [ultimate] Alex Admin <alex@example.com> sub cv25519/1B2C3D4E5F6G7H8I 2024-01-15 [E] # Листни private ключове $ gpg --list-secret-keys --keyid-format LONG # Експортирай публичен ключ $ gpg --armor --export alex@example.com | pbcopy # Fingerprint на ключ $ gpg --fingerprint alex@example.com
# Настрой git да ползва GPG ключа $ git config --global user.signingkey 3AA5C34371567BD2 $ git config --global commit.gpgsign true $ git config --global gpg.program gpg # Кажи на GPG agent да ползва правилния TTY $ echo 'export GPG_TTY=$(tty)' >> ~/.zshrc # Подпиши commit ръчно (ако нямаш auto-sign) $ git commit -S -m "feat: add authentication" # Провери подписа на commit $ git log --show-signature -1 gpg: Signature made Wed Jan 15 14:23:11 2024 gpg: Good signature from "Alex Admin <alex@example.com>" commit abc123def456...
# Криптирай файл за конкретен получател $ gpg --encrypt --recipient colleague@example.com --armor secrets.txt # → secrets.txt.asc # Криптирай само за себе си (backup на sensitive файлове) $ gpg --encrypt --recipient alex@example.com credentials.csv # Декриптирай $ gpg --decrypt secrets.txt.gpg > secrets.txt # Подпиши файл (доказва автентичност, не криптира) $ gpg --armor --detach-sign release-v1.0.tar.gz # → release-v1.0.tar.gz.asc # Верифицирай подпис $ gpg --verify release-v1.0.tar.gz.asc release-v1.0.tar.gz gpg: Good signature from "Alex Admin <alex@example.com>"
# ~/.gnupg/gpg-agent.conf pinentry-program /opt/homebrew/bin/pinentry-mac default-cache-ttl 3600 # кеширай passphrase 1 час max-cache-ttl 86400 # максимум 24 часа enable-ssh-support # GPG agent като SSH agent # Рестартирай agent след промяна на конфига $ gpgconf --kill gpg-agent $ gpg-agent --daemon # Провери дали agent работи $ gpgconf --list-dirs agent-socket
CERT инспекция
openssl и security командата за инспекция на TLS сертификати — remote и локално. Незаменими при debugging на HTTPS проблеми.
# Пълна cert информация за домейн $ echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \ | openssl x509 -noout -text # Само дата на изтичане $ echo | openssl s_client -connect example.com:443 2>/dev/null \ | openssl x509 -noout -dates notBefore=Jan 15 00:00:00 2024 GMT notAfter=Apr 15 23:59:59 2024 GMT # Subject Alternative Names (всички домейни в cert-а) $ echo | openssl s_client -connect example.com:443 2>/dev/null \ | openssl x509 -noout -ext subjectAltName # Дни до изтичане (за мониторинг) $ echo | openssl s_client -connect example.com:443 2>/dev/null \ | openssl x509 -noout -checkend 2592000 # 30 дни = 2592000 секунди Certificate will not expire # или: Certificate will expire # → alert!
# Пълна cert chain $ openssl s_client -connect example.com:443 -showcerts 2>/dev/null \ | grep "s:\|i:" s:CN = example.com i:CN = Let's Encrypt R3 s:CN = Let's Encrypt R3 i:CN = ISRG Root X1 # Тествай конкретна TLS версия $ openssl s_client -connect example.com:443 -tls1_2 2>&1 | grep "Protocol" $ openssl s_client -connect example.com:443 -tls1_3 2>&1 | grep "Protocol" # Провери cipher suite $ openssl s_client -connect example.com:443 2>/dev/null \ | grep "Cipher is" Cipher is TLS_AES_256_GCM_SHA384 # Инспектирай локален .pem / .crt файл $ openssl x509 -in certificate.pem -noout -text $ openssl x509 -in certificate.crt -noout -subject -issuer -dates
# Генерирай self-signed cert за localhost (10 години) $ openssl req -x509 -newkey rsa:4096 -keyout localhost.key \ -out localhost.crt -days 3650 -nodes \ -subj "/CN=localhost" \ -addext "subjectAltName=DNS:localhost,IP:127.0.0.1" # Добави в macOS Keychain и trust-вай $ security add-trusted-cert -d -r trustRoot \ -k /Library/Keychains/System.keychain localhost.crt # Провери дали е trusted $ security verify-cert -c localhost.crt -p ssl ...certificate verification successful.
Security ОДИТ
Бързи команди за проверка на security статуса на macOS системата.
# FileVault статус (disk encryption) $ fdesetup status FileVault is On. # SIP статус $ csrutil status System Integrity Protection status: enabled. # Firewall статус $ /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate Firewall is enabled. (State = 1) # Gatekeeper $ spctl --status assessments enabled # Провери всички sudoers $ cat /etc/sudoers $ ls -la /etc/sudoers.d/ # Потребители с admin права $ dscl . -read /Groups/admin GroupMembership GroupMembership: root alex # Намери SUID/SGID binaries (потенциален exploit вектор) $ sudo find / -perm -4000 -type f 2>/dev/null | head -20
# Launch Agents за текущия потребител $ ls -la ~/Library/LaunchAgents/ $ ls -la /Library/LaunchAgents/ $ ls -la /Library/LaunchDaemons/ # Всички заредени launch jobs $ launchctl list | grep -v "com.apple" # само third-party # Login items (Settings → General → Login Items) $ sfltool dumpbtm 2>/dev/null | grep "url\|name" # Намери persistence механизми (malware hunting) $ find ~/Library/LaunchAgents /Library/Launch{Agents,Daemons} \ -name "*.plist" -newer /tmp -ls 2>/dev/null
# Всички LISTEN портове с процес $ sudo lsof -iTCP -sTCP:LISTEN -n -P # Провери за outbound конекции към непознати IP-та $ netstat -an | grep ESTABLISHED | awk '{print $5}' \ | cut -d: -f1 | sort -u # Resolve IP-тата към домейни $ netstat -an | grep ESTABLISHED | awk '{print $5}' \ | cut -d: -f1 | sort -u \ | xargs -I{} sh -c 'echo -n "{} → "; host {} 2>/dev/null | grep "domain name" | head -1' # Провери /etc/hosts за манипулация $ cat /etc/hosts | grep -v "^#\|^$\|localhost\|broadcasthost"