From 9038b997a078dd113337e2d8756f7833ab7efbd7 Mon Sep 17 00:00:00 2001 From: Alexey Lunin <alexey.lunin@vereign.com> Date: Tue, 25 Jul 2023 18:06:37 +0300 Subject: [PATCH] Make agent to be a mediator for mobile wallet --- .env.example | 5 ++- apps/gateway/src/main.ts | 1 + compose/docker-compose.simple.yml | 2 + compose/docker-compose.yml | 2 + compose/env/holder.env | 10 +++-- compose/env/holder.simple.env | 9 ++-- compose/env/issuer.env | 7 ++- compose/env/issuer.simple.env | 7 ++- libs/askar/src/agent.utils.ts | 20 +++++++-- libs/askar/src/askar/agent.service.ts | 2 +- libs/askar/src/askar/askar.service.ts | 45 ++++++++++++++++--- libs/config/src/config/agent.config.ts | 28 +++++++++++- libs/config/src/config/ledgers.config.ts | 2 + .../src/interfaces/agent.config.interface.ts | 7 ++- .../interfaces/ledgers.config.interface.ts | 2 + libs/config/src/schemas/agent.schema.ts | 1 + libs/config/src/schemas/ledgers.schema.ts | 2 + libs/ledgers/src/idunion/idunion.provider.ts | 19 +++++--- 18 files changed, 141 insertions(+), 30 deletions(-) diff --git a/.env.example b/.env.example index 381d0cb6..89977bd5 100644 --- a/.env.example +++ b/.env.example @@ -1,10 +1,13 @@ LEDGERS="BCOVRIN_TEST" IDUNION_KEY=#add if you are using IDUNION as a ledger +IDUNION_BASIC_USER= +IDUNION_BASIC_PASS= -AGENT_PEER_URL="http://localhost:8001" +AGENT_PEER_URL=http://localhost:8001,ws://localhost:8002 AGENT_NAME=EXAMPTTLE_AGENT_45 AGENT_KEY=EXAMPLE_AGENT_45_KEY AGENT_DID_SEED=200000000000000000000000ExampleT21 #random string min 32 chars +AGENT_RUN_AS_MEDIATOR=false AGENT_DB_HOST=0.0.0.0:5432 AGENT_DB_USER=postgres diff --git a/apps/gateway/src/main.ts b/apps/gateway/src/main.ts index 37b744b5..c6f57ec7 100644 --- a/apps/gateway/src/main.ts +++ b/apps/gateway/src/main.ts @@ -21,6 +21,7 @@ async function bootstrap() { const gatewayConfig = configService.get<IGateway>("gateway")!; const globalPrefix = "api"; + app.enableCors(); app.setGlobalPrefix(globalPrefix); app.enableShutdownHooks(); diff --git a/compose/docker-compose.simple.yml b/compose/docker-compose.simple.yml index 0d8d9ad9..0544a788 100644 --- a/compose/docker-compose.simple.yml +++ b/compose/docker-compose.simple.yml @@ -21,6 +21,7 @@ services: ports: - "8080:8080" - "8001:8001" + - "8002:8002" depends_on: pg_db: condition: service_started @@ -35,6 +36,7 @@ services: ports: - "8081:8080" - "6001:6001" + - "6002:6002" depends_on: pg_db: condition: service_started diff --git a/compose/docker-compose.yml b/compose/docker-compose.yml index 3646983b..e9e3bc1f 100644 --- a/compose/docker-compose.yml +++ b/compose/docker-compose.yml @@ -36,6 +36,7 @@ services: ports: - "8080:8080" - "8001:8001" + - "8002:8002" env_file: - ./env/issuer.env depends_on: @@ -141,6 +142,7 @@ services: ports: - "8090:8080" - "6001:6001" + - "6002:6002" env_file: - ./env/holder.env depends_on: diff --git a/compose/env/holder.env b/compose/env/holder.env index c395fb46..538ac094 100644 --- a/compose/env/holder.env +++ b/compose/env/holder.env @@ -1,10 +1,13 @@ -LEDGERS="BCOVRIN_TEST" +LEDGERS=BCOVRIN_TEST IDUNION_KEY= +IDUNION_BASIC_USER= +IDUNION_BASIC_PASS= -AGENT_PEER_URL="http://agent-holder:6001" +AGENT_PEER_URL=http://agent-holder:6001,ws://agent-holder:6002 AGENT_NAME=DEV_AGENT_HOLDER_OCM_4 # this should be changed to company name AGENT_KEY=DEV_AGENT_HOLDER_OCM_4 #example random string -AGENT_DID_SEED=2000000000000000CCA120000000TCuste21jsjs #did private key seed min lenght 32 +AGENT_DID_SEED=2000000000000000CCA120000000TCuste21jsjs #did private key seed min length 32 +AGENT_RUN_AS_MEDIATOR=false AGENT_DB_HOST=pg_db:5432 AGENT_DB_USER=postgres AGENT_DB_PASS=postgres @@ -14,6 +17,7 @@ AGENT_IS_REST=false AGENT_MAX_MESSAGES=10 AGENT_RETE_LIMIT=5 + NATS_SERVERS=broker-holder:4222 NATS_STREAM_NAME=ssi_holder_stream NATS_SUBJECTS="connections.*,proofs.*,credentials.*,schemas.*,messages.*" diff --git a/compose/env/holder.simple.env b/compose/env/holder.simple.env index 0db552de..c023e232 100644 --- a/compose/env/holder.simple.env +++ b/compose/env/holder.simple.env @@ -1,10 +1,13 @@ -LEDGERS="BCOVRIN_TEST" +LEDGERS=BCOVRIN_TEST IDUNION_KEY= +IDUNION_BASIC_USER= +IDUNION_BASIC_PASS= -AGENT_PEER_URL="http://agent-holder:6001" +AGENT_PEER_URL=http://agent-holder:6001,ws://agent-holder:6002 AGENT_NAME=DEV_SIMPLE_AGENT_HOLDER_OCM # this should be changed to company name AGENT_KEY=DEV_SIMPLE_AGENT_HOLDER_OCM #example random string -AGENT_DID_SEED=200000000000000000000000TCuste21xh #did private key seed min lenght 32 +AGENT_DID_SEED=200000000000000000000000TCuste21xh #did private key seed min length 32 +AGENT_RUN_AS_MEDIATOR=false AGENT_DB_HOST=pg_db:5432 AGENT_DB_USER=postgres AGENT_DB_PASS=postgres diff --git a/compose/env/issuer.env b/compose/env/issuer.env index d3774abd..65a6160a 100644 --- a/compose/env/issuer.env +++ b/compose/env/issuer.env @@ -1,10 +1,13 @@ -LEDGERS="BCOVRIN_TEST" +LEDGERS=BCOVRIN_TEST IDUNION_KEY= +IDUNION_BASIC_USER= +IDUNION_BASIC_PASS= -AGENT_PEER_URL="http://agent-issuer:8001" +AGENT_PEER_URL=http://agent-issuer:8001,ws://agent-issuer:8002 AGENT_NAME=DEV_AGENT_ISSUER_OCM_4 # this should be changed to company name AGENT_KEY=DEV_AGENT_ISSUER_OCM_4 #example random string AGENT_DID_SEED=20000000000000000000000aca0xxaDTCuste21udhasjs #did private key seed min lenght 32 +AGENT_RUN_AS_MEDIATOR=false AGENT_DB_HOST=pg_db:5432 AGENT_DB_USER=postgres AGENT_DB_PASS=postgres diff --git a/compose/env/issuer.simple.env b/compose/env/issuer.simple.env index 22c8de61..92156c7b 100644 --- a/compose/env/issuer.simple.env +++ b/compose/env/issuer.simple.env @@ -1,10 +1,13 @@ -LEDGERS="BCOVRIN_TEST" +LEDGERS=BCOVRIN_TEST IDUNION_KEY= +IDUNION_BASIC_USER= +IDUNION_BASIC_PASS= -AGENT_PEER_URL="http://agent-issuer:8001" +AGENT_PEER_URL=http://agent-issuer:8001,ws://agent-issuer:8002 AGENT_NAME=DEV_SIMPLE_AGENT_ISSUER_OCM # this should be changed to company name AGENT_KEY=DEV_SIMPLE_AGENT_ISSUER_OCM #example random string AGENT_DID_SEED=200000000000000000000000TCuste21js #did private key seed min lenght 32 +AGENT_RUN_AS_MEDIATOR=false AGENT_DB_HOST=pg_db:5432 AGENT_DB_USER=postgres AGENT_DB_PASS=postgres diff --git a/libs/askar/src/agent.utils.ts b/libs/askar/src/agent.utils.ts index 3eae5e95..76df1159 100644 --- a/libs/askar/src/agent.utils.ts +++ b/libs/askar/src/agent.utils.ts @@ -3,6 +3,7 @@ import { AutoAcceptCredential, AutoAcceptProof, ConnectionsModule, + MediatorModule, CredentialsModule, DidsModule, Key, @@ -13,6 +14,8 @@ import { V2ProofProtocol, WalletError, WalletKeyExistsError, + KeyDidResolver, + KeyDidRegistrar, } from "@aries-framework/core"; import { AnonCredsCredentialFormatService, @@ -93,8 +96,8 @@ export const generateDidFromKey = (key: Key): string => { }; //eslint-disable-next-line -export const getAskarAnonCredsIndyModules = (networks: any) => { - return { +export const getAskarAnonCredsIndyModules = (networks: any, enableMediator: boolean) => { + const modules = { connections: new ConnectionsModule({ autoAcceptConnections: true, }), @@ -125,11 +128,20 @@ export const getAskarAnonCredsIndyModules = (networks: any) => { networks, }), dids: new DidsModule({ - registrars: [new IndyVdrIndyDidRegistrar()], - resolvers: [new IndyVdrIndyDidResolver()], + registrars: [new IndyVdrIndyDidRegistrar(), new KeyDidRegistrar()], + resolvers: [new IndyVdrIndyDidResolver(), new KeyDidResolver()], }), askar: new AskarModule({ ariesAskar, }), } as const; + + if (enableMediator) { + const obj = modules as never as { mediator: MediatorModule }; + obj.mediator = new MediatorModule({ + autoAcceptMediationRequests: true, + }); + } + + return modules; }; diff --git a/libs/askar/src/askar/agent.service.ts b/libs/askar/src/askar/agent.service.ts index 27fe92a7..581b81ef 100644 --- a/libs/askar/src/askar/agent.service.ts +++ b/libs/askar/src/askar/agent.service.ts @@ -33,7 +33,7 @@ export class AgentService { const i = new CreateInvitationResponseDto(); i.invitationUrl = outOfBoundRecord.outOfBandInvitation.toUrl({ - domain: this.askar.agentConfig.agentPeerAddress, + domain: this.askar.agentConfig.agentHttpPeerAddress || this.askar.agentConfig.agentWsPeerAddress || '', }); return i; diff --git a/libs/askar/src/askar/askar.service.ts b/libs/askar/src/askar/askar.service.ts index e07eb52a..4b545005 100644 --- a/libs/askar/src/askar/askar.service.ts +++ b/libs/askar/src/askar/askar.service.ts @@ -14,7 +14,11 @@ import { TypedArrayEncoder, WsOutboundTransport, } from "@aries-framework/core"; -import { agentDependencies, HttpInboundTransport } from "@aries-framework/node"; +import { + agentDependencies, + HttpInboundTransport, + WsInboundTransport, +} from "@aries-framework/node"; import { ConfigService } from "@nestjs/config"; import { LedgersService } from "@ocm-engine/ledgers"; import { @@ -38,6 +42,12 @@ export class AskarService implements OnModuleInit, OnModuleDestroy { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.agentConfig = configService.get<IConfAgent>("agent")!; + const endpoints: string[] = []; + if (this.agentConfig.agentHttpPeerAddress) + endpoints.push(this.agentConfig.agentHttpPeerAddress); + if (this.agentConfig.agentWsPeerAddress) + endpoints.push(this.agentConfig.agentWsPeerAddress); + const config = { label: this.agentConfig.agentName, logger: new ConsoleLogger(LogLevel.debug), @@ -55,7 +65,7 @@ export class AskarService implements OnModuleInit, OnModuleDestroy { id: this.agentConfig.agentName, key: this.agentConfig.agentKey, }, - endpoints: [this.agentConfig.agentPeerAddress], + endpoints, } satisfies InitConfig; this.agent = new Agent({ @@ -63,12 +73,24 @@ export class AskarService implements OnModuleInit, OnModuleDestroy { dependencies: agentDependencies, modules: getAskarAnonCredsIndyModules( this.ledgersSerivce.ledgersConfig(), + this.agentConfig.agentRunAsMediator, ), }); - this.agent.registerInboundTransport( - new HttpInboundTransport({ port: this.agentConfig.agentPeerPort }), - ); + if (this.agentConfig.agentWsPeerPort) { + this.agent.registerInboundTransport( + new WsInboundTransport({ + port: this.agentConfig.agentWsPeerPort as number, + }), + ); + } + if (this.agentConfig.agentHttpPeerPort && !this.agentConfig.agentRunAsMediator) { + this.agent.registerInboundTransport( + new HttpInboundTransport({ + port: this.agentConfig.agentHttpPeerPort as number, + }), + ); + } this.agent.registerOutboundTransport(new WsOutboundTransport()); this.agent.registerOutboundTransport(new HttpOutboundTransport()); @@ -84,6 +106,19 @@ export class AskarService implements OnModuleInit, OnModuleDestroy { throw new Error("agent not initialized"); } + if (this.agentConfig.agentRunAsMediator) { + const invitation = await this.agent.oob.createInvitation({ + label: "Mediator", + multiUseInvitation: true, + autoAcceptConnection: true, + }); + const url = invitation.outOfBandInvitation.toUrl({ + domain: this.agentConfig.agentHttpPeerAddress || this.agentConfig.agentWsPeerAddress || 'http://localhost' + }); + this.logger.log("MEDIATOR MODE: agent is running as mediator"); + this.logger.log(url); + } + const dids = await this.agent.dids.getCreatedDids({ method: "indy" }); if (dids.length) { diff --git a/libs/config/src/config/agent.config.ts b/libs/config/src/config/agent.config.ts index d71fa86e..7bf9478e 100644 --- a/libs/config/src/config/agent.config.ts +++ b/libs/config/src/config/agent.config.ts @@ -2,11 +2,34 @@ import { registerAs } from "@nestjs/config"; import * as process from "process"; import { IConfAgent } from "../interfaces/agent.config.interface"; +const endpoints = process.env["AGENT_PEER_URL"]!.split(","); +let agentWsPeerPort: number | null = null; +let agentWsPeerAddress: string | null = null; +let agentHttpPeerPort: number | null = null; +let agentHttpPeerAddress: string | null = null; + +const wsEndpoint = endpoints.find( + (p) => p.startsWith("ws") || p.startsWith("wss"), +); +if (wsEndpoint) { + agentWsPeerPort = parseInt(wsEndpoint.split(":")[2]); + agentWsPeerAddress = wsEndpoint; +} +const httpEndpoint = endpoints.find( + (p) => p.startsWith("http") || p.startsWith("https"), +); +if (httpEndpoint) { + agentHttpPeerPort = parseInt(httpEndpoint.split(":")[2]); + agentHttpPeerAddress = httpEndpoint; +} + export const agentConfig = registerAs( "agent", (): IConfAgent => ({ - agentPeerPort: parseInt(process.env["AGENT_PEER_URL"]!.split(":")[2]), - agentPeerAddress: process.env["AGENT_PEER_URL"]!, + agentWsPeerPort, + agentWsPeerAddress, + agentHttpPeerPort, + agentHttpPeerAddress, agentName: process.env["AGENT_NAME"]!, agentKey: process.env["AGENT_KEY"]!, agentDidSeed: process.env["AGENT_DID_SEED"]!, @@ -14,6 +37,7 @@ export const agentConfig = registerAs( agentDbUser: process.env["AGENT_DB_USER"]!, agentDbPass: process.env["AGENT_DB_PASS"]!, agentIsRest: process.env["AGENT_IS_REST"] === "true", + agentRunAsMediator: process.env["AGENT_RUN_AS_MEDIATOR"] === "true", agentConsumerName: process.env["AGENT_CONSUMER_NAME"]!, agentConsumerMaxMessagess: parseInt(process.env["AGENT_MAX_MESSAGES"]!), agentConsumerRateLimit: parseInt(process.env["AGENT_RETE_LIMIT"]!), diff --git a/libs/config/src/config/ledgers.config.ts b/libs/config/src/config/ledgers.config.ts index de79f8a9..8d7c3c67 100644 --- a/libs/config/src/config/ledgers.config.ts +++ b/libs/config/src/config/ledgers.config.ts @@ -7,5 +7,7 @@ export const ledgersConfig = registerAs( (): ILedgers => ({ ledgers: process.env["LEDGERS"]!.split(","), idUnionApiKey: process.env["IDUNION_KEY"]!, + idUnionApiBasicUser: process.env["IDUNION_BASIC_USER"]!, + idUnionApiBasicPass: process.env["IDUNION_BASIC_PASS"]!, }), ); diff --git a/libs/config/src/interfaces/agent.config.interface.ts b/libs/config/src/interfaces/agent.config.interface.ts index 1f0e7a85..011ecf1f 100644 --- a/libs/config/src/interfaces/agent.config.interface.ts +++ b/libs/config/src/interfaces/agent.config.interface.ts @@ -2,12 +2,15 @@ export interface IConfAgent { agentDbHost: string; agentDbUser: string; agentDbPass: string; - agentPeerPort: number; - agentPeerAddress: string; + agentWsPeerPort: number | null; + agentWsPeerAddress: string | null; + agentHttpPeerPort: number | null; + agentHttpPeerAddress: string | null; agentName: string; agentKey: string; agentDidSeed: string; agentIsRest: boolean; + agentRunAsMediator: boolean; agentConsumerName: string; agentConsumerMaxMessagess: number; agentConsumerRateLimit: number; diff --git a/libs/config/src/interfaces/ledgers.config.interface.ts b/libs/config/src/interfaces/ledgers.config.interface.ts index a49c9850..c7af9b9a 100644 --- a/libs/config/src/interfaces/ledgers.config.interface.ts +++ b/libs/config/src/interfaces/ledgers.config.interface.ts @@ -1,4 +1,6 @@ export interface ILedgers { ledgers: Array<string>; idUnionApiKey: string; + idUnionApiBasicUser: string; + idUnionApiBasicPass: string; } diff --git a/libs/config/src/schemas/agent.schema.ts b/libs/config/src/schemas/agent.schema.ts index 9cf56915..ef0a0f93 100644 --- a/libs/config/src/schemas/agent.schema.ts +++ b/libs/config/src/schemas/agent.schema.ts @@ -5,6 +5,7 @@ export const agentSchema = Joi.object({ AGENT_NAME: Joi.string().required(), AGENT_KEY: Joi.string().required(), AGENT_DID_SEED: Joi.string().required(), + AGENT_RUN_AS_MEDIATOR: Joi.string(), AGENT_DB_HOST: Joi.string().required(), AGENT_DB_USER: Joi.string().required(), AGENT_DB_PASS: Joi.string().required(), diff --git a/libs/config/src/schemas/ledgers.schema.ts b/libs/config/src/schemas/ledgers.schema.ts index d305f728..67a2cf3f 100644 --- a/libs/config/src/schemas/ledgers.schema.ts +++ b/libs/config/src/schemas/ledgers.schema.ts @@ -3,4 +3,6 @@ import Joi from "joi"; export const ledgersSchema = Joi.object({ LEDGERS: Joi.string().required(), IDUNION_KEY: Joi.string(), + IDUNION_BASIC_USER: Joi.string(), + IDUNION_BASIC_PASS: Joi.string(), }); diff --git a/libs/ledgers/src/idunion/idunion.provider.ts b/libs/ledgers/src/idunion/idunion.provider.ts index 5c6dcf46..0a5fa67c 100644 --- a/libs/ledgers/src/idunion/idunion.provider.ts +++ b/libs/ledgers/src/idunion/idunion.provider.ts @@ -30,11 +30,20 @@ export class IdunionProvider implements IRegistrator { this.logger.log(`Trying to register ${did} to idunion`); try { - await axios.post(`${URL}?apiKey=${this.config.idUnionApiKey}`, { - role: "ENDORSER", - did: unqualifiedIndyDid, - verkey, - }); + await axios.post( + `${URL}?apiKey=${this.config.idUnionApiKey}`, + { + role: "ENDORSER", + did: unqualifiedIndyDid, + verkey, + }, + { + auth: { + username: this.config.idUnionApiBasicUser, + password: this.config.idUnionApiBasicPass, + }, + }, + ); this.logger.log("Registration successful"); return did; -- GitLab