ssh_tunnel_proxy 1.2.11 → 2.0.3

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.
package/test/test.js DELETED
@@ -1,214 +0,0 @@
1
- /*
2
- todo:
3
- add generate and store keys test
4
- add ngrok api test with stored api key in ssh_tunnel_proxy config
5
- to run ssh tunnel api tests edit config.json and provide api keys for each service
6
- */
7
-
8
- const assert = require('assert');
9
- const { describe, it } = require('mocha');
10
- const fs = require('fs');
11
-
12
- const { SSHTunnelProxy, KeypairStorage, NgrokApi } = require('../lib/index.js');
13
-
14
- // get config file containing api keys
15
- const homedir = require('os').homedir();
16
- const config = JSON.parse(fs.readFileSync(homedir + '/.config/ssh_tunnel_proxy/config.json'), 'utf8');
17
- const opts = config[0];
18
-
19
- const sshTunnelProxy = new SSHTunnelProxy();
20
- const keypairStorage = new KeypairStorage();
21
- const ngrokApi = new NgrokApi(opts.ngrok_api);
22
-
23
- const whitelist = {
24
- 80: true,
25
- 443: true,
26
- 22: true
27
- }
28
-
29
- // port value validation tests
30
- describe('Validate ports', function () {
31
- //const validate_port_number = sshTunnelProxy.__get__('validate_port_number');
32
- it('valid port number 1024', function () {
33
- assert(sshTunnelProxy.validate_port_number(1024, whitelist), 'should be valid');
34
- });
35
- it('valid port number 80', function () {
36
- assert(sshTunnelProxy.validate_port_number(80, whitelist), 'should be valid');
37
- });
38
- it('invalid port number -1', function () {
39
- assert.equal(false, sshTunnelProxy.validate_port_number(-1, whitelist), 'should be invalid');
40
- });
41
- it('invalid port number 65536', function () {
42
- assert.equal(false, sshTunnelProxy.validate_port_number(65536, whitelist), 'should be invalid');
43
- });
44
- it('invalid system port number 137', function () {
45
- assert.equal(false, sshTunnelProxy.validate_port_number(137, whitelist), 'should be invalid');
46
- });
47
- it('port number nan', function () {
48
- assert.equal(false, sshTunnelProxy.validate_port_number('nan', whitelist), 'should be invalid');
49
- });
50
- });
51
-
52
- // local forward format and value validation test
53
- describe('Validate local forwards', function () {
54
- //const validate_local_forward = sshTunnelProxy.__get__('validate_local_forward');
55
- var local_forward = [
56
- '8080:127.0.0.1:80',
57
- '9000:192.168.43.5:9000',
58
- '9000:192.168.43.5',
59
- '192.168.43.5:9000',
60
- '8137:127.0.0.1:137',
61
- '-1:127.0.0.1:65537',
62
- ];
63
- it('valid local forward to 80 ' + local_forward[0], function () {
64
- assert(() => { return sshTunnelProxy.validate_local_forward([local_forward[0]], whitelist) }, 'should be valid');
65
- });
66
- it('valid local forward to 9000 ' + local_forward[1], function () {
67
- assert(() => { return sshTunnelProxy.validate_local_forward([local_forward[1]], whitelist) }, 'should be valid');
68
- });
69
- it('invalid local forward format ' + local_forward[2], function () {
70
- const err = {
71
- message: 'Invalid local forward',
72
- info: {
73
- local_ports: '',
74
- remote_ports: '',
75
- }
76
- };
77
- assert.throws(() => { sshTunnelProxy.validate_local_forward([local_forward[2]], whitelist) }, err);
78
- });
79
- it('invalid local forward format ' + local_forward[3], function () {
80
- const err = {
81
- message: 'Invalid local forward',
82
- info: {
83
- local_ports: '192.168.43.5',
84
- remote_ports: '',
85
- }
86
- };
87
- assert.throws(() => { sshTunnelProxy.validate_local_forward([local_forward[3]], whitelist) }, err, 'should be invalid');
88
- });
89
- it('invalid local forward system port ' + local_forward[4], function () {
90
- const err = {
91
- message: 'Invalid local forward',
92
- info: {
93
- local_ports: '',
94
- remote_ports: '137',
95
- }
96
- };
97
- assert.throws(() => { sshTunnelProxy.validate_local_forward([local_forward[4]], whitelist) }, err, 'should be invalid');
98
- });
99
- it('invalid local forward port range ' + local_forward[5], function () {
100
- const err = {
101
- message: 'Invalid local forward',
102
- info: {
103
- local_ports: '-1',
104
- remote_ports: '65537',
105
- }
106
- };
107
- assert.throws(() => { sshTunnelProxy.validate_local_forward([local_forward[5]], whitelist) }, err, 'should be invalid');
108
- });
109
- });
110
-
111
- // generate, store and retrieve private key test
112
- describe('Store and retrieve private key in system keychain', function () {
113
- const service_name = 'ssh_proxy_tunnel';
114
- const account = 'test';
115
- const keypair = keypairStorage.generate_keypair();
116
- it('generated key should contain a private key', function () {
117
- assert(keypair.private_key, 'should not be empty');
118
- });
119
- it('generated key should contain a public key', function () {
120
- assert(keypair.public_key, 'should not be empty');
121
- });
122
- it('should store generated private key', () => {
123
- return keypairStorage.set_keypair(service_name, account, keypair.private_key).then(result => {
124
- assert.equal(result, undefined, 'should not return error');
125
- })
126
- });
127
- it('stored private key should match generated key', () => {
128
- return keypairStorage.get_keypair(service_name, account).then(stored_key => {
129
- assert.equal(stored_key, keypair.private_key, 'should match');
130
- });
131
- });
132
- it('stored public key should match generated key', () => {
133
- return keypairStorage.get_public_key_from_keychain(service_name, account).then(stored_key => {
134
- assert.equal(stored_key, keypair.public_key, 'should match');
135
- });
136
- });
137
- it('remove key should return true', () => {
138
- return keypairStorage.delete_keypair(service_name, account).then((result) => {
139
- assert(result, 'should return true');
140
- });
141
- });
142
- it('retrieve stored private key after delete should return null', () => {
143
- return keypairStorage.get_keypair(service_name, account).then((result) => {
144
- assert.equal(result, null, 'should return null');
145
- });
146
- });
147
- it('retrieve stored public key after delete should return null', () => {
148
- return keypairStorage.get_public_key_from_keychain(service_name, account).then((result) => {
149
- assert.equal(result, null, 'should return null');
150
- });
151
- });
152
- });
153
-
154
- /*
155
- // generate and store private key test
156
- describe('', function () {
157
- it('', function () {
158
- assert('', '');
159
- });
160
- });
161
- */
162
-
163
- describe('Get ngrok hostport', function () {
164
- //const parse_ngrok_hostport = ngrok_service.__get__('parse_ngrok_hostport');
165
- var test_endpoint = [{
166
- hostport: '8.tcp.ngrok.io:17632'
167
- }];
168
- var result_opts = ngrokApi.parse_ngrok_hostport(test_endpoint, opts);
169
- it('host should match 8.tcp.ngrok.io', function () {
170
- assert.equal(result_opts.host, '8.tcp.ngrok.io');
171
- });
172
- it('port should match 17632', function () {
173
- assert.equal(result_opts.port, '17632');
174
- });
175
- it('host, port should be obtained from api', async () => {
176
- const result = await ngrokApi.get_hostport(opts);
177
- assert(result.host, 'host should exist');
178
- assert(result.port, 'port should exist');
179
- }, (err) => {
180
- assert.equal(err, null);
181
- });
182
-
183
- });
184
-
185
- /*
186
- describe('ssh connection client ready', function () {
187
- });
188
-
189
- it('myEmitter should be enabled', function () {
190
- assert(myEmitter, 'received event emitter');
191
- });
192
-
193
- describe('ssh connection integration test', function () {
194
-
195
- it('ssh connect should invoke the ssh ready function', function (done) {
196
- this.timeout(10000);
197
- myEmitter.on('ssh_client_ready', (ssh_client) => {
198
- assert(ssh_client, 'ssh client created');
199
- done();
200
- });
201
- });
202
- var ws_socket = false;
203
- it('two websocket servers should be created', function (done) {
204
- this.timeout(18000);
205
- myEmitter.on('websocket_server_created', (socket) => {
206
- assert(socket, 'ssh websocket server created:' + socket.remotePort);
207
- if (!ws_socket) done();
208
- ws_socket = true;
209
- });
210
- });
211
- connect_ssh(opts);
212
-
213
- });
214
- */
@@ -1,217 +0,0 @@
1
- /*
2
- test exec cmd on remote server, parse to json object stream
3
- */
4
-
5
- //const assert = require('assert');
6
- //const { describe, it } = require('mocha');
7
-
8
- const fs = require('fs');
9
- const process = require('node:process');
10
- const { SSHTunnelProxy } = require('..');
11
- const { PassThrough, pipeline } = require("stream");
12
- const through = require('through');
13
- const split = require('split');
14
-
15
- // get config file containing api keys
16
- const homedir = require('os').homedir();
17
- var config = null;
18
- try {
19
- config = JSON.parse(fs.readFileSync(homedir + '/.config/ssh_tunnel_proxy/config.json'), 'utf8');
20
- } catch (err) {
21
- console.log('Error reading config:' + err);
22
- process.exit();
23
- }
24
-
25
- if (!config && !config[1]) {
26
- console.log('Specified config not found in configs');
27
- process.exit();
28
- }
29
-
30
- const opts = config[1];
31
-
32
- const sshTunnelProxy = new SSHTunnelProxy();
33
-
34
- // parse shell command result into array of strings
35
- function parse_cmd(str) {
36
-
37
- let result = [];
38
-
39
- let regex = /(([\w-/_~.\:\[\]]+)|("(.*?)")|('(.*?)'))/g;
40
- let groups = [2, 4, 6];
41
- let match;
42
-
43
- while ((match = regex.exec(str)) !== null) {
44
- // This is necessary to avoid infinite loops
45
- // with zero-width matches
46
- if (match.index === regex.lastIndex) {
47
- regex.lastIndex++;
48
- }
49
-
50
- // For this to work the regex groups need to
51
- // be mutually exclusive
52
- groups.forEach(function (group) {
53
- if (match[group]) {
54
- result.push(match[group]);
55
- }
56
- });
57
- /*
58
- let log_matches = false;
59
- // show matches for debugging
60
- log_matches && match.forEach(function (m, group) {
61
- if (m) {
62
- console.log(`Match '${m}' found in group: ${group}`);
63
- }
64
- });
65
- */
66
- }
67
- return result;
68
- }
69
-
70
- // generate object from arrays of names/values
71
- function toObj(names, values) {
72
- const obj = {};
73
- for (var i = 0; i < names.length; i++) {
74
- obj[names[i]] = values[i];
75
- }
76
- return obj;
77
- }
78
-
79
-
80
- // merge array items beginning at start into single item and append back to array
81
- function mergeArray(ar, start) {
82
- const ar2 = ar.slice(start);
83
- const ar1 = ar.slice(0, start);
84
- const item = ar2.join(' ');
85
- ar1.push(item);
86
- return ar1;
87
- }
88
-
89
- /*
90
- Feb 4 21:34:17 tim-ThinkPad-P50s systemd[1]: Started Run anacron jobs.
91
- */
92
- function parseSyslog(line) {
93
- const format = ['M', 'D', 'T', 'host', 'proc', 'msg'];
94
- const values = parse_cmd(line);
95
- const log = mergeArray(values, 5);
96
- const obj = toObj(format, log);
97
- if (obj.M && obj.D && obj.T) {
98
- obj.date = obj.M + ' ' + obj.D + ' ' + obj.T;
99
- delete obj.M;
100
- delete obj.D;
101
- delete obj.T;
102
- }
103
- return obj;
104
- }
105
-
106
- // parse ls long line output into json object
107
- function processLSLong(line) {
108
- const format10 = ['pm', 'links', 'user', 'group', 'size', 'M', 'D', 'H', 'MM', 'name'];
109
- const format9 = ['pm', 'links', 'user', 'group', 'size', 'M', 'D', 'Y', 'name'];
110
- const values = parse_cmd(line);
111
- const obj = toObj((values.length < 10) ? format9 : format10, values);
112
- if (obj.pm) {
113
- obj.type = obj.pm.substring(0, 1);
114
- obj.pm = obj.pm.substring(1);
115
- }
116
- if (obj.M && obj.D) {
117
- obj.date = obj.M + ' ' + obj.D;
118
- delete obj.M;
119
- delete obj.D;
120
- if (obj.Y) {
121
- obj.date += ' ' + obj.Y;
122
- delete obj.Y;
123
- }
124
- }
125
- if (obj.H && obj.MM) {
126
- obj.time = obj.H + ':' + obj.MM;
127
- delete obj.H;
128
- delete obj.MM;
129
- }
130
- return obj;
131
- }
132
-
133
- function to_lsParse() {
134
- return new through(function (data) {
135
- const obj = processLSLong(data);
136
- if (obj.name) this.queue(obj);
137
- });
138
- }
139
-
140
- function to_syslogParse() {
141
- return new through(function (data) {
142
- const obj = parseSyslog(data);
143
- if (obj.proc) this.queue(obj);
144
- });
145
- }
146
-
147
- function to_JSONString() {
148
- return new through(function (data) {
149
- this.queue(JSON.stringify(data) + '\n');
150
- })
151
- }
152
-
153
- // lsLongShellProc conversion tests
154
- async function lsTest(sshTunnelProxy) {
155
- return new Promise(async (resolve) => {
156
-
157
- // exec remote command and pipe data through tunnel until end of data
158
- const tunnel = new PassThrough();
159
- pipeline(tunnel,
160
- split(),
161
- to_lsParse(),
162
- to_JSONString(),
163
- process.stdout,
164
- () => { }
165
- );
166
-
167
- const lscmd = 'ls -all';
168
- console.log('\ninvoking ' + lscmd + ' on remote host:\n');
169
- await sshTunnelProxy.execCmd(lscmd, tunnel);
170
-
171
- // stream processing complete
172
- console.log('ls -all completed');
173
- resolve();
174
- })
175
- }
176
-
177
- // lsLongShellProc conversion tests
178
- async function syslogTest(sshTunnelProxy) {
179
- return new Promise(async (resolve) => {
180
-
181
- // exec remote command and pipe data through tunnel until end of data
182
- const tunnel = new PassThrough();
183
- pipeline(tunnel,
184
- split(),
185
- to_syslogParse(),
186
- to_JSONString(),
187
- process.stdout,
188
- () => { }
189
- );
190
- const syslogcmd = 'tail /var/log/syslog';
191
- console.log('\ninvoking ' + syslogcmd + ' on remote host:\n');
192
- await sshTunnelProxy.execCmd(syslogcmd, tunnel);
193
-
194
- // stream processing complete
195
- console.log(syslogcmd+' completed');
196
- resolve();
197
- })
198
- }
199
-
200
- async function runTests() {
201
-
202
- // connect to remote host
203
- sshTunnelProxy.debug_en = true;
204
- await sshTunnelProxy.connectSSH(opts);
205
-
206
- // invoke ls -all on remote host and parse result to json object string
207
- await lsTest(sshTunnelProxy);
208
-
209
- // invoke tail /var/log/syslog on remote host and parse result to json object string
210
- await syslogTest(sshTunnelProxy);
211
-
212
- process.exit();
213
- }
214
-
215
- runTests();
216
-
217
-