-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbootstrap_env.sh
More file actions
executable file
·142 lines (129 loc) · 5.64 KB
/
Copy pathbootstrap_env.sh
File metadata and controls
executable file
·142 lines (129 loc) · 5.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/env bash
#
# Gera a configuração local do SinalACS: `.env` e o `passwords.yaml` do
# Serverpod, ambos com segredos aleatórios desta máquina.
#
# ./scripts/dev/bootstrap_env.sh # cria o que faltar, preserva o resto
# ./scripts/dev/bootstrap_env.sh --force # recria, sobrescrevendo
#
# Por que existe:
# · o repositório não traz `.env` nenhum, e o docker-compose.yml agora exige
# um — cada segredo é `${VAR:?}`, então subir sem ele falha dizendo o que
# falta, em vez de usar uma senha embutida no arquivo versionado;
# · `backend/sinalacs_server/config/passwords.yaml` é gitignored e portanto
# NÃO existe num clone limpo. Sem ele o Serverpod falha ao carregar a
# config e chama exit(1); como o exit() do Dart não dá flush no stdout, a
# mensagem se perde e a suíte de testes morre com exit 1 e zero linhas de
# log. Era preciso recriar o arquivo à mão para rodar os testes.
#
# Nenhum valor gerado é impresso.
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
cd "$repo_root"
env_file="$repo_root/.env"
env_example="$repo_root/.env.example"
passwords_file="$repo_root/backend/sinalacs_server/config/passwords.yaml"
force=0
for arg in "$@"; do
case "$arg" in
--force) force=1 ;;
-h|--help) sed -n '2,20p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'; exit 0 ;;
*) echo "argumento desconhecido: $arg" >&2; exit 2 ;;
esac
done
if ! command -v openssl >/dev/null 2>&1; then
echo 'erro: openssl não encontrado — é ele que gera os segredos.' >&2
exit 1
fi
secret() { openssl rand -hex 32; }
# --- .env ------------------------------------------------------------------
if [[ -f "$env_file" && "$force" -eq 0 ]]; then
echo ".env já existe — preservado. Use --force para recriar."
else
if [[ ! -f "$env_example" ]]; then
echo "erro: $env_example não existe." >&2
exit 1
fi
if [[ -f "$env_file" ]]; then
backup="$env_file.bak.$(date +%Y%m%d%H%M%S)"
cp "$env_file" "$backup"
chmod 600 "$backup"
echo " .env anterior salvo em $(basename "$backup")"
fi
# Preenche cada chave de segredo vazia do modelo; o resto passa intacto,
# para que comentários e defaults não-secretos continuem valendo.
POSTGRES_PASSWORD="$(secret)" \
TEST_DATABASE_PASSWORD="$(secret)" \
MQTT_BACKEND_PASSWORD="$(secret)" \
MQTT_ACS_PASSWORD="$(secret)" \
JWT_SECRET="$(secret)" \
AUDIT_CHAIN_SECRET="$(secret)" \
HEALTH_DATA_ENCRYPTION_KEY="$(secret)" \
CPF_HASH_PEPPER="$(secret)" \
DEV_ACS_PASSWORD="$(secret)" \
awk '
{
split($0, kv, "=")
key = kv[1]
# Só mexe em linha "CHAVE=" sem valor, e só nas chaves de segredo.
if ($0 ~ /^[A-Z_]+=$/ && ENVIRON[key] != "") {
print key "=" ENVIRON[key]
} else {
print
}
}
' "$env_example" > "$env_file"
chmod 600 "$env_file"
echo " .env gerado (POSTGRES_PASSWORD, TEST_DATABASE_PASSWORD,"
echo " MQTT_BACKEND_PASSWORD, MQTT_ACS_PASSWORD, JWT_SECRET,"
echo " AUDIT_CHAIN_SECRET, HEALTH_DATA_ENCRYPTION_KEY,"
echo " CPF_HASH_PEPPER, DEV_ACS_PASSWORD)"
fi
# --- config/passwords.yaml -------------------------------------------------
# O valor PRECISA ser o mesmo TEST_DATABASE_PASSWORD do .env: é a senha do
# Postgres de teste (profile `test`, porta 9090) que o harness do Serverpod
# espera segundo config/test.yaml. Divergir traz de volta a falha silenciosa.
test_password="$(grep -E '^TEST_DATABASE_PASSWORD=' "$env_file" | head -1 | cut -d= -f2-)"
if [[ -z "$test_password" ]]; then
echo 'erro: TEST_DATABASE_PASSWORD está vazio no .env.' >&2
exit 1
fi
if [[ -f "$passwords_file" && "$force" -eq 0 ]]; then
echo "config/passwords.yaml já existe — preservado. Use --force para recriar."
stored="$(awk '/^test:/{f=1;next} /^[a-z]+:/{f=0} f && /database:/{print $2}' "$passwords_file" | tr -d "'\"")"
if [[ "$stored" != "$test_password" ]]; then
echo ' AVISO: a senha em passwords.yaml[test] NÃO bate com TEST_DATABASE_PASSWORD do .env.' >&2
echo ' O harness de teste vai falhar sem log. Rode com --force para alinhar.' >&2
fi
else
mkdir -p "$(dirname "$passwords_file")"
cat > "$passwords_file" <<YAML
# Gerado por scripts/dev/bootstrap_env.sh. Não versionado (.gitignore).
#
# A senha de `test` é a mesma do TEST_DATABASE_PASSWORD do .env, que alimenta o
# serviço postgres-test do docker-compose. Se as duas divergirem, o Serverpod
# falha ao carregar a config e a suíte morre sem log.
test:
database: '$test_password'
YAML
chmod 600 "$passwords_file"
echo " config/passwords.yaml gerado (bloco test:, alinhado com o .env)"
fi
# --- avisos ----------------------------------------------------------------
if [[ -d "$repo_root/pg_data" ]]; then
echo
echo 'AVISO: ./pg_data/ já existe de uma stack anterior.'
echo ' POSTGRES_PASSWORD só vale na PRIMEIRA inicialização do volume, então o'
echo ' banco continuará exigindo a senha antiga e o backend não vai conectar.'
echo ' Para adotar a senha nova: docker compose down && rm -rf pg_data/'
echo
echo ' HEALTH_DATA_ENCRYPTION_KEY é diferente: a chave nova NÃO impede o Postgres'
echo ' nem o backend de subir, mas torna ILEGÍVEL qualquer dado clínico já cifrado'
echo ' com a chave anterior (patients.chronicConditions, triage_sessions.answers,'
echo ' visits.notes) — falha silenciosa na leitura, não um erro de boot.'
echo ' Para adotar a chave nova sem perder dados legíveis, restaure a chave antiga'
echo ' no .env; para começar do zero, a mesma limpeza acima resolve os dois:'
echo ' docker compose down && rm -rf pg_data/'
fi
echo
echo 'Pronto. Próximo passo: docker compose up --build'