@interopio/gateway-server 0.19.4 → 0.21.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.
@@ -1,18 +1,75 @@
1
1
  import { IOGateway } from '@interopio/gateway';
2
2
  import type { AddressInfo } from 'node:net';
3
3
  import type { ServerCorsConfig, ServerConfigurer, ServerWebSocketOptions } from './types/web/server';
4
+
4
5
  export default GatewayServer.Factory;
5
6
 
6
7
  export namespace GatewayServer {
7
8
  export const Factory: (options: ServerConfig) => Promise<Server>
8
- export type SslConfig = Readonly<{ key?: string, cert?: string, ca?: string }>
9
+ /**
10
+ * SSL/TLS configuration.
11
+ * All key and certificate files must be in PEM format.
12
+ */
13
+ export type SslConfig = Readonly<{
14
+ /** Path to server private key file (PEM format) */
15
+ key?: string,
16
+ /** Path to server certificate file (PEM format) */
17
+ cert?: string,
18
+ /** Path to CA certificate for client certificate verification (PEM format) */
19
+ ca?: string,
20
+ /**
21
+ * Passphrase for encrypted private key
22
+ * @since 0.20.0
23
+ */
24
+ passphrase?: string,
25
+ /**
26
+ * Request client certificate during TLS handshake.
27
+ * When false (default), clients will not send certificates.
28
+ * When true, clients are asked to send a certificate.
29
+ * @since 0.20.0
30
+ */
31
+ requestCert?: boolean,
32
+ /**
33
+ * Reject clients with invalid or missing certificates.
34
+ * Only effective when requestCert is true.
35
+ * When false, clients without valid certs are still allowed.
36
+ * When true, enforces mutual TLS authentication.
37
+ * @since 0.20.0
38
+ */
39
+ rejectUnauthorized?: boolean
40
+ }>
9
41
 
10
42
  export import LoggerConfig = IOGateway.Logging.LogConfig;
43
+
11
44
  export type AuthConfig = Readonly<{
12
- type: 'none' | 'basic' | 'oauth2',
13
- basic?: { user?: {name: string, password?: string}, realm?: string }
14
- oauth2?: { jwt: { issuerUri: string, issuer?: string, audience?: string | string[] } }
45
+ type: 'none'
46
+ | 'basic'
47
+ | 'x509' // since 0.20.0
48
+ | 'oauth2'
49
+ ,
50
+ /** X.509 client certificate authentication configuration
51
+ * @since 0.20.0
52
+ */
53
+ x509?: {
54
+ /** Path to CA private key file (PEM format), for generating client certificates and server certificates */
55
+ key?: string,
56
+ /** Passphrase for encrypted CA private key */
57
+ passphrase?: string,
58
+ /** Extract principal from Subject Alternative Name. Use 'email' to extract from email SAN. If undefined, uses subject (default). */
59
+ principalAltName?: 'email'
60
+ },
61
+ /** Basic authentication configuration */
62
+ basic?: {
63
+ realm?: string
64
+ },
65
+ /** OAuth2 authentication configuration */
66
+ oauth2?: {
67
+ jwt: { issuerUri: string, issuer?: string, audience?: string | string[] }
68
+ },
69
+ // in-memory user for basic auth
70
+ user?: { name: string, password?: string, readonly roles?: string[] }
15
71
  }>;
72
+
16
73
  export type ServerCustomizer = (configurer: ServerConfigurer, config: ServerConfig) => Promise<void>;
17
74
 
18
75
  export type ServerConfig = {
@@ -21,7 +78,7 @@ export namespace GatewayServer {
21
78
  * Accepts a single value or a range.
22
79
  * If a range is specified, will bind to the first available port in the range.
23
80
  *
24
- * Default: 0 - a random port.
81
+ * @defaultValue 0 (random port)
25
82
  */
26
83
  port?: number | string
27
84
  /**
@@ -52,18 +109,65 @@ export namespace GatewayServer {
52
109
  },
53
110
 
54
111
  app?: ServerCustomizer,
112
+ resources?: {
113
+ enabled?: boolean,
114
+ locations: string[]
115
+ },
55
116
  gateway?: IOGateway.GatewayConfig & ServerWebSocketOptions & {
56
- route?: string
117
+ route?: string,
118
+ /**
119
+ * Gateway scope - determines how gateway instances are managed:
120
+ * - 'principal': Each authenticated principal gets their own gateway instance.
121
+ * A default (shared) gateway instance handles all unauthenticated connections.
122
+ * - 'singleton': All connections share the same gateway instance
123
+ *
124
+ * @defaultValue 'principal'
125
+ * @since 0.20.0
126
+ */
127
+ scope?: 'singleton' | 'principal',
128
+ mesh?: IOGateway.MeshConfig & {
129
+ enabled?: boolean
130
+ }
131
+ metrics?: IOGateway.MetricsConfig & {
132
+ enabled?: boolean
133
+ }
57
134
  }
58
135
  }
59
136
 
60
137
  export interface Server {
61
- readonly gateway: IOGateway.Gateway
138
+ readonly gateway: ScopedGateway
62
139
  /**
63
140
  * Returns the bound address info.
64
141
  * Useful when the server is bound to a random port.
65
142
  */
66
143
  readonly address: AddressInfo | null
144
+
67
145
  close(): Promise<void>
68
146
  }
147
+
148
+ /**
149
+ * A scoped gateway that extends the base Gateway interface with methods
150
+ * to access and manage multiple gateway instances based on scope.
151
+ * @since 0.20.0
152
+ */
153
+ export interface ScopedGateway extends IOGateway.Gateway {
154
+
155
+ /**
156
+ * Get gateway info.
157
+ * @param gatewayId - The gateway ID. If omitted, returns aggregated info for all gateways.
158
+ */
159
+ info(gatewayId?: string): Record<string, unknown>
160
+
161
+ /**
162
+ * Stop a gateway instance.
163
+ * @param gatewayId - The gateway ID to stop. If omitted, stops all gateways.
164
+ */
165
+ stop(gatewayId?: string): Promise<IOGateway.Gateway>;
166
+
167
+ /**
168
+ * Get all managed gateway instances.
169
+ * @returns A map of gateway IDs to their corresponding Gateway instances
170
+ */
171
+ getGateways(): Map<string, IOGateway.Gateway>;
172
+ }
69
173
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interopio/gateway-server",
3
- "version": "0.19.4",
3
+ "version": "0.21.0",
4
4
  "keywords": [
5
5
  "gateway",
6
6
  "server",
@@ -48,6 +48,10 @@
48
48
  "types": "./types/web/test.d.ts",
49
49
  "import": "./dist/web/test.js"
50
50
  },
51
+ "./tools": {
52
+ "types": "./types/tools.d.ts",
53
+ "import": "./dist/tools/index.js"
54
+ },
51
55
  "./metrics/publisher/rest": {
52
56
  "import": "./dist/metrics/publisher/rest.js",
53
57
  "node": "./dist/metrics/publisher/rest.cjs",
@@ -68,20 +72,23 @@
68
72
  }
69
73
  }
