@milaboratories/pl-deployments 1.1.0 → 1.1.2

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,3 +1,4 @@
1
+ import type { StartedTestContainer } from 'testcontainers';
1
2
  import { describe, it, beforeAll, afterAll, expect } from 'vitest';
2
3
  import { writeFileSync, readFileSync } from 'fs';
3
4
  import { SshClient } from '../ssh';
@@ -6,9 +7,10 @@ import { downloadsFolder, cleanUp, getConnectionForSsh, getContainerHostAndPort,
6
7
  import { ConsoleLoggerAdapter } from '@milaboratories/ts-helpers';
7
8
 
8
9
  let client: SshClient;
9
- const testContainer = await initContainer('ssh');
10
+ let testContainer: StartedTestContainer;
10
11
 
11
12
  beforeAll(async () => {
13
+ testContainer = await initContainer('ssh');
12
14
  client = await SshClient.init(new ConsoleLoggerAdapter(), getConnectionForSsh(testContainer));
13
15
  });
14
16
 
@@ -143,7 +145,58 @@ describe('sshConnect', () => {
143
145
  });
144
146
 
145
147
  it('should fail with invalid credentials', async () => {
146
- await expect(SshClient.init(new ConsoleLoggerAdapter(), { ...getConnectionForSsh(testContainer), privateKey: '123' })).rejects.toThrow();
148
+ await expect(SshClient.init(new ConsoleLoggerAdapter(), { ...getConnectionForSsh(testContainer), username: 'dfasdfa' })).rejects.toThrow();
149
+ });
150
+
151
+ it('should fail with invalid passphrase', async () => {
152
+ let catched = false;
153
+ try {
154
+ await SshClient.init(new ConsoleLoggerAdapter(), { ...getConnectionForSsh(testContainer), passphrase: 'dfasdfa' });
155
+ } catch (e) {
156
+ console.log(e);
157
+ expect((e as Error).message.includes('Cannot parse privateKey: OpenSSH key integrity check failed')).toBe(true);
158
+ catched = true;
159
+ }
160
+ expect(catched).toBe(true);
161
+ });
162
+
163
+ it('should fail with invalid username', async () => {
164
+ let catched = false;
165
+ try {
166
+ await SshClient.init(new ConsoleLoggerAdapter(), { ...getConnectionForSsh(testContainer), username: 'dfasdfa' });
167
+ } catch (e) {
168
+ console.log(e);
169
+ expect((e as Error).message.includes('All configured authentication methods failed')).toBe(true);
170
+ catched = true;
171
+ }
172
+ expect(catched).toBe(true);
173
+ });
174
+
175
+ it('should fail with invalid host', async () => {
176
+ let catched = false;
177
+ try {
178
+ await SshClient.init(new ConsoleLoggerAdapter(), { ...getConnectionForSsh(testContainer), host: '192.100.100.100' });
179
+ } catch (e) {
180
+ console.log(e);
181
+ expect((e as Error).message.includes('Timed out while waiting for handshake')).toBe(true);
182
+ catched = true;
183
+ }
184
+ expect(catched).toBe(true);
185
+ });
186
+
187
+ it('should fail with invalid private key', async () => {
188
+ let catched = false;
189
+
190
+ const invalidPk = ssh.utils.generateKeyPairSync('ecdsa', { bits: 256, comment: 'node.js rules!', passphrase: 'password', cipher: 'aes256-cbc' });
191
+
192
+ try {
193
+ await SshClient.init(new ConsoleLoggerAdapter(), { ...getConnectionForSsh(testContainer), privateKey: invalidPk.private, passphrase: 'password' });
194
+ } catch (e) {
195
+ console.log(e);
196
+ expect((e as Error).message.includes('All configured authentication methods failed')).toBe(true);
197
+ catched = true;
198
+ }
199
+ expect(catched).toBe(true);
147
200
  });
148
201
 
149
202
  it('should timeout if the server is unreachable', async () => {
package/src/ssh/ssh.ts CHANGED
@@ -6,7 +6,11 @@ import fs from 'fs';
6
6
  import { readFile } from 'fs/promises';
7
7
  import upath from 'upath';
8
8
  import type { MiLogger } from '@milaboratories/ts-helpers';
9
- import { fileExists } from '@milaboratories/ts-helpers';
9
+
10
+ const defaultConfig: ConnectConfig = {
11
+ keepaliveInterval: 60000,
12
+ keepaliveCountMax: 10,
13
+ }
10
14
 
11
15
  export type SshAuthMethods = 'publickey' | 'password';
12
16
  export type SshAuthMethodsResult = SshAuthMethods[];
@@ -26,8 +30,13 @@ export class SshClient {
26
30
  * @returns A new instance of SshClient with an active connection.
27
31
  */
28
32
  public static async init(logger: MiLogger, config: ConnectConfig): Promise<SshClient> {
33
+ const withDefaults = {
34
+ ...defaultConfig,
35
+ ...config
36
+ };
37
+
29
38
  const client = new SshClient(logger, new Client());
30
- await client.connect(config);
39
+ await client.connect(withDefaults);
31
40
 
32
41
  return client;
33
42
  }
@@ -178,13 +187,13 @@ export class SshClient {
178
187
  });
179
188
 
180
189
  conn.on('error', (err) => {
181
- console.error('[SSH] SSH connection error', 'ports', ports, err.message);
190
+ this.logger.error(`[SSH] SSH connection error, ports: ${JSON.stringify(ports)}, err: ${err.message}`);
182
191
  server?.close();
183
192
  reject(`ssh.forwardPort: conn.err: ${err}`);
184
193
  });
185
194
 
186
195
  conn.on('close', () => {
187
- this.logger.info(`[SSH] Connection closed, ports: ${ports}`);
196
+ this.logger.info(`[SSH] Connection closed, ports: ${JSON.stringify(ports)}`);
188
197
  });
189
198
 
190
199
  conn.connect(config);
@@ -1,29 +0,0 @@
1
- FROM node:20
2
-
3
- RUN apt-get update && \
4
- apt-get install -y openssh-server && \
5
- mkdir /var/run/sshd
6
-
7
- # RUN echo 'root:rootpassword' | chpasswd
8
-
9
- RUN useradd 'pl-doctor'
10
- RUN echo 'pl-doctor:pl-doctor-password' | chpasswd
11
-
12
- RUN sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config && \
13
- sed -i 's/^#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config
14
-
15
- RUN apt-get install -y locales && \
16
- locale-gen en_US.UTF-8
17
- ENV LANG en_US.UTF-8
18
-
19
- EXPOSE 22 3001
20
-
21
- COPY ./test-assets/pub-key.pub /home/pl-doctor/.ssh/authorized_keys
22
- COPY ./test-assets/simple-server.js /home/pl-doctor/simple-server.js
23
-
24
- RUN chmod 755 /home/pl-doctor
25
- RUN chown pl-doctor:pl-doctor /home/pl-doctor
26
-
27
- RUN chmod +x /home/pl-doctor/simple-server.js
28
-
29
- CMD ["/bin/bash", "-c", "/usr/sbin/sshd -D & node /home/pl-doctor/simple-server.js"]
@@ -1,10 +0,0 @@
1
- const http = require('http');
2
- const PORT = 3001;
3
- const MESSAGE = "Hello, this is a simple Node.js server!";
4
- const server = http.createServer((req, res) => {
5
- res.writeHead(200, { 'Content-Type': 'text/plain' });
6
- res.end(MESSAGE);
7
- });
8
- server.listen(PORT, () => {
9
- console.log(`Server is running on port ${PORT}`);
10
- });