* Create a topology to open the connection, must be locked to avoid topology leaks in concurrency scenario. * Locking is enforced by the connect method. * * @internal
()
| 617 | * @internal |
| 618 | */ |
| 619 | private async _connect(): Promise<this> { |
| 620 | if (this.topology && this.topology.isConnected()) { |
| 621 | return this; |
| 622 | } |
| 623 | |
| 624 | const options = this.options; |
| 625 | |
| 626 | if (options.tls) { |
| 627 | if (typeof options.tlsCAFile === 'string') { |
| 628 | options.ca ??= await fs.readFile(options.tlsCAFile); |
| 629 | } |
| 630 | if (typeof options.tlsCRLFile === 'string') { |
| 631 | options.crl ??= await fs.readFile(options.tlsCRLFile); |
| 632 | } |
| 633 | if (typeof options.tlsCertificateKeyFile === 'string') { |
| 634 | if (!options.key || !options.cert) { |
| 635 | const contents = await fs.readFile(options.tlsCertificateKeyFile); |
| 636 | options.key ??= contents; |
| 637 | options.cert ??= contents; |
| 638 | } |
| 639 | } |
| 640 | } |
| 641 | if (typeof options.srvHost === 'string') { |
| 642 | const hosts = await resolveSRVRecord(options); |
| 643 | |
| 644 | for (const [index, host] of hosts.entries()) { |
| 645 | options.hosts[index] = host; |
| 646 | } |
| 647 | } |
| 648 | |
| 649 | // It is important to perform validation of hosts AFTER SRV resolution, to check the real hostname, |
| 650 | // but BEFORE we even attempt connecting with a potentially not allowed hostname |
| 651 | if (options.credentials?.mechanism === AuthMechanism.MONGODB_OIDC) { |
| 652 | const allowedHosts = |
| 653 | options.credentials?.mechanismProperties?.ALLOWED_HOSTS || DEFAULT_ALLOWED_HOSTS; |
| 654 | const isServiceAuth = !!options.credentials?.mechanismProperties?.ENVIRONMENT; |
| 655 | if (!isServiceAuth) { |
| 656 | for (const host of options.hosts) { |
| 657 | if (!hostMatchesWildcards(host.toHostPort().host, allowedHosts)) { |
| 658 | throw new MongoInvalidArgumentError( |
| 659 | `Host '${host}' is not valid for OIDC authentication with ALLOWED_HOSTS of '${allowedHosts.join( |
| 660 | ',' |
| 661 | )}'` |
| 662 | ); |
| 663 | } |
| 664 | } |
| 665 | } |
| 666 | } |
| 667 | |
| 668 | this.topology = new Topology(this, options.hosts, options); |
| 669 | // Events can be emitted before initialization is complete so we have to |
| 670 | // save the reference to the topology on the client ASAP if the event handlers need to access it |
| 671 | |
| 672 | this.topology.once(Topology.OPEN, () => this.emit('open', this)); |
| 673 | |
| 674 | for (const event of MONGO_CLIENT_EVENTS) { |
| 675 | this.topology.on(event, (...args: any[]) => this.emit(event, ...(args as any))); |
| 676 | } |
no test coverage detected