Skip to content

Commit

Permalink
WIP: add admin panel for pre-provisionning
Browse files Browse the repository at this point in the history
  • Loading branch information
NicoFgrx committed Jun 14, 2024
1 parent 5637eb1 commit 88a4570
Show file tree
Hide file tree
Showing 7 changed files with 228 additions and 0 deletions.
25 changes: 25 additions & 0 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,30 @@ def admin_list_mana():
user_mode=user_mode,
sources=sources["data"])

# Route to monitor & manage running instances
@page_blueprint.route('/admin/panel')
@admins_only
def admin_panel():

# Retrieve sourceId
user_mode = get_config("user_mode")

if user_mode == "users":
query_sql = """select id from users;"""

elif user_mode == "teams":
query_sql = """select id from teams;"""

sources = db.session.execute(text(query_sql)).fetchall()

# retrieve dynamic_ia_c_challenges
challenges = db.session.execute(text("""select id from dynamic_ia_c_challenge;"""))

print(f"source = {sources}")
print(f" challengee = {challenges}")

return render_template("chall_manager_panel.html",
sources=sources,
challenges=challenges)

app.register_blueprint(page_blueprint)
41 changes: 41 additions & 0 deletions api.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,47 @@ def get():
'message': json.loads(r.text),
}}


@staticmethod
@admins_only
def post():
# retrieve all instance deployed by chall-manager
cm_api_url = get_config("chall-manager:chall-manager_api_url")

## mandatory
challengeId = request.args.get("challengeId")
sourceId = request.args.get("sourceId")

payload = {}

if not challengeId or not sourceId:
return {'success': False, 'data':{
'message': "Missing argument : challengeId or sourceId",
}}

# TODO check user inputs

url = f"{cm_api_url}/instance"

payload['sourceId'] = sourceId
payload['challengeId'] = challengeId

headers = {
"Content-type": "application/json"
}

try:
r = requests.post(url, data = json.dumps(payload), headers=headers)
except requests.exceptions.RequestException as e :
return {'success': False, 'data':{
'message': f"An error occured while Plugins communication with Challmanager API : {e}",
}}


return {'success': True, 'data': {
'message': json.loads(r.text),
}}

@staticmethod
@admins_only
def patch():
Expand Down
40 changes: 40 additions & 0 deletions assets/instances.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ async function renew_instance(challengeId, sourceId) {
return response;
}

async function create_instance(challengeId, sourceId) {
let response = await CTFd.fetch("/api/v1/plugins/ctfd-chall-manager/admin/instance?challengeId=" + challengeId + "&sourceId=" + sourceId, {
method: "POST",
credentials: "same-origin",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
}
});
console.log(response)
response = await response.json();
return response;
}

$(".delete-instance").click(function (e) {
e.preventDefault();
Expand Down Expand Up @@ -117,3 +130,30 @@ $('#instances-renew-button').click(function (e) {
});
});

$('#instances-create-button').click(function (e) {
let sourceId = $("input[data-source-id]:checked").map(function () {
return $(this).data("source-id");
});

let challengeId = $("input[data-challenge-id]:checked").map(function () {
return $(this).data("challenge-id");
});

let challengeIds = challengeId.toArray()
let sourceIds = sourceId.toArray()

CTFd.ui.ezq.ezQuery({
title: "Create instances",
body: `Are you sure you want to create the selected ${sourceId.length} instance(s)?`,
success: async function () {
for (let i=0; i< sourceId.length; i++){
for (let j=0; j< challengeId.length; j++){
console.log(challengeIds[j], sourceIds[i])
create_instance(challengeIds[j], sourceIds[i]) // don't await and let CM deploys instances in //
}
}
location.reload();
}
});
});

3 changes: 3 additions & 0 deletions templates/chall_manager_config.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
<li class="nav-item">
<a class="nav-link" href="/plugins/ctfd-chall-manager/admin/mana">🔗 Mana</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/plugins/ctfd-chall-manager/admin/panel">🔗 Panel</a>
</li>
{% endblock %}

{% block panel %}
Expand Down
3 changes: 3 additions & 0 deletions templates/chall_manager_instances.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
<li class="nav-item">
<a class="nav-link" href="/plugins/ctfd-chall-manager/admin/mana">🔗 Mana</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/plugins/ctfd-chall-manager/admin/panel">🔗 Panel</a>
</li>
{% endblock %}

{% block panel %}
Expand Down
3 changes: 3 additions & 0 deletions templates/chall_manager_mana.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
<li class="nav-item">
<a class="nav-link active" href="#">Mana</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/plugins/ctfd-chall-manager/admin/panel">🔗 Panel</a>
</li>
{% endblock %}

{% block panel %}
Expand Down
113 changes: 113 additions & 0 deletions templates/chall_manager_panel.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
{% extends "chall_manager_base.html" %}

{% block menu %}
<li class="nav-item">
<a class="nav-link" href="/plugins/ctfd-chall-manager/admin/settings">🔗 Settings</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/plugins/ctfd-chall-manager/admin/instances">🔗 Instances</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/plugins/ctfd-chall-manager/admin/mana">🔗 Mana</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="#">Panel</a>
</li>
{% endblock %}

{% block panel %}


<a class="row">
<div class="col-md-12">
<div class="col-md-6">
<table class="table table-striped border">
<thead>
<tr>
<th class="border-right" data-checkbox>
<div class="form-check text-center">&nbsp;
<input type="checkbox" class="form-check-input" data-checkbox-all>
</div>
</th>
<th class="sort-col text-center"><b>Source ID</b></td>
</tr>
</thead>

<tbody>
{% for source in sources %}
<tr>
<td class="border-right" data-checkbox>
<div class="form-check text-center">&nbsp;
<input type="checkbox" class="form-check-input"
data-source-id="{{ source.id }}">
</div>
</td>

<td class="text-center">
<div class="form-check" id="source-id-div">
{% if user_mode == "teams" %}
<a href="{{ url_for('admin.teams_detail', team_id=source.id) }}">
{{ source.id }}
</a>
{% else %}
<a href="{{ url_for('admin.users_detail', user_id=source.id) }}">
{{ source.id }}
</a>
{% endif %}
</div>
</td>
{% endfor %}

</tbody>
</table>
</div>


<div class="col-md-6">
<table class="table table-striped border">
<thead>
<tr>
<th class="border-right" data-checkbox>
<div class="form-check text-center">&nbsp;
<input type="checkbox" class="form-check-input" data-checkbox-all>
</div>
</th>
<th class="sort-col text-center"><b>ID</b></td>
</tr>
</thead>

<tbody>
{% for challenge in challenges %}
<tr>
<td class="border-right" data-checkbox>
<div class="form-check text-center">&nbsp;
<input type="checkbox" class="form-check-input"
data-challenge-id="{{ challenge.id }}">
</div>
</td>

<td class="text-center">
<div class="form-check" id="challenge-id-div">
<a href="{{ url_for('admin.challenges_detail', challenge_id=challenge.id) }}">
{{ challenge.id }}
</a>
</div>
</td>
{% endfor %}

</tbody>
</table>
</div>
</div>

<button type="button" class="btn btn-outline-secondary" data-toggle="tooltip" title="" id="instances-create-button" data-original-title="Provisioner">
<i class="fa-solid fa-octagon-plus"></i>
<!-- FIXME -->
</button>


{% endblock %}

{% block scripts %}
<script defer src="{{ url_for('plugins.ctfd-chall-manager.assets', path='instances.js') }}"></script>
{% endblock %}

0 comments on commit 88a4570

Please sign in to comment.