mirror of https://git.48k.eu/ogcp
ogcp: add support to view script output
Add view at /action/script/output to visualize the result of /shell/run for multiple clients. Use shell/output to request the execution data of the selected clients. Each client element has execution timestamip (UTC), client ip, cmd, return code and stdout of the executed command.master
parent
af8236b189
commit
0ed9ecdae9
|
@ -0,0 +1,74 @@
|
|||
{% extends 'commands.html' %}
|
||||
{% import "bootstrap/wtf.html" as wtf %}
|
||||
{% import "macros.html" as macros %}
|
||||
|
||||
{% set sidebar_state = 'disabled' %}
|
||||
{% set btn_back = true %}
|
||||
|
||||
{% block nav_client %} active {% endblock %}
|
||||
{% block nav_script_output %} active {% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<h1 class="m-5">
|
||||
{{ _('Script output') }}
|
||||
</h1>
|
||||
|
||||
{{ macros.cmd_selected_clients(selected_clients) }}
|
||||
|
||||
<br>
|
||||
|
||||
<style>
|
||||
.card-header {
|
||||
padding: 0;
|
||||
margin-bottom: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.btn-link {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.card-header button {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.bg-failed {
|
||||
background-color: rgba(255,0,0,0.2);
|
||||
}
|
||||
|
||||
.bg-ok {
|
||||
background-color: rgba(0,255,0,0.2);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="accordion" id="shellAccordion">
|
||||
{% for client in client_data %}
|
||||
<div class="card">
|
||||
<div class="card-header" id="heading_1">
|
||||
<h2 class="mb-0">
|
||||
<button class="btn btn-link" type="button" data-toggle="collapse" data-target="#collapse_{{ loop.index }}" aria-expanded="true" aria-controls="collapse_{{ loop.index }}">
|
||||
<table class="table table-bordered mb-0">
|
||||
<thead class="thead">
|
||||
<tr>
|
||||
<th class="col-2">{{ client['tstamp'] }}</th>
|
||||
<th class="col-2"><b>{{ client['addr'] }}</b></th>
|
||||
<th>{{ client['cmd'] }}</th>
|
||||
<th class="col-2 {% if client['retcode'] == 0 %}bg-ok{% else %}bg-failed{% endif %}">return: {{ client['retcode'] }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</button>
|
||||
</h2>
|
||||
</div>
|
||||
<div id="collapse_{{ loop.index }}" class="collapse" aria-labelledby="heading_{{ loop.index }}">
|
||||
<div class="card-body">
|
||||
<p><samp>{{ client['output'] }}</samp></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -94,6 +94,8 @@
|
|||
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
|
||||
<input class="btn btn-light dropdown-item{% block nav_run_script %}{% endblock %}" type="submit" value="{{ _('Run') }}"
|
||||
form="scopesForm" formaction="{{ url_for('action_run_script') }}" formmethod="get">
|
||||
<input class="btn btn-light dropdown-item{% block nav_display_output %}{% endblock %}" type="submit" value="{{ _('Display output') }}"
|
||||
form="scopesForm" formaction="{{ url_for('action_script_display_output') }}" formmethod="get">
|
||||
</div>
|
||||
|
||||
<div class="dropdown btn">
|
||||
|
|
|
@ -1881,6 +1881,48 @@ def action_run_script():
|
|||
selected_clients=selected_clients,
|
||||
scopes=scopes)
|
||||
|
||||
@app.route('/action/script/output', methods=['GET'])
|
||||
@login_required
|
||||
def action_script_display_output():
|
||||
ips = parse_elements(request.args.to_dict())
|
||||
|
||||
if not validate_elements(ips):
|
||||
return redirect(url_for('commands'))
|
||||
|
||||
server = get_server_from_clients(ips)
|
||||
|
||||
r = server.get('/shell/output', payload={'clients': list(ips)})
|
||||
if not r:
|
||||
return ogserver_down('commands')
|
||||
if r.status_code != requests.codes.ok:
|
||||
return ogserver_error('commands')
|
||||
|
||||
client_data = r.json()['clients']
|
||||
|
||||
for client in client_data:
|
||||
if not 'output' in client:
|
||||
client['output'] = _('No output')
|
||||
|
||||
if not 'retcode' in client:
|
||||
client['retcode'] = 0
|
||||
|
||||
if not 'cmd' in client:
|
||||
client['cmd'] = ['Null']
|
||||
|
||||
if not 'tstamp' in client:
|
||||
client['tstamp'] = _('No time available')
|
||||
else:
|
||||
timestamp_utc = datetime.datetime.utcfromtimestamp(client['tstamp'])
|
||||
client['tstamp'] = timestamp_utc.strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
client_data.sort(key=lambda x:x['tstamp'], reverse=True)
|
||||
|
||||
scopes, clients = get_scopes(set(ips))
|
||||
selected_clients = list(get_selected_clients(scopes['scope']).items())
|
||||
return render_template('actions/script_output.html',
|
||||
selected_clients=selected_clients,
|
||||
scopes=scopes, client_data=client_data)
|
||||
|
||||
def get_clients_modes(ips, server):
|
||||
modes = {}
|
||||
for ip in ips:
|
||||
|
|
Loading…
Reference in New Issue