raijin-server 0.2.3__py3-none-any.whl → 0.2.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- raijin_server/__init__.py +1 -1
- raijin_server/cli.py +77 -0
- raijin_server/healthchecks.py +61 -2
- raijin_server/modules/apokolips_demo.py +40 -4
- raijin_server/modules/cert_manager.py +950 -71
- raijin_server/modules/full_install.py +44 -1
- raijin_server/utils.py +79 -2
- {raijin_server-0.2.3.dist-info → raijin_server-0.2.5.dist-info}/METADATA +65 -1
- {raijin_server-0.2.3.dist-info → raijin_server-0.2.5.dist-info}/RECORD +13 -13
- {raijin_server-0.2.3.dist-info → raijin_server-0.2.5.dist-info}/WHEEL +0 -0
- {raijin_server-0.2.3.dist-info → raijin_server-0.2.5.dist-info}/entry_points.txt +0 -0
- {raijin_server-0.2.3.dist-info → raijin_server-0.2.5.dist-info}/licenses/LICENSE +0 -0
- {raijin_server-0.2.3.dist-info → raijin_server-0.2.5.dist-info}/top_level.txt +0 -0
|
@@ -25,6 +25,49 @@ from raijin_server.modules import (
|
|
|
25
25
|
)
|
|
26
26
|
|
|
27
27
|
|
|
28
|
+
def _cert_manager_install_only(ctx: ExecutionContext) -> None:
|
|
29
|
+
"""Wrapper para instalar cert-manager sem interação."""
|
|
30
|
+
if not cert_manager.install_only(ctx):
|
|
31
|
+
raise RuntimeError("Falha na instalação do cert-manager")
|
|
32
|
+
|
|
33
|
+
# Cria issuer HTTP01 padrão para staging (teste) e produção
|
|
34
|
+
# O usuário pode criar issuers adicionais depois com 'raijin-server cert install'
|
|
35
|
+
email = os.environ.get("RAIJIN_ACME_EMAIL", "")
|
|
36
|
+
if email and "@" in email:
|
|
37
|
+
typer.secho("\n📜 Criando ClusterIssuers padrão...", fg=typer.colors.CYAN)
|
|
38
|
+
|
|
39
|
+
# Cria issuer de staging (para testes)
|
|
40
|
+
cert_manager.create_issuer(
|
|
41
|
+
ctx,
|
|
42
|
+
name="letsencrypt-staging",
|
|
43
|
+
email=email,
|
|
44
|
+
challenge_type="http01",
|
|
45
|
+
staging=True,
|
|
46
|
+
ingress_class="traefik",
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Cria issuer de produção
|
|
50
|
+
cert_manager.create_issuer(
|
|
51
|
+
ctx,
|
|
52
|
+
name="letsencrypt-prod",
|
|
53
|
+
email=email,
|
|
54
|
+
challenge_type="http01",
|
|
55
|
+
staging=False,
|
|
56
|
+
ingress_class="traefik",
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
typer.secho("✓ ClusterIssuers 'letsencrypt-staging' e 'letsencrypt-prod' criados", fg=typer.colors.GREEN)
|
|
60
|
+
else:
|
|
61
|
+
typer.secho(
|
|
62
|
+
"ℹ Para criar ClusterIssuers automaticamente, defina RAIJIN_ACME_EMAIL",
|
|
63
|
+
fg=typer.colors.YELLOW,
|
|
64
|
+
)
|
|
65
|
+
typer.secho(
|
|
66
|
+
" Exemplo: export RAIJIN_ACME_EMAIL=admin@seudominio.com",
|
|
67
|
+
fg=typer.colors.YELLOW,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
28
71
|
# Ordem de execucao dos modulos para instalacao completa
|
|
29
72
|
# Modulos marcados com skip_env podem ser pulados via variavel de ambiente
|
|
30
73
|
INSTALL_SEQUENCE = [
|
|
@@ -36,7 +79,7 @@ INSTALL_SEQUENCE = [
|
|
|
36
79
|
("firewall", firewall.run, "Firewall UFW", None),
|
|
37
80
|
("kubernetes", kubernetes.run, "Cluster Kubernetes (kubeadm)", None),
|
|
38
81
|
("calico", calico.run, "CNI Calico + NetworkPolicy", None),
|
|
39
|
-
("cert_manager",
|
|
82
|
+
("cert_manager", _cert_manager_install_only, "cert-manager (instalacao base)", None),
|
|
40
83
|
("secrets", secrets.run, "Sealed-Secrets + External-Secrets", None),
|
|
41
84
|
("prometheus", prometheus.run, "Monitoramento Prometheus", None),
|
|
42
85
|
("grafana", grafana.run, "Dashboards Grafana", None),
|
raijin_server/utils.py
CHANGED
|
@@ -299,6 +299,62 @@ def helm_repo_update(ctx: ExecutionContext) -> None:
|
|
|
299
299
|
run_cmd(["helm", "repo", "update"], ctx)
|
|
300
300
|
|
|
301
301
|
|
|
302
|
+
def _get_helm_release_status(release: str, namespace: str) -> str:
|
|
303
|
+
"""Retorna status do release Helm (lowercased) ou string vazia se nao existir."""
|
|
304
|
+
try:
|
|
305
|
+
import json
|
|
306
|
+
result = subprocess.run(
|
|
307
|
+
["helm", "status", release, "-n", namespace, "-o", "json"],
|
|
308
|
+
capture_output=True,
|
|
309
|
+
text=True,
|
|
310
|
+
timeout=30,
|
|
311
|
+
)
|
|
312
|
+
if result.returncode != 0 or not result.stdout:
|
|
313
|
+
return ""
|
|
314
|
+
data = json.loads(result.stdout)
|
|
315
|
+
return str(data.get("info", {}).get("status", "")).lower()
|
|
316
|
+
except Exception:
|
|
317
|
+
return ""
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def _cleanup_pending_helm_release(release: str, namespace: str, ctx: ExecutionContext) -> None:
|
|
321
|
+
"""Remove release Helm em estado pendente que bloqueia novas operacoes."""
|
|
322
|
+
if ctx.dry_run:
|
|
323
|
+
return
|
|
324
|
+
|
|
325
|
+
status = _get_helm_release_status(release, namespace)
|
|
326
|
+
if not status:
|
|
327
|
+
return
|
|
328
|
+
|
|
329
|
+
# Estados que bloqueiam: pending-install, pending-upgrade, pending-rollback
|
|
330
|
+
if status.startswith("pending"):
|
|
331
|
+
typer.secho(
|
|
332
|
+
f"⚠ Release '{release}' em estado '{status}'. Limpando antes de prosseguir...",
|
|
333
|
+
fg=typer.colors.YELLOW,
|
|
334
|
+
)
|
|
335
|
+
# Tenta rollback primeiro (funciona para pending-upgrade)
|
|
336
|
+
subprocess.run(
|
|
337
|
+
["helm", "rollback", release, "-n", namespace, "--wait", "--timeout", "2m"],
|
|
338
|
+
capture_output=True,
|
|
339
|
+
timeout=150,
|
|
340
|
+
)
|
|
341
|
+
# Verifica se resolveu
|
|
342
|
+
new_status = _get_helm_release_status(release, namespace)
|
|
343
|
+
if new_status.startswith("pending"):
|
|
344
|
+
# Se ainda pendente, desinstala
|
|
345
|
+
typer.secho(
|
|
346
|
+
f" Rollback nao resolveu. Desinstalando release '{release}'...",
|
|
347
|
+
fg=typer.colors.YELLOW,
|
|
348
|
+
)
|
|
349
|
+
subprocess.run(
|
|
350
|
+
["helm", "uninstall", release, "-n", namespace, "--wait", "--timeout", "3m"],
|
|
351
|
+
capture_output=True,
|
|
352
|
+
timeout=200,
|
|
353
|
+
)
|
|
354
|
+
time.sleep(5)
|
|
355
|
+
typer.secho(f"✓ Release '{release}' limpo.", fg=typer.colors.GREEN)
|
|
356
|
+
|
|
357
|
+
|
|
302
358
|
def helm_upgrade_install(
|
|
303
359
|
release: str,
|
|
304
360
|
chart: str,
|
|
@@ -311,9 +367,16 @@ def helm_upgrade_install(
|
|
|
311
367
|
create_namespace: bool = True,
|
|
312
368
|
extra_args: list[str] | None = None,
|
|
313
369
|
) -> None:
|
|
314
|
-
"""Executa helm upgrade --install com opcoes comuns.
|
|
370
|
+
"""Executa helm upgrade --install com opcoes comuns.
|
|
371
|
+
|
|
372
|
+
Automaticamente detecta e limpa releases em estado pendente antes de instalar.
|
|
373
|
+
"""
|
|
315
374
|
|
|
316
375
|
ensure_tool("helm", ctx, install_hint="Instale helm ou habilite dry-run para so visualizar.")
|
|
376
|
+
|
|
377
|
+
# Limpa releases pendentes antes de tentar instalar
|
|
378
|
+
_cleanup_pending_helm_release(release, namespace, ctx)
|
|
379
|
+
|
|
317
380
|
if repo and repo_url:
|
|
318
381
|
helm_repo_add(repo, repo_url, ctx)
|
|
319
382
|
helm_repo_update(ctx)
|
|
@@ -328,7 +391,21 @@ def helm_upgrade_install(
|
|
|
328
391
|
cmd.extend(["--set", value])
|
|
329
392
|
if extra_args:
|
|
330
393
|
cmd.extend(extra_args)
|
|
331
|
-
|
|
394
|
+
|
|
395
|
+
try:
|
|
396
|
+
run_cmd(cmd, ctx)
|
|
397
|
+
except Exception as e:
|
|
398
|
+
err_text = str(e).lower()
|
|
399
|
+
# Se falhou por operacao em progresso, tenta limpar e reinstalar uma vez
|
|
400
|
+
if "another operation" in err_text and "in progress" in err_text:
|
|
401
|
+
typer.secho(
|
|
402
|
+
f"⚠ Helm detectou operacao pendente em '{release}'. Limpando e tentando novamente...",
|
|
403
|
+
fg=typer.colors.YELLOW,
|
|
404
|
+
)
|
|
405
|
+
_cleanup_pending_helm_release(release, namespace, ctx)
|
|
406
|
+
run_cmd(cmd, ctx)
|
|
407
|
+
else:
|
|
408
|
+
raise
|
|
332
409
|
|
|
333
410
|
|
|
334
411
|
def kubectl_apply(target: str, ctx: ExecutionContext) -> None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: raijin-server
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Summary: CLI para automacao de setup e hardening de servidores Ubuntu Server.
|
|
5
5
|
Home-page: https://example.com/raijin-server
|
|
6
6
|
Author: Equipe Raijin
|
|
@@ -37,6 +37,14 @@ CLI em Python (Typer) para automatizar setup e hardening de servidores Ubuntu Se
|
|
|
37
37
|
|
|
38
38
|
**✨ Versão Auditada e Resiliente para Produção**
|
|
39
39
|
|
|
40
|
+
## Links úteis
|
|
41
|
+
|
|
42
|
+
- Repositório: https://github.com/rafaelluisdacostacoelho/raijin-server
|
|
43
|
+
- Documentação completa: [docs/INFRASTRUCTURE_GUIDE.md](docs/INFRASTRUCTURE_GUIDE.md)
|
|
44
|
+
- Arquitetura: [ARCHITECTURE.md](ARCHITECTURE.md)
|
|
45
|
+
- Auditoria: [AUDIT.md](AUDIT.md)
|
|
46
|
+
- Segurança: [SECURITY.md](SECURITY.md)
|
|
47
|
+
|
|
40
48
|
## Destaques
|
|
41
49
|
|
|
42
50
|
- ✅ **Validações de Pré-requisitos**: OS, espaço em disco, memória, conectividade, ambiente Python (venv)
|
|
@@ -81,6 +89,36 @@ source .venv/bin/activate
|
|
|
81
89
|
python -m pip install -e .
|
|
82
90
|
```
|
|
83
91
|
|
|
92
|
+
### Instalação em Produção (Recomendado)
|
|
93
|
+
|
|
94
|
+
Para servidores em produção, use um venv isolado e execute com sudo preservando o ambiente:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# 1. Sair do venv atual (se estiver ativo)
|
|
98
|
+
deactivate
|
|
99
|
+
|
|
100
|
+
# 2. (Opcional) Remover venv antigo
|
|
101
|
+
rm -rf ~/.venvs/raijin
|
|
102
|
+
|
|
103
|
+
# 3. Criar venv novo
|
|
104
|
+
python3 -m venv ~/.venvs/raijin
|
|
105
|
+
source ~/.venvs/raijin/bin/activate
|
|
106
|
+
pip install -U pip setuptools
|
|
107
|
+
|
|
108
|
+
# 4. Instalar a versão mais recente
|
|
109
|
+
pip install -U raijin-server
|
|
110
|
+
|
|
111
|
+
# 5. Rodar usando root preservando o venv
|
|
112
|
+
sudo -E ~/.venvs/raijin/bin/raijin-server --version
|
|
113
|
+
sudo -E ~/.venvs/raijin/bin/raijin-server validate
|
|
114
|
+
sudo -E ~/.venvs/raijin/bin/raijin-server full-install
|
|
115
|
+
|
|
116
|
+
# 6. Para sair do venv quando terminar
|
|
117
|
+
deactivate
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
> **Nota**: O `-E` no sudo preserva as variáveis de ambiente, garantindo que o Python use o venv correto mesmo como root.
|
|
121
|
+
|
|
84
122
|
## Uso rapido
|
|
85
123
|
|
|
86
124
|
### Validar Sistema
|
|
@@ -375,6 +413,32 @@ pytest
|
|
|
375
413
|
ruff check src tests
|
|
376
414
|
```
|
|
377
415
|
|
|
416
|
+
## Publicar no PyPI (Twine)
|
|
417
|
+
|
|
418
|
+
O Twine é a ferramenta oficial para enviar pacotes Python ao PyPI com upload seguro (HTTPS e checagem de hash). Use sempre um token de API.
|
|
419
|
+
|
|
420
|
+
Passo a passo:
|
|
421
|
+
```bash
|
|
422
|
+
# 1) Gere artefatos
|
|
423
|
+
python -m build --sdist --wheel --outdir dist/
|
|
424
|
+
|
|
425
|
+
# 2) Configure o token (crie em https://pypi.org/manage/account/token/)
|
|
426
|
+
export TWINE_USERNAME=__token__
|
|
427
|
+
export TWINE_PASSWORD="<seu-token>"
|
|
428
|
+
|
|
429
|
+
# 3) Envie para o PyPI
|
|
430
|
+
python -m twine upload dist/*
|
|
431
|
+
|
|
432
|
+
# 4) Verifique instalação
|
|
433
|
+
python -m pip install -U raijin-server
|
|
434
|
+
raijin-server --version
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
Boas práticas:
|
|
438
|
+
- Use venv dedicado para publicar (`python -m venv ~/.venvs/publish && source ~/.venvs/publish/bin/activate`).
|
|
439
|
+
- Nunca commite ou exponha o token; mantenha em variável de ambiente/secret manager.
|
|
440
|
+
- Sempre suba primeiro para TestPyPI se quiser validar (`--repository testpypi`).
|
|
441
|
+
|
|
378
442
|
## Acesso remoto seguro (VPN + SSH)
|
|
379
443
|
|
|
380
444
|
Execute `raijin-server ssh-hardening` para aplicar as politicas abaixo automaticamente e `raijin-server vpn` para subir o servidor WireGuard com um cliente inicial. Use `--dry-run` se quiser apenas revisar os comandos.
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
raijin_server/__init__.py,sha256=
|
|
2
|
-
raijin_server/cli.py,sha256=
|
|
1
|
+
raijin_server/__init__.py,sha256=7-69Vj-HYrv98hWrKmwDqDQ-ehtTqJebx1JeP4St6Q4,94
|
|
2
|
+
raijin_server/cli.py,sha256=PfuIXc-pw1yZtJzCrxDVSWSsPAVBt9wqZBF-dWh6mwo,19274
|
|
3
3
|
raijin_server/config.py,sha256=Dta2CS1d6RgNiQ84P6dTXk98boFrjzuvhs_fCdlm0I4,4810
|
|
4
|
-
raijin_server/healthchecks.py,sha256
|
|
5
|
-
raijin_server/utils.py,sha256=
|
|
4
|
+
raijin_server/healthchecks.py,sha256=BJyWyUDtEswEblvGwWMejtMnsUb8kJcULVdS9iycrcc,14565
|
|
5
|
+
raijin_server/utils.py,sha256=MNIevCttKq5fVS-I4ZwlY7f7JZtEiwwY_kj69WV4AsQ,14330
|
|
6
6
|
raijin_server/validators.py,sha256=qOZMHgwjHogVf17UPlxfUCpQd9qAGQW7tycd8mUvnEs,9404
|
|
7
7
|
raijin_server/modules/__init__.py,sha256=e_IbkhLGPcF8to9QUmIESP6fpcTOYcIhaXLKIvqRJMY,920
|
|
8
|
-
raijin_server/modules/apokolips_demo.py,sha256=
|
|
8
|
+
raijin_server/modules/apokolips_demo.py,sha256=8ltsXRbVDwlDwLMIvh02NG-FeAfBWw_v6lh7IGOyNqs,13725
|
|
9
9
|
raijin_server/modules/bootstrap.py,sha256=oVIGNRW_JbgY8zXNHGAIP0vGbbHNHyQexthxo5zhbcw,9762
|
|
10
10
|
raijin_server/modules/calico.py,sha256=a8N7YYv7NoaspPKdhRtwHy3V2mM4cP5xA1H8BwslB18,4139
|
|
11
|
-
raijin_server/modules/cert_manager.py,sha256=
|
|
11
|
+
raijin_server/modules/cert_manager.py,sha256=dse7AIUVOM2h7d2i3DWsvHLsA9NtcazebTPgOEUWB-8,34473
|
|
12
12
|
raijin_server/modules/essentials.py,sha256=2xUXCyCQtFGd2DnCKV81N1R6bEJqH8zaet8mLovtQ1I,689
|
|
13
13
|
raijin_server/modules/firewall.py,sha256=h6AISqiZeTinVT7BjmQIS872qRAFZJLg7meqlth3cfw,757
|
|
14
|
-
raijin_server/modules/full_install.py,sha256=
|
|
14
|
+
raijin_server/modules/full_install.py,sha256=aR3yOuD7y0KLI20eMrxuFBNrWWn7JMpI4HFKNizEF3o,7464
|
|
15
15
|
raijin_server/modules/grafana.py,sha256=zxYpWBM-fD8vTgoJ2Hmb9P66wz_JuiidO6_cGK3jG30,1809
|
|
16
16
|
raijin_server/modules/hardening.py,sha256=4hz3ifkMhPlXa2n7gPxN0gitQgzALZ-073vuU3LM4RI,1616
|
|
17
17
|
raijin_server/modules/harness.py,sha256=dhZ89YIhlkuxiRU1deN6wXVWnXm0xeI03PwYf_qgfak,1527
|
|
@@ -36,9 +36,9 @@ raijin_server/scripts/checklist.sh,sha256=j6E0Kmk1EfjLvKK1VpCqzXJAXI_7Bm67LK4ndy
|
|
|
36
36
|
raijin_server/scripts/install.sh,sha256=IZOTujOSGmKpznwgL59picsQNVzYkai6FtfFS3Klf34,3908
|
|
37
37
|
raijin_server/scripts/log_size_metric.sh,sha256=rC2Ck4xnYVJV4Qymu24-indC8bkzfZs4FBqqxGPRl1I,1143
|
|
38
38
|
raijin_server/scripts/pre-deploy-check.sh,sha256=naPUgKjnKgsh-eGDH2623C7zcr9VjDEw1H0lfYaXW8c,4853
|
|
39
|
-
raijin_server-0.2.
|
|
40
|
-
raijin_server-0.2.
|
|
41
|
-
raijin_server-0.2.
|
|
42
|
-
raijin_server-0.2.
|
|
43
|
-
raijin_server-0.2.
|
|
44
|
-
raijin_server-0.2.
|
|
39
|
+
raijin_server-0.2.5.dist-info/licenses/LICENSE,sha256=kJsMCjOiRZE0AQNtxWqBa32z9kMAaF4EUxyHj3hKaJo,1105
|
|
40
|
+
raijin_server-0.2.5.dist-info/METADATA,sha256=TVzTE_0qlyVoyy3lsoWfFn97hJylE_oKyXDFv32BMkg,18925
|
|
41
|
+
raijin_server-0.2.5.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
42
|
+
raijin_server-0.2.5.dist-info/entry_points.txt,sha256=3ZvxDX4pvcjkIRsXAJ69wIfVmKa78LKo-C3QhqN2KVM,56
|
|
43
|
+
raijin_server-0.2.5.dist-info/top_level.txt,sha256=Yz1xneCRtsZOzbPIcTAcrSxd-1p80pohMXYAZ74dpok,14
|
|
44
|
+
raijin_server-0.2.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|