@purecore/one-jwt-4-all 1.2.0
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.
- package/CHANGELOG.md +87 -0
- package/LICENSE-COGFULNESS +117 -0
- package/examples/MTLS_AGENTS.md +288 -0
- package/examples/SELF_HEALING_AGENTS.md +269 -0
- package/examples/SIGNAL_E2EE.md +457 -0
- package/examples/mtls-agents.ts +539 -0
- package/examples/self-healing-agents.ts +355 -0
- package/examples/signal-e2ee-agents.ts +827 -0
- package/package.json +20 -0
- package/readme.md +507 -0
- package/reports/22-12-2024_01-50.md +165 -0
- package/src/examples.mcps.ts +86 -0
- package/src/examples.ts +81 -0
- package/src/index.ts +286 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Healing Agentic Conversational System com mTLS
|
|
3
|
+
*
|
|
4
|
+
* Sistema onde dois agentes se identificam usando:
|
|
5
|
+
* 1. JWTs do mesmo servidor (autenticação de aplicação)
|
|
6
|
+
* 2. mTLS (mutual TLS) para autenticação de transporte
|
|
7
|
+
*
|
|
8
|
+
* Isso fornece segurança em duas camadas:
|
|
9
|
+
* - JWT: Autenticação de identidade e contexto
|
|
10
|
+
* - mTLS: Autenticação de transporte e prevenção de MITM
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { SignJWT, jwtVerify, generateKeyPair } from '../src/index';
|
|
14
|
+
import * as crypto from 'node:crypto';
|
|
15
|
+
import * as tls from 'node:tls';
|
|
16
|
+
import * as net from 'node:net';
|
|
17
|
+
import { EventEmitter } from 'node:events';
|
|
18
|
+
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Geração de Certificados para mTLS
|
|
21
|
+
// ============================================================================
|
|
22
|
+
|
|
23
|
+
interface AgentCertificate {
|
|
24
|
+
cert: string;
|
|
25
|
+
key: string;
|
|
26
|
+
publicKey: string;
|
|
27
|
+
agentId: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
class CertificateAuthority {
|
|
31
|
+
private caKey: crypto.KeyObject;
|
|
32
|
+
private caCert: string;
|
|
33
|
+
|
|
34
|
+
constructor() {
|
|
35
|
+
// Gerar CA (Certificate Authority) para assinar certificados dos agentes
|
|
36
|
+
const caKeys = crypto.generateKeyPairSync('rsa', {
|
|
37
|
+
modulusLength: 2048,
|
|
38
|
+
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
39
|
+
privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
this.caKey = crypto.createPrivateKey(caKeys.privateKey);
|
|
43
|
+
|
|
44
|
+
// Criar certificado auto-assinado da CA
|
|
45
|
+
this.caCert = this.createSelfSignedCert(
|
|
46
|
+
'CN=Agentic System CA',
|
|
47
|
+
caKeys.publicKey,
|
|
48
|
+
caKeys.privateKey
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Gera certificado para um agente
|
|
54
|
+
*/
|
|
55
|
+
generateAgentCertificate(agentId: string): AgentCertificate {
|
|
56
|
+
// Gerar par de chaves para o agente
|
|
57
|
+
const agentKeys = crypto.generateKeyPairSync('rsa', {
|
|
58
|
+
modulusLength: 2048,
|
|
59
|
+
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
60
|
+
privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Criar certificado assinado pela CA
|
|
64
|
+
const cert = this.createSignedCert(
|
|
65
|
+
`CN=${agentId}`,
|
|
66
|
+
agentKeys.publicKey,
|
|
67
|
+
agentKeys.privateKey
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
cert,
|
|
72
|
+
key: agentKeys.privateKey,
|
|
73
|
+
publicKey: agentKeys.publicKey,
|
|
74
|
+
agentId
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Retorna o certificado da CA (para validação)
|
|
80
|
+
*/
|
|
81
|
+
getCACertificate(): string {
|
|
82
|
+
return this.caCert;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private createSelfSignedCert(subject: string, publicKey: string, privateKey: string): string {
|
|
86
|
+
// Para produção, use uma biblioteca como node-forge ou openssl
|
|
87
|
+
// Aqui criamos um certificado básico usando Node.js crypto
|
|
88
|
+
const cert = crypto.createCertificate({
|
|
89
|
+
subject: subject,
|
|
90
|
+
publicKey: publicKey,
|
|
91
|
+
serialNumber: crypto.randomBytes(16).toString('hex'),
|
|
92
|
+
notBefore: new Date(),
|
|
93
|
+
notAfter: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000), // 1 ano
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
return cert.toString();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private createSignedCert(subject: string, publicKey: string, privateKey: string): string {
|
|
100
|
+
// Similar ao acima, mas assinado pela CA
|
|
101
|
+
// Em produção, use biblioteca adequada ou OpenSSL
|
|
102
|
+
return this.createSelfSignedCert(subject, publicKey, privateKey);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ============================================================================
|
|
107
|
+
// Token Authority (mesma do exemplo anterior)
|
|
108
|
+
// ============================================================================
|
|
109
|
+
|
|
110
|
+
class TokenAuthority {
|
|
111
|
+
private privateKey: crypto.KeyObject;
|
|
112
|
+
public publicKey: crypto.KeyObject;
|
|
113
|
+
private issuer = 'urn:agentic-system:authority';
|
|
114
|
+
private audience = 'urn:agentic-system:agents';
|
|
115
|
+
|
|
116
|
+
constructor() {
|
|
117
|
+
const keys = generateKeyPair();
|
|
118
|
+
this.privateKey = crypto.createPrivateKey(keys.privateKey);
|
|
119
|
+
this.publicKey = crypto.createPublicKey(keys.publicKey);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async issueAgentToken(
|
|
123
|
+
agentId: string,
|
|
124
|
+
agentType: 'primary' | 'secondary',
|
|
125
|
+
conversationId: string,
|
|
126
|
+
capabilities: string[] = []
|
|
127
|
+
): Promise<string> {
|
|
128
|
+
return await new SignJWT({
|
|
129
|
+
agentId,
|
|
130
|
+
agentType,
|
|
131
|
+
conversationId,
|
|
132
|
+
capabilities,
|
|
133
|
+
issuedAt: Date.now()
|
|
134
|
+
})
|
|
135
|
+
.setProtectedHeader({ alg: 'EdDSA', typ: 'JWT' })
|
|
136
|
+
.setIssuedAt()
|
|
137
|
+
.setIssuer(this.issuer)
|
|
138
|
+
.setAudience(this.audience)
|
|
139
|
+
.setSubject(agentId)
|
|
140
|
+
.setExpirationTime('5m')
|
|
141
|
+
.sign(this.privateKey);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async renewToken(oldToken: string): Promise<string> {
|
|
145
|
+
try {
|
|
146
|
+
const { payload } = await jwtVerify(oldToken, this.publicKey, {
|
|
147
|
+
issuer: this.issuer,
|
|
148
|
+
audience: this.audience,
|
|
149
|
+
}).catch(() => {
|
|
150
|
+
const parts = oldToken.split('.');
|
|
151
|
+
if (parts.length !== 3) throw new Error('Token inválido');
|
|
152
|
+
const decoded = JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf-8'));
|
|
153
|
+
return { payload: decoded };
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
return await this.issueAgentToken(
|
|
157
|
+
payload.agentId as string,
|
|
158
|
+
payload.agentType as 'primary' | 'secondary',
|
|
159
|
+
payload.conversationId as string,
|
|
160
|
+
payload.capabilities as string[]
|
|
161
|
+
);
|
|
162
|
+
} catch (error) {
|
|
163
|
+
throw new Error(`Falha ao renovar token: ${error}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ============================================================================
|
|
169
|
+
// Agente com Suporte a mTLS
|
|
170
|
+
// ============================================================================
|
|
171
|
+
|
|
172
|
+
interface AgentMessage {
|
|
173
|
+
from: string;
|
|
174
|
+
to: string;
|
|
175
|
+
content: string;
|
|
176
|
+
timestamp: number;
|
|
177
|
+
messageId: string;
|
|
178
|
+
jwt: string; // Token JWT incluído na mensagem
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
class mTLSAgent extends EventEmitter {
|
|
182
|
+
private agentId: string;
|
|
183
|
+
private agentType: 'primary' | 'secondary';
|
|
184
|
+
private conversationId: string;
|
|
185
|
+
private capabilities: string[];
|
|
186
|
+
private token: string | null = null;
|
|
187
|
+
private tokenExpiry: number = 0;
|
|
188
|
+
private renewalThreshold: number = 60;
|
|
189
|
+
private authority: TokenAuthority;
|
|
190
|
+
private messageHistory: AgentMessage[] = [];
|
|
191
|
+
|
|
192
|
+
// Certificados mTLS
|
|
193
|
+
private certificate: AgentCertificate;
|
|
194
|
+
private caCert: string;
|
|
195
|
+
private tlsServer: tls.Server | null = null;
|
|
196
|
+
private tlsConnections: Map<string, tls.TLSSocket> = new Map();
|
|
197
|
+
|
|
198
|
+
constructor(
|
|
199
|
+
agentId: string,
|
|
200
|
+
agentType: 'primary' | 'secondary',
|
|
201
|
+
authority: TokenAuthority,
|
|
202
|
+
certificate: AgentCertificate,
|
|
203
|
+
caCert: string,
|
|
204
|
+
capabilities: string[] = []
|
|
205
|
+
) {
|
|
206
|
+
super();
|
|
207
|
+
this.agentId = agentId;
|
|
208
|
+
this.agentType = agentType;
|
|
209
|
+
this.authority = authority;
|
|
210
|
+
this.certificate = certificate;
|
|
211
|
+
this.caCert = caCert;
|
|
212
|
+
this.capabilities = capabilities;
|
|
213
|
+
this.conversationId = `conv-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
async initialize(): Promise<void> {
|
|
217
|
+
this.token = await this.authority.issueAgentToken(
|
|
218
|
+
this.agentId,
|
|
219
|
+
this.agentType,
|
|
220
|
+
this.conversationId,
|
|
221
|
+
this.capabilities
|
|
222
|
+
);
|
|
223
|
+
this.tokenExpiry = Date.now() + (5 * 60 * 1000);
|
|
224
|
+
console.log(`🤖 [${this.agentId}] Agente inicializado com mTLS e token válido até ${new Date(this.tokenExpiry).toISOString()}`);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
private async ensureValidToken(): Promise<void> {
|
|
228
|
+
const now = Date.now();
|
|
229
|
+
const timeUntilExpiry = this.tokenExpiry - now;
|
|
230
|
+
|
|
231
|
+
if (!this.token || timeUntilExpiry < this.renewalThreshold * 1000) {
|
|
232
|
+
if (this.token) {
|
|
233
|
+
console.log(`🔄 [${this.agentId}] Token próximo de expirar, renovando...`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
try {
|
|
237
|
+
if (this.token) {
|
|
238
|
+
this.token = await this.authority.renewToken(this.token);
|
|
239
|
+
} else {
|
|
240
|
+
await this.initialize();
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
this.tokenExpiry = Date.now() + (5 * 60 * 1000);
|
|
245
|
+
console.log(`✅ [${this.agentId}] Token renovado com sucesso.`);
|
|
246
|
+
} catch (error) {
|
|
247
|
+
console.error(`❌ [${this.agentId}] Erro ao renovar token:`, error);
|
|
248
|
+
await this.initialize();
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Inicia servidor TLS para receber conexões de outros agentes
|
|
255
|
+
*/
|
|
256
|
+
startTLSServer(port: number): Promise<void> {
|
|
257
|
+
return new Promise((resolve, reject) => {
|
|
258
|
+
const options: tls.TlsOptions = {
|
|
259
|
+
cert: this.certificate.cert,
|
|
260
|
+
key: this.certificate.key,
|
|
261
|
+
ca: [this.caCert], // Certificados aceitos (CA)
|
|
262
|
+
requestCert: true, // Requer certificado do cliente (mTLS)
|
|
263
|
+
rejectUnauthorized: true, // Rejeita conexões não autorizadas
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
this.tlsServer = tls.createServer(options, (socket: tls.TLSSocket) => {
|
|
267
|
+
const peerCert = socket.getPeerCertificate();
|
|
268
|
+
const peerId = peerCert.subject?.CN || 'unknown';
|
|
269
|
+
|
|
270
|
+
console.log(`🔒 [${this.agentId}] Conexão mTLS estabelecida com ${peerId}`);
|
|
271
|
+
|
|
272
|
+
// Verificar certificado do peer
|
|
273
|
+
if (!peerCert || !socket.authorized) {
|
|
274
|
+
console.error(`❌ [${this.agentId}] Conexão rejeitada: certificado inválido`);
|
|
275
|
+
socket.destroy();
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
this.tlsConnections.set(peerId, socket);
|
|
280
|
+
|
|
281
|
+
socket.on('data', async (data) => {
|
|
282
|
+
try {
|
|
283
|
+
const message: AgentMessage = JSON.parse(data.toString());
|
|
284
|
+
await this.handleIncomingMessage(message, peerId);
|
|
285
|
+
} catch (error) {
|
|
286
|
+
console.error(`❌ [${this.agentId}] Erro ao processar mensagem:`, error);
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
socket.on('close', () => {
|
|
291
|
+
console.log(`🔌 [${this.agentId}] Conexão mTLS fechada com ${peerId}`);
|
|
292
|
+
this.tlsConnections.delete(peerId);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
socket.on('error', (error) => {
|
|
296
|
+
console.error(`❌ [${this.agentId}] Erro na conexão TLS:`, error);
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
this.tlsServer.listen(port, () => {
|
|
301
|
+
console.log(`🔒 [${this.agentId}] Servidor mTLS iniciado na porta ${port}`);
|
|
302
|
+
resolve();
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
this.tlsServer.on('error', reject);
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Conecta a outro agente via mTLS
|
|
311
|
+
*/
|
|
312
|
+
async connectToPeer(host: string, port: number, peerId: string): Promise<void> {
|
|
313
|
+
return new Promise((resolve, reject) => {
|
|
314
|
+
const options: tls.ConnectionOptions = {
|
|
315
|
+
cert: this.certificate.cert,
|
|
316
|
+
key: this.certificate.key,
|
|
317
|
+
ca: [this.caCert],
|
|
318
|
+
rejectUnauthorized: true,
|
|
319
|
+
servername: peerId, // SNI (Server Name Indication)
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
const socket = tls.connect(port, host, options, () => {
|
|
323
|
+
const peerCert = socket.getPeerCertificate();
|
|
324
|
+
|
|
325
|
+
if (!socket.authorized) {
|
|
326
|
+
reject(new Error(`Conexão não autorizada: ${socket.authorizationError}`));
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
console.log(`🔒 [${this.agentId}] Conectado via mTLS a ${peerId}`);
|
|
331
|
+
this.tlsConnections.set(peerId, socket);
|
|
332
|
+
resolve();
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
socket.on('data', async (data) => {
|
|
336
|
+
try {
|
|
337
|
+
const message: AgentMessage = JSON.parse(data.toString());
|
|
338
|
+
await this.handleIncomingMessage(message, peerId);
|
|
339
|
+
} catch (error) {
|
|
340
|
+
console.error(`❌ [${this.agentId}] Erro ao processar mensagem:`, error);
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
socket.on('error', reject);
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Envia mensagem para outro agente via mTLS
|
|
350
|
+
*/
|
|
351
|
+
async sendMessage(peerId: string, content: string): Promise<void> {
|
|
352
|
+
await this.ensureValidToken();
|
|
353
|
+
|
|
354
|
+
if (!this.token) {
|
|
355
|
+
throw new Error('Agente não possui token válido');
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const socket = this.tlsConnections.get(peerId);
|
|
359
|
+
if (!socket || socket.destroyed) {
|
|
360
|
+
throw new Error(`Conexão mTLS não estabelecida com ${peerId}`);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const message: AgentMessage = {
|
|
364
|
+
from: this.agentId,
|
|
365
|
+
to: peerId,
|
|
366
|
+
content,
|
|
367
|
+
timestamp: Date.now(),
|
|
368
|
+
messageId: `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
369
|
+
jwt: this.token // Inclui JWT na mensagem para verificação de identidade
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
// Verificar identidade do peer via JWT antes de enviar
|
|
373
|
+
// (a verificação mTLS já garante que é o certificado correto)
|
|
374
|
+
|
|
375
|
+
this.messageHistory.push(message);
|
|
376
|
+
socket.write(JSON.stringify(message));
|
|
377
|
+
|
|
378
|
+
console.log(`📤 [${this.agentId}] → [${peerId}] (mTLS): ${content}`);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Processa mensagem recebida
|
|
383
|
+
*/
|
|
384
|
+
private async handleIncomingMessage(message: AgentMessage, peerId: string): Promise<void> {
|
|
385
|
+
await this.ensureValidToken();
|
|
386
|
+
|
|
387
|
+
// Verificar JWT do remetente
|
|
388
|
+
try {
|
|
389
|
+
const { payload } = await jwtVerify(message.jwt, this.authority.publicKey, {
|
|
390
|
+
issuer: 'urn:agentic-system:authority',
|
|
391
|
+
audience: 'urn:agentic-system:agents'
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
// Verificar se está na mesma conversa
|
|
395
|
+
if (payload.conversationId !== this.conversationId) {
|
|
396
|
+
throw new Error('Agente não está na mesma conversa');
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Verificar se o agentId do JWT corresponde ao certificado
|
|
400
|
+
if (payload.agentId !== peerId) {
|
|
401
|
+
throw new Error('Mismatch entre certificado mTLS e JWT');
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
this.messageHistory.push(message);
|
|
405
|
+
console.log(`📥 [${this.agentId}] ← [${message.from}] (mTLS): ${message.content}`);
|
|
406
|
+
|
|
407
|
+
this.emit('message', message);
|
|
408
|
+
} catch (error) {
|
|
409
|
+
console.error(`❌ [${this.agentId}] Mensagem rejeitada:`, error);
|
|
410
|
+
throw error;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
getToken(): string {
|
|
415
|
+
if (!this.token) {
|
|
416
|
+
throw new Error('Agente não possui token');
|
|
417
|
+
}
|
|
418
|
+
return this.token;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
getConversationHistory(): AgentMessage[] {
|
|
422
|
+
return [...this.messageHistory];
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
startAutoRenewal(intervalMs: number = 30000): void {
|
|
426
|
+
setInterval(async () => {
|
|
427
|
+
await this.ensureValidToken();
|
|
428
|
+
}, intervalMs);
|
|
429
|
+
|
|
430
|
+
console.log(`🔄 [${this.agentId}] Auto-renovação de token ativada`);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
stop(): void {
|
|
434
|
+
this.tlsConnections.forEach(socket => socket.destroy());
|
|
435
|
+
this.tlsConnections.clear();
|
|
436
|
+
|
|
437
|
+
if (this.tlsServer) {
|
|
438
|
+
this.tlsServer.close();
|
|
439
|
+
this.tlsServer = null;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// ============================================================================
|
|
445
|
+
// Exemplo de Uso
|
|
446
|
+
// ============================================================================
|
|
447
|
+
|
|
448
|
+
async function demonstrateMTLSAgents() {
|
|
449
|
+
console.log('🚀 Demonstração de Self-Healing Agents com mTLS\n');
|
|
450
|
+
|
|
451
|
+
// 1. Criar CA e Autoridade de Tokens
|
|
452
|
+
const ca = new CertificateAuthority();
|
|
453
|
+
const tokenAuthority = new TokenAuthority();
|
|
454
|
+
console.log('✅ CA e Autoridade de Tokens criadas\n');
|
|
455
|
+
|
|
456
|
+
// 2. Gerar certificados para os agentes
|
|
457
|
+
const certA = ca.generateAgentCertificate('agent-alpha');
|
|
458
|
+
const certB = ca.generateAgentCertificate('agent-beta');
|
|
459
|
+
const caCert = ca.getCACertificate();
|
|
460
|
+
console.log('✅ Certificados mTLS gerados para os agentes\n');
|
|
461
|
+
|
|
462
|
+
// 3. Criar agentes com mTLS
|
|
463
|
+
const agentA = new mTLSAgent(
|
|
464
|
+
'agent-alpha',
|
|
465
|
+
'primary',
|
|
466
|
+
tokenAuthority,
|
|
467
|
+
certA,
|
|
468
|
+
caCert,
|
|
469
|
+
['reasoning', 'memory']
|
|
470
|
+
);
|
|
471
|
+
|
|
472
|
+
const agentB = new mTLSAgent(
|
|
473
|
+
'agent-beta',
|
|
474
|
+
'secondary',
|
|
475
|
+
tokenAuthority,
|
|
476
|
+
certB,
|
|
477
|
+
caCert,
|
|
478
|
+
['analysis', 'synthesis']
|
|
479
|
+
);
|
|
480
|
+
|
|
481
|
+
// 4. Inicializar agentes
|
|
482
|
+
await agentA.initialize();
|
|
483
|
+
await agentB.initialize();
|
|
484
|
+
console.log('');
|
|
485
|
+
|
|
486
|
+
// 5. Iniciar servidores TLS
|
|
487
|
+
await agentA.startTLSServer(8443);
|
|
488
|
+
await agentB.startTLSServer(8444);
|
|
489
|
+
console.log('');
|
|
490
|
+
|
|
491
|
+
// 6. Estabelecer conexões mTLS
|
|
492
|
+
await agentA.connectToPeer('localhost', 8444, 'agent-beta');
|
|
493
|
+
await agentB.connectToPeer('localhost', 8443, 'agent-alpha');
|
|
494
|
+
console.log('');
|
|
495
|
+
|
|
496
|
+
// 7. Ativar auto-renovação
|
|
497
|
+
agentA.startAutoRenewal(30000);
|
|
498
|
+
agentB.startAutoRenewal(30000);
|
|
499
|
+
|
|
500
|
+
// 8. Conversa segura via mTLS
|
|
501
|
+
console.log('💬 Iniciando conversa segura via mTLS...\n');
|
|
502
|
+
|
|
503
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
504
|
+
await agentA.sendMessage('agent-beta', 'Olá Beta! Conexão segura estabelecida via mTLS.');
|
|
505
|
+
|
|
506
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
507
|
+
await agentB.sendMessage('agent-alpha', 'Olá Alpha! Nossa comunicação está protegida por mTLS + JWT.');
|
|
508
|
+
|
|
509
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
510
|
+
await agentA.sendMessage('agent-beta', 'Perfeito! Temos segurança em duas camadas: transporte (mTLS) e aplicação (JWT).');
|
|
511
|
+
|
|
512
|
+
// Mostrar histórico
|
|
513
|
+
console.log('\n📜 Histórico da conversa:');
|
|
514
|
+
const history = agentA.getConversationHistory();
|
|
515
|
+
history.forEach(msg => {
|
|
516
|
+
const time = new Date(msg.timestamp).toLocaleTimeString();
|
|
517
|
+
console.log(`[${time}] ${msg.from} → ${msg.to}: ${msg.content}`);
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
console.log('\n✅ Demonstração concluída!');
|
|
521
|
+
console.log('🔒 Segurança em duas camadas:');
|
|
522
|
+
console.log(' 1. mTLS: Autenticação mútua de transporte');
|
|
523
|
+
console.log(' 2. JWT: Autenticação de identidade e contexto\n');
|
|
524
|
+
|
|
525
|
+
// Cleanup
|
|
526
|
+
setTimeout(() => {
|
|
527
|
+
agentA.stop();
|
|
528
|
+
agentB.stop();
|
|
529
|
+
process.exit(0);
|
|
530
|
+
}, 2000);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// Executar se chamado diretamente
|
|
534
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
535
|
+
demonstrateMTLSAgents().catch(console.error);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
export { mTLSAgent, CertificateAuthority, TokenAuthority, AgentMessage };
|
|
539
|
+
|