Skip to content

Commit fa1f8ee

Browse files
committed
Adiciona regras de validação para tipos de dados: Double, Duration, Enum, Field, Fixed32, Fixed64 e Float
- Criação de arquivos de definição e implementação para regras de validação de tipos Double, Duration, Enum, Field, Fixed32, Fixed64 e Float. - Implementação de interfaces que descrevem as restrições aplicadas a cada tipo de dado. - Geração de arquivos de mapa de origem para facilitar o mapeamento de tipos.
1 parent 0adcaa5 commit fa1f8ee

5,388 files changed

Lines changed: 1084415 additions & 11 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/publish.yml

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,35 +40,68 @@ jobs:
4040
username: ${{ github.actor }}
4141
password: ${{ secrets.GITHUB_TOKEN }}
4242

43-
# Gera tags OCI a partir da release publicada.
44-
- name: Extract Docker metadata
45-
id: meta
43+
# Gera tags OCI a partir da release publicada para debugtools.
44+
- name: Extract Docker metadata for debugtools
45+
id: meta-debugtools
4646
uses: docker/metadata-action@v6
4747
with:
4848
images: ghcr.io/${{ github.repository_owner }}/debugtools
4949
tags: |
5050
type=raw,value=${{ github.event.release.tag_name }}
5151
type=raw,value=latest,enable=${{ github.event.release.prerelease == false }}
5252
53-
# Monta a imagem, roda o build multiplataforma e publica no GHCR quando a release for publicada.
54-
- name: Build and push
55-
id: build
53+
# Monta a imagem, roda o build multiplataforma e publica no GHCR para debugtools.
54+
- name: Build and push debugtools
55+
id: build-debugtools
5656
uses: docker/build-push-action@v7
5757
with:
5858
context: .
5959
file: ./Dockerfile
6060
platforms: linux/amd64,linux/arm64
6161
pull: true
6262
push: true
63-
tags: ${{ steps.meta.outputs.tags }}
64-
labels: ${{ steps.meta.outputs.labels }}
63+
tags: ${{ steps.meta-debugtools.outputs.tags }}
64+
labels: ${{ steps.meta-debugtools.outputs.labels }}
6565
cache-from: type=gha
6666
cache-to: type=gha,mode=max
6767

68-
# Publica atestacao de proveniencia da imagem publicada no GHCR.
69-
- name: Attest build provenance
68+
# Publica atestacao de proveniencia da imagem debugtools publicada no GHCR.
69+
- name: Attest build provenance for debugtools
7070
uses: actions/attest-build-provenance@v4
7171
with:
7272
subject-name: ghcr.io/${{ github.repository_owner }}/debugtools
73-
subject-digest: ${{ steps.build.outputs.digest }}
73+
subject-digest: ${{ steps.build-debugtools.outputs.digest }}
74+
push-to-registry: true
75+
76+
# Gera tags OCI a partir da release publicada para debugtools-mcp.
77+
- name: Extract Docker metadata for debugtools-mcp
78+
id: meta-mcp
79+
uses: docker/metadata-action@v6
80+
with:
81+
images: ghcr.io/${{ github.repository_owner }}/debugtools-mcp
82+
tags: |
83+
type=raw,value=${{ github.event.release.tag_name }}
84+
type=raw,value=latest,enable=${{ github.event.release.prerelease == false }}
85+
86+
# Monta a imagem, roda o build multiplataforma e publica no GHCR para o mcp-server.
87+
- name: Build and push debugtools-mcp
88+
id: build-mcp
89+
uses: docker/build-push-action@v7
90+
with:
91+
context: ./mcp-server
92+
file: ./mcp-server/Dockerfile
93+
platforms: linux/amd64,linux/arm64
94+
pull: true
95+
push: true
96+
tags: ${{ steps.meta-mcp.outputs.tags }}
97+
labels: ${{ steps.meta-mcp.outputs.labels }}
98+
cache-from: type=gha
99+
cache-to: type=gha,mode=max
100+
101+
# Publica atestacao de proveniencia da imagem debugtools-mcp publicada no GHCR.
102+
- name: Attest build provenance for debugtools-mcp
103+
uses: actions/attest-build-provenance@v4
104+
with:
105+
subject-name: ghcr.io/${{ github.repository_owner }}/debugtools-mcp
106+
subject-digest: ${{ steps.build-mcp.outputs.digest }}
74107
push-to-registry: true

