From a0d7d8abcb4704d435586fe85616882787930e2b Mon Sep 17 00:00:00 2001 From: CodeKevin Date: Tue, 3 May 2016 01:11:29 -0400 Subject: [PATCH] Starting containers --- CTFd/admin.py | 24 +++++++- CTFd/models.py | 13 +++++ CTFd/templates/admin/base.html | 1 + CTFd/templates/admin/containers.html | 87 ++++++++++++++++++++++++++++ CTFd/templates/admin/hosts.html | 66 --------------------- CTFd/utils.py | 32 +++++++++- 6 files changed, 154 insertions(+), 69 deletions(-) create mode 100644 CTFd/templates/admin/containers.html delete mode 100644 CTFd/templates/admin/hosts.html diff --git a/CTFd/admin.py b/CTFd/admin.py index c6b59c81..b0b1366d 100644 --- a/CTFd/admin.py +++ b/CTFd/admin.py @@ -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(): diff --git a/CTFd/models.py b/CTFd/models.py index 05b3ff09..66ee0821 100644 --- a/CTFd/models.py +++ b/CTFd/models.py @@ -38,6 +38,19 @@ class Pages(db.Model): return "".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 "".format(self.id, self.name) + + class Challenges(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80)) diff --git a/CTFd/templates/admin/base.html b/CTFd/templates/admin/base.html index c64fcf6b..8f7611ba 100644 --- a/CTFd/templates/admin/base.html +++ b/CTFd/templates/admin/base.html @@ -35,6 +35,7 @@
  • Pages
  • Teams
  • Scoreboard
  • +
  • Containers
  • Challenges
  • Statistics
  • Config
  • diff --git a/CTFd/templates/admin/containers.html b/CTFd/templates/admin/containers.html new file mode 100644 index 00000000..df8a47b0 --- /dev/null +++ b/CTFd/templates/admin/containers.html @@ -0,0 +1,87 @@ +{% extends "admin/base.html" %} + +{% block content %} + + +
    +
    +
    +

    Containers

    + +
    +
    +{% if containers %} + + + + + + + + + + + + + {% for c in containers %} + + + + + + + + + {% endfor %} + +
    Status + Name + IP Address + Memory + Disk + Settings +
    {{ c.name }}{{ c.status }}{{ c.ip_address }}{{ c.memory }} MB{{ c.disk }} GB + + + + +
    +{% endif %} +
    +{% endblock %} + +{% block scripts %} +{% endblock %} \ No newline at end of file diff --git a/CTFd/templates/admin/hosts.html b/CTFd/templates/admin/hosts.html deleted file mode 100644 index c4f8fad7..00000000 --- a/CTFd/templates/admin/hosts.html +++ /dev/null @@ -1,66 +0,0 @@ -{% extends "admin/base.html" %} - -{% block content %} -
    -

    Create Droplet

    - -

    - × -
    - -
    -
    -

    Hosts

    -
    - {% for error in errors %} -
    -
    - {{ error }} - × -
    -
    - {% endfor %} - - - - - - - - - - - - - - {% for host in hosts %} - - - - - - - - - - {% endfor %} - -
    ID - Status - Name - IP Address - Memory - Disk - Settings -
    {{ host.id }}{{ host.status }}{{ host.name }}{{ host.ip_address }}{{ host.memory }} MB{{ host.disk }} GB - - - - -
    - Create New Host -
    -{% endblock %} - -{% block scripts %} -{% endblock %} \ No newline at end of file diff --git a/CTFd/utils.py b/CTFd/utils.py index 663b9ef4..8bea5bea 100644 --- a/CTFd/utils.py +++ b/CTFd/utils.py @@ -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 \ No newline at end of file