示例#1
0
    def export(self, export_dir, include_disabled):
        '''Exports challenge

        Creates an archive containing all of the challenge "exportable" files.
        '''
        if not self.is_standalone:
            app_log.warning(f"challenge ignored (not standalone): {self.slug}.")
            return {'ignored': True}
        if not include_disabled and not self.enabled:
            app_log.warning(f"challenge ignored (disabled): {self.slug}.")
            return {'ignored': True}
        app_log.info(f"exporting {self.slug}...")
        archive_name = f'{self.slug}.tgz'
        archive_path = export_dir.joinpath(archive_name)
        with tarfile.open(str(archive_path), 'w:gz') as arch:
            for entry in self.exportable():
                arch.add(entry.path, arcname=entry.name)
        checksum_name = f'{archive_name}.sha256'
        checksum_path = export_dir.joinpath(checksum_name)
        archive_hash = hash_file(archive_path)
        checksum_path.write_text(f'{archive_hash}  {archive_name}\n')
        app_log.info("done.")
        return {
            'archive_path': archive_path,
            'checksum_path': checksum_path
        }
示例#2
0
 async def _run(self, script, dev, timeout):
     '''Runs a script as an asynchronous subprocess
     '''
     script_path = Path(script)
     script_parents = script_path.parents
     script = f'./{script_path.name}'
     if script_path.is_absolute():
         cwd = script_parents[0]
     else:
         cwd = self.path
         if len(script_parents) > 1:
             cwd /= script_parents[0]
     app_log.info(f"running {script_path.name} within {cwd}.")
     if dev:
         proc = await create_subprocess_exec(script,
                                             '--dev',
                                             stdout=PIPE,
                                             stderr=PIPE,
                                             cwd=str(cwd))
     else:
         proc = await create_subprocess_exec(script,
                                             stdout=PIPE,
                                             stderr=PIPE,
                                             cwd=str(cwd))
     rcode = -1
     stdout = None
     stderr = None
     exception = None
     try:
         stdout, stderr = await wait_for(proc.communicate(),
                                         timeout=timeout)
         rcode = proc.returncode
     except TimeoutError:
         proc.terminate()
         exception = 'timeout'
     except CalledProcessError as exc:
         proc.terminate()
         rcode = exc.returncode
         stdout = exc.stdout
         stderr = exc.stderr
         exception = 'called process error'
     except Exception as exc:
         exception = str(exc)
     if rcode == 0:
         app_log.info("subprocess terminated successfully.")
     else:
         app_log.warning(
             f"subprocess terminated unsuccessfully (rcode={rcode}).")
     return {
         'rcode': rcode,
         'stdout': stdout,
         'stderr': stderr,
         'exception': exception
     }
示例#3
0
async def main():
    '''Main function
    '''
    app_log.info(__banner__)
    args = parse_args()
    log_enable_debug(args.debug)
    format_enable_colors(not args.no_color)
    app_log.debug(args)
    api = MKCTFAPI(args.repo_root)
    try:
        rcode = 0 if await args.func(api, args) else 1
    except:
        app_log.exception("Ouch... unhandled exception... (>_<)")
        rcode = 2
    return rcode
示例#4
0
def main():
    '''Main function
    '''
    parser = MKCTFArgumentParser(banner=BANNER, description="An HTTP API to perform operations on a mkCTF repository.")
    args = parser.parse_args()
    api = MKCTFAPI(args.repo_dir)
    handler = MKCTFWebHandler(api)
    app = web.Application()
    app.add_routes([
        web.get(r'/challenges', handler.enum_challenges),
        web.get(r'/{slug:[a-z0-9\-]+}/health', handler.challenge_status),
        web.post(r'/{slug:[a-z0-9\-]+}/check-flag', handler.check_challenge_flag),
    ])
    app_log.info(f"serving from {args.repo_dir}")
    web.run_app(app)