70
74
  },
75
+ "bin": {
76
+ "gateway-server": "./gateway-server"
77
+ },
71
78
  "main": "dist/index.js",
72
79
  "types": "gateway-server.d.ts",
73
80
  "type": "module",
74
81
  "engines": {
75
- "node": ">=20.10 || >= 22.12 || >= 24"
82
+ "node": ">=20.18 || >=22.12 || >=24"
76
83
  },
77
84
  "dependencies": {
78
- "@interopio/gateway": "^0.22.3",
79
- "ws": "^8.18.3",
85
+ "@interopio/gateway": "^0.23.0",
80
86
  "tough-cookie": "^6.0.0",
81
- "http-cookie-agent": "^7.0.3"
87
+ "http-cookie-agent": "^7.0.3",
88
+ "ws": "^8.19.0"
82
89
  },
83
90
  "peerDependencies": {
84
- "undici": "^7.16.0"
91
+ "undici": "^7.18.2"
85
92
  },
86
93
  "peerDependenciesMeta": {
87
94
  "undici": {
package/readme.md CHANGED
@@ -10,9 +10,13 @@ The `@interopio/gateway-server` package is the web server used to run the gatewa
10
10
  The server is general purpose http server with support for:
11
11
  - HTTP and HTTPS
12
12
  - CORS configuration
13
- - Basic and OAuth2 authentication
13
+ - Basic, mTLS, and OAuth2 authentication
14
14
  - Custom API routes (both for HTTP and WebSocket)
15
15
 
16
+ ```shell
17
+ npm install @interopio/gateway-server
18
+ ```
19
+
16
20
  ## Table of Contents
17
21
 
18
22
  - [Getting Started](#getting-started)
@@ -21,17 +25,22 @@ The server is general purpose http server with support for:
21
25
 
22
26
  ## Getting Started
23
27
 
28
+ ### CLI:
29
+ ```shell
30
+ npx @interopio/gateway-server run --port 8385 --gateway
31
+ ```
32
+ ### API:
24
33
  ```typescript
25
- import GatewayServer, {type Server} from '@interopio/gateway-server';
34
+ import GatewayServer, { type Server } from '@interopio/gateway-server';
26
35
 
27
36
  const server: Server = await GatewayServer({
28
37
  port: 8385,
29
38
  gateway: {
30
39
  route: '/gw',
31
- access: 'authenticated',
40
+ authorize: { access: 'authenticated' },
32
41
  ping: {
33
42
  interval: 30000, // 30 seconds
34
- type: 'timestamp'
43
+ data: 'timestamp'
35
44
  }
36
45
  }
37
46
  });
@@ -44,28 +53,201 @@ await server.close();
44
53
 
45
54
  ## Configure HTTPS
46
55
 
56
+ SSL/TLS configuration supports PEM-formatted certificates. Two modes are available:
57
+
58
+ **1. Explicit certificates** - Provide your own key and certificate files (both must exist):
59
+ ```typescript
60
+ const server = await GatewayServer({
61
+ port: 8443,
62
+ ssl: {
63
+ key: "./ssl/gateway-server.key",
64
+ cert: "./ssl/gateway-server.crt",
65
+ passphrase: "secret" // optional, if key is encrypted
66
+ }
67
+ });
68
+ ```
69
+
70
+ > **Recommended for production:** Generate your own server certificates using a trusted CA or create your own CA infrastructure. See [Generating Server Certificates with OpenSSL](#generating-server-certificates-with-openssl) below.
71
+
72
+ **2. Auto-generated server certificates** - Provide a CA key via `auth.x509.key` to auto-generate server certificates:
73
+
74
+ > **⚠️ Development only:** Auto-generated certificates are intended for development and testing. For production environments, use explicit certificates (mode 1) with proper certificate management.
75
+
76
+ > **Note:** The CA private key is stored under `auth.x509.key` since its primary purpose is generating client certificates for X.509 authentication. It is incidentally used to generate self-signed server certificates when no explicit server cert is provided and ssl is enabled.
77
+
78
+ ```typescript
79
+ // Option A: Specify custom CA paths
80
+ await GatewayServer({
81
+ port: 8443,
82
+ host: "example.com", // optional: used in generated certificate's CN and SAN
83
+ ssl: {
84
+ ca: "./ssl/gateway-ca.crt", // CA certificate for client verification (optional)
85
+ key: "./ssl/gateway-server.key", // optional: save generated server key to file
86
+ cert: "./ssl/gateway-server.crt", // optional: save generated server cert to file
87
+ passphrase: undefined // optional, if key is encrypted
88
+ },
89
+ auth: {
90
+ type: 'x509',
91
+ x509: {
92
+ key: "./ssl/gateway-ca.key", // CA private key (auto-generates CA if missing)
93
+ passphrase: undefined, // optional, if CA key is encrypted
94
+ }
95
+ }
96
+ });
97
+
98
+ // Option B: Use default development CA (simplest for development)
99
+ await GatewayServer({
100
+ port: 8443,
101
+ ssl: {},
102
+ auth: {
103
+ type: 'x509',
104
+ x509: {
105
+ key: "./ssl/gateway-ca.key" // ca cert derives to ./ssl/gateway-ca.crt
106
+ }
107
+ }
108
+ });
109
+
110
+ // Option C: Minimal mode (uses gateway-ca.key and gateway-ca.crt)
111
+ await GatewayServer({
112
+ port: 8443,
113
+ ssl: {},
114
+ auth: {
115
+ type: 'x509',
116
+ x509: {
117
+ key: undefined // defaults to gateway-ca.key in current directory
118
+ }
119
+ }
120
+ });
121
+ ```
122
+
123
+ > **Client Configuration:** For mode 2, distribute the Root CA certificate (`.crt` file) to clients. Clients must import this CA into their trust store. Server certificates are regenerated on each startup (in memory or saved to disk if key/cert paths specified) and are automatically trusted by clients who trust the Root CA.
124
+ >
125
+ > **Auto-generation:** If CA files don't exist (specified in `auth.x509.key`), they are automatically generated and saved to disk. The CA certificate path is derived from the key path by replacing the extension with `.crt` (if not explicitly specified via `ssl.ca`). The CA is valid for 10 years and uses ECDSA secp384r1. Server certificates are regenerated on startup with 7-day validity.
126
+ >
127
+ > **Hostname in certificates:** When auto-generating server certificates (mode 2), the `host` parameter (if specified) is used as the Common Name (CN) and in the Subject Alternative Name (SAN) of the certificate. If `host` is not specified, defaults to `localhost`.
128
+ >
129
+ > **Note:** When both `ssl.key` and `ssl.crt` files exist, mode 1 is used (explicit certificates). Otherwise mode 2 is used (auto-generated from CA key in `auth.x509.key`). **For production deployments, always use mode 1 with properly managed certificates.**
130
+
131
+ ### Generating Server Certificates with OpenSSL
132
+
133
+ To generate your own server certificates for mode 1 (explicit certificates) using OpenSSL:
134
+
135
+ > **Production Best Practice:** Use this approach to create properly signed certificates for your production environment. Ensure certificates are renewed before expiration and follow your organization's certificate management policies.
136
+
137
+ ```shell
138
+ # Set the domain name for the server certificate
139
+ DOMAIN=gateway.localhost
140
+
141
+ # Set paths to your CA certificate and key
142
+ CA_CERT=./ssl/gateway-ca.crt
143
+ CA_KEY=./ssl/gateway-ca.key
144
+
145
+ # Generate server private key (ECDSA secp256r1)
146
+ openssl ecparam -name prime256v1 -genkey -noout -out ./ssl/gateway-server.key
147
+
148
+ # Create a certificate signing request (CSR) with extensions
149
+ openssl req -new -key ./ssl/gateway-server.key -out ./ssl/gateway-server.csr \
150
+ -subj "/CN=${DOMAIN}" \
151
+ -addext "basicConstraints=CA:FALSE" \
152
+ -addext "keyUsage=critical,digitalSignature,keyEncipherment" \
153
+ -addext "extendedKeyUsage=serverAuth" \
154
+ -addext "subjectAltName=DNS:${DOMAIN},DNS:*.${DOMAIN}"
155
+
156
+ # Sign the CSR with your Root CA
157
+ openssl x509 -req -in ./ssl/gateway-server.csr \
158
+ -CA ${CA_CERT} -CAkey ${CA_KEY} \
159
+ -out ./ssl/gateway-server.crt -days 365 -sha256 \
160
+ -copy_extensions copyall
161
+ ```
162
+
163
+ > **Important:** The `subjectAltName` with DNS entries is **required** for server certificates. Modern browsers and clients reject certificates without SAN, even if the Common Name (CN) matches the hostname.
164
+
165
+ ### Mutual TLS (Client Certificate Authentication)
166
+
167
+ Enable client certificate verification for mutual TLS authentication:
168
+
169
+ ```typescript
170
+ const server = await GatewayServer({
171
+ port: 8443,
172
+ ssl: {
173
+ key: "./ssl/gateway-server.key", // Server private key
174
+ cert: "./ssl/gateway-server.crt", // Server certificate
175
+ ca: "./ssl/gateway-client-ca.crt", // CA that signed client certificates
176
+ requestCert: true, // Ask clients to send certificates
177
+ rejectUnauthorized: true // Reject clients without valid certs
178
+ }
179
+ });
180
+ ```
181
+
182
+ **Configuration options:**
183
+ - `requestCert: false` (default) - Server does not request client certificates
184
+ - `requestCert: true, rejectUnauthorized: false` - Client certs optional (allow anonymous)
185
+ - `requestCert: true, rejectUnauthorized: true` - Client certs required (enforce mutual TLS)
186
+
187
+ > **Note:** When `requestCert` is `false`, clients will not send certificates even if they have them. The server must explicitly request them during the TLS handshake.
188
+
189
+ #### Generating Client Certificates with OpenSSL
190
+
191
+ To generate client certificates for mutual TLS authentication using OpenSSL:
192
+
193
+ ```shell
194
+ # Set paths to your CA certificate and key
195
+ CA_CERT=./ssl/gateway-ca.crt
196
+ CA_KEY=./ssl/gateway-ca.key
197
+
198
+ # Generate client private key (ECDSA secp256r1)
199
+ openssl ecparam -name prime256v1 -genkey -noout -out ./ssl/gateway-client.key
200
+
201
+ # Create a certificate signing request (CSR) with extensions
202
+ openssl req -new -key ./ssl/gateway-client.key -out ./ssl/gateway-client.csr \
203
+ -subj "/CN=dev-user" \
204
+ -addext "basicConstraints=CA:FALSE" \
205
+ -addext "keyUsage=critical,digitalSignature,keyEncipherment" \
206
+ -addext "extendedKeyUsage=clientAuth" \
207
+ -addext "subjectAltName=email:test@example.com"
208
+
209
+ # Sign the CSR with your Root CA
210
+ openssl x509 -req -in ./ssl/gateway-client.csr \
211
+ -CA ${CA_CERT} -CAkey ${CA_KEY} \
212
+ -out ./ssl/gateway-client.crt -days 365 -sha256 \
213
+ -copy_extensions copyall
214
+
215
+ openssl pkcs12 -export -out ./ssl/gateway-client.p12 \
216
+ -inkey ./ssl/gateway-client.key -in ./ssl/gateway-client.crt \
217
+ -passout pass:changeit
218
+ ```
219
+
220
+ > **Important:** The `extendedKeyUsage=clientAuth` is critical for client certificates. Without it, the certificate may be rejected during mutual TLS authentication.
221
+
222
+ ### Full Example with Authentication
223
+
47
224
  ```typescript
48
225
  import GatewayServer, {type Server} from '@interopio/gateway-server';
49
226
 
50
227
  const server: Server = await GatewayServer({
51
228
  port: 8443,
229
+ // Enable HTTPS with Development CA
52
230
  ssl: {
53
- cert: "glue42.crt",
54
- ca: "intermediate.crt",
55
- key: "glue42.key"
231
+ ca: './ssl/gateway-ca.crt', // CA cert for client verification
232
+ rejectUnauthorized: false, // allow anonymous if no client cert
233
+ requestCert: true, // request client certificates for mutual TLS
56
234
  },
57
235
  auth: {
58
- type: 'oauth2', // or 'basic'
236
+ type: 'oauth2', // or 'basic' or 'x509'
59
237
  oauth2: {
60
238
  jwt: {
61
- issuer: 'https://auth.example.com',
62
- audience: 'https://api.example.com'
239
+ issuerUri: 'https://auth.example.com',
240
+ audience: 'https://api.example.com',
241
+ principalClaimName: 'sub', // claim to use as principal
63
242
  }
64
243
  },
244
+ x509: {
245
+ principalAltName: 'email', // extract principal from certificate email SAN (default: uses subject)
246
+ key: './ssl/gateway-ca.key' // CA key for generating certs
247
+ },
65
248
  basic: {
66
- username: 'interopio',
67
- password: 'passwordo'
68
- }
249
+ realm: 'My Gateway'
250
+ },
69
251
  },
70
252
  app: async ({handle}) => {
71
253
  handle(
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Argon2 version 1.0 (0x10)
3
+ */
4
+ export const ARGON2_VERSION_10: number;
5
+
6
+ /**
7
+ * Argon2 version 1.3 (0x13) - current version
8
+ */
9
+ export const ARGON2_VERSION_13: number;
10
+
11
+ /**
12
+ * Current Argon2 version used by default
13
+ */
14
+ export const ARGON2_VERSION: number;
15
+
16
+ /**
17
+ * Default salt length in bytes (16)
18
+ */
19
+ export const DEFAULT_SALT_LENGTH: number;
20
+
21
+ /**
22
+ * Default hash length in bytes (32)
23
+ */
24
+ export const DEFAULT_HASH_LENGTH: number;
25
+
26
+ /**
27
+ * Default parallelism parameter (4)
28
+ */
29
+ export const DEFAULT_PARALLELISM: number;
30
+
31
+ /**
32
+ * Default memory cost in KiB (65536 = 64 MB)
33
+ */
34
+ export const DEFAULT_MEMORY: number;
35
+
36
+ /**
37
+ * Default number of iterations (3)
38
+ */
39
+ export const DEFAULT_PASSES: number;
40
+
41
+ /**
42
+ * Argon2 algorithm variants
43
+ */
44
+ export type Argon2Algorithm = 'argon2d' | 'argon2i' | 'argon2id';
45
+
46
+ /**
47
+ * Argon2 hash parameters
48
+ */
49
+ export type Argon2HashParameters = {
50
+ memory: number;
51
+ passes: number;
52
+ parallelism: number;
53
+ nonce: Buffer;
54
+ };
55
+
56
+ /**
57
+ * Decoded Argon2 hash structure
58
+ */
59
+ export type Argon2Hash = {
60
+ algorithm: Argon2Algorithm;
61
+ version: number;
62
+ parameters: Argon2HashParameters;
63
+ hash: Buffer;
64
+ };
65
+
66
+ /**
67
+ * Hash a password using Argon2.
68
+ *
69
+ * @param password - The plain text password to hash
70
+ * @param options - Optional parameters. If not provided, defaults will be used.
71
+ * @returns The encoded Argon2 hash string
72
+ */
73
+ export function hash(
74
+ password: string,
75
+ options?: {
76
+ saltLength?: number;
77
+ hashLength?: number;
78
+ parallelism?: number;
79
+ memory?: number;
80
+ passes?: number;
81
+ }
82
+ ): Promise<string>;
83
+
84
+ /**
85
+ * Verify a password against an Argon2 hash.
86
+ *
87
+ * @param encodedHash - The encoded Argon2 hash to verify against
88
+ * @param password - The plain text password to verify
89
+ * @returns true if password matches the hash, false otherwise
90
+ */
91
+ export function verify(encodedHash: string, password: string): Promise<boolean>;
92
+
93
+ /**
94
+ * Create an Argon2 hash from parameters.
95
+ * Low-level wrapper around node:crypto's argon2Sync.
96
+ *
97
+ * @param algorithm - Argon2 algorithm variant ('argon2d' | 'argon2i' | 'argon2id')
98
+ * @param password - The password to hash
99
+ * @param hashLength - Length of the output hash in bytes
100
+ * @param parameters - Argon2 parameters (nonce, memory, passes, parallelism). If not provided, defaults will be used.
101
+ * @returns The hash buffer
102
+ */
103
+ export function createHash(
104
+ algorithm: Argon2Algorithm,
105
+ password: string,
106
+ hashLength: number,
107
+ parameters?: Argon2HashParameters
108
+ ): Promise<Buffer>;
109
+
110
+ /**
111
+ * Decode an encoded Argon2 hash string into its components.
112
+ * Format: $argon2id$v=19$m=65536,t=3,p=4$base64salt$base64hash
113
+ *
114
+ * @param encodedHash - The encoded Argon2 hash string
115
+ * @returns Decoded hash components
116
+ */
117
+ export function decode(encodedHash: string): Argon2Hash;
118
+
119
+ /**
120
+ * Encode Argon2 hash components into a standard string format.
121
+ * Format: $argon2id$v=19$m=65536,t=3,p=4$base64salt$base64hash
122
+ *
123
+ * @param hashData - The hash components to encode
124
+ * @returns Encoded hash string
125
+ */
126
+ export function encode(hashData: Argon2Hash): string;
127
+
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Create a random salt (nonce) for cryptographic operations.
3
+ *
4
+ * @param length - Length of the salt in bytes
5
+ * @returns Random salt buffer
6
+ */
7
+ export function createSalt(length: number): Buffer;
@@ -0,0 +1,47 @@
1
+ import type { RSAKey, KJUR } from 'jsrsasign';
2
+
3
+ /**
4
+ * CA private key type - can be a PEM string or a jsrsasign key object
5
+ */
6
+ type CAPrivateKey = string | RSAKey | KJUR.crypto.DSA | KJUR.crypto.ECDSA;
7
+
8
+ /**
9
+ * Default Common Name for the root CA certificate.
10
+ */
11
+ export const DEFAULT_CA_NAME: string;
12
+
13
+ /**
14
+ * Generate a root Certificate Authority (CA) certificate.
15
+ *
16
+ * @param options - Options for generating the CA
17
+ * @param options.name - Common Name for the CA certificate (default: "io.Gateway Dev CA user@host")
18
+ * @param options.passphrase - Optional passphrase to protect the private key
19
+ * @returns Object containing the private key and certificate in PEM format
20
+ */
21
+ export function generateRootCA(options?: { name?: string, passphrase?: string }): {
22
+ key: string;
23
+ cert: string;
24
+ };
25
+
26
+
27
+ /**
28
+ * Generate a certificate with custom SAN (Subject Alternative Name) entries.
29
+ *
30
+ * @param caKey - CA private key (PEM string or jsrsasign key object)
31
+ * @param issuer - Issuer DN string from CA certificate
32
+ * @param sanEntries - Array of SAN entries (e.g., "localhost", "IP:192.168.1.1", "EMAIL:user@example.com")
33
+ * @param isClient - Generate client certificate (clientAuth) vs server certificate (serverAuth) (default: false)
34
+ * @param validityDays - Certificate validity in days (default: 7)
35
+ * @returns Object containing the private key and certificate in PEM format
36
+ */
37
+ export function generateCert(
38
+ caKey: CAPrivateKey,
39
+ issuer: string,
40
+ sanEntries: string[],
41
+ isClient?: boolean,
42
+ validityDays?: number
43
+ ): {
44
+ key: string;
45
+ cert: string;
46
+ };
47
+
@@ -0,0 +1,6 @@
1
+
2
+ export * as argon2 from './crypto/argon2';
3
+ export * as keygen from './crypto/keygen';
4
+ export * as mkcert from './crypto/mkcert';
5
+
6
+
@@ -9,11 +9,12 @@ import type {
9
9
  ReadonlyHttpHeaders,
10
10
  ResponseCookie
11
11
  } from './http';
12
- import type {WebSocketHandler} from './socket';
13
- import type {Principal, AuthorizationRule} from '../auth';
14
- import {AsyncLocalStorage} from 'node:async_hooks';
15
- import type {AddressInfo} from 'node:net';
16
- import {IOGateway} from '@interopio/gateway';
12
+ import type { WebSocketHandler } from './socket';
13
+ import type { Principal, AuthorizationRule } from '../auth';
14
+ import type { AsyncLocalStorage } from 'node:async_hooks';
15
+ import type { X509Certificate } from 'node:crypto';
16
+ import type { AddressInfo } from 'node:net';
17
+ import { IOGateway } from '@interopio/gateway';
17
18
 
18
19
  export type OriginFilters = {
19
20
  non_matched?: IOGateway.Filtering.Action
@@ -91,6 +92,10 @@ export interface ServerWebExchangeBuilder<Request extends ServerHttpRequest = Se
91
92
  build(): ServerWebExchange<Request, Response>
92
93
  }
93
94
 
95
+ /**
96
+ * SSL/TLS connection information
97
+ */
98
+ export type SslInfo = { peerCertificate?: X509Certificate };
94
99
 
95
100
  export type ServerHttpRequest = HttpRequest<ReadonlyHttpHeaders> & HttpInputMessage<ReadonlyHttpHeaders> & {
96
101
  readonly id: string
@@ -108,6 +113,8 @@ export type ServerHttpRequest = HttpRequest<ReadonlyHttpHeaders> & HttpInputMess
108
113
 
109
114
  readonly upgrade: boolean
110
115
  readonly remoteAddress?: AddressInfo
116
+ /** SSL/TLS connection information (available for HTTPS requests) */
117
+ readonly sslInfo?: SslInfo
111
118
  }
112
119
 
113
120
  export interface ServerHttpResponse extends HttpResponse<MutableHttpHeaders>, HttpOutputMessage<MutableHttpHeaders> {