You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+42-41Lines changed: 42 additions & 41 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,15 +13,15 @@ It is important to note, that despite the use-case described below for this proj
13
13
*[Security](#security)
14
14
*[Related Tools](#related)
15
15
16
-
###<aid="Origin"></a> Origin
16
+
###<aid="Origin"></a> Origin
17
17
18
-
This project originated out of the need to execute various Powershell commands (at fairly high volume and frequency) against services within Office365/Azure bridged via a custom node.js implemented REST API; this was due to the lack of certain features in the REST GraphAPI for Azure/o365, that are available only in Powershell.
18
+
This project originated out of the need to execute various Powershell commands (at fairly high volume and frequency) against services within Office365/Azure bridged via a custom node.js implemented REST API; this was due to the lack of certain features in the REST GraphAPI for Azure/o365, that are available only in Powershell.
19
19
20
20
If you have done any work with Powershell and o365, then you know that there is considerable overhead in both establishing a remote session and importing and downloading various needed cmdlets. This is an expensive operation and there is a lot of value in being able to keep this remote session open for longer periods of time rather than repeating this entire process for every single command that needs to be executed and then tearing everything down.
21
21
22
22
Simply doing an child_process.**exec** per command to launch an external process, run the command, and then killing the process is not really an option under such scenarios, as it is expensive and very singular in nature; no state can be maintained if need be. We also tried using [edge.js with powershell](https://github.com/tjanczuk/edge#how-to-script-powershell-in-a-nodejs-application) and this simply would not work with o365 exchange commands and heavy session cmdlet imports (the entire node.js process would crash). Using this module gives you full un-fettered access to the externally connected child_process, with no restrictions other than what uid/gid (permissions) the spawned process is running under (which you **really** have to consider from security standpoint!)
23
23
24
-
The diagram below should conceptually give you an idea of what this module does.
24
+
The diagram below should conceptually give you an idea of what this module does.
25
25
26
26
**The local user that the node process runs as should have virtually zero rights! Also be sure to properly configure a restricted UID/GID when instatiating a new instance of this. See security notes below.**
27
27
@@ -42,75 +42,76 @@ mocha test/all.js
42
42
43
43
```
44
44
v1.0-beta.3 - 2014-01-26
45
-
- New options for command blacklisting regex matching and interval
45
+
- New options for command blacklisting regex matching and interval
46
46
based self auto-invalidation of ProcessProxy instances
47
-
47
+
48
48
v1.0-beta.2 - 2014-01-21
49
49
- New return types for executeCommands - is now an array
50
-
50
+
51
51
v1.0-beta.1 - 2014-01-17
52
52
- Initial version
53
53
```
54
54
55
-
###<aid="usage"></a> Usage
55
+
###<aid="usage"></a> Usage
56
56
57
57
To use StatefulProcessCommandProxy the constructor takes one parameter which is a configuration object who's properties are described below. Please refer to the example (following) and the unit-test for more details.
58
58
59
59
```
60
60
name: The name of this instance, arbitrary
61
-
61
+
62
62
max: maximum number of processes to maintain
63
-
63
+
64
64
min: minimum number of processes to maintain
65
-
65
+
66
66
idleTimeoutMS: idle in milliseconds by which a process will be destroyed
67
-
67
+
68
68
processCommand: full path to the actual process to be spawned (i.e. /bin/bash)
69
-
69
+
70
70
processArgs: arguments to pass to the process command
71
-
71
+
72
72
processRetainMaxCmdHistory: for each process spawned, the maximum number
73
73
of command history objects to retain in memory
74
74
(useful for debugging), default 0
75
-
75
+
76
76
processInvalidateOnRegex: optional config of regex patterns who if match
77
77
their respective type, will flag the process as invalid
78
78
{
79
-
'any' : ['regex1', ....],
80
-
'stdout' : ['regex1', ....],
81
-
'stderr' : ['regex1', ....]
79
+
'any' : [ {regex:'regex1',flags:'ig'}, ....],
80
+
'stdout' : [ {regex:'regex1',flags:'m'}, ....],
81
+
'stderr' : [ {regex:'regex1',flags:'ig'}, ....]
82
82
}
83
-
83
+
84
84
processCmdBlacklistRegex: optional config array regex patterns who if match the
85
85
command requested to be executed will be rejected
86
86
with an error
87
-
[ 'regex1', 'regex2'...]
88
-
87
+
[ {regex:'regex1',flags:'ig'},
88
+
{regex:'regex2',flags:'ig'}...]
89
+
89
90
processCwd: optional current working directory for the processes to be spawned
90
-
91
+
91
92
processEnvMap: optional hash/object of key-value pairs for environment variables
92
93
to set for the spawned processes
93
-
94
+
94
95
processUid: optional uid to launch the processes as
95
-
96
+
96
97
processGid: optional gid to launch the processes as
97
-
98
+
98
99
logFunction: optional function that should have the signature
99
100
(severity,origin,message), where log messages will
100
101
be sent to. If null, logs will just go to console
101
-
102
+
102
103
initCommands: optional array of actual commands to execute on each newly
103
104
spawned ProcessProxy in the pool before it is made available
104
-
105
+
105
106
preDestroyCommands: optional array of actual commands to execute on a process
106
107
before it is killed/destroyed on shutdown or being invalid
107
-
108
+
108
109
validateFunction: optional function that should have the signature to accept
109
110
a ProcessProxy object, and should return true/false if the
110
111
process is valid or not, at a minimum this should call
111
112
ProcessProxy.isValid(). If the function is not provided
112
113
the default behavior is to only check ProcessProxy.isValid()
113
-
114
+
114
115
autoInvalidationConfig optional configuration that will run the specified
115
116
commands in the background on the given interval,
116
117
and if the given regexes match/do-not-match for each command the
@@ -122,22 +123,22 @@ To use StatefulProcessCommandProxy the constructor takes one parameter which is
122
123
commands:
123
124
[
124
125
{ command:'cmd1toRun',
125
-
126
+
126
127
// OPTIONAL: because you can configure multiple commands
127
128
// where the first ones doe some prep, then the last one's
128
129
// output needs to be evaluated hence 'regexes' may not
129
130
// always be present, (but your LAST command must have a
130
131
// regexes config to eval prior work, otherwise whats the point
// test that our invalidation regex above traps and destroys this process instance
210
211
statefulProcessCommandProxy.executeCommand('echo "this command has an error and will be '+
211
212
' destroyed after check-in because it matches our invalidation regex"')
@@ -239,19 +240,19 @@ setTimeout(function() {
239
240
},10000);
240
241
241
242
```
242
-
243
-
###<aid="security"></a> Security
243
+
244
+
###<aid="security"></a> Security
244
245
245
246
Obviously this module can expose you to some insecure situations depending on how you use it... you are providing a gateway to an external process via Node on your host os! (likely a shell in most use-cases). Here are some tips; ultimately its your responsibility to secure your system.
246
247
247
248
* Ensure that the node process is running as a user with very limited rights
248
249
* Make use of the uid/gid configuration appropriately to further limit the processes
249
-
* Never expose calls to this module directly, instead you should write a wrapper layer around StatefulProcessCommandProxy that protects, analyzes and sanitizes external input that can materialize in a `command` statement.
250
+
* Never expose calls to this module directly, instead you should write a wrapper layer around StatefulProcessCommandProxy that protects, analyzes and sanitizes external input that can materialize in a `command` statement.
250
251
* All commands you pass to `execute` should be sanitized to protect from injection attacks
251
-
252
+
252
253
###<aid="related"></a> Related Tools
253
254
254
255
Have a look at these related projects which build on top of this module to provide some higher level functionality
255
256
256
-
*https://github.com/bitsofinfo/powershell-command-executor - Introduces a higher level "registry" of powershell commands which can be generated, have arguments applied to them (and sanitized), then executed.
257
+
*https://github.com/bitsofinfo/powershell-command-executor - Introduces a higher level "registry" of powershell commands which can be generated, have arguments applied to them (and sanitized), then executed.
257
258
*https://github.com/bitsofinfo/powershell-command-executor-ui - Builds on top of powershell-command-executor to provide a simple Node REST API and AngularJS interface for testing the execution of commands in the registry
0 commit comments