/** * @module node-opcua-server */ import { type OPCUACertificateManager } from "node-opcua-certificate-manager"; import { type IOPCUASecureObjectOptions, OPCUASecureObject } from "node-opcua-common"; import type { Message, Request, Response, ServerSecureChannelLayer } from "node-opcua-secure-channel"; import { ApplicationDescription, ApplicationType } from "node-opcua-service-endpoints"; import { ServiceFault } from "node-opcua-service-secure-channel"; import { type StatusCode } from "node-opcua-status-code"; import type { ApplicationDescriptionOptions, EndpointDescription } from "node-opcua-types"; import type { IChannelData } from "./i_channel_data"; import type { ISocketData } from "./i_socket_data"; import type { OPCUAServerEndPoint } from "./server_end_point"; /** * */ export interface OPCUABaseServerOptions extends IOPCUASecureObjectOptions { /** * the information used in the end point description */ serverInfo?: ApplicationDescriptionOptions; /** * the server Certificate Manager */ serverCertificateManager?: OPCUACertificateManager; } export interface OPCUABaseServerEvents { request: [request: Request, channel: ServerSecureChannelLayer]; response: [response: Response, channel: ServerSecureChannelLayer]; newChannel: [channel: ServerSecureChannelLayer, endpoint: OPCUAServerEndPoint]; channelSecured: [channel: ServerSecureChannelLayer, endpoint: OPCUAServerEndPoint]; closeChannel: [channel: ServerSecureChannelLayer, endpoint: OPCUAServerEndPoint]; connectionRefused: [socketData: ISocketData, endpoint: OPCUAServerEndPoint]; openSecureChannelFailure: [socketData: ISocketData, channelData: IChannelData, endpoint: OPCUAServerEndPoint]; } export declare class OPCUABaseServer extends OPCUASecureObject { static makeServiceFault: typeof makeServiceFault; /** * The type of server */ get serverType(): ApplicationType; serverInfo: ApplicationDescription; endpoints: OPCUAServerEndPoint[]; readonly serverCertificateManager: OPCUACertificateManager; capabilitiesForMDNS: string[]; protected _preInitTask: (() => Promise)[]; protected options: OPCUABaseServerOptions; constructor(options?: OPCUABaseServerOptions); /** * Return additional DNS hostnames to include in the self-signed * certificate's SubjectAlternativeName (SAN). * * The base implementation returns an empty array. Subclasses * (e.g. `OPCUAServer`) override this to include hostnames from * `alternateHostname` and `advertisedEndpoints`. * * @internal */ protected getConfiguredHostnames(): string[]; /** * Return additional IP addresses to include in the self-signed * certificate's SubjectAlternativeName (SAN) iPAddress entries. * * The base implementation returns an empty array. Subclasses * (e.g. `OPCUAServer`) override this to include IP literals * found in `alternateHostname` and `advertisedEndpoints`. * * These IPs are considered **explicitly configured** by the * user and are therefore checked by `checkCertificateSAN()`. * In contrast, auto-detected IPs from `getIpAddresses()` are * included in the certificate at creation time but are NOT * checked later — see `checkCertificateSAN()` for rationale. * * @internal */ protected getConfiguredIPs(): string[]; createDefaultCertificate(): Promise; initializeCM(): Promise; /** * Check that the server's certificate PEM contains the full * chain (leaf + issuer CAs). If the certificate is CA-signed * but the PEM only contains the leaf, a prominent warning is * logged so the operator can detect the mismatch easily. * * This method intentionally does NOT attempt to auto-heal the * certificate file — the provisioning layer (GDS UpdateCertificate, * CLI tools, etc.) is responsible for writing the full chain. * Use {@link CertificateManager.completeCertificateChain} in * provisioning code to reconstruct a partial chain. * * @internal */ private _checkOwnCertificateChainCompleteness; /** * Compare the current certificate's SAN entries against all * explicitly configured hostnames and IPs, and return any * that are missing. * * Returns an empty array when the certificate covers every * configured hostname and IP. * * **Important — ephemeral IP mitigation:** * Auto-detected IPs (from `getIpAddresses()`) are deliberately * NOT included in this check. Network interfaces are transient * — WiFi IPs change on reconnect, tethering IPs appear/disappear, * VPN adapters come and go. Including them would cause the * `[NODE-OPCUA-W26]` warning to fire on every server restart * whenever the network state differs from when the certificate * was originally created. * * Only **explicitly configured** values are checked: * - Hostnames: FQDN, os.hostname(), `alternateHostname` (non-IP), * hostnames from `advertisedEndpoints` URLs * - IPs: IP literals from `alternateHostname`, IP literals * from `advertisedEndpoints` URLs * * The certificate itself still includes auto-detected IPs at * creation time — this is fine because it captures the network * state at that moment. But the *mismatch warning* only fires * for things the user explicitly asked for. */ checkCertificateSAN(): string[]; /** * Delete the existing self-signed certificate and create a new * one that includes all currently configured hostnames. * * @throws if the current certificate was NOT self-signed * (i.e. issued by a CA or GDS) */ regenerateSelfSignedCertificate(): Promise; private _checkCertificateSanMismatch; /** * start all registered endPoint, in parallel, and call done when all endPoints are listening. */ start(): Promise; start(done: () => void): void; protected performPreInitialization(): Promise; protected startAsync(): Promise; /** * shutdown all server endPoints */ shutdown(done: (err?: Error | null) => void): void; shutdownChannels(): Promise; shutdownChannels(callback: (err?: Error | null) => void): void; /** * @private */ on_request(message: Message, channel: ServerSecureChannelLayer): void; /** * Find endpoint descriptions matching a given endpoint URL. * * When `endpointUrl` is provided, only endpoints whose URL matches * (case-insensitive) are returned. When `null` or omitted, all * endpoints from every `OPCUAServerEndPoint` are returned. * * This is the shared resolution path used by both `GetEndpoints` * and `CreateSession` (`validate_security_endpoint`). * * @internal (was _get_endpoints) */ findMatchingEndpoints(endpointUrl?: string | null): EndpointDescription[]; /** * get one of the possible endpointUrl */ getEndpointUrl(): string; getDiscoveryUrls(): string[]; getServers(_channel: ServerSecureChannelLayer): ApplicationDescription[]; /** * set all the end point into a state where they do not accept further connections * * note: * this method is useful for testing purpose * */ suspendEndPoints(): Promise; suspendEndPoints(callback: (err?: Error | null) => void): void; /** * set all the end point into a state where they do accept connections * note: * this method is useful for testing purpose */ resumeEndPoints(): Promise; resumeEndPoints(callback: (err?: Error | null) => void): void; protected prepare(_message: Message, _channel: ServerSecureChannelLayer): void; /** * @private */ protected _on_GetEndpointsRequest(message: Message, channel: ServerSecureChannelLayer): void; /** * @private */ protected _on_FindServersRequest(message: Message, channel: ServerSecureChannelLayer): void; /** * returns a array of currently active channels */ protected getChannels(): ServerSecureChannelLayer[]; } /** * construct a service Fault response */ declare function makeServiceFault(statusCode: StatusCode, messages: string[]): ServiceFault; export {};