mirror of
https://github.com/hoshikawa2/agent_platform_oci.git
synced 2026-09-07 10:13:46 +00:00
Authorization Feature
This commit is contained in:
987
Implementando_Basic_Auth.md
Normal file
987
Implementando_Basic_Auth.md
Normal file
@@ -0,0 +1,987 @@
|
||||
# Implementando Basic Auth
|
||||
|
||||
Para validar **todo o circuito com Basic Auth**, você precisa configurar três relações distintas:
|
||||
|
||||
```text
|
||||
Cliente de teste
|
||||
└─ Basic Auth A ─► Agent Gateway :8010
|
||||
└─ Basic Auth B ─► Agent Backend :8000
|
||||
└─ Basic Auth C ─► MCP Gateway :8300
|
||||
```
|
||||
|
||||
Há um detalhe importante: no pacote atual, a autenticação Basic já funciona para chamadas **de entrada**, mas os clientes internos ainda não enviam Basic Auth:
|
||||
|
||||
* `Agent Gateway → Agent Backend` não envia credencial;
|
||||
* `Agent Backend → MCP Gateway` envia apenas Bearer Token.
|
||||
|
||||
Portanto, para testar o circuito inteiro com Basic Auth, faça os dois pequenos ajustes de código descritos abaixo.
|
||||
|
||||
---
|
||||
|
||||
# 1. Preparar o ambiente
|
||||
|
||||
Considere que o ZIP foi extraído em:
|
||||
|
||||
```bash
|
||||
cd agent_framework_oci_authentication_v2_1
|
||||
```
|
||||
|
||||
Crie um único ambiente virtual para facilitar o teste:
|
||||
|
||||
```bash
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
No Windows PowerShell:
|
||||
|
||||
```powershell
|
||||
python -m venv .venv
|
||||
.\.venv\Scripts\Activate.ps1
|
||||
```
|
||||
|
||||
Instale o framework e as dependências dos três componentes:
|
||||
|
||||
```bash
|
||||
pip install -U pip
|
||||
|
||||
pip install -e ./libs/agent_framework
|
||||
|
||||
pip install \
|
||||
-r ./Tuning-Performance/Authentication/agent_template_backend_authentication/requirements.txt \
|
||||
-r ./apps/agent_gateway/requirements.txt \
|
||||
-r ./apps/mcp_gateway/requirements.txt
|
||||
```
|
||||
|
||||
Confirme a importação:
|
||||
|
||||
```bash
|
||||
python -c "from agent_framework.security import install_authentication; print('framework ok')"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 2. Criar três pares de Client ID e Secret
|
||||
|
||||
Use credenciais diferentes para cada trecho. Para teste local:
|
||||
|
||||
| Fluxo | Client ID | Secret de teste |
|
||||
| ----------------------- | -------------------- | --------------------------- |
|
||||
| Cliente → Agent Gateway | `tia-test` | `TiaGateway-Test-2026!` |
|
||||
| Agent Gateway → Backend | `agent-gateway-test` | `GatewayBackend-Test-2026!` |
|
||||
| Backend → MCP Gateway | `agent-backend-test` | `BackendMcp-Test-2026!` |
|
||||
|
||||
Esses valores são apenas para ambiente local. Não os reutilize em produção.
|
||||
|
||||
## Gerar os hashes
|
||||
|
||||
O script está em:
|
||||
|
||||
```text
|
||||
Tuning-Performance/Authentication/
|
||||
agent_template_backend_authentication/
|
||||
scripts/generate_secret_hash.py
|
||||
```
|
||||
|
||||
Execute:
|
||||
|
||||
```bash
|
||||
python Tuning-Performance/Authentication/agent_template_backend_authentication/scripts/generate_secret_hash.py \
|
||||
--secret 'TiaGateway-Test-2026!'
|
||||
```
|
||||
|
||||
Depois:
|
||||
|
||||
```bash
|
||||
python Tuning-Performance/Authentication/agent_template_backend_authentication/scripts/generate_secret_hash.py \
|
||||
--secret 'GatewayBackend-Test-2026!'
|
||||
```
|
||||
|
||||
E:
|
||||
|
||||
```bash
|
||||
python Tuning-Performance/Authentication/agent_template_backend_authentication/scripts/generate_secret_hash.py \
|
||||
--secret 'BackendMcp-Test-2026!'
|
||||
```
|
||||
|
||||
Você receberá três valores semelhantes a:
|
||||
|
||||
```text
|
||||
pbkdf2_sha256:310000:<salt>:<digest>
|
||||
```
|
||||
|
||||
Guarde-os temporariamente:
|
||||
|
||||
```bash
|
||||
HASH_CLIENT_GATEWAY='pbkdf2_sha256:310000:...'
|
||||
HASH_GATEWAY_BACKEND='pbkdf2_sha256:310000:...'
|
||||
HASH_BACKEND_MCP='pbkdf2_sha256:310000:...'
|
||||
```
|
||||
|
||||
O hash muda a cada execução porque o salt é aleatório. Isso é esperado.
|
||||
|
||||
---
|
||||
|
||||
# 3. Configurar o Agent Gateway
|
||||
|
||||
Entre no diretório:
|
||||
|
||||
```bash
|
||||
cd apps/agent_gateway
|
||||
```
|
||||
|
||||
Copie o exemplo:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Adicione ao final do `.env`:
|
||||
|
||||
```env
|
||||
# Entrada: cliente/TIA -> Agent Gateway
|
||||
AGENT_GATEWAY_AUTH_ENABLED=true
|
||||
AGENT_GATEWAY_AUTH_MODE=basic
|
||||
AGENT_GATEWAY_AUTH_BASIC_CLIENT_ID=tia-test
|
||||
AGENT_GATEWAY_AUTH_BASIC_SECRET_HASH=COLE_AQUI_HASH_CLIENT_GATEWAY
|
||||
AGENT_GATEWAY_AUTH_BASIC_REALM=agent-gateway
|
||||
|
||||
AGENT_GATEWAY_AUTH_PUBLIC_PATHS=/health,/docs,/openapi.json,/redoc
|
||||
AGENT_GATEWAY_AUTH_PUBLIC_PREFIXES=
|
||||
|
||||
# Saída: Agent Gateway -> Agent Backend
|
||||
BACKEND_AUTH_MODE=basic
|
||||
BACKEND_AUTH_CLIENT_ID=agent-gateway-test
|
||||
BACKEND_AUTH_SECRET=GatewayBackend-Test-2026!
|
||||
```
|
||||
|
||||
Não coloque aspas no `.env`:
|
||||
|
||||
```env
|
||||
BACKEND_AUTH_SECRET=GatewayBackend-Test-2026!
|
||||
```
|
||||
|
||||
O arquivo de backends já aponta o backend Contas para:
|
||||
|
||||
```yaml
|
||||
contas:
|
||||
url: http://localhost:8000
|
||||
```
|
||||
|
||||
Arquivo:
|
||||
|
||||
```text
|
||||
apps/agent_gateway/config/backends.yaml
|
||||
```
|
||||
|
||||
Para este teste, mantenha apenas o backend `contas` ou force o backend no payload. Caso contrário, pedidos sobre ofertas e suporte podem ser roteados para portas em que nenhum backend está rodando.
|
||||
|
||||
---
|
||||
|
||||
# 4. Fazer o Agent Gateway enviar Basic Auth ao backend
|
||||
|
||||
Abra:
|
||||
|
||||
```text
|
||||
libs/agent_framework/src/agent_framework/global_supervisor/client.py
|
||||
```
|
||||
|
||||
Substitua a classe `BackendClient` por uma versão que aceite autenticação Basic.
|
||||
|
||||
No início do arquivo, adicione:
|
||||
|
||||
```python
|
||||
import os
|
||||
```
|
||||
|
||||
Altere o construtor:
|
||||
|
||||
```python
|
||||
class BackendClient:
|
||||
def __init__(
|
||||
self,
|
||||
timeout_seconds: float = 120.0,
|
||||
basic_client_id: str | None = None,
|
||||
basic_secret: str | None = None,
|
||||
):
|
||||
self.timeout_seconds = timeout_seconds
|
||||
self.basic_client_id = basic_client_id
|
||||
self.basic_secret = basic_secret
|
||||
|
||||
def _auth(self) -> httpx.BasicAuth | None:
|
||||
if self.basic_client_id and self.basic_secret:
|
||||
return httpx.BasicAuth(
|
||||
username=self.basic_client_id,
|
||||
password=self.basic_secret,
|
||||
)
|
||||
return None
|
||||
```
|
||||
|
||||
No método `call_message`, troque:
|
||||
|
||||
```python
|
||||
resp = await client.post(url, json=payload)
|
||||
```
|
||||
|
||||
por:
|
||||
|
||||
```python
|
||||
resp = await client.post(
|
||||
url,
|
||||
json=payload,
|
||||
auth=self._auth(),
|
||||
)
|
||||
```
|
||||
|
||||
No método `health`, você pode manter `/health` público. Caso queira enviar autenticação também, use:
|
||||
|
||||
```python
|
||||
resp = await client.get(url, auth=self._auth())
|
||||
```
|
||||
|
||||
Agora abra:
|
||||
|
||||
```text
|
||||
apps/agent_gateway/app/main.py
|
||||
```
|
||||
|
||||
Adicione:
|
||||
|
||||
```python
|
||||
import os
|
||||
```
|
||||
|
||||
Troque:
|
||||
|
||||
```python
|
||||
backend_client = BackendClient(
|
||||
timeout_seconds=settings.BACKEND_TIMEOUT_SECONDS
|
||||
)
|
||||
```
|
||||
|
||||
por:
|
||||
|
||||
```python
|
||||
backend_client = BackendClient(
|
||||
timeout_seconds=settings.BACKEND_TIMEOUT_SECONDS,
|
||||
basic_client_id=os.getenv("BACKEND_AUTH_CLIENT_ID"),
|
||||
basic_secret=os.getenv("BACKEND_AUTH_SECRET"),
|
||||
)
|
||||
```
|
||||
|
||||
Isso implementa:
|
||||
|
||||
```text
|
||||
Agent Gateway → Agent Backend
|
||||
Authorization: Basic base64(agent-gateway-test:GatewayBackend-Test-2026!)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 5. Configurar o Agent Backend autenticado
|
||||
|
||||
Entre no diretório:
|
||||
|
||||
```bash
|
||||
cd Tuning-Performance/Authentication/agent_template_backend_authentication
|
||||
```
|
||||
|
||||
Copie o exemplo:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Ajuste a seção de autenticação:
|
||||
|
||||
```env
|
||||
# Entrada: Agent Gateway -> Agent Backend
|
||||
AGENT_AUTH_ENABLED=true
|
||||
AGENT_AUTH_MODE=basic
|
||||
AGENT_AUTH_BASIC_CLIENT_ID=agent-gateway-test
|
||||
AGENT_AUTH_BASIC_SECRET_HASH=COLE_AQUI_HASH_GATEWAY_BACKEND
|
||||
AGENT_AUTH_BASIC_REALM=agent-contas
|
||||
|
||||
AGENT_AUTH_PUBLIC_PATHS=/health,/docs,/openapi.json,/redoc
|
||||
AGENT_AUTH_PUBLIC_PREFIXES=
|
||||
```
|
||||
|
||||
Para usar o MCP Gateway:
|
||||
|
||||
```env
|
||||
MCP_GATEWAY_ENABLED=true
|
||||
MCP_GATEWAY_URL=http://localhost:8300
|
||||
MCP_GATEWAY_TIMEOUT_SECONDS=60
|
||||
|
||||
# Saída: Agent Backend -> MCP Gateway
|
||||
MCP_GATEWAY_AUTH_MODE=basic
|
||||
MCP_GATEWAY_BASIC_CLIENT_ID=agent-backend-test
|
||||
MCP_GATEWAY_BASIC_SECRET=BackendMcp-Test-2026!
|
||||
```
|
||||
|
||||
Para evitar dependências externas durante o primeiro teste, configure também:
|
||||
|
||||
```env
|
||||
LLM_PROVIDER=mock
|
||||
ENABLE_LANGFUSE=false
|
||||
ENABLE_ANALYTICS=false
|
||||
|
||||
SESSION_REPOSITORY_PROVIDER=memory
|
||||
MEMORY_REPOSITORY_PROVIDER=memory
|
||||
CHECKPOINT_REPOSITORY_PROVIDER=memory
|
||||
CACHE_PROVIDER=memory
|
||||
USAGE_REPOSITORY_PROVIDER=memory
|
||||
```
|
||||
|
||||
Os nomes exatos de alguns providers podem depender do arquivo de configuração atual do framework. Caso o `.env.example` já contenha valores locais ou mock, preserve-os.
|
||||
|
||||
---
|
||||
|
||||
# 6. Fazer o Backend enviar Basic Auth ao MCP Gateway
|
||||
|
||||
Abra:
|
||||
|
||||
```text
|
||||
libs/agent_framework/src/agent_framework/gateways/mcp_gateway_client.py
|
||||
```
|
||||
|
||||
Substitua a implementação por:
|
||||
|
||||
```python
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
|
||||
|
||||
class MCPGatewayClient:
|
||||
def __init__(
|
||||
self,
|
||||
base_url: str,
|
||||
token: str | None = None,
|
||||
timeout_seconds: int = 60,
|
||||
auth_mode: str | None = None,
|
||||
basic_client_id: str | None = None,
|
||||
basic_secret: str | None = None,
|
||||
):
|
||||
self.base_url = base_url.rstrip("/")
|
||||
self.token = token
|
||||
self.timeout_seconds = timeout_seconds
|
||||
self.auth_mode = (auth_mode or "").strip().lower()
|
||||
self.basic_client_id = basic_client_id
|
||||
self.basic_secret = basic_secret
|
||||
|
||||
def _headers(self) -> dict[str, str]:
|
||||
if (
|
||||
self.auth_mode == "basic"
|
||||
and self.basic_client_id
|
||||
and self.basic_secret
|
||||
):
|
||||
raw = f"{self.basic_client_id}:{self.basic_secret}".encode("utf-8")
|
||||
encoded = base64.b64encode(raw).decode("ascii")
|
||||
return {"Authorization": f"Basic {encoded}"}
|
||||
|
||||
if self.token:
|
||||
return {"Authorization": f"Bearer {self.token}"}
|
||||
|
||||
return {}
|
||||
|
||||
async def list_tools(self) -> dict[str, Any]:
|
||||
async with httpx.AsyncClient(
|
||||
timeout=self.timeout_seconds
|
||||
) as client:
|
||||
response = await client.get(
|
||||
f"{self.base_url}/v1/tools",
|
||||
headers=self._headers(),
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
async def invoke_tool(
|
||||
self,
|
||||
*,
|
||||
tenant_id: str,
|
||||
agent_id: str,
|
||||
channel: str | None,
|
||||
tool_name: str,
|
||||
arguments: dict[str, Any] | None = None,
|
||||
business_context: dict[str, Any] | None = None,
|
||||
metadata: dict[str, Any] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
payload = {
|
||||
"tenant_id": tenant_id,
|
||||
"agent_id": agent_id,
|
||||
"channel": channel,
|
||||
"tool_name": tool_name,
|
||||
"arguments": arguments or {},
|
||||
"business_context": business_context or {},
|
||||
"metadata": metadata or {},
|
||||
}
|
||||
|
||||
async with httpx.AsyncClient(
|
||||
timeout=self.timeout_seconds
|
||||
) as client:
|
||||
response = await client.post(
|
||||
f"{self.base_url}/v1/tools/{tool_name}/invoke",
|
||||
json=payload,
|
||||
headers=self._headers(),
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
```
|
||||
|
||||
Agora abra:
|
||||
|
||||
```text
|
||||
libs/agent_framework/src/agent_framework/mcp/tool_router.py
|
||||
```
|
||||
|
||||
Localize:
|
||||
|
||||
```python
|
||||
MCPGatewayClient(
|
||||
base_url=getattr(
|
||||
settings,
|
||||
"MCP_GATEWAY_URL",
|
||||
"http://localhost:8300",
|
||||
),
|
||||
token=getattr(settings, "MCP_GATEWAY_TOKEN", None),
|
||||
timeout_seconds=getattr(
|
||||
settings,
|
||||
"MCP_GATEWAY_TIMEOUT_SECONDS",
|
||||
settings.MCP_TOOL_TIMEOUT_SECONDS,
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
Altere para:
|
||||
|
||||
```python
|
||||
MCPGatewayClient(
|
||||
base_url=getattr(
|
||||
settings,
|
||||
"MCP_GATEWAY_URL",
|
||||
"http://localhost:8300",
|
||||
),
|
||||
token=getattr(settings, "MCP_GATEWAY_TOKEN", None),
|
||||
timeout_seconds=getattr(
|
||||
settings,
|
||||
"MCP_GATEWAY_TIMEOUT_SECONDS",
|
||||
settings.MCP_TOOL_TIMEOUT_SECONDS,
|
||||
),
|
||||
auth_mode=getattr(
|
||||
settings,
|
||||
"MCP_GATEWAY_AUTH_MODE",
|
||||
None,
|
||||
),
|
||||
basic_client_id=getattr(
|
||||
settings,
|
||||
"MCP_GATEWAY_BASIC_CLIENT_ID",
|
||||
None,
|
||||
),
|
||||
basic_secret=getattr(
|
||||
settings,
|
||||
"MCP_GATEWAY_BASIC_SECRET",
|
||||
None,
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
Adicione estes campos em:
|
||||
|
||||
```text
|
||||
libs/agent_framework/src/agent_framework/config/settings.py
|
||||
```
|
||||
|
||||
Próximo das configurações existentes de MCP Gateway:
|
||||
|
||||
```python
|
||||
MCP_GATEWAY_AUTH_MODE: str | None = None
|
||||
MCP_GATEWAY_BASIC_CLIENT_ID: str | None = None
|
||||
MCP_GATEWAY_BASIC_SECRET: str | None = None
|
||||
```
|
||||
|
||||
Há também uma factory local em:
|
||||
|
||||
```text
|
||||
Tuning-Performance/Authentication/
|
||||
agent_template_backend_authentication/
|
||||
app/mcp_gateway_client_factory.py
|
||||
```
|
||||
|
||||
Ajuste para:
|
||||
|
||||
```python
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
from agent_framework.gateways import MCPGatewayClient
|
||||
|
||||
|
||||
def build_mcp_gateway_client() -> MCPGatewayClient | None:
|
||||
if os.getenv("MCP_GATEWAY_ENABLED", "true").lower() != "true":
|
||||
return None
|
||||
|
||||
return MCPGatewayClient(
|
||||
base_url=os.getenv(
|
||||
"MCP_GATEWAY_URL",
|
||||
"http://localhost:8300",
|
||||
),
|
||||
token=os.getenv("MCP_GATEWAY_TOKEN") or None,
|
||||
timeout_seconds=int(
|
||||
os.getenv("MCP_GATEWAY_TIMEOUT_SECONDS", "60")
|
||||
),
|
||||
auth_mode=os.getenv("MCP_GATEWAY_AUTH_MODE"),
|
||||
basic_client_id=os.getenv(
|
||||
"MCP_GATEWAY_BASIC_CLIENT_ID"
|
||||
),
|
||||
basic_secret=os.getenv(
|
||||
"MCP_GATEWAY_BASIC_SECRET"
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 7. Configurar o MCP Gateway
|
||||
|
||||
Entre no diretório:
|
||||
|
||||
```bash
|
||||
cd apps/mcp_gateway
|
||||
```
|
||||
|
||||
Crie `.env`:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Adicione:
|
||||
|
||||
```env
|
||||
# Entrada: Agent Backend -> MCP Gateway
|
||||
MCP_GATEWAY_AUTH_ENABLED=true
|
||||
MCP_GATEWAY_AUTH_MODE=basic
|
||||
MCP_GATEWAY_AUTH_BASIC_CLIENT_ID=agent-backend-test
|
||||
MCP_GATEWAY_AUTH_BASIC_SECRET_HASH=COLE_AQUI_HASH_BACKEND_MCP
|
||||
MCP_GATEWAY_AUTH_BASIC_REALM=mcp-gateway
|
||||
|
||||
MCP_GATEWAY_AUTH_PUBLIC_PATHS=/health,/ready,/docs,/openapi.json,/redoc
|
||||
MCP_GATEWAY_AUTH_PUBLIC_PREFIXES=
|
||||
|
||||
MCP_GATEWAY_CONFIG_PATH=config/mcp_gateway.yaml
|
||||
```
|
||||
|
||||
## Desabilitar o mecanismo Bearer legado
|
||||
|
||||
O MCP Gateway ainda possui um segundo mecanismo antigo, configurado dentro de:
|
||||
|
||||
```text
|
||||
apps/mcp_gateway/config/mcp_gateway.yaml
|
||||
```
|
||||
|
||||
Localize a seção:
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
Altere para:
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
enabled: false
|
||||
```
|
||||
|
||||
Isso é necessário porque o novo middleware já faz a autenticação Basic. Caso o `auth_check()` legado continue habilitado, a requisição passará pelo Basic e depois será rejeitada por não possuir Bearer Token.
|
||||
|
||||
---
|
||||
|
||||
# 8. Subir os componentes
|
||||
|
||||
Use quatro terminais.
|
||||
|
||||
## Terminal 1 — MCP Servers
|
||||
|
||||
O MCP Gateway precisa ter pelo menos um servidor MCP disponível para demonstrar uma chamada real.
|
||||
|
||||
Na raiz do projeto:
|
||||
|
||||
```bash
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
Suba o servidor telecom:
|
||||
|
||||
```bash
|
||||
uvicorn mcp.servers.telecom_mcp_server.main:app \
|
||||
--host 0.0.0.0 \
|
||||
--port 8100 \
|
||||
--reload
|
||||
```
|
||||
|
||||
Em outro terminal, caso queira também o retail:
|
||||
|
||||
```bash
|
||||
uvicorn mcp.servers.retail_mcp_server.main:app \
|
||||
--host 0.0.0.0 \
|
||||
--port 8200 \
|
||||
--reload
|
||||
```
|
||||
|
||||
Confira as URLs configuradas em:
|
||||
|
||||
```text
|
||||
apps/mcp_gateway/config/mcp_gateway.yaml
|
||||
```
|
||||
|
||||
Para execução local, devem apontar para:
|
||||
|
||||
```yaml
|
||||
url: http://localhost:8100
|
||||
```
|
||||
|
||||
e:
|
||||
|
||||
```yaml
|
||||
url: http://localhost:8200
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Terminal 2 — MCP Gateway
|
||||
|
||||
```bash
|
||||
cd apps/mcp_gateway
|
||||
source ../../.venv/bin/activate
|
||||
```
|
||||
|
||||
Suba usando `--env-file`. Isso é importante porque o middleware lê variáveis com `os.getenv()`:
|
||||
|
||||
```bash
|
||||
uvicorn app.main:app \
|
||||
--host 0.0.0.0 \
|
||||
--port 8300 \
|
||||
--reload \
|
||||
--env-file .env
|
||||
```
|
||||
|
||||
Teste a saúde pública:
|
||||
|
||||
```bash
|
||||
curl http://localhost:8300/health
|
||||
```
|
||||
|
||||
Teste um endpoint protegido sem credencial:
|
||||
|
||||
```bash
|
||||
curl -i http://localhost:8300/v1/tools
|
||||
```
|
||||
|
||||
Esperado:
|
||||
|
||||
```text
|
||||
HTTP/1.1 401 Unauthorized
|
||||
```
|
||||
|
||||
Teste com Basic Auth:
|
||||
|
||||
```bash
|
||||
curl -i \
|
||||
-u 'agent-backend-test:BackendMcp-Test-2026!' \
|
||||
http://localhost:8300/v1/tools
|
||||
```
|
||||
|
||||
Esperado:
|
||||
|
||||
```text
|
||||
HTTP/1.1 200 OK
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Terminal 3 — Agent Backend
|
||||
|
||||
```bash
|
||||
cd Tuning-Performance/Authentication/agent_template_backend_authentication
|
||||
source ../../../.venv/bin/activate
|
||||
```
|
||||
|
||||
Suba:
|
||||
|
||||
```bash
|
||||
uvicorn app.main:app \
|
||||
--host 0.0.0.0 \
|
||||
--port 8000 \
|
||||
--reload \
|
||||
--env-file .env
|
||||
```
|
||||
|
||||
Teste saúde:
|
||||
|
||||
```bash
|
||||
curl http://localhost:8000/health
|
||||
```
|
||||
|
||||
Teste endpoint protegido sem credencial:
|
||||
|
||||
```bash
|
||||
curl -i http://localhost:8000/agents
|
||||
```
|
||||
|
||||
Esperado:
|
||||
|
||||
```text
|
||||
HTTP/1.1 401 Unauthorized
|
||||
```
|
||||
|
||||
Teste com a credencial usada pelo Agent Gateway:
|
||||
|
||||
```bash
|
||||
curl -i \
|
||||
-u 'agent-gateway-test:GatewayBackend-Test-2026!' \
|
||||
http://localhost:8000/agents
|
||||
```
|
||||
|
||||
Esperado:
|
||||
|
||||
```text
|
||||
HTTP/1.1 200 OK
|
||||
```
|
||||
|
||||
Teste mensagem diretamente:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/gateway/message \
|
||||
-u 'agent-gateway-test:GatewayBackend-Test-2026!' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"channel": "web",
|
||||
"agent_id": "telecom_contas",
|
||||
"tenant_id": "default",
|
||||
"payload": {
|
||||
"text": "Quero consultar minha fatura",
|
||||
"session_id": "teste-backend-001",
|
||||
"user_id": "user-001",
|
||||
"customer_id": "12345",
|
||||
"message_id": "msg-001"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Terminal 4 — Agent Gateway
|
||||
|
||||
```bash
|
||||
cd apps/agent_gateway
|
||||
source ../../.venv/bin/activate
|
||||
```
|
||||
|
||||
Suba:
|
||||
|
||||
```bash
|
||||
uvicorn app.main:app \
|
||||
--host 0.0.0.0 \
|
||||
--port 8010 \
|
||||
--reload \
|
||||
--env-file .env
|
||||
```
|
||||
|
||||
Teste saúde:
|
||||
|
||||
```bash
|
||||
curl http://localhost:8010/health
|
||||
```
|
||||
|
||||
Teste endpoint protegido sem credencial:
|
||||
|
||||
```bash
|
||||
curl -i http://localhost:8010/backends
|
||||
```
|
||||
|
||||
Esperado:
|
||||
|
||||
```text
|
||||
HTTP/1.1 401 Unauthorized
|
||||
```
|
||||
|
||||
Teste com a credencial externa:
|
||||
|
||||
```bash
|
||||
curl -i \
|
||||
-u 'tia-test:TiaGateway-Test-2026!' \
|
||||
http://localhost:8010/backends
|
||||
```
|
||||
|
||||
Esperado:
|
||||
|
||||
```text
|
||||
HTTP/1.1 200 OK
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 9. Validar o circuito completo
|
||||
|
||||
Force o backend `contas` para evitar que o roteador selecione um backend não iniciado:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8010/gateway/message \
|
||||
-u 'tia-test:TiaGateway-Test-2026!' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"channel": "web",
|
||||
"backend_id": "contas",
|
||||
"tenant_id": "default",
|
||||
"agent_id": "telecom_contas",
|
||||
"session_id": "circuito-basic-001",
|
||||
"payload": {
|
||||
"text": "Quero consultar minha fatura",
|
||||
"session_id": "circuito-basic-001",
|
||||
"user_id": "user-001",
|
||||
"customer_id": "12345",
|
||||
"message_id": "msg-circuito-001"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
O circuito esperado é:
|
||||
|
||||
```text
|
||||
curl
|
||||
│ Basic tia-test
|
||||
▼
|
||||
Agent Gateway :8010
|
||||
│ Basic agent-gateway-test
|
||||
▼
|
||||
Agent Backend :8000
|
||||
│ Basic agent-backend-test
|
||||
▼
|
||||
MCP Gateway :8300
|
||||
▼
|
||||
MCP Server :8100 ou :8200
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 10. Como comprovar cada autenticação
|
||||
|
||||
Faça testes negativos em cada trecho.
|
||||
|
||||
## Secret externo incorreto
|
||||
|
||||
```bash
|
||||
curl -i \
|
||||
-u 'tia-test:senha-errada' \
|
||||
http://localhost:8010/backends
|
||||
```
|
||||
|
||||
Resultado esperado:
|
||||
|
||||
```text
|
||||
401 Unauthorized
|
||||
```
|
||||
|
||||
## Secret do gateway para backend incorreto
|
||||
|
||||
Altere temporariamente no `apps/agent_gateway/.env`:
|
||||
|
||||
```env
|
||||
BACKEND_AUTH_SECRET=senha-errada
|
||||
```
|
||||
|
||||
Reinicie o Agent Gateway e envie uma mensagem.
|
||||
|
||||
O gateway deverá retornar erro de backend, normalmente:
|
||||
|
||||
```text
|
||||
502 Bad Gateway
|
||||
```
|
||||
|
||||
O erro interno será originado por um:
|
||||
|
||||
```text
|
||||
401 Unauthorized
|
||||
```
|
||||
|
||||
do Agent Backend.
|
||||
|
||||
## Secret do backend para MCP incorreto
|
||||
|
||||
Altere temporariamente:
|
||||
|
||||
```env
|
||||
MCP_GATEWAY_BASIC_SECRET=senha-errada
|
||||
```
|
||||
|
||||
Reinicie o backend e execute uma frase que acione uma ferramenta MCP.
|
||||
|
||||
O backend deverá registrar falha na chamada ao MCP Gateway com:
|
||||
|
||||
```text
|
||||
401 Unauthorized
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 11. Verificação rápida de portas
|
||||
|
||||
No Linux ou WSL:
|
||||
|
||||
```bash
|
||||
ss -lntp | grep -E ':8000|:8010|:8100|:8200|:8300'
|
||||
```
|
||||
|
||||
No Windows PowerShell:
|
||||
|
||||
```powershell
|
||||
Get-NetTCPConnection -State Listen |
|
||||
Where-Object LocalPort -in 8000,8010,8100,8200,8300 |
|
||||
Sort-Object LocalPort
|
||||
```
|
||||
|
||||
Você deverá ver:
|
||||
|
||||
```text
|
||||
8000 Agent Backend
|
||||
8010 Agent Gateway
|
||||
8100 Telecom MCP Server
|
||||
8200 Retail MCP Server
|
||||
8300 MCP Gateway
|
||||
```
|
||||
|
||||
## Observação importante
|
||||
|
||||
O segredo original precisa existir no componente cliente:
|
||||
|
||||
```text
|
||||
TIA ou curl:
|
||||
TiaGateway-Test-2026!
|
||||
|
||||
Agent Gateway:
|
||||
GatewayBackend-Test-2026!
|
||||
|
||||
Agent Backend:
|
||||
BackendMcp-Test-2026!
|
||||
```
|
||||
|
||||
Os componentes servidores armazenam apenas os hashes:
|
||||
|
||||
```text
|
||||
Agent Gateway:
|
||||
hash de TiaGateway-Test-2026!
|
||||
|
||||
Agent Backend:
|
||||
hash de GatewayBackend-Test-2026!
|
||||
|
||||
MCP Gateway:
|
||||
hash de BackendMcp-Test-2026!
|
||||
```
|
||||
|
||||
Em produção, os segredos originais e hashes devem vir de Vault ou Kubernetes Secret, não de arquivos `.env`.
|
||||
Reference in New Issue
Block a user