Перенесены секреты из .env в SM
This commit is contained in:
@@ -1,10 +1,22 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
cd "$(dirname "$0")/../.."
|
||||
CONFIG_FILE=${CONFIG_FILE:-.env}
|
||||
SECRETS_LAUNCHER=${SECRETS_LAUNCHER:-deployment/secrets/han-secrets}
|
||||
|
||||
if [ -z "${PG_BACKUP_DSN:-}" ]; then
|
||||
echo "PG_BACKUP_DSN is required (managed PostgreSQL TLS DSN, supplied via secure environment)." >&2
|
||||
if [ "${HAN_SECRETS_ACTIVE:-0}" != "1" ]; then
|
||||
[ -x "$SECRETS_LAUNCHER" ] || {
|
||||
echo "Secret launcher is required: $SECRETS_LAUNCHER" >&2
|
||||
exit 66
|
||||
}
|
||||
exec "$SECRETS_LAUNCHER" run --config "$CONFIG_FILE" -- "$0" "$@"
|
||||
fi
|
||||
|
||||
if [ -z "${PG_BACKUP_DSN_FILE:-}" ] || [ ! -r "$PG_BACKUP_DSN_FILE" ]; then
|
||||
echo "PG_BACKUP_DSN_FILE is required from the secret launcher." >&2
|
||||
exit 64
|
||||
fi
|
||||
PG_BACKUP_DSN=$(cat "$PG_BACKUP_DSN_FILE")
|
||||
case "$PG_BACKUP_DSN" in
|
||||
*sslmode=verify-full*sslrootcert=*) ;;
|
||||
*) echo "PG_BACKUP_DSN must enforce sslmode=verify-full and sslrootcert." >&2; exit 64 ;;
|
||||
@@ -16,7 +28,9 @@ mkdir -p "$output_dir"
|
||||
stamp=$(date -u +%Y%m%dT%H%M%SZ)
|
||||
archive="$output_dir/han-chat-$stamp.dump"
|
||||
|
||||
pg_dump --dbname="$PG_BACKUP_DSN" --format=custom --no-owner --no-privileges --file="$archive"
|
||||
PGDATABASE="$PG_BACKUP_DSN" pg_dump \
|
||||
--format=custom --no-owner --no-privileges --file="$archive"
|
||||
unset PG_BACKUP_DSN
|
||||
pg_restore --list "$archive" >/dev/null
|
||||
sha256sum "$archive" > "$archive.sha256"
|
||||
chmod 600 "$archive" "$archive.sha256"
|
||||
|
||||
@@ -1,20 +1,34 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
cd "$(dirname "$0")/../.."
|
||||
CONFIG_FILE=${CONFIG_FILE:-.env}
|
||||
SECRETS_LAUNCHER=${SECRETS_LAUNCHER:-deployment/secrets/han-secrets}
|
||||
|
||||
if [ "${HAN_SECRETS_ACTIVE:-0}" != "1" ]; then
|
||||
[ -x "$SECRETS_LAUNCHER" ] || {
|
||||
echo "Secret launcher is required: $SECRETS_LAUNCHER" >&2
|
||||
exit 66
|
||||
}
|
||||
exec "$SECRETS_LAUNCHER" run --config "$CONFIG_FILE" -- "$0" "$@"
|
||||
fi
|
||||
|
||||
if [ "${PITR_MARKER_CONFIRMED:-false}" != "true" ]; then
|
||||
echo "Refusing migration: create provider PITR marker, then set PITR_MARKER_CONFIRMED=true" >&2
|
||||
exit 64
|
||||
fi
|
||||
|
||||
./scripts/validate-env "${ENV_FILE:-.env}"
|
||||
docker compose --env-file "${ENV_FILE:-.env}" config --quiet
|
||||
docker compose --env-file "${ENV_FILE:-.env}" --profile ops run --rm migrate-api alembic current
|
||||
docker compose --env-file "${ENV_FILE:-.env}" --profile ops run --rm migrate-bitrix-local alembic current
|
||||
docker compose --env-file "${ENV_FILE:-.env}" --profile ops run --rm migrate-bitrix-sync alembic current
|
||||
docker compose --env-file "${ENV_FILE:-.env}" --profile ops run --rm migrate-sms alembic current
|
||||
docker compose --env-file "${ENV_FILE:-.env}" --profile ops run --rm migrate-api
|
||||
docker compose --env-file "${ENV_FILE:-.env}" --profile ops run --rm migrate-bitrix-local
|
||||
docker compose --env-file "${ENV_FILE:-.env}" --profile ops run --rm migrate-bitrix-sync
|
||||
docker compose --env-file "${ENV_FILE:-.env}" --profile ops run --rm migrate-sms
|
||||
if [ -n "${HAN_RUNTIME_SECRET_MANIFEST:-}" ]; then
|
||||
./scripts/validate-env "$CONFIG_FILE" --runtime-manifest "$HAN_RUNTIME_SECRET_MANIFEST"
|
||||
else
|
||||
./scripts/validate-env "$CONFIG_FILE" --runtime-env
|
||||
fi
|
||||
docker compose --env-file "$CONFIG_FILE" config --quiet
|
||||
docker compose --env-file "$CONFIG_FILE" --profile ops run --rm migrate-api alembic current
|
||||
docker compose --env-file "$CONFIG_FILE" --profile ops run --rm migrate-bitrix-local alembic current
|
||||
docker compose --env-file "$CONFIG_FILE" --profile ops run --rm migrate-bitrix-sync alembic current
|
||||
docker compose --env-file "$CONFIG_FILE" --profile ops run --rm migrate-sms alembic current
|
||||
docker compose --env-file "$CONFIG_FILE" --profile ops run --rm migrate-api
|
||||
docker compose --env-file "$CONFIG_FILE" --profile ops run --rm migrate-bitrix-local
|
||||
docker compose --env-file "$CONFIG_FILE" --profile ops run --rm migrate-bitrix-sync
|
||||
docker compose --env-file "$CONFIG_FILE" --profile ops run --rm migrate-sms
|
||||
echo "Migrations completed; record revisions in release evidence."
|
||||
|
||||
@@ -1,21 +1,34 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
cd "$(dirname "$0")/../.."
|
||||
CONFIG_FILE=${CONFIG_FILE:-.env}
|
||||
SECRETS_LAUNCHER=${SECRETS_LAUNCHER:-deployment/secrets/han-secrets}
|
||||
|
||||
previous_env=${1:-}
|
||||
if [ -z "$previous_env" ] || [ ! -r "$previous_env" ]; then
|
||||
echo "Usage: $0 /secure/path/previous-release.env" >&2
|
||||
previous_release=${1:-}
|
||||
if [ -z "$previous_release" ]; then
|
||||
echo "Usage: $0 <previous-immutable-release>" >&2
|
||||
exit 64
|
||||
fi
|
||||
if [ "${HAN_SECRETS_ACTIVE:-0}" != "1" ]; then
|
||||
[ -x "$SECRETS_LAUNCHER" ] || {
|
||||
echo "Secret launcher is required: $SECRETS_LAUNCHER" >&2
|
||||
exit 66
|
||||
}
|
||||
exec "$SECRETS_LAUNCHER" run --config "$CONFIG_FILE" -- "$0" "$@"
|
||||
fi
|
||||
if [ "${SCHEMA_BACKWARD_COMPATIBLE_CONFIRMED:-false}" != "true" ]; then
|
||||
echo "Refusing rollback: set SCHEMA_BACKWARD_COMPATIBLE_CONFIRMED=true after migration review." >&2
|
||||
exit 64
|
||||
fi
|
||||
|
||||
./scripts/validate-env "$previous_env"
|
||||
docker compose --env-file "$previous_env" config --quiet
|
||||
docker compose --env-file "$previous_env" up -d --remove-orphans
|
||||
docker compose --env-file "$previous_env" ps
|
||||
if [ -n "${HAN_RUNTIME_SECRET_MANIFEST:-}" ]; then
|
||||
./scripts/validate-env "$CONFIG_FILE" --runtime-manifest "$HAN_RUNTIME_SECRET_MANIFEST"
|
||||
else
|
||||
./scripts/validate-env "$CONFIG_FILE" --runtime-env
|
||||
fi
|
||||
RELEASE_VERSION="$previous_release" docker compose --env-file "$CONFIG_FILE" config --quiet
|
||||
RELEASE_VERSION="$previous_release" docker compose --env-file "$CONFIG_FILE" up -d --remove-orphans
|
||||
docker compose --env-file "$CONFIG_FILE" ps
|
||||
|
||||
echo "Application images rolled back without Alembic downgrade."
|
||||
echo "Run deployment/scripts/smoke.sh with ENV_FILE=$previous_env and verify outbox/inbox idempotency."
|
||||
echo "Run deployment/scripts/smoke.sh and verify outbox/inbox idempotency."
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
cd "$(dirname "$0")/../.."
|
||||
CONFIG_FILE=${ENV_FILE:-.env}
|
||||
SECRETS_LAUNCHER=${SECRETS_LAUNCHER:-deployment/secrets/han-secrets}
|
||||
|
||||
./scripts/validate-env "${ENV_FILE:-.env}"
|
||||
docker compose --env-file "${ENV_FILE:-.env}" --profile ops run --rm seed-settings
|
||||
if [ "${HAN_SECRETS_ACTIVE:-0}" != "1" ]; then
|
||||
[ -x "$SECRETS_LAUNCHER" ] || {
|
||||
echo "Secret launcher is required: $SECRETS_LAUNCHER" >&2
|
||||
exit 66
|
||||
}
|
||||
exec "$SECRETS_LAUNCHER" run --config "$CONFIG_FILE" -- "$0" "$@"
|
||||
fi
|
||||
|
||||
./scripts/validate-env "$CONFIG_FILE" \
|
||||
--runtime-manifest "$HAN_RUNTIME_SECRET_MANIFEST"
|
||||
docker compose --env-file "$CONFIG_FILE" --profile ops run --rm seed-settings
|
||||
echo "Seed and mandatory-settings validation completed."
|
||||
|
||||
@@ -435,6 +435,46 @@ configure_application_security() {
|
||||
fi
|
||||
}
|
||||
|
||||
install_secret_loader_if_possible() {
|
||||
step "Загрузчик секретов"
|
||||
local source_dir="${DEPLOY_DIR}/deployment/secrets"
|
||||
if [[ ! -f "${source_dir}/secrets_loader.py" || ! -f "${source_dir}/han-secrets" ]]; then
|
||||
log "Проект еще не скопирован: загрузчик секретов будет установлен при повторном запуске"
|
||||
return
|
||||
fi
|
||||
chmod 0750 "${source_dir}/han-secrets" "${source_dir}/han-compose"
|
||||
|
||||
install -d -m 0700 -o root -g root \
|
||||
/etc/han \
|
||||
/etc/han/secrets \
|
||||
/etc/han/credentials
|
||||
install -d -m 0755 -o root -g root \
|
||||
/usr/local/lib/han-secrets \
|
||||
/usr/local/share/doc/han-secrets
|
||||
install -m 0750 -o root -g root \
|
||||
"${source_dir}/secrets_loader.py" \
|
||||
/usr/local/lib/han-secrets/secrets_loader.py
|
||||
install -m 0750 -o root -g root \
|
||||
"${source_dir}/han-secrets" \
|
||||
/usr/local/lib/han-secrets/han-secrets
|
||||
install -m 0750 -o root -g root \
|
||||
"${source_dir}/han-compose" \
|
||||
/usr/local/bin/han-compose
|
||||
install -m 0644 -o root -g root \
|
||||
"${source_dir}/han-secrets@.service" \
|
||||
/etc/systemd/system/han-secrets@.service
|
||||
install -m 0644 -o root -g root \
|
||||
"${source_dir}/SELECTEL_RUNBOOK.ru.md" \
|
||||
/usr/local/share/doc/han-secrets/SELECTEL_RUNBOOK.ru.md
|
||||
if [[ ! -e /etc/han/secrets/production.selectel.json.example ]]; then
|
||||
install -m 0600 -o root -g root \
|
||||
"${source_dir}/config.example.json" \
|
||||
/etc/han/secrets/production.selectel.json.example
|
||||
fi
|
||||
systemctl daemon-reload
|
||||
log "Загрузчик установлен, но не включен: сначала выполните SELECTEL_RUNBOOK.ru.md"
|
||||
}
|
||||
|
||||
install_ssl_timer_if_possible() {
|
||||
step "Таймер продления TLS"
|
||||
local renew_script="${DEPLOY_DIR}/deployment/scripts/ssl-renew.sh"
|
||||
@@ -504,14 +544,18 @@ HSTS max-age: ${HSTS_MAX_AGE_SECONDS}
|
||||
${DEPLOY_DIR}
|
||||
3. Поместите CA PostgreSQL:
|
||||
${DEPLOY_DIR}/secrets/pg/ca.pem
|
||||
4. Создайте и заполните окружение:
|
||||
4. Создайте только несекретный config:
|
||||
cd ${DEPLOY_DIR}
|
||||
cp .env.example .env
|
||||
chmod 600 .env
|
||||
./scripts/validate-env .env
|
||||
5. Продолжите с Gate 7 в:
|
||||
5. Настройте Selectel, encrypted bootstrap credential и fallback map:
|
||||
deployment/secrets/SELECTEL_RUNBOOK.ru.md
|
||||
6. Выполняйте Compose только через:
|
||||
sudo deployment/secrets/han-compose <command>
|
||||
7. Продолжите с Gate 7 в:
|
||||
deployment/RUNBOOK.ru.md
|
||||
6. После копирования проекта повторно запустите этот скрипт для установки TLS-таймера.
|
||||
8. После копирования проекта повторно запустите этот скрипт для установки unit-файлов.
|
||||
|
||||
Важно: членство в группе docker начнет действовать после нового входа в систему.
|
||||
EOF
|
||||
@@ -538,6 +582,7 @@ main() {
|
||||
configure_docker_firewall
|
||||
configure_ssh
|
||||
configure_application_security
|
||||
install_secret_loader_if_possible
|
||||
install_ssl_timer_if_possible
|
||||
verify
|
||||
summary
|
||||
|
||||
@@ -2,11 +2,23 @@
|
||||
set -eu
|
||||
cd "$(dirname "$0")/../.."
|
||||
|
||||
ENV_FILE=${ENV_FILE:-.env}
|
||||
./scripts/validate-env "$ENV_FILE"
|
||||
CONFIG_FILE=${CONFIG_FILE:-.env}
|
||||
SECRETS_LAUNCHER=${SECRETS_LAUNCHER:-deployment/secrets/han-secrets}
|
||||
if [ "${HAN_SECRETS_ACTIVE:-0}" != "1" ]; then
|
||||
[ -x "$SECRETS_LAUNCHER" ] || {
|
||||
echo "Secret launcher is required: $SECRETS_LAUNCHER" >&2
|
||||
exit 66
|
||||
}
|
||||
exec "$SECRETS_LAUNCHER" run --config "$CONFIG_FILE" -- "$0" "$@"
|
||||
fi
|
||||
if [ -n "${HAN_RUNTIME_SECRET_MANIFEST:-}" ]; then
|
||||
./scripts/validate-env "$CONFIG_FILE" --runtime-manifest "$HAN_RUNTIME_SECRET_MANIFEST"
|
||||
else
|
||||
./scripts/validate-env "$CONFIG_FILE" --runtime-env
|
||||
fi
|
||||
|
||||
env_value() {
|
||||
python3 - "$ENV_FILE" "$1" <<'PY'
|
||||
python3 - "$CONFIG_FILE" "$1" <<'PY'
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
cd "$(dirname "$0")/../.."
|
||||
CONFIG_FILE=${CONFIG_FILE:-.env}
|
||||
SECRETS_LAUNCHER=${SECRETS_LAUNCHER:-deployment/secrets/han-secrets}
|
||||
|
||||
if [ "${HAN_SECRETS_ACTIVE:-0}" != "1" ]; then
|
||||
[ -x "$SECRETS_LAUNCHER" ] || {
|
||||
echo "Secret launcher is required: $SECRETS_LAUNCHER" >&2
|
||||
exit 66
|
||||
}
|
||||
exec "$SECRETS_LAUNCHER" run --config "$CONFIG_FILE" -- "$0" "$@"
|
||||
fi
|
||||
|
||||
lock=/tmp/han-chat-cert-renew.lock
|
||||
exec 9>"$lock"
|
||||
flock -n 9 || { echo '{"event":"tls.renew.skipped","reason":"lock_busy"}'; exit 0; }
|
||||
|
||||
compose() {
|
||||
docker compose --env-file .env "$@"
|
||||
docker compose --env-file "$CONFIG_FILE" "$@"
|
||||
}
|
||||
|
||||
nginx_container="$(compose ps --status running --quiet nginx)"
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
cd "$(dirname "$0")/../.."
|
||||
CONFIG_FILE="${CONFIG_FILE:-.env}"
|
||||
SECRETS_LAUNCHER="${SECRETS_LAUNCHER:-deployment/secrets/han-secrets}"
|
||||
|
||||
if [[ "${HAN_SECRETS_ACTIVE:-0}" != 1 ]]; then
|
||||
[[ -x "$SECRETS_LAUNCHER" ]] || {
|
||||
echo "Secret launcher is required: $SECRETS_LAUNCHER" >&2
|
||||
exit 66
|
||||
}
|
||||
exec "$SECRETS_LAUNCHER" run --config "$CONFIG_FILE" -- "$0" "$@"
|
||||
fi
|
||||
|
||||
compose() { docker compose --env-file "$CONFIG_FILE" "$@"; }
|
||||
|
||||
NETWORK="${OBSERVABILITY_NETWORK:-han-chat-observability}"
|
||||
COLLECTOR_SERVICE="${COLLECTOR_SERVICE:-otel-collector}"
|
||||
@@ -8,7 +21,7 @@ errors=0
|
||||
ok() { printf 'OK %s\n' "$*"; }
|
||||
fail() { printf 'FAIL %s\n' "$*" >&2; errors=$((errors + 1)); }
|
||||
|
||||
collector_id="$(docker compose ps -q "$COLLECTOR_SERVICE" 2>/dev/null || true)"
|
||||
collector_id="$(compose ps -q "$COLLECTOR_SERVICE" 2>/dev/null || true)"
|
||||
if [[ -n "$collector_id" ]] &&
|
||||
[[ "$(docker inspect --format '{{.State.Status}}' "$collector_id")" == running ]]; then
|
||||
ok "Collector service is running"
|
||||
@@ -17,7 +30,7 @@ else
|
||||
fi
|
||||
|
||||
for service in sms-service sms-worker; do
|
||||
if docker compose exec -T "$service" python - <<'PY' >/dev/null 2>&1
|
||||
if compose exec -T "$service" python - <<'PY' >/dev/null 2>&1
|
||||
import os
|
||||
import urllib.request
|
||||
port = os.environ.get("SMS_METRICS_PORT", "9464") if "worker" in os.environ.get("OTEL_SERVICE_NAME", "") else "8080"
|
||||
@@ -38,7 +51,7 @@ docker run --rm --network "$NETWORK" \
|
||||
|| fail "telemetrygen failed"
|
||||
|
||||
bad_logs="$(
|
||||
docker compose logs --since=10m "$COLLECTOR_SERVICE" 2>&1 |
|
||||
compose logs --since=10m "$COLLECTOR_SERVICE" 2>&1 |
|
||||
grep -Ei 'queue is full|connection refused|tls:|Unauthenticated|Permanent error' || true
|
||||
)"
|
||||
if [[ -z "$bad_logs" ]]; then
|
||||
|
||||
Reference in New Issue
Block a user