Exemple #1
0
    def mutate(self, info, category, title, points, description, flag, hosted, ports, image_name=None, upload=None):
        user = info.context.user
        # Validate user is admin
        validate_user_is_admin(user)

        # sanitize all the input fields
        validate_flag(flag)
        validate_flag_unique(flag)
        validate_points(points)
        validate_title(title)
        validate_description(description)
        validate_category_exists(category)
        if image_name:
            validate_imageName(image_name)
        if ports:
            validate_ports(ports)
        # if path_prefix:
        #     validate_pathPrefix(path_prefix)
        #     validate_pathPrefix_unique(path_prefix)

        # parse dockerfile for list of ports
        if upload:
            try:
                ports = list()
                for line in upload:
                    line = line.decode('utf-8')
                    start = 'EXPOSE '

                    if (start in line):
                        possible_port = (line[line.find(start)+len(start):])
                        ports.append(possible_port.split())

                # flatten list
                flattened_ports = list(
                    set([val for sublist in ports for val in sublist]))
                print(flattened_ports)

            except Exception as e:
                raise Exception('Error parsing uploaded Dockerfile: ', e)

        challenge_category = Category.objects.get(id=category)

        # Save the challenge flag to the database
        challenge = Challenge(category=challenge_category, title=title, description=description,
                              flag=flag, points=points, hosted=hosted, imageName=image_name, ports=ports)
        challenge.save()

        # set var for pathPrefix and tag
        path_tag = str(challenge.id)
        challenge.pathPrefix = path_tag

        if upload:
            image_name = path_tag + ':latest'

            # build image
            build = d.buildImage(fileobj=upload.file, tag=path_tag)

            # delete already saved challenge if build fails
            if not build:
                chall_id = challenge.id
                try:
                    challenge.delete()
                except:
                    # raise exception if unable to delete already saved challenge requiring manual intervention
                    raise Exception(
                        'Unable to delete challenge ID: %i. Manual deletion necessary.' % (chall_id))

                raise Exception(
                    'Unable to build image.  Reverted challenge creation.')

            challenge.upload = upload
            challenge.imageName = image_name

        challenge.save()

        # Push the realtime data to rethinkdb
        connection = r.connect(host=RDB_HOST, port=RDB_PORT)
        try:
            r.db(CTF_DB).table('challenges').insert({'sid': challenge.id, 'category': challenge.category.id, 'title': title, 'points': points, 'description': description,
                                                     'hosted': hosted, 'imageName': image_name, 'ports': ports, 'pathPrefix': path_tag, 'created': format(challenge.created, 'U')}).run(connection)
        except RqlRuntimeError as e:
            raise Exception(
                'Error adding challenge to realtime database: %s' % (e))
        finally:
            connection.close()

        return AddChallenge(status='Challenge Created')