Initial commit: interview prep repo (resume, legend, stack cases, Kubernetes course)

This commit is contained in:
Tot Maxim
2026-07-18 00:37:41 +03:00
commit 9bb7f6263f
47 changed files with 3548 additions and 0 deletions

67
stack/vault/CASE.md Normal file
View File

@@ -0,0 +1,67 @@
# Кейс: HashiCorp Vault (dev-режим + интеграция с CI)
Связь с легендой: [../../legend/LEGEND.md](../../legend/LEGEND.md) — раздел «Домашняя лаборатория / pet-проект». Vault спрашивали в Альфа-Банке («как работает Hashicorp Vault: как вкладываются секреты, синхронизация с CI/CD») — в рабочем стеке компаний из резюме секреты хранятся через `ansible-vault` (см. [../ansible/QUESTIONS.md](../ansible/QUESTIONS.md)), Vault — отдельный честный pet-кейс поверх этого опыта.
## Что нужно реально сделать (домашний стенд)
Vault в dev-режиме (single binary, in-memory storage — не для прода, но для понимания механики более чем достаточно), положить секрет через KV-движок, прочитать его через CLI и через HTTP API, завести простую политику доступа, и на уровне паттерна разобрать, как секрет из Vault попадает в CI/CD-пайплайн.
### 1. Запуск
```bash
docker run --cap-add=IPC_LOCK -d --name vault-lab \
-p 8200:8200 \
-e 'VAULT_DEV_ROOT_TOKEN_ID=lab-root-token' \
hashicorp/vault server -dev
```
Dev-режим сразу распечатан (unsealed), с готовым root-токеном — специально упрощённый режим для локальной практики, в проде Vault разворачивается с реальным storage backend (Consul/Raft) и требует ручного unseal через Shamir's Secret Sharing (несколько ключей, из которых нужен кворум для распечатывания).
### 2. Положить и прочитать секрет через KV
```bash
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='lab-root-token'
vault kv put secret/ci/db-credentials username=labuser password=labpass
vault kv get secret/ci/db-credentials
vault kv get -field=password secret/ci/db-credentials
```
### 3. То же самое через HTTP API (то, что реально дёргает CI-раннер)
```bash
curl -s -H "X-Vault-Token: lab-root-token" \
http://127.0.0.1:8200/v1/secret/data/ci/db-credentials | jq .data.data
```
### 4. Политика доступа (принцип наименьших привилегий)
```hcl
# ci-readonly-policy.hcl
path "secret/data/ci/*" {
capabilities = ["read"]
}
```
```bash
vault policy write ci-readonly ci-readonly-policy.hcl
vault token create -policy="ci-readonly" -ttl=1h
```
Полученным ограниченным токеном (не root) повторить `vault kv get` — сработает (есть право read); попробовать `vault kv put` этим же токеном — должно быть отказано (Permission denied), так как в политике только `read`. Это ядро модели Vault: не «все или ничего», а точечные политики на конкретные пути.
### 5. Паттерн интеграции с CI/CD (концептуально, без реального раннера)
Типичная схема: CI-раннер (GitLab CI/TeamCity) на старте job аутентифицируется в Vault не статическим токеном в переменных окружения, а через auth-метод (например, AppRole или JWT/OIDC-аутентификация от самого CI, если поддерживается) — получает короткоживущий токен с ограниченной политикой → читает нужные секреты через API → использует их в рамках job → токен истекает сам по TTL. Ключевое отличие от простого хранения секрета в CI-переменных: секрет не лежит статично в конфигурации пайплайна, доступ временный и аудируемый (Vault логирует каждое обращение).
## Что это даёт в разговоре с интервьюером
- Практическое понимание KV secrets engine — как секрет реально «вкладывается» и читается, а не абстрактно.
- Понимание политик доступа Vault (HCL, path-based capabilities) на реальном примере — не просто «там есть права», а конкретный сценарий read-only токена.
- Понимание разницы между dev-режимом (для лабы) и продовым Vault (unseal, storage backend, HA) — честная граница того, что реально прогнано.
- Осмысленное представление о паттерне интеграции с CI/CD через short-lived токены, а не статичные секреты в переменных.
## Как это ложится в легенду
Vault — pet-кейс, не приписанный к опыту в компаниях. В резюме и легенде реальный опыт хранения секретов зафиксирован через `ansible-vault` в АО ТНИИС; Vault добавляется отдельно как самостоятельно проработанная технология в навыках, без утверждения, что она использовалась на рабочем месте.

19
stack/vault/QUESTIONS.md Normal file
View File

@@ -0,0 +1,19 @@
# Вопросы: HashiCorp Vault
Опираются на кейс: [CASE.md](CASE.md). Источник — [Alfa-Bank.md](../../interview/Alfa-Bank.md).
### Как работает Hashicorp Vault: как вкладываются секреты?
Секреты хранятся через secrets engine — самый базовый и распространённый вариант KV (key-value): секрет кладётся по конкретному пути (`vault kv put secret/ci/db-credentials username=... password=...`) и читается тем же путём (`vault kv get`). Под капотом Vault шифрует данные перед записью в storage backend (в моей лабе — in-memory dev-режим, в проде обычно Raft или Consul) собственным мастер-ключом, который в продовом режиме получается через unseal-процесс (Shamir's Secret Sharing — несколько частей ключа, кворум которых нужен, чтобы распечатать хранилище после старта). Помимо статичного KV есть и динамические secrets engines (например, для БД) — Vault может сам генерировать короткоживущие учётные данные на лету, но этого я на своей лабе не поднимал, только статичный KV.
### Как наполняется файл секрета?
Секрет не «файл» в файловой системе в привычном смысле — это запись в хранилище Vault по определённому пути, доступ к которой идёт через CLI (`vault kv put/get`) или HTTP API. Если приложению/пайплайну нужен именно файл (например, `.env` или конфиг с паролем), это обычно результат отдельного шага: агент/раннер запрашивает секрет через API и материализует его во временный файл на своей стороне непосредственно перед использованием, не храня его в репозитории или в постоянном хранилище.
### Как идёт синхронизация с CI/CD?
CI-раннер аутентифицируется в Vault (в идеале — не статичным root-токеном, а через auth-метод вроде AppRole или через встроенную OIDC/JWT-аутентификацию от самой CI-системы, если она поддерживается), получает короткоживущий токен с ограниченной политикой доступа, читает нужные секреты через API в рамках выполнения job, и токен истекает сам по TTL после использования. Я на своей лабе прогнал часть этой схемы вручную: завёл политику `ci-readonly` с правом только `read` на путь `secret/data/ci/*`, выписал по ней ограниченный токен и убедился, что им можно читать секрет, но нельзя его перезаписать (`vault kv put` тем же токеном отдаёт Permission denied) — сам CI-раннер (GitLab CI/TeamCity) я в эту схему не встраивал, это на уровне понимания паттерна.
### Чем это отличается от того, что секрет просто лежит в переменных CI?
Секрет в переменных CI-системы статичен: один раз задан — лежит вечно, доступен всем job без разбора, изменения/ротация требуют ручного вмешательства, и нет отдельного лога, кто и когда именно его читал. Vault даёт: точечные политики доступа (кто и к какому пути может обращаться), короткоживущие токены вместо постоянных секретов, аудит-лог обращений, и возможность динамически генерировать секреты вместо хранения статичных значений.