pywebexec 1.1.0__tar.gz → 1.1.2__tar.gz
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.
- {pywebexec-1.1.0/pywebexec.egg-info → pywebexec-1.1.2}/PKG-INFO +10 -9
- {pywebexec-1.1.0 → pywebexec-1.1.2}/README.md +9 -8
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec/pywebexec.py +7 -8
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec/static/js/script.js +3 -3
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec/templates/index.html +2 -2
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec/version.py +2 -2
- {pywebexec-1.1.0 → pywebexec-1.1.2/pywebexec.egg-info}/PKG-INFO +10 -9
- {pywebexec-1.1.0 → pywebexec-1.1.2}/.github/workflows/python-publish.yml +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/.gitignore +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/LICENSE +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pyproject.toml +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec/__init__.py +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec/static/css/style.css +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec/static/images/aborted.svg +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec/static/images/copy.svg +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec/static/images/copy_ok.svg +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec/static/images/failed.svg +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec/static/images/favicon.svg +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec/static/images/running.svg +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec/static/images/success.svg +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec/templates/__init__.py +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec.egg-info/SOURCES.txt +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec.egg-info/dependency_links.txt +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec.egg-info/entry_points.txt +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec.egg-info/requires.txt +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/pywebexec.egg-info/top_level.txt +0 -0
- {pywebexec-1.1.0 → pywebexec-1.1.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: pywebexec
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.2
|
|
4
4
|
Summary: Simple Python HTTP Exec Server
|
|
5
5
|
Home-page: https://github.com/joknarf/pywebexec
|
|
6
6
|
Author: Franck Jouvanceau
|
|
@@ -83,7 +83,9 @@ $ pywebexec
|
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
* Launch commands with params/view live output/Status using browser
|
|
86
|
-

|
|
87
|
+
|
|
88
|
+
all commands output / statuses are available in the executables directory in subdirectory `.web_status`
|
|
87
89
|
|
|
88
90
|
## features
|
|
89
91
|
|
|
@@ -102,8 +104,8 @@ $ pywebexec
|
|
|
102
104
|
|
|
103
105
|
## Customize server
|
|
104
106
|
```shell
|
|
105
|
-
$ pywebexec --dir ~/myscripts --listen 0.0.0.0 --port 8080
|
|
106
|
-
$ pywebexec -d ~/myscripts -l 0.0.0.0 -p 8080
|
|
107
|
+
$ pywebexec --dir ~/myscripts --listen 0.0.0.0 --port 8080 --title myscripts
|
|
108
|
+
$ pywebexec -d ~/myscripts -l 0.0.0.0 -p 8080 -t myscripts
|
|
107
109
|
```
|
|
108
110
|
|
|
109
111
|
## Basic auth
|
|
@@ -117,11 +119,10 @@ Generated password is given if no `--pasword` option
|
|
|
117
119
|
|
|
118
120
|
* ldap(s) password check / group member
|
|
119
121
|
```shell
|
|
120
|
-
$ export PYWEBEXEC_LDAP_SERVER=ldap.forumsys.com
|
|
121
|
-
$ export PYWEBEXEC_LDAP_USE_SSL=0
|
|
122
|
+
$ export PYWEBEXEC_LDAP_SERVER=ldap://ldap.forumsys.com:389
|
|
122
123
|
$ export PYWEBEXEC_LDAP_BIND_DN="cn=read-only-admin,dc=example,dc=com"
|
|
123
124
|
$ export PYWEBEXEC_LDAP_BIND_PASSWORD="password"
|
|
124
|
-
$ export PYWEBEXEC_LDAP_GROUPS=mathematicians,scientists
|
|
125
|
+
$ export PYWEBEXEC_LDAP_GROUPS=ou=mathematicians,ou=scientists
|
|
125
126
|
$ export PYWEBEXEC_LDAP_USER_ID="uid"
|
|
126
127
|
$ export PYWEBEXEC_LDAP_BASE_DN="dc=example,dc=com"
|
|
127
128
|
$ pywebexec
|
|
@@ -162,7 +163,7 @@ $ curl http://myhost:8080/run_script -H 'Content-Type: application/json' -X POST
|
|
|
162
163
|
|-----------|-----------------------------|--------------------|---------------------|
|
|
163
164
|
| POST | /run_command | command: str<br>params: array[str] | command_id: uuid<br>message: str |
|
|
164
165
|
| POST | /stop_command/command_id | | message: str |
|
|
165
|
-
| GET | /command_status/command_id | | command_id: uuid<br>command: str<br>params: array[str]<br>start_time: isotime<br>end_time: isotime<br>status: str<br>exit_code: int |
|
|
166
|
+
| GET | /command_status/command_id | | command_id: uuid<br>command: str<br>params: array[str]<br>start_time: isotime<br>end_time: isotime<br>status: str<br>exit_code: int<br>last_output_line: str |
|
|
166
167
|
| GET | /command_output/command_id | | output: str<br>status: str |
|
|
167
|
-
| GET | /commands | | array of<br>command_id: uuid<br>command: str<br>start_time: isotime<br>end_time: isotime<br>status: str<br>exit_code: int |
|
|
168
|
+
| GET | /commands | | array of<br>command_id: uuid<br>command: str<br>start_time: isotime<br>end_time: isotime<br>status: str<br>exit_code: int<br>last_output_line: str |
|
|
168
169
|
| GET | /executables | | array of str |
|
|
@@ -21,7 +21,9 @@ $ pywebexec
|
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
* Launch commands with params/view live output/Status using browser
|
|
24
|
-

|
|
25
|
+
|
|
26
|
+
all commands output / statuses are available in the executables directory in subdirectory `.web_status`
|
|
25
27
|
|
|
26
28
|
## features
|
|
27
29
|
|
|
@@ -40,8 +42,8 @@ $ pywebexec
|
|
|
40
42
|
|
|
41
43
|
## Customize server
|
|
42
44
|
```shell
|
|
43
|
-
$ pywebexec --dir ~/myscripts --listen 0.0.0.0 --port 8080
|
|
44
|
-
$ pywebexec -d ~/myscripts -l 0.0.0.0 -p 8080
|
|
45
|
+
$ pywebexec --dir ~/myscripts --listen 0.0.0.0 --port 8080 --title myscripts
|
|
46
|
+
$ pywebexec -d ~/myscripts -l 0.0.0.0 -p 8080 -t myscripts
|
|
45
47
|
```
|
|
46
48
|
|
|
47
49
|
## Basic auth
|
|
@@ -55,11 +57,10 @@ Generated password is given if no `--pasword` option
|
|
|
55
57
|
|
|
56
58
|
* ldap(s) password check / group member
|
|
57
59
|
```shell
|
|
58
|
-
$ export PYWEBEXEC_LDAP_SERVER=ldap.forumsys.com
|
|
59
|
-
$ export PYWEBEXEC_LDAP_USE_SSL=0
|
|
60
|
+
$ export PYWEBEXEC_LDAP_SERVER=ldap://ldap.forumsys.com:389
|
|
60
61
|
$ export PYWEBEXEC_LDAP_BIND_DN="cn=read-only-admin,dc=example,dc=com"
|
|
61
62
|
$ export PYWEBEXEC_LDAP_BIND_PASSWORD="password"
|
|
62
|
-
$ export PYWEBEXEC_LDAP_GROUPS=mathematicians,scientists
|
|
63
|
+
$ export PYWEBEXEC_LDAP_GROUPS=ou=mathematicians,ou=scientists
|
|
63
64
|
$ export PYWEBEXEC_LDAP_USER_ID="uid"
|
|
64
65
|
$ export PYWEBEXEC_LDAP_BASE_DN="dc=example,dc=com"
|
|
65
66
|
$ pywebexec
|
|
@@ -100,7 +101,7 @@ $ curl http://myhost:8080/run_script -H 'Content-Type: application/json' -X POST
|
|
|
100
101
|
|-----------|-----------------------------|--------------------|---------------------|
|
|
101
102
|
| POST | /run_command | command: str<br>params: array[str] | command_id: uuid<br>message: str |
|
|
102
103
|
| POST | /stop_command/command_id | | message: str |
|
|
103
|
-
| GET | /command_status/command_id | | command_id: uuid<br>command: str<br>params: array[str]<br>start_time: isotime<br>end_time: isotime<br>status: str<br>exit_code: int |
|
|
104
|
+
| GET | /command_status/command_id | | command_id: uuid<br>command: str<br>params: array[str]<br>start_time: isotime<br>end_time: isotime<br>status: str<br>exit_code: int<br>last_output_line: str |
|
|
104
105
|
| GET | /command_output/command_id | | output: str<br>status: str |
|
|
105
|
-
| GET | /commands | | array of<br>command_id: uuid<br>command: str<br>start_time: isotime<br>end_time: isotime<br>status: str<br>exit_code: int |
|
|
106
|
+
| GET | /commands | | array of<br>command_id: uuid<br>command: str<br>start_time: isotime<br>end_time: isotime<br>status: str<br>exit_code: int<br>last_output_line: str |
|
|
106
107
|
| GET | /executables | | array of str |
|
|
@@ -34,7 +34,6 @@ app.config['LDAP_GROUPS'] = os.environ.get('PYWEBEXEC_LDAP_GROUPS')
|
|
|
34
34
|
app.config['LDAP_BASE_DN'] = os.environ.get('PYWEBEXEC_LDAP_BASE_DN')
|
|
35
35
|
app.config['LDAP_BIND_DN'] = os.environ.get('PYWEBEXEC_LDAP_BIND_DN')
|
|
36
36
|
app.config['LDAP_BIND_PASSWORD'] = os.environ.get('PYWEBEXEC_LDAP_BIND_PASSWORD')
|
|
37
|
-
app.config['LDAP_USE_SSL'] = int(os.environ.get('PYWEBEXEC_LDAP_USE_SSL', False))
|
|
38
37
|
|
|
39
38
|
# Directory to store the command status and output
|
|
40
39
|
COMMAND_STATUS_DIR = '.web_status'
|
|
@@ -401,14 +400,14 @@ def verify_password(username, password):
|
|
|
401
400
|
return False
|
|
402
401
|
|
|
403
402
|
def verify_ldap(username, password):
|
|
404
|
-
tls_configuration = Tls(validate=ssl.CERT_NONE, version=ssl.PROTOCOL_TLSv1_2) if app.config['
|
|
405
|
-
server = Server(app.config['LDAP_SERVER'],
|
|
403
|
+
tls_configuration = Tls(validate=ssl.CERT_NONE, version=ssl.PROTOCOL_TLSv1_2) if app.config['LDAP_SERVER'].startswith("ldaps:") else None
|
|
404
|
+
server = Server(app.config['LDAP_SERVER'], tls=tls_configuration, get_info=ALL)
|
|
406
405
|
user_filter = f"({app.config['LDAP_USER_ID']}={username})"
|
|
407
406
|
try:
|
|
408
407
|
# Bind with the bind DN and password
|
|
409
|
-
conn = Connection(server, user=app.config['LDAP_BIND_DN'], password=app.config['LDAP_BIND_PASSWORD'], authentication=SIMPLE, auto_bind=True)
|
|
408
|
+
conn = Connection(server, user=app.config['LDAP_BIND_DN'], password=app.config['LDAP_BIND_PASSWORD'], authentication=SIMPLE, auto_bind=True, read_only=True)
|
|
410
409
|
try:
|
|
411
|
-
conn.search(search_base=app.config['LDAP_BASE_DN'], search_filter=user_filter)
|
|
410
|
+
conn.search(search_base=app.config['LDAP_BASE_DN'], search_filter=user_filter, search_scope=SUBTREE)
|
|
412
411
|
if len(conn.entries) == 0:
|
|
413
412
|
print(f"User {username} not found in LDAP.")
|
|
414
413
|
return False
|
|
@@ -417,13 +416,13 @@ def verify_ldap(username, password):
|
|
|
417
416
|
conn.unbind()
|
|
418
417
|
|
|
419
418
|
# Bind with the user DN and password to verify credentials
|
|
420
|
-
conn = Connection(server, user=user_dn, password=password, authentication=SIMPLE, auto_bind=True)
|
|
419
|
+
conn = Connection(server, user=user_dn, password=password, authentication=SIMPLE, auto_bind=True, read_only=True)
|
|
421
420
|
try:
|
|
422
421
|
if not app.config['LDAP_GROUPS'] and conn.result["result"] == 0:
|
|
423
422
|
return True
|
|
424
|
-
group_filter = "".join([f'(
|
|
423
|
+
group_filter = "".join([f'({group})' for group in app.config['LDAP_GROUPS'].split(",")])
|
|
425
424
|
group_filter = f"(&{group_filter}(|(member={user_dn})(uniqueMember={user_dn})))"
|
|
426
|
-
conn.search(search_base=app.config['LDAP_BASE_DN'], search_filter=group_filter)
|
|
425
|
+
conn.search(search_base=app.config['LDAP_BASE_DN'], search_filter=group_filter, search_scope=SUBTREE)
|
|
427
426
|
result = len(conn.entries) > 0
|
|
428
427
|
if not result:
|
|
429
428
|
print(f"User {username} is not a member of groups {app.config['LDAP_GROUPS']}.")
|
|
@@ -40,11 +40,11 @@ async function fetchCommands() {
|
|
|
40
40
|
<td>${command.status === 'running' ? formatDuration(command.start_time, new Date().toISOString()) : formatDuration(command.start_time, command.end_time)}</td>
|
|
41
41
|
<td>${command.exit_code}</td>
|
|
42
42
|
<td>${command.command.replace(/^\.\//, '')}</td>
|
|
43
|
-
<td class="monospace outcol">${command.last_output_line || ''}</td>
|
|
44
43
|
<td>
|
|
45
|
-
<button onclick="relaunchCommand('${command.command_id}')">
|
|
46
|
-
|
|
44
|
+
${command.status === 'running' ? `<button onclick="stopCommand('${command.command_id}')">Stop</button>` : ` <button onclick="relaunchCommand('${command.command_id}')">Run</button>
|
|
45
|
+
`}
|
|
47
46
|
</td>
|
|
47
|
+
<td class="monospace outcol">${command.last_output_line || ''}</td>
|
|
48
48
|
`;
|
|
49
49
|
commandsTbody.appendChild(commandRow);
|
|
50
50
|
});
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<select id="commandName" name="commandName"></select>
|
|
14
14
|
<label for="params">Params</label>
|
|
15
15
|
<input type="text" id="params" name="params">
|
|
16
|
-
<button type="submit">
|
|
16
|
+
<button type="submit">Run</button>
|
|
17
17
|
</form>
|
|
18
18
|
<div class="table-container" id="tableContainer">
|
|
19
19
|
<table>
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
<th>Duration</th>
|
|
26
26
|
<th>Exit</th>
|
|
27
27
|
<th>Command</th>
|
|
28
|
+
<th>Action</th>
|
|
28
29
|
<th>Output</th>
|
|
29
|
-
<th>Actions</th>
|
|
30
30
|
</tr>
|
|
31
31
|
</thead>
|
|
32
32
|
<tbody id="commands"></tbody>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: pywebexec
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.2
|
|
4
4
|
Summary: Simple Python HTTP Exec Server
|
|
5
5
|
Home-page: https://github.com/joknarf/pywebexec
|
|
6
6
|
Author: Franck Jouvanceau
|
|
@@ -83,7 +83,9 @@ $ pywebexec
|
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
* Launch commands with params/view live output/Status using browser
|
|
86
|
-

|
|
87
|
+
|
|
88
|
+
all commands output / statuses are available in the executables directory in subdirectory `.web_status`
|
|
87
89
|
|
|
88
90
|
## features
|
|
89
91
|
|
|
@@ -102,8 +104,8 @@ $ pywebexec
|
|
|
102
104
|
|
|
103
105
|
## Customize server
|
|
104
106
|
```shell
|
|
105
|
-
$ pywebexec --dir ~/myscripts --listen 0.0.0.0 --port 8080
|
|
106
|
-
$ pywebexec -d ~/myscripts -l 0.0.0.0 -p 8080
|
|
107
|
+
$ pywebexec --dir ~/myscripts --listen 0.0.0.0 --port 8080 --title myscripts
|
|
108
|
+
$ pywebexec -d ~/myscripts -l 0.0.0.0 -p 8080 -t myscripts
|
|
107
109
|
```
|
|
108
110
|
|
|
109
111
|
## Basic auth
|
|
@@ -117,11 +119,10 @@ Generated password is given if no `--pasword` option
|
|
|
117
119
|
|
|
118
120
|
* ldap(s) password check / group member
|
|
119
121
|
```shell
|
|
120
|
-
$ export PYWEBEXEC_LDAP_SERVER=ldap.forumsys.com
|
|
121
|
-
$ export PYWEBEXEC_LDAP_USE_SSL=0
|
|
122
|
+
$ export PYWEBEXEC_LDAP_SERVER=ldap://ldap.forumsys.com:389
|
|
122
123
|
$ export PYWEBEXEC_LDAP_BIND_DN="cn=read-only-admin,dc=example,dc=com"
|
|
123
124
|
$ export PYWEBEXEC_LDAP_BIND_PASSWORD="password"
|
|
124
|
-
$ export PYWEBEXEC_LDAP_GROUPS=mathematicians,scientists
|
|
125
|
+
$ export PYWEBEXEC_LDAP_GROUPS=ou=mathematicians,ou=scientists
|
|
125
126
|
$ export PYWEBEXEC_LDAP_USER_ID="uid"
|
|
126
127
|
$ export PYWEBEXEC_LDAP_BASE_DN="dc=example,dc=com"
|
|
127
128
|
$ pywebexec
|
|
@@ -162,7 +163,7 @@ $ curl http://myhost:8080/run_script -H 'Content-Type: application/json' -X POST
|
|
|
162
163
|
|-----------|-----------------------------|--------------------|---------------------|
|
|
163
164
|
| POST | /run_command | command: str<br>params: array[str] | command_id: uuid<br>message: str |
|
|
164
165
|
| POST | /stop_command/command_id | | message: str |
|
|
165
|
-
| GET | /command_status/command_id | | command_id: uuid<br>command: str<br>params: array[str]<br>start_time: isotime<br>end_time: isotime<br>status: str<br>exit_code: int |
|
|
166
|
+
| GET | /command_status/command_id | | command_id: uuid<br>command: str<br>params: array[str]<br>start_time: isotime<br>end_time: isotime<br>status: str<br>exit_code: int<br>last_output_line: str |
|
|
166
167
|
| GET | /command_output/command_id | | output: str<br>status: str |
|
|
167
|
-
| GET | /commands | | array of<br>command_id: uuid<br>command: str<br>start_time: isotime<br>end_time: isotime<br>status: str<br>exit_code: int |
|
|
168
|
+
| GET | /commands | | array of<br>command_id: uuid<br>command: str<br>start_time: isotime<br>end_time: isotime<br>status: str<br>exit_code: int<br>last_output_line: str |
|
|
168
169
|
| GET | /executables | | array of str |
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|