-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsimpleCommandServer.sh
More file actions
executable file
·102 lines (88 loc) · 4.16 KB
/
simpleCommandServer.sh
File metadata and controls
executable file
·102 lines (88 loc) · 4.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#!/usr/local/bin/node
// Lightweight server that accepts requests over http on a configurable port, and runs
// commands on the host in a safe and flexible manner. Commands MUST be defined in the
// "cmdMaps" object; users can pass in params.
// Ex: http://localhost:port/<CMD>/paramOne/paramTwo
// see also netcatLoanerPseudoServer.sh for an early experiment in a different direction
//
// Real power of this comes from when I am splitting my work over multiple computers / servers but still
// want to do stuff like reload webpages with chromix, access helper scripts, etc.
//
// I have at least two use cases for this:
// 1. borrowing a loaner laptop for a trip
// In this case, I run simpleCommandServer on the loaner, and then run "connectToOffice.sh" to ssh/tunnel/portforward
// back to my main Carleton desktop. Once there I can call 'curl localhost:XXXX/command' which will talk back
// to the loaner laptop and run commands there (typically, reload a webpage of interest)
//
// 2. ssh'ing to a server like the one for CLAMP development work
// In this case, I run simpleCommandServer on my main Carleton desktop, and then run something like "connectToMitre.sh"
// to ssh/tunnel/portforward to that server. Again I can curl localhost and talk back to my desktop, which
// can be used to reload webpages or run other things (like vimKeywordLookup.js for instance...). Commands
// can accept user input; for instance the "vk" command can be called via, for example,
// "curl -s localhost:2499/vk/php/implode | less" -- 'php' and 'implode' are passed to the keywordLookup.js program
// and output is piped (or redirected, or what have you). This lets me do stuff like use my nice customized
// scripts that are installed in just one place, even if I'm ssh'ed in someplace else. (and I can't just do them
// over ssh as my machine is not visible to the internet, and I don't want to always multihop through the gateway)
var sys = require("sys"), child_process = require("child_process"), my_http = require("http");
// see https://blog.liftsecurity.io/2014/08/19/Avoid-Command-Injection-Node.js for
// a good discussion of how to be safe with this approach
// be sure to start chromix manually (chromix-server) for chromix commands
var cmdMaps = {
"vk": {
command: "/Users/tfeiler/development/shellScripts/vim/keyword/keywordLookup.js",
returnResults: true
},
"chromix": {
command: "chromix",
},
"random": {
command: "chromix",
params: ["with", "random.org", "reload"]
}
};
var sensitiveBashScript = process.env.HOME + "/development/configurations/bash/sensitive_data.bash";
child_process.exec('source', [sensitiveBashScript], function() {
var portToListenOn;
if (process.argv.length == 3) {
portToListenOn = process.argv[2];
} else {
portToListenOn = process.env._TJF_COMMANDSERVER_PORT;
}
my_http.createServer(function(request,response){
var mapKey = request.url.substring(1);
// are there additional params passed in by user?
var slashIdx = mapKey.indexOf("/");
var userInputParams = [];
if (slashIdx != -1) {
userInputParams = mapKey.substring(slashIdx+1).split("/");
mapKey = mapKey.substring(0, slashIdx);
}
var mappedCmd = cmdMaps[mapKey];
if (mappedCmd != undefined) {
// child_process.exec(mappedCmd);
var commandParams = mappedCmd.params ? mappedCmd.params : [];
var combinedParams = commandParams.concat(userInputParams);
sys.puts("execing [" + mappedCmd.command + "] with params [" + combinedParams + "]...");
var spawnedProc = child_process.spawn(mappedCmd.command, combinedParams);
spawnedProc.stderr.on('data', function(data) {
console.log("stderr: " + data);
});
if (mappedCmd.returnResults) {
// response.writeHead(200, {"Content-Type": "text/plain"});
spawnedProc.stdout.on('data', function(data) {
console.log("stdout: " + data);
response.write(data.toString());
});
spawnedProc.on('close', function(code) {
console.log("close: exited with code '" + code + "'");
response.end();
});
} else {
response.end();
}
} else {
sys.puts("unsupported command [" + request.url + "]");
}
}).listen(portToListenOn);
sys.puts("command server Running on " + portToListenOn);
});