示例#5
0
def main():
    '''Main function
    '''
    app_log.info(__banner__)
    args = parse_args()
    log_enable_debug(args.debug)
    format_enable_colors(not args.no_color)
    api = MKCTFAPI(args.repo_root)
    handler = MKCTFWebHandler(api)
    app = web.Application()
    app.add_routes([
        web.get(r'/challenges', handler.enum_challenges),
        web.get(r'/{slug:[a-z0-9\-]+}/status', handler.challenge_status),
        web.post(r'/{slug:[a-z0-9\-]+}/check-flag', handler.check_challenge_flag),
    ])
    app_log.info(f"serving from {args.repo_root}")
    web.run_app(app)
示例#6
0
    def export(self, export_dir, include_disabled):
        '''Export the challenge

        Creates a gzipped tar archive containing all of the challenge "exportable" files
        '''
        if not include_disabled and not self.conf.enabled:
            app_log.warning(f"export ignored {self.conf.slug} (disabled)")
            return

        app_log.info(f"exporting {self.conf.slug}...")
        archive_name = self.conf.static_url.split('/')[-1]
        if not archive_name:
            app_log.error(
                f"export ignored {self.conf.slug} (invalid/empty static_url)")
            app_log.error(
                f"running `mkctf-cli update-meta` should be enough to fix this issue."
            )
            return

        archive_path = export_dir.joinpath(archive_name)
        checksum_file = ChecksumFile()
        with tarfile.open(str(archive_path), 'w:gz') as arch:
            for directory in self.repo.conf.directories(self.conf.category,
                                                        public_only=True):
                dir_path = self.path.joinpath(directory)
                for entry in scandir(dir_path):
                    entry_path = Path(entry.path)
                    if entry_path.is_dir():
                        app_log.warning(
                            f"export ignored {entry_path} within {self.conf.slug} (directory)"
                        )
                        continue
                    checksum_file.add(entry_path)
                    app_log.debug(f"adding {entry_path} to archive...")
                    arch.add(str(entry_path), arcname=entry.name)
            with tempfile.NamedTemporaryFile('w') as tmpfile:
                tmpfile.write(checksum_file.content)
                tmpfile.flush()
                app_log.debug(f"adding checksum.sha256 to archive...")
                arch.add(tmpfile.name, arcname='checksum.sha256')

        arch_checksum_file = ChecksumFile()
        arch_checksum_file.add(archive_path)
        export_dir.joinpath(f'{archive_name}.sha256').write_text(
            arch_checksum_file.content)
        return archive_path
示例#7
0
async def export(api, args):
    '''Exports one or more challenges

    Creates one archive per challenge in a given directory
    '''
    found = False
    export_dir = args.export_dir.resolve()
    exported = [
        info for info in api.export(export_dir,
                                    tags=args.tags,
                                    categories=args.categories,
                                    slug=args.slug,
                                    include_disabled=args.include_disabled)
    ]
    export_map = {info['slug']: str(info['archive_path']) for info in exported}
    app_log.info("creating export.map...")
    with export_dir.joinpath('export.map').open('w') as fp:
        dump(export_map, fp)
    app_log.info("done.")
    return exported
示例#8
0
 def init(self):
     '''[summary]
     '''
     if not self.initialized:
         wizard = RepositoryConfigurationWizard(self._general_conf)
         if not wizard.show():
             return False
         self._conf = wizard.result
         self.path.mkdir(parents=True, exist_ok=True)
         self.challenges_dir.mkdir(parents=True, exist_ok=True)
         app_log.info("copying templates...")
         shutil.copytree(str(GeneralConfiguration.TEMPLATES_DIR),
                         str(self.template_dir))
         app_log.info("copying monitoring...")
         shutil.copytree(str(GeneralConfiguration.MONITORING_DIR),
                         str(self.monitoring_dir))
         app_log.info("saving repository configuration...")
         return self._save_conf()
     return False