package infosecmodules

import (
	"rubric/utils"
)

var AuthnModule = Module{
	Key:         "authn",
	Aliases:     []string{"auth", "mfa", "jwt", "oauth"},
	Title:       "Аутентификация и авторизация",
	Description: "MFA, JWT, OAuth2, OIDC, RBAC, LDAP/AD, управление доступом",
	Run:         showAuthn,
}

func showAuthn() {
	utils.Header("InfoSec — Аутентификация и авторизация")

	utils.Section("Основные понятия")
	utils.Code(`Authentication (AuthN) — кто ты? Проверка идентичности.
Authorization  (AuthZ) — что тебе можно? Проверка прав.

Факторы аутентификации:
  Something you know  — пароль, PIN, секретный вопрос
  Something you have  — токен, телефон, смарт-карта
  Something you are   — биометрика (отпечаток, лицо)
  Somewhere you are   — геолокация, IP (дополнительный фактор)

MFA (Multi-Factor Authentication) — два и более фактора.
2FA — два фактора (подмножество MFA).

Типы MFA (от слабого к сильному):
  SMS OTP    — уязвим к SIM-swap, SS7 атакам
  TOTP       — RFC 6238, Google Authenticator (лучше SMS)
  HOTP       — счётчик, менее популярен
  Push Auth  — Duo, Microsoft Authenticator
  FIDO2/WebAuthn — аппаратные ключи, phishing-resistant (лучший вариант)`)

	utils.Section("Пароли и хранение")
	utils.Code(`Правила паролей (NIST SP 800-63B — актуальные рекомендации):
  - Минимальная длина: 8+ символов (лучше 12-14+)
  - НЕ требовать обязательную смену (только при компрометации)
  - НЕ требовать сложность (но и не запрещать)
  - Проверять по словарю скомпрометированных паролей
  - Разрешать пробелы и Unicode
  - Показывать пароль при вводе (опционально)
  - Поддерживать менеджеры паролей (не ограничивать длину)

Хранение паролей:
  ❌ Открытый текст
  ❌ Обратимое шифрование
  ❌ MD5 / SHA-1 без соли
  ✓  bcrypt (cost ≥ 12), Argon2id, scrypt

Проверка скомпрометированных паролей:
  Have I Been Pwned API — проверить hashed пароль
  k-Anonymity: отправить первые 5 символов хэша
  https://api.pwnedpasswords.com/range/{hash_prefix}

Account Lockout:
  Блокировать после N неудачных попыток (3-5)
  Экспоненциальная задержка между попытками
  Уведомлять пользователя о неудачных попытках`)

	utils.Section("TOTP — Time-based One-Time Password")
	utils.Code(`RFC 6238. Основан на HMAC-SHA1 + временном счётчике.

Как работает:
  1. Общий секрет (seed) обменивается один раз (QR-код)
  2. Counter = floor(UnixTime / 30)  # меняется каждые 30 сек
  3. OTP = HOTP(secret, counter) — 6-8 цифр
  4. Сервер проверяет OTP ± 1 временной шаг

Уязвимости:
  - Фишинг в реальном времени (attacker-in-the-middle)
  - Не защищает от SIM-swap (только SMS)
  - Потеря устройства = потеря доступа

# Python реализация:
import pyotp
secret = pyotp.random_base32()
totp = pyotp.TOTP(secret)
print(totp.now())           # текущий OTP
print(totp.verify("123456"))  # проверить

# Provisioning URI для QR-кода:
uri = totp.provisioning_uri("alice@example.com", issuer_name="MyApp")`)

	utils.Section("FIDO2 / WebAuthn — беспарольная аутентификация")
	utils.Code(`FIDO2 = WebAuthn (W3C) + CTAP (Client-to-Authenticator Protocol)
Phishing-resistant: ключ привязан к origin (домену).

Аутентификаторы:
  Platform    — встроенный в устройство (Touch ID, Windows Hello)
  Roaming     — внешний ключ (YubiKey, Titan Key)

Как работает:
  Регистрация:
    1. Сервер отправляет challenge
    2. Аутентификатор создаёт пару ключей для этого origin
    3. Публичный ключ сохраняется на сервере
    4. Приватный ключ НИКОГДА не покидает устройство

  Аутентификация:
    1. Сервер отправляет challenge
    2. Аутентификатор подписывает challenge приватным ключом
    3. Сервер верифицирует подпись публичным ключом

  Атака фишингом НЕВОЗМОЖНА: ключ не работает на evil.com

Паспорты (Passkeys):
  = FIDO2 ключи, синхронизируемые через облако (iCloud, Google, 1Password)
  Удобство ключей + синхронизация устройств`)

	utils.Section("JWT — JSON Web Token")
	utils.Code(`JWT — компактный токен для передачи claims между сторонами.
Используется для stateless аутентификации (API, микросервисы).

Структура: header.payload.signature
  
  # Header (base64url):
  {"alg": "HS256", "typ": "JWT"}
  
  # Payload (base64url):
  {
    "sub": "1234567890",     # subject (user ID)
    "name": "Alice Smith",
    "iat": 1516239022,       # issued at
    "exp": 1516242622,       # expiration
    "jti": "uuid",           # JWT ID (для revocation)
    "iss": "https://auth.example.com",  # issuer
    "aud": "https://api.example.com"    # audience
  }
  
  # Signature:
  HMAC-SHA256(base64(header) + "." + base64(payload), secret)

Типы алгоритмов:
  Симметричные (один ключ):
    HS256, HS384, HS512 — HMAC-SHA
  Асимметричные (ключевая пара):
    RS256 — RSA + SHA256 (рекомендуется для распределённых систем)
    ES256 — ECDSA + SHA256 (компактнее)
    EdDSA — Ed25519 (современный)

Уязвимости JWT:
  alg=none — КРИТИЧНО, проверяй алгоритм!
    Атака: изменить alg на "none", удалить подпись
  RS256→HS256 подмена
    Атака: использовать публичный RSA ключ как HMAC секрет
  Слабый секрет — поддаётся брутфорсу
  Отсутствие exp — токен не истекает
  Хранение в localStorage — доступен XSS атаке

Лучшие практики:
  - Короткий TTL (access token: 15 мин, refresh: 7 дней)
  - Использовать RS256 или ES256 (не HS256 в распределённых системах)
  - Хранить в HttpOnly cookie (не localStorage!)
  - Проверять iss, aud, exp
  - Реализовать token revocation (Redis blacklist или jti)`)

	utils.Section("OAuth2 и OpenID Connect")
	utils.Code(`OAuth2 — фреймворк делегированной авторизации (не аутентификации!).
OIDC (OpenID Connect) — слой аутентификации поверх OAuth2.

OAuth2 Roles:
  Resource Owner    — пользователь
  Client            — приложение (запрашивает доступ)
  Resource Server   — API с защищёнными данными
  Authorization Server — выдаёт токены

OAuth2 Grant Types (потоки):
  Authorization Code — для веб-приложений (РЕКОМЕНДУЕТСЯ)
    1. Redirect → Auth Server с code_challenge (PKCE)
    2. Пользователь авторизуется
    3. Redirect обратно с code
    4. Обмен code на tokens (server-side)
  
  Client Credentials — сервис-к-сервису (без пользователя)
  
  Device Authorization — умные устройства, CLI
  
  ❌ Implicit Flow — устаревший, уязвим (токен в URL)
  ❌ Resource Owner Password — только для доверенных приложений

PKCE (Proof Key for Code Exchange):
  Защита от перехвата authorization code.
  Обязателен для публичных клиентов (SPA, мобильные).
  code_verifier = random()
  code_challenge = base64url(sha256(code_verifier))

Токены OAuth2:
  Access Token  — краткоживущий, доступ к API
  Refresh Token — долгоживущий, получение нового access token
  ID Token      — OIDC, JWT с данными пользователя

OIDC Scopes:
  openid   — обязательный для OIDC, возвращает ID Token
  profile  — имя, аватар, locale
  email    — email и верификация
  address  — адрес
  phone    — телефон`)

	utils.Section("RBAC, ABAC и управление доступом")
	utils.Code(`DAC (Discretionary Access Control):
  Владелец решает кто имеет доступ (Linux chmod, ACL)

MAC (Mandatory Access Control):
  Системная политика (SELinux, AppArmor)

RBAC (Role-Based Access Control):
  Права назначаются ролям, роли — пользователям.
  Пример: admin, editor, viewer
  Kubernetes RBAC: Role → RoleBinding → ServiceAccount/User

ABAC (Attribute-Based Access Control):
  Решения на основе атрибутов (пользователь, ресурс, контекст)
  Пример: OPA (Open Policy Agent), AWS IAM

ReBAC (Relationship-Based Access Control):
  Права через отношения между объектами
  Пример: Google Zanzibar, SpiceDB, OpenFGA

Принцип наименьших привилегий:
  Давать только необходимые права
  Just-in-Time (JIT) доступ — временное повышение привилегий
  Privileged Access Management (PAM):
    CyberArk, HashiCorp Vault, AWS IAM Identity Center

# OPA — Open Policy Agent (пример Rego политики):
package authz

default allow = false

allow if {
    input.method == "GET"
    input.path == ["api", "public"]
}

allow if {
    input.user.role == "admin"
}`)

	utils.Section("LDAP и Active Directory")
	utils.Code(`LDAP (Lightweight Directory Access Protocol):
  Протокол доступа к каталогам (пользователи, группы, ресурсы).
  
Active Directory — Microsoft LDAP + Kerberos + DNS.

LDAP структура:
  DC=example,DC=com           — домен
  OU=Users                    — организационная единица
  CN=Alice Smith              — объект (пользователь)

Полный DN: CN=Alice Smith,OU=Users,DC=example,DC=com

# ldapsearch — поиск в LDAP:
ldapsearch -H ldap://dc.example.com \
  -D "CN=binduser,DC=example,DC=com" \
  -w password \
  -b "DC=example,DC=com" \
  "(sAMAccountName=alice)"

# Атаки на LDAP/AD:
Pass-the-Hash       — использование хэша NTLM без пароля
Pass-the-Ticket     — использование Kerberos билета
Kerberoasting       — получение хэшей service tickets
AS-REP Roasting     — атака на аккаунты без Kerberos preauth
DCSync              — имитация контроллера домена (миллионы хэшей)
LDAP Injection      — инъекция в LDAP-запросы

# Защита:
- Kerberos AES вместо NTLM/RC4
- Protected Users группа (не кэшировать credentials)
- Отключить NTLMv1, ограничить NTLMv2
- LAPS (Local Admin Password Solution)
- Tiered Administration Model`)

	utils.Section("Secrets Management")
	utils.Code(`НЕ хранить секреты в:
  ❌ Git / исходном коде
  ❌ Docker image / Dockerfile
  ❌ Environment variables (видны в /proc)
  ❌ Логах

Инструменты управления секретами:
  HashiCorp Vault — де-факто стандарт:
    Динамические секреты (генерация по запросу)
    Lease и автообновление
    Аудит всех обращений

  AWS Secrets Manager / Parameter Store
  GCP Secret Manager
  Azure Key Vault
  Kubernetes Secrets (base64, не зашифровано по умолчанию!)
    + Sealed Secrets (Bitnami) — зашифрованные секреты в Git
    + External Secrets Operator — синхронизация с Vault/AWS

# HashiCorp Vault — основные операции:
vault server -config=vault.hcl
vault operator init      # инициализация (ключи разуплотнения)
vault operator unseal    # разуплотнение
vault login

vault secrets enable kv-v2
vault kv put secret/myapp db_password=s3cret api_key=abc123
vault kv get secret/myapp
vault kv get -field=db_password secret/myapp

# Динамические секреты PostgreSQL:
vault secrets enable database
vault write database/config/mydb \
    plugin_name=postgresql-database-plugin \
    connection_url="postgresql://{{username}}:{{password}}@db:5432/mydb" \
    allowed_roles="my-role"
vault write database/roles/my-role \
    db_name=mydb \
    creation_statements="CREATE ROLE..." \
    default_ttl="1h" max_ttl="24h"

# Получить временные credentials:
vault read database/creds/my-role
# → username: v-root-xyz123, password: A1B2C3..., lease_duration: 1h`)

	utils.Footer()
}
