raijin-server 0.2.3__tar.gz → 0.2.5__tar.gz
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-0.2.3/src/raijin_server.egg-info → raijin_server-0.2.5}/PKG-INFO +65 -1
- {raijin_server-0.2.3 → raijin_server-0.2.5}/README.md +64 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/setup.cfg +1 -1
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/__init__.py +1 -1
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/cli.py +77 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/healthchecks.py +61 -2
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/apokolips_demo.py +40 -4
- raijin_server-0.2.5/src/raijin_server/modules/cert_manager.py +1035 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/full_install.py +44 -1
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/utils.py +79 -2
- {raijin_server-0.2.3 → raijin_server-0.2.5/src/raijin_server.egg-info}/PKG-INFO +65 -1
- raijin_server-0.2.3/src/raijin_server/modules/cert_manager.py +0 -156
- {raijin_server-0.2.3 → raijin_server-0.2.5}/LICENSE +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/pyproject.toml +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/config.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/__init__.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/bootstrap.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/calico.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/essentials.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/firewall.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/grafana.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/hardening.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/harness.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/istio.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/kafka.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/kong.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/kubernetes.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/loki.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/minio.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/network.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/observability_dashboards.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/observability_ingress.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/prometheus.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/sanitize.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/secrets.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/ssh_hardening.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/traefik.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/velero.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/modules/vpn.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/scripts/__init__.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/scripts/checklist.sh +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/scripts/install.sh +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/scripts/log_size_metric.sh +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/scripts/pre-deploy-check.sh +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server/validators.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server.egg-info/SOURCES.txt +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server.egg-info/dependency_links.txt +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server.egg-info/entry_points.txt +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server.egg-info/requires.txt +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/src/raijin_server.egg-info/top_level.txt +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/tests/test_full_install_sequence.py +0 -0
- {raijin_server-0.2.3 → raijin_server-0.2.5}/tests/test_registry.py +0 -0
|
@@ -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.
|
|
@@ -4,6 +4,14 @@ CLI em Python (Typer) para automatizar setup e hardening de servidores Ubuntu Se
|
|
|
4
4
|
|
|
5
5
|
**✨ Versão Auditada e Resiliente para Produção**
|
|
6
6
|
|
|
7
|
+
## Links úteis
|
|
8
|
+
|
|
9
|
+
- Repositório: https://github.com/rafaelluisdacostacoelho/raijin-server
|
|
10
|
+
- Documentação completa: [docs/INFRASTRUCTURE_GUIDE.md](docs/INFRASTRUCTURE_GUIDE.md)
|
|
11
|
+
- Arquitetura: [ARCHITECTURE.md](ARCHITECTURE.md)
|
|
12
|
+
- Auditoria: [AUDIT.md](AUDIT.md)
|
|
13
|
+
- Segurança: [SECURITY.md](SECURITY.md)
|
|
14
|
+
|
|
7
15
|
## Destaques
|
|
8
16
|
|
|
9
17
|
- ✅ **Validações de Pré-requisitos**: OS, espaço em disco, memória, conectividade, ambiente Python (venv)
|
|
@@ -48,6 +56,36 @@ source .venv/bin/activate
|
|
|
48
56
|
python -m pip install -e .
|
|
49
57
|
```
|
|
50
58
|
|
|
59
|
+
### Instalação em Produção (Recomendado)
|
|
60
|
+
|
|
61
|
+
Para servidores em produção, use um venv isolado e execute com sudo preservando o ambiente:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# 1. Sair do venv atual (se estiver ativo)
|
|
65
|
+
deactivate
|
|
66
|
+
|
|
67
|
+
# 2. (Opcional) Remover venv antigo
|
|
68
|
+
rm -rf ~/.venvs/raijin
|
|
69
|
+
|
|
70
|
+
# 3. Criar venv novo
|
|
71
|
+
python3 -m venv ~/.venvs/raijin
|
|
72
|
+
source ~/.venvs/raijin/bin/activate
|
|
73
|
+
pip install -U pip setuptools
|
|
74
|
+
|
|
75
|
+
# 4. Instalar a versão mais recente
|
|
76
|
+
pip install -U raijin-server
|
|
77
|
+
|
|
78
|
+
# 5. Rodar usando root preservando o venv
|
|
79
|
+
sudo -E ~/.venvs/raijin/bin/raijin-server --version
|
|
80
|
+
sudo -E ~/.venvs/raijin/bin/raijin-server validate
|
|
81
|
+
sudo -E ~/.venvs/raijin/bin/raijin-server full-install
|
|
82
|
+
|
|
83
|
+
# 6. Para sair do venv quando terminar
|
|
84
|
+
deactivate
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
> **Nota**: O `-E` no sudo preserva as variáveis de ambiente, garantindo que o Python use o venv correto mesmo como root.
|
|
88
|
+
|
|
51
89
|
## Uso rapido
|
|
52
90
|
|
|
53
91
|
### Validar Sistema
|
|
@@ -342,6 +380,32 @@ pytest
|
|
|
342
380
|
ruff check src tests
|
|
343
381
|
```
|
|
344
382
|
|
|
383
|
+
## Publicar no PyPI (Twine)
|
|
384
|
+
|
|
385
|
+
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.
|
|
386
|
+
|
|
387
|
+
Passo a passo:
|
|
388
|
+
```bash
|
|
389
|
+
# 1) Gere artefatos
|
|
390
|
+
python -m build --sdist --wheel --outdir dist/
|
|
391
|
+
|
|
392
|
+
# 2) Configure o token (crie em https://pypi.org/manage/account/token/)
|
|
393
|
+
export TWINE_USERNAME=__token__
|
|
394
|
+
export TWINE_PASSWORD="<seu-token>"
|
|
395
|
+
|
|
396
|
+
# 3) Envie para o PyPI
|
|
397
|
+
python -m twine upload dist/*
|
|
398
|
+
|
|
399
|
+
# 4) Verifique instalação
|
|
400
|
+
python -m pip install -U raijin-server
|
|
401
|
+
raijin-server --version
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
Boas práticas:
|
|
405
|
+
- Use venv dedicado para publicar (`python -m venv ~/.venvs/publish && source ~/.venvs/publish/bin/activate`).
|
|
406
|
+
- Nunca commite ou exponha o token; mantenha em variável de ambiente/secret manager.
|
|
407
|
+
- Sempre suba primeiro para TestPyPI se quiser validar (`--repository testpypi`).
|
|
408
|
+
|
|
345
409
|
## Acesso remoto seguro (VPN + SSH)
|
|
346
410
|
|
|
347
411
|
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.
|
|
@@ -470,6 +470,83 @@ def sanitize(ctx: typer.Context) -> None:
|
|
|
470
470
|
_run_module(ctx, "sanitize")
|
|
471
471
|
|
|
472
472
|
|
|
473
|
+
# ============================================================================
|
|
474
|
+
# Subcomandos Cert-Manager
|
|
475
|
+
# ============================================================================
|
|
476
|
+
cert_app = typer.Typer(help="Comandos para gerenciamento do cert-manager")
|
|
477
|
+
app.add_typer(cert_app, name="cert")
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
@cert_app.command(name="install")
|
|
481
|
+
def cert_install(ctx: typer.Context) -> None:
|
|
482
|
+
"""Instala cert-manager e configura ClusterIssuer interativamente."""
|
|
483
|
+
_run_module(ctx, "cert_manager")
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
@cert_app.command(name="status")
|
|
487
|
+
def cert_status(ctx: typer.Context) -> None:
|
|
488
|
+
"""Exibe status detalhado do cert-manager, pods, webhook e certificados."""
|
|
489
|
+
exec_ctx = ctx.obj or ExecutionContext()
|
|
490
|
+
cert_manager.status(exec_ctx)
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
@cert_app.command(name="diagnose")
|
|
494
|
+
def cert_diagnose(ctx: typer.Context) -> None:
|
|
495
|
+
"""Executa diagnóstico completo para troubleshooting do cert-manager."""
|
|
496
|
+
exec_ctx = ctx.obj or ExecutionContext()
|
|
497
|
+
cert_manager.diagnose(exec_ctx)
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
@cert_app.command(name="list-certs")
|
|
501
|
+
def cert_list(ctx: typer.Context) -> None:
|
|
502
|
+
"""Lista todos os certificados no cluster."""
|
|
503
|
+
import subprocess
|
|
504
|
+
|
|
505
|
+
typer.secho("\n📜 Certificados no Cluster", fg=typer.colors.CYAN, bold=True)
|
|
506
|
+
try:
|
|
507
|
+
result = subprocess.run(
|
|
508
|
+
[
|
|
509
|
+
"kubectl", "get", "certificates", "-A",
|
|
510
|
+
"-o", "wide"
|
|
511
|
+
],
|
|
512
|
+
capture_output=False,
|
|
513
|
+
timeout=15,
|
|
514
|
+
)
|
|
515
|
+
if result.returncode != 0:
|
|
516
|
+
typer.secho("Nenhum certificado encontrado ou erro ao listar.", fg=typer.colors.YELLOW)
|
|
517
|
+
except Exception as e:
|
|
518
|
+
typer.secho(f"Erro: {e}", fg=typer.colors.RED)
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
@cert_app.command(name="list-issuers")
|
|
522
|
+
def cert_list_issuers(ctx: typer.Context) -> None:
|
|
523
|
+
"""Lista todos os ClusterIssuers e Issuers."""
|
|
524
|
+
import subprocess
|
|
525
|
+
|
|
526
|
+
typer.secho("\n🔐 ClusterIssuers", fg=typer.colors.CYAN, bold=True)
|
|
527
|
+
try:
|
|
528
|
+
subprocess.run(
|
|
529
|
+
["kubectl", "get", "clusterissuers", "-o", "wide"],
|
|
530
|
+
timeout=15,
|
|
531
|
+
)
|
|
532
|
+
except Exception:
|
|
533
|
+
pass
|
|
534
|
+
|
|
535
|
+
typer.secho("\n🔐 Issuers (por namespace)", fg=typer.colors.CYAN, bold=True)
|
|
536
|
+
try:
|
|
537
|
+
subprocess.run(
|
|
538
|
+
["kubectl", "get", "issuers", "-A", "-o", "wide"],
|
|
539
|
+
timeout=15,
|
|
540
|
+
)
|
|
541
|
+
except Exception:
|
|
542
|
+
pass
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
# ============================================================================
|
|
546
|
+
# Comandos Existentes
|
|
547
|
+
# ============================================================================
|
|
548
|
+
|
|
549
|
+
|
|
473
550
|
@app.command(name="bootstrap")
|
|
474
551
|
def bootstrap_cmd(ctx: typer.Context) -> None:
|
|
475
552
|
"""Instala todas as ferramentas necessarias: helm, kubectl, istioctl, velero, containerd."""
|
|
@@ -264,8 +264,67 @@ def verify_helm_chart(release: str, namespace: str, ctx: ExecutionContext) -> bo
|
|
|
264
264
|
|
|
265
265
|
|
|
266
266
|
def verify_cert_manager(ctx: ExecutionContext) -> bool:
|
|
267
|
-
"""Health check para cert-manager."""
|
|
268
|
-
|
|
267
|
+
"""Health check completo para cert-manager."""
|
|
268
|
+
logger.info("Verificando health check: cert-manager")
|
|
269
|
+
typer.secho("\n=== Health Check: Cert-Manager ===", fg=typer.colors.CYAN)
|
|
270
|
+
|
|
271
|
+
all_ok = True
|
|
272
|
+
|
|
273
|
+
# Verifica release Helm
|
|
274
|
+
ok, status = check_helm_release("cert-manager", CERT_NS, ctx)
|
|
275
|
+
if ok:
|
|
276
|
+
typer.secho(f" ✓ Release cert-manager: {status}", fg=typer.colors.GREEN)
|
|
277
|
+
else:
|
|
278
|
+
typer.secho(f" ✗ Release cert-manager: {status}", fg=typer.colors.RED)
|
|
279
|
+
return False
|
|
280
|
+
|
|
281
|
+
# Verifica pods
|
|
282
|
+
if not check_k8s_pods_in_namespace(CERT_NS, ctx, timeout=180):
|
|
283
|
+
all_ok = False
|
|
284
|
+
|
|
285
|
+
# Verifica CRDs
|
|
286
|
+
if not ctx.dry_run:
|
|
287
|
+
try:
|
|
288
|
+
import subprocess
|
|
289
|
+
result = subprocess.run(
|
|
290
|
+
["kubectl", "get", "crd", "certificates.cert-manager.io"],
|
|
291
|
+
capture_output=True,
|
|
292
|
+
timeout=10,
|
|
293
|
+
)
|
|
294
|
+
if result.returncode == 0:
|
|
295
|
+
typer.secho(" ✓ CRDs instalados", fg=typer.colors.GREEN)
|
|
296
|
+
else:
|
|
297
|
+
typer.secho(" ✗ CRDs não encontrados", fg=typer.colors.RED)
|
|
298
|
+
all_ok = False
|
|
299
|
+
except Exception as e:
|
|
300
|
+
typer.secho(f" ✗ Erro ao verificar CRDs: {e}", fg=typer.colors.RED)
|
|
301
|
+
all_ok = False
|
|
302
|
+
|
|
303
|
+
# Verifica webhook ready
|
|
304
|
+
if not ctx.dry_run:
|
|
305
|
+
try:
|
|
306
|
+
import subprocess
|
|
307
|
+
result = subprocess.run(
|
|
308
|
+
[
|
|
309
|
+
"kubectl", "get", "deployment", "cert-manager-webhook",
|
|
310
|
+
"-n", CERT_NS,
|
|
311
|
+
"-o", "jsonpath={.status.readyReplicas}"
|
|
312
|
+
],
|
|
313
|
+
capture_output=True,
|
|
314
|
+
text=True,
|
|
315
|
+
timeout=10,
|
|
316
|
+
)
|
|
317
|
+
ready = result.returncode == 0 and result.stdout.strip() and int(result.stdout.strip()) >= 1
|
|
318
|
+
if ready:
|
|
319
|
+
typer.secho(" ✓ Webhook pronto", fg=typer.colors.GREEN)
|
|
320
|
+
else:
|
|
321
|
+
typer.secho(" ✗ Webhook não está pronto", fg=typer.colors.RED)
|
|
322
|
+
all_ok = False
|
|
323
|
+
except Exception as e:
|
|
324
|
+
typer.secho(f" ✗ Erro ao verificar webhook: {e}", fg=typer.colors.RED)
|
|
325
|
+
all_ok = False
|
|
326
|
+
|
|
327
|
+
return all_ok
|
|
269
328
|
|
|
270
329
|
|
|
271
330
|
def verify_secrets(ctx: ExecutionContext) -> bool:
|
|
@@ -244,7 +244,15 @@ def _resolve_tls_secret() -> str | None:
|
|
|
244
244
|
return secret.strip() or None
|
|
245
245
|
|
|
246
246
|
|
|
247
|
-
def
|
|
247
|
+
def _resolve_ip_access() -> bool:
|
|
248
|
+
"""Pergunta se deseja acesso via IP direto (para testes)."""
|
|
249
|
+
env_ip = os.environ.get("APOKOLIPS_IP_ACCESS")
|
|
250
|
+
if env_ip:
|
|
251
|
+
return env_ip.strip().lower() in ("1", "true", "yes")
|
|
252
|
+
return typer.confirm("Habilitar acesso via IP direto? (apenas para testes)", default=True)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def _build_manifest(host: str, tls_secret: str | None, ip_access: bool = False) -> str:
|
|
248
256
|
html_block = indent(HTML_TEMPLATE.strip("\n"), " " * 4)
|
|
249
257
|
tls_block = ""
|
|
250
258
|
if tls_secret:
|
|
@@ -254,6 +262,20 @@ def _build_manifest(host: str, tls_secret: str | None) -> str:
|
|
|
254
262
|
f" - {host}\n"
|
|
255
263
|
f" secretName: {tls_secret}\n"
|
|
256
264
|
)
|
|
265
|
+
|
|
266
|
+
# Regra adicional para acesso via IP (sem host)
|
|
267
|
+
ip_rule = ""
|
|
268
|
+
if ip_access:
|
|
269
|
+
ip_rule = """
|
|
270
|
+
- http:
|
|
271
|
+
paths:
|
|
272
|
+
- path: /
|
|
273
|
+
pathType: Prefix
|
|
274
|
+
backend:
|
|
275
|
+
service:
|
|
276
|
+
name: apokolips-demo
|
|
277
|
+
port:
|
|
278
|
+
number: 80"""
|
|
257
279
|
|
|
258
280
|
template = """\
|
|
259
281
|
apiVersion: v1
|
|
@@ -340,12 +362,13 @@ spec:
|
|
|
340
362
|
service:
|
|
341
363
|
name: apokolips-demo
|
|
342
364
|
port:
|
|
343
|
-
number:
|
|
365
|
+
number: 80__IP_RULE__
|
|
344
366
|
__TLS__
|
|
345
367
|
"""
|
|
346
368
|
|
|
347
369
|
manifest = template.format(namespace=NAMESPACE, host=host)
|
|
348
370
|
manifest = manifest.replace("__HTML__", html_block)
|
|
371
|
+
manifest = manifest.replace("__IP_RULE__", ip_rule)
|
|
349
372
|
manifest = manifest.replace("__TLS__", tls_block.rstrip())
|
|
350
373
|
return f"{manifest.strip()}\n"
|
|
351
374
|
|
|
@@ -354,7 +377,8 @@ def run(ctx: ExecutionContext) -> None:
|
|
|
354
377
|
ensure_tool("kubectl", ctx, install_hint="Instale kubectl para aplicar o manifesto do site.")
|
|
355
378
|
host = _resolve_host()
|
|
356
379
|
tls_secret = _resolve_tls_secret()
|
|
357
|
-
|
|
380
|
+
ip_access = _resolve_ip_access()
|
|
381
|
+
manifest = _build_manifest(host, tls_secret, ip_access)
|
|
358
382
|
|
|
359
383
|
typer.echo("Gerando manifesto Apokolips...")
|
|
360
384
|
write_file(TMP_MANIFEST, manifest, ctx)
|
|
@@ -369,10 +393,22 @@ def run(ctx: ExecutionContext) -> None:
|
|
|
369
393
|
typer.echo(f" • Host: {host}")
|
|
370
394
|
if tls_secret:
|
|
371
395
|
typer.echo(f" • Secret TLS: {tls_secret}")
|
|
396
|
+
if ip_access:
|
|
397
|
+
typer.secho(" • Acesso via IP: HABILITADO (apenas para testes)", fg=typer.colors.YELLOW)
|
|
398
|
+
|
|
372
399
|
typer.echo("\nTestes sugeridos:")
|
|
373
|
-
|
|
400
|
+
if ip_access:
|
|
401
|
+
typer.echo(" # Acesso direto via IP (teste):")
|
|
402
|
+
typer.echo(" curl http://<IP_DO_SERVIDOR>/")
|
|
403
|
+
typer.echo("")
|
|
404
|
+
typer.echo(f" # Acesso via DNS (produção):")
|
|
405
|
+
typer.echo(f" curl -H 'Host: {host}' http://<IP_DO_LOAD_BALANCER>/")
|
|
374
406
|
typer.echo(f" kubectl -n {NAMESPACE} get ingress {NAMESPACE}")
|
|
375
407
|
typer.echo(f" kubectl -n {NAMESPACE} get pods")
|
|
376
408
|
|
|
409
|
+
if ip_access:
|
|
410
|
+
typer.secho("\n⚠️ Lembre-se de desabilitar o acesso via IP após configurar o DNS!", fg=typer.colors.YELLOW)
|
|
411
|
+
typer.echo(" Rode novamente com APOKOLIPS_IP_ACCESS=false ou responda 'não' na pergunta.")
|
|
412
|
+
|
|
377
413
|
typer.echo("\nPara remover:")
|
|
378
414
|
typer.echo(f" kubectl delete namespace {NAMESPACE}")
|