mcp-server/Dockerfile

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# =========================================================
2+
# Stage 1: Build the TypeScript server
3+
# =========================================================
4+
FROM node:20-alpine AS builder
5+
6+
WORKDIR /usr/src/app
7+
8+
COPY package*.json tsconfig.json ./
9+
RUN npm ci
10+
11+
COPY src/ ./src
12+
RUN npm run build
13+
14+
# =========================================================
15+
# Stage 2: Clean and secure lightweight production runner
16+
# =========================================================
17+
FROM node:20-alpine
18+
19+
# Set Node environment
20+
ENV NODE_ENV=production
21+
22+
# Install essential system-level networking tools needed by binary probes
23+
# - bind-tools: provides 'dig' and 'nslookup'
24+
# - iputils: provides robust 'ping' supporting -M do (DF flags) and high-resolution timing
25+
# - mtr: provides My Traceroute
26+
# - traceroute: fallback hops mapping
27+
# - curl: L7 detailed client (supports HTTP/1, HTTP/2, and depending on build, HTTP/3)
28+
RUN apk add --no-cache \
29+
bind-tools \
30+
iputils \
31+
mtr \
32+
traceroute \
33+
curl
34+
35+
WORKDIR /usr/src/app
36+
37+
COPY package*.json ./
38+
RUN npm ci --only=production
39+
40+
# Copy compiled JavaScript from builder stage
41+
COPY --from=builder /usr/src/app/dist ./dist
42+
COPY src/utils/health.proto ./dist/utils/health.proto
43+
44+
# Ensure system ping has setuid permission so non-root 'node' user can execute ICMP probes safely
45+
RUN chmod u+s /bin/ping || true
46+
47+
# Switch to standard non-privileged node user for high security
48+
USER node
49+
50+
# Expose SSE listener port
51+
EXPOSE 3000
52+
53+
ENV PORT=3000
54+
55+
CMD ["node", "dist/index.js"]

