Starting containers

selenium-screenshot-testing
CodeKevin 2016-05-03 01:11:29 -04:00
parent c769f5865f
commit a0d7d8abcb
6 changed files with 154 additions and 69 deletions

View File

@ -1,6 +1,6 @@
from flask import render_template, request, redirect, abort, jsonify, url_for, session, Blueprint
from CTFd.utils import sha512, is_safe_url, authed, admins_only, is_admin, unix_time, unix_time_millis, get_config, set_config, sendmail, rmdir
from CTFd.models import db, Teams, Solves, Awards, Challenges, WrongKeys, Keys, Tags, Files, Tracking, Pages, Config, DatabaseError
from CTFd.utils import sha512, is_safe_url, authed, admins_only, is_admin, unix_time, unix_time_millis, get_config, set_config, sendmail, rmdir, create_container
from CTFd.models import db, Teams, Solves, Awards, Containers, Challenges, WrongKeys, Keys, Tags, Files, Tracking, Pages, Config, DatabaseError
from itsdangerous import TimedSerializer, BadTimeSignature
from sqlalchemy.sql import and_, or_, not_
from sqlalchemy.sql.expression import union_all
@ -223,6 +223,26 @@ def delete_page(pageroute):
return '1'
@admin.route('/admin/containers', methods=['GET'])
@admins_only
def list_container():
containers = Containers.query.all()
return render_template('admin/containers.html', containers=containers)
@admin.route('/admin/containers/new', methods=['POST'])
@admins_only
def new_container():
name = request.form.get('name')
buildfile = request.form.get('buildfile')
files = request.files.getlist('files[]')
print name
print buildfile
print files
create_container(name=name, buildfile=buildfile, files=files)
@admin.route('/admin/chals', methods=['POST', 'GET'])
@admins_only
def admin_chals():

View File

@ -38,6 +38,19 @@ class Pages(db.Model):
return "<Tag {0} for challenge {1}>".format(self.tag, self.chal)
class Containers(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80))
buildfile = db.Column(db.Text)
def __init__(self, name, buildfile):
self.name = name
self.buildfile = buildfile
def __repr__(self):
return "<Container ID:(0) {1}>".format(self.id, self.name)
class Challenges(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80))

View File

@ -35,6 +35,7 @@
<li><a href="/admin/pages">Pages</a></li>
<li><a href="/admin/teams">Teams</a></li>
<li><a href="/admin/scoreboard">Scoreboard</a></li>
<li><a href="/admin/containers">Containers</a></li>
<li><a href="/admin/chals">Challenges</a></li>
<li><a href="/admin/statistics">Statistics</a></li>
<li><a href="/admin/config">Config</a></li>

View File

@ -0,0 +1,87 @@
{% extends "admin/base.html" %}
{% block content %}
<div class="modal fade" id="create-container-modal" tabindex="-1" role="dialog" aria-labelledby="container-modal-label">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="container-modal-label">Create Container</h4>
</div>
<form method="POST" action="/admin/containers/new" enctype="multipart/form-data">
<div class="modal-body">
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" name="name" placeholder="Enter container name">
</div>
<div class="form-group">
<label for="buildfile-editor" class="control-label">Build File</label>
<textarea id="buildfile-editor" class="form-control" name="buildfile" rows="10"></textarea>
</div>
<div class="form-group">
<label for="container-files">File input</label>
<input type="file" name="files[]" id="container-files" multiple>
<p class="help-block">These files are uploaded alongside your buildfile</p>
</div>
<input type="hidden" value="{{ nonce }}" name="nonce" id="nonce">
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Create</button>
</div>
</form>
</div>
</div>
</div>
<div class="row">
<br>
<div style="text-align:center">
<h1>Containers</h1>
<button class="btn btn-theme btn-outlined create-challenge" data-toggle="modal" data-target="#create-container-modal">
New Container
</button>
</div>
<br>
{% if containers %}
<table id="teamsboard">
<thead>
<tr>
<td><b>Status</b>
</td>
<td><b>Name</b>
</td>
<td><b>IP Address</b>
</td>
<td><b>Memory</b>
</td>
<td><b>Disk</b>
</td>
<td><b>Settings</b>
</td>
</tr>
</thead>
<tbody>
{% for c in containers %}
<tr>
<td>{{ c.name }}</td>
<td>{{ c.status }}</td>
<td>{{ c.ip_address }}</td>
<td>{{ c.memory }} <sub>MB</sub></td>
<td>{{ c.disk }} <sub>GB</sub></td>
<td>
<span>
<i class="fa fa-pencil-square-o"></i>
<i class="fa fa-times"></i>
</span>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</div>
{% endblock %}
{% block scripts %}
{% endblock %}

View File

@ -1,66 +0,0 @@
{% extends "admin/base.html" %}
{% block content %}
<div id="create-droplet-modal" class="reveal-modal" data-reveal>
<h2 class="text-center">Create Droplet</h2>
<p></p>
<a class="close-reveal-modal">&#215;</a>
</div>
<div class="row">
<br>
<h1>Hosts</h1>
<br>
{% for error in errors %}
<div class="large-8 large-centered columns">
<div data-alert class="alert-box alert radius centered text-center">
<span>{{ error }}</span>
<a href="#" class="close">×</a>
</div>
</div>
{% endfor %}
<table id="teamsboard">
<thead>
<tr>
<td><b>ID</b>
</td>
<td><b>Status</b>
</td>
<td><b>Name</b>
</td>
<td><b>IP Address</b>
</td>
<td><b>Memory</b>
</td>
<td><b>Disk</b>
</td>
<td><b>Settings</b>
</td>
</tr>
</thead>
<tbody>
{% for host in hosts %}
<tr>
<td>{{ host.id }}</td>
<td>{{ host.status }}</td>
<td>{{ host.name }}</td>
<td>{{ host.ip_address }}</td>
<td>{{ host.memory }} <sub>MB</sub></td>
<td>{{ host.disk }} <sub>GB</sub></td>
<td>
<span>
<i class="fa fa-pencil-square-o"></i>
<i class="fa fa-times"></i>
</span>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<a href="#" data-reveal-id="create-droplet-modal" class="radius button">Create New Host</a>
</div>
{% endblock %}
{% block scripts %}
{% endblock %}

View File

@ -1,6 +1,7 @@
from CTFd.models import db, WrongKeys, Pages, Config, Tracking, Teams
from six.moves.urllib.parse import urlparse, urljoin
from six.moves.urllib.parse import urlparse, urljoin
from werkzeug.utils import secure_filename
from functools import wraps
from flask import current_app as app, g, request, redirect, url_for, session, render_template, abort
from itsdangerous import Signer, BadSignature
@ -21,6 +22,8 @@ import re
import time
import smtplib
import email
import tempfile
import subprocess
def init_logs(app):
logger_keys = logging.getLogger('keys')
@ -381,3 +384,30 @@ def validate_url(url):
def sha512(string):
return hashlib.sha512(string).hexdigest()
def can_create_container():
try:
output = subprocess.check_output(['docker', 'version'])
return True
except subprocess.CalledProcessError:
return False
def create_container(name, buildfile, files):
if not can_create_container():
return False
folder = tempfile.mkdtemp(prefix='ctfd')
tmpfile = tempfile.NamedTemporaryFile(dir=folder, delete=False)
tmpfile.write(buildfile)
tmpfile.close()
for f in files:
filename = os.path.basename(f.filename)
f.save(os.path.join(folder, filename))
# docker build -f tmpfile.name -t name
try:
subprocess.call(['docker', 'build', '-f', tmpfile.name, '-t', name])
return True
except subprocess.CalledProcessError:
return False