mcp-server/README.md

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
# Servidor MCP de Diagnósticos de Rede Externos ("de fora para dentro")
2+
3+
Este é um servidor **Model Context Protocol (MCP)** altamente especializado em diagnósticos de rede externos. Ele roda exposto à internet (ex: VPS Oracle Cloud) e permite que agentes SRE internos (como o **Hermes**, rodando em clusters Kubernetes privados) executem testes de rede sob a perspectiva de um usuário externo, eliminando pontos cegos causados por CDNs, Firewalls de borda, WAFs e resoluções DNS públicas.
4+
5+
---
6+
7+
## 🛠️ Canivete Suíço de Ferramentas (Tools)
8+
9+
O servidor expõe as seguintes ferramentas para o MCP:
10+
11+
### 🌐 Categoria: DNS & Roteamento (L3)
12+
* `dns_propagation_check`: Consulta o domínio informado contra múltiplos resolvers DNS (Google `8.8.8.8`, Cloudflare `1.1.1.1`, Quad9 `9.9.9.9` e o resolver local da VPS) para mapear discrepâncias de resolução IP.
13+
* *Argumentos:* `hostname: string`, `record_type: string` (padrão: "A").
14+
* `icmp_ping`: Envia pacotes ICMP e retorna latência (min/avg/max/stddev) e perda de pacotes.
15+
* *Argumentos:* `target: string` (IP/Hostname), `count: number` (padrão: 4).
16+
* `mtu_path_discovery`: Descobre o MTU máximo do caminho sem fragmentação enviando pings ICMP com a flag DF (*Don't Fragment*) ativa.
17+
* *Argumentos:* `target: string`, `start_size: number` (padrão: 1500).
18+
* `trace_route`: Executa um traceroute ou mtr detalhado para listar os saltos de rede entre a VPS e o destino.
19+
* *Argumentos:* `target: string`.
20+
21+
### 🔌 Categoria: Conectividade de Portas (L4)
22+
* `tcp_port_probe`: Tenta estabelecer um handshake TCP básico em uma porta específica para validar se ela está aberta, fechada ou filtrada por Firewall de borda.
23+
* *Argumentos:* `ip: string`, `port: number`, `timeout_ms: number` (padrão: 2000).
24+
* `udp_port_probe`: Tenta sondar portas UDP enviando payloads vazios e escutando por respostas ICMP de erro.
25+
* *Argumentos:* `ip: string`, `port: number`.
26+
27+
### 🔐 Categoria: Criptografia & Segurança (L5/L6)
28+
* `tls_cipher_audit`: Valida as versões TLS aceitas pelo servidor (SSLv3, TLS 1.0, 1.1, 1.2, 1.3) e audita as Cipher Suites suportadas para expor ciphers fracos ou incompatibilidades.
29+
* *Argumentos:* `hostname: string`, `port: number` (padrão: 443).
30+
* `ssl_certificate_check`: Retorna a validade temporal, emissor, SANs e cadeia completa de certificação SSL de um domínio.
31+
* *Argumentos:* `hostname: string`.
32+
* `cdn_bypass_probe`: Tenta contornar a CDN fazendo uma requisição HTTPS direta para o IP público do LoadBalancer de origem, mas injetando o header `Host` correto.
33+
* *Argumentos:* `origin_ip: string`, `domain: string`, `port: number` (padrão: 443).
34+
35+
### 🚀 Categoria: Protocolos de Aplicação (L7)
36+
* `http_detailed_probe`: Efetua uma requisição HTTP customizada de alta fidelidade com coleta detalhada de tempos de resposta (DNS, TCP Handshake, TLS Handshake, TTFB). Suporta especificação de protocolo HTTP/1.1, HTTP/2 ou HTTP/3.
37+
* *Argumentos:* `url: string`, `method: string` (GET, POST, etc.), `protocol_version: string` (http1, http2, http3), `headers: object` (opcional), `user_agent: string` (opcional).
38+
* `websocket_handshake_test`: Tenta estabelecer uma conexão ws/wss de longa duração na borda, realiza o handshake de upgrade e envia/recebe um frame de teste.
39+
* *Argumentos:* `url: string`, `headers: object` (opcional).
40+
* `grpc_health_check`: Testa a saúde de um serviço gRPC exposto externamente enviando uma chamada de Health Check padrão (`grpc.health.v1.Health`).
41+
* *Argumentos:* `target: string` (host:port), `service_name: string` (opcional).
42+
* `http_rate_limit_stress`: Envia uma rajada curta e rápida de requisições HTTP para testar se as barreiras de Rate Limit da borda (WAF ou Ingress) estão ativas e gerando respostas HTTP 429.
43+
* *Argumentos:* `url: string`, `requests_count: number` (padrão: 30), `concurrency: number` (padrão: 5).
44+
45+
---
46+
47+
## 🔒 Segurança e Sanitização contra Injeção
48+
49+
Como o servidor executa ferramentas do sistema (`ping`, `traceroute`, `mtr`, `curl`), ele possui proteção rígida contra **Command Injection**:
50+
1. **Validação por Regex:** Todos os IPs/Hostnames fornecidos como parâmetros passam pela regex `^[a-zA-Z0-9.-]+$`. Qualquer caractere suspeito (como `;`, `&`, `|`, `$`, `\n`) resulta em rejeição imediata do payload com HTTP 400.
51+
2. **Parâmetros Isolados:** Executamos subprocessos via `child_process.execFile` em vez de `exec`. Isso evita que os argumentos passem por um shell interpretador, impedindo qualquer chance de injeção de parâmetros adicionais.
52+
3. **Segurança HTTP:** Toda a comunicação é protegida por um Bearer Token (`MCP_API_KEY`) passado no header `Authorization`.
53+
54+
---
55+
56+
## 🚀 Como Iniciar e Compilar (Localmente)
57+
58+
### 1. Instalar as dependências
59+
```bash
60+
npm install
61+
```
62+
63+
### 2. Configurar a chave de segurança no ambiente
64+
```bash
65+
export MCP_API_KEY="uma-chave-secreta-e-longa-aqui"
66+
```
67+
68+
### 3. Rodar em modo de desenvolvimento
69+
```bash
70+
npm run dev
71+
```
72+
73+
### 4. Compilar e Rodar em produção
74+
```bash
75+
npm run build
76+
npm start
77+
```
78+
79+
O servidor escutará na porta `3000` (ou na porta definida na variável de ambiente `PORT`).
80+
81+
---
82+
83+
## 🐳 Construindo e Executando via Docker
84+
85+
O Dockerfile utiliza build multi-estágio para manter a imagem leve e segura, e roda as ferramentas sob o usuário não-root `node`.
86+
87+
### Build da Imagem
88+
```bash
89+
docker build -t ghcr.io/heraque/debugtools-mcp:v1.0.0 .
90+
```
91+
92+
### Executar Localmente via Container
93+
```bash
94+
docker run -d \
95+
-p 3000:3000 \
96+
-e MCP_API_KEY="sua-chave-secreta" \
97+
--cap-add=NET_RAW \
98+
ghcr.io/heraque/debugtools-mcp:v1.0.0
99+
```
100+
101+
> [!NOTE]
102+
> A permissão `--cap-add=NET_RAW` é opcional, mas recomendada para que os comandos de `ping` e `mtu_path_discovery` executados dentro do container Linux tenham permissão para abrir sockets ICMP diretamente.
103+
104+
---
105+
106+
## ☸️ Implantação no Kubernetes (VPS Oracle Cloud)
107+
108+
Os manifestos estão disponíveis na pasta `./k8s`. Eles sobem o servidor de forma isolada e o expõem na internet por meio de um serviço com `LoadBalancer` (que aloca um IP público na Oracle Cloud).
109+
110+
### 1. Criar a Secret com o Token de API
111+
Substitua pelo seu token secreto:
112+
```bash
113+
kubectl create secret generic debugtools-mcp-secret \
114+
--from-literal=api-key="sua-chave-secreta-hermes-mcp"
115+
```
116+
117+
### 2. Aplicar os Manifestos
118+
```bash
119+
kubectl apply -f k8s/deployment.yaml
120+
kubectl apply -f k8s/service.yaml
121+
```
122+
123+
---
124+
125+
## 🤝 Integração do Agente SRE "Hermes" (Cliente MCP)
126+
127+
Como o Hermes está rodando dentro de um cluster Kubernetes privado e precisa se conectar à VPS remota, ele fará o transporte via **Server-Sent Events (SSE)**.
128+
129+
Aqui está um exemplo completo de como o agente Hermes pode se conectar ao servidor MCP remoto usando o SDK oficial do MCP em TypeScript/Node.js:
130+
131+
```typescript
132+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
133+
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
134+
135+
async function connectHermesToMcp() {
136+
const vpsServerUrl = "https://seu-mcp-vps.sua-oracle-vps.com"; // IP público ou domínio da VPS
137+
const apiKey = "sua-chave-secreta-hermes-mcp"; // A mesma definida na Secret
138+
139+
console.log("Iniciando transporte SSE com o MCP Diagnostics Server...");
140+
141+
// Configura a conexão SSE apontando para a rota de handshake (/sse)
142+
// Passamos o cabeçalho de autenticação via headers personalizados
143+
const transport = new SSEClientTransport(
144+
new URL(`${vpsServerUrl}/sse`),
145+
{
146+
requestInit: {
147+
headers: {
148+
"Authorization": `Bearer ${apiKey}`
149+
}
150+
}
151+
}
152+
);
153+
154+
const client = new Client(
155+
{
156+
name: "hermes-sre-agent",
157+
version: "1.0.0"
158+
},
159+
{
160+
capabilities: {
161+
tools: {}
162+
}
163+
}
164+
);
165+
166+
// Conecta o cliente Hermes ao servidor remoto
167+
await client.connect(transport);
168+
console.log("Hermes conectado com sucesso ao servidor MCP de diagnósticos!");
169+
170+
// Listar ferramentas de rede disponíveis na VPS
171+
const tools = await client.listTools();
172+
console.log("Ferramentas disponíveis para o Hermes:", tools);
173+
174+
// Exemplo de execução: Testar conectividade de porta de fora para dentro
175+
const probeResponse = await client.callTool({
176+
name: "tcp_port_probe",
177+
arguments: {
178+
ip: "185.190.140.1",
179+
port: 443,
180+
timeout_ms: 3000
181+
}
182+
});
183+
184+
console.log("Resultado do teste de porta de fora para dentro:");
185+
console.log(probeResponse.content[0].text);
186+
}
187+
188+
connectHermesToMcp().catch(console.error);
189+
```

0 commit comments

Comments
 (0)