def challenge_setup(): """Set up some sample data to test with. This is a bit clearer and hopefully more flexible than using fixtures. """ challenge_teardown() # In case other tests didn't clean up p = Project() p.name = 'My Project' p.slug = getattr(settings, 'IGNITE_PROJECT_SLUG', 'my-project') p.description = 'My super awesome project of awesomeness.' p.long_description = 'Did I mention how awesome it was?' p.allow_participation = True p.save() c = Challenge() c.project = p c.title, 'My Challenge' c.slug = getattr(settings, 'IGNITE_CHALLENGE_SLUG', 'my-challenge') c.summary = 'Are you up to it?' c.description = 'This is a challenge of supreme challengingness.' c.end_date = datetime.utcnow() + timedelta(days=365) c.save() ph = Phase() ph.challenge = c ph.name = 'Ideation' ph.order = 1 ph.save() cat = Category() cat.name = 'Beer' cat.slug = 'beer' cat.save()
def create_challenge( title, start_date, end_date, host_team, participant_host_team, anon_leaderboard=False, is_featured=False, ): """ Creates a challenge. """ evaluation_script = open( os.path.join( settings.BASE_DIR, "examples", "example1", "sample_evaluation_script.zip", ), "rb", ) queue = "".join(random.choice(string.ascii_letters) for _ in range(75)) year = datetime.date.today().year # add UUID here uuid_stamp = uuid.uuid4().hex[0:10] slug = "{t}-{y}-{z}".format(t=title, y=year, z=uuid_stamp) slug = slug.lower().replace(" ", "-")[:198] image_file = ContentFile(get_file_content(CHALLENGE_IMAGE_PATH, "rb"), "logo.png") challenge = Challenge( title=title, short_description=fake.paragraph(), description=fake.paragraph(), terms_and_conditions=fake.paragraph(), submission_guidelines=fake.paragraph(), evaluation_details=fake.paragraph(), evaluation_script=SimpleUploadedFile(evaluation_script.name, evaluation_script.read()), approved_by_admin=True, leaderboard_description=fake.paragraph(), creator=host_team, published=True, enable_forum=True, anonymous_leaderboard=anon_leaderboard, start_date=start_date, end_date=end_date, queue=queue, featured=is_featured, image=image_file, ) challenge.save() challenge.slug = slug challenge.participant_teams.add(participant_host_team) challenge.save() print( "Challenge created with title: {} creator: {} start_date: {} end_date: {}" .format(title, host_team.team_name, start_date, end_date))
def test_null_start_date(self): ch4 = Challenge(title='Challenge 4', external_id=12) ch4.save() response = self.client.get('/') challenge = response.data['challenge'] self.assertEqual(3, challenge['id'])
def test_all_ended_one_null(self): ch4 = Challenge(title='Challenge 4', external_id=12) ch4.save() self.timezone_mock.now.return_value = datetime(2020, 10, 1) response = self.client.get('/') challenge = response.data['challenge'] self.assertEqual(5, challenge['id'])
def test_all_ended_one_upcoming(self): ch4 = Challenge(title='Challenge 4', external_id=12, start_date=date(2021, 1, 1), end_date=date(2021, 1, 30)) ch4.save() self.timezone_mock.now.return_value = datetime(2020, 10, 1) response = self.client.get('/') challenge = response.data['challenge'] self.assertEqual(2, challenge['id'])
def test_non_final_challenges(self): ch = Challenge(title='Challenge Recently Ended', external_id=30, start_date=date(2020, 2, 1), end_date=date(2020, 2, 25)) ch.save() challenges = Challenge.objects.get_non_final() eids = set(ch.external_id for ch in challenges) # 5, 6: ongoing # 12: upcoming # 14: no date # 30: recendly ended self.assertEqual({5, 6, 12, 14, 30}, eids)
def setUp(self): super().setUp() challenge = Challenge(external_id=10) self.challenge = challenge challenge.save() challenge_page = Mock() self.challenge_page = challenge_page self.challenge_title = 'My Challenge!' self.start_date = date(2019, 10, 20) self.end_date = date(2020, 1, 22) challenge_page.title = self.challenge_title challenge_page.end_date = self.end_date challenge_page.start_date = self.start_date challenge_page.competitors = []
def makeChallenges(): ctf_categories = ['Web', 'Pwn', 'Crypto', 'Reverse', 'Triva', 'Script'] ctf_challenge_points = [100, 200, 300, 400, 500] for category in ctf_categories: cat = Category.objects.get(name=category) for challenge_points in ctf_challenge_points: chal_str = "%s %s" % (category, str(challenge_points)) chal = Challenge(category=cat, name=chal_str, description="{0} challenge".format(chal_str), points=challenge_points, hidden=True) chal.save() flag = Flag(value=hashlib.md5('flag'.encode('utf-8')).hexdigest(), challenge=chal) flag.save()
def mutate(self, info, name, description, category, flag, precomputed, hashed, points=0, encoded=False, hidden=False): validate_user_is_admin(info.context.user) get_category = Category.objects.get(name=category) newChallenge = Challenge(name=name, description=description, encoded=encoded, points=points, hidden=hidden, category=get_category) newChallenge.save() if hashed: if precomputed: flag = Flag(value=flag, challenge=newChallenge) else: flag = Flag(value=hashlib.sha256(flag.encode('utf-8')).hexdigest(), challenge=newChallenge) else: flag = Flag(value=flag, challenge=newChallenge) flag.save() return AddChallenge(code=0)
def handle(self, *args, **options): if len(args) < 1: self.stderr.write('Please provide a directory containing the files '+ 'relative to PROJECT_DIR.') base_dir = os.path.join(settings.PROJECT_DIR, '..', args[0]) # Go through all of the challenges and compile them. This will update # existing challenges and add new ones. for slug in os.listdir( os.path.join(base_dir) ): try: data = "" f = open(os.path.join(base_dir, slug)) data = f.read() f.close() # If the challenge is already there, update it! try: c = Challenge.objects.get(slug=slug) except: c = Challenge(slug=slug) c.description = "" c.preamble = "" c.postamble = "" c.autograde = "" stage = "description" for l in data.splitlines(): if l.startswith("%% "): l = l[3:].strip() if l.startswith("name:"): c.name = l[5:].strip() elif l.startswith("pattern:"): c.pattern = Pattern.objects.get(name=l[8:].strip()) elif l.startswith("autograde:"): c.autograde = l[10:].strip() elif l.startswith("ordering:"): c.ordering = int(l[9:].strip()) elif l.startswith("% "): stage = l[2:].strip() elif stage == "description": c.description += l+"\n" elif stage == "preamble": c.preamble += l+"\n" elif stage == "postamble": c.postamble += l+"\n" c.save() self.stdout.write('Wrote challenge: %s\n'%(slug)) except: self.stderr.write('Skipped challenge: %s\n'%(slug)) self.stdout.write('Successfully compiled challenges!\n')
def mutate(self, info, name, description, points=0, flag="", show=False, category=None): validate_user_is_admin(info.context.user) try: if category: try: category = Category.objects.get(name=category) newChallenge = Challenge(name=name, description=description, points=points, show=show, category=category) newChallenge.save() flag = Flag(value=hashlib.md5( flag.encode('utf-8')).hexdigest(), challenge=newChallenge) flag.save() except: # Category not found message = "failure" else: newChallenge = Challenge(name=name, description=description, points=points, show=show) newChallenge.save() flag = Flag(value=flag, challenge=newChallenge) flag.save() message = "success" except: message = "failure" return AddChallenge(message)
def setUp(self): super().setUp() ch4 = Challenge(title='Challenge 4', external_id=12, start_date=date(2020, 6, 1), end_date=date(2020, 6, 30)) ch5 = Challenge(title='Challenge 5', external_id=13, start_date=date(2018, 1, 1), end_date=date(2018, 1, 30)) ch6 = Challenge(title='Challenge 6', external_id=14) ch4.save() ch5.save() ch6.save() datetime_patch = patch('challenges.views.timezone') self.timezone_mock = datetime_patch.start() self.timezone_mock.now.return_value = datetime(2020, 2, 25) datetime2_patch = patch('challenges.models.challenge.timezone') self.timezone2_mock = datetime2_patch.start() self.timezone2_mock.now.return_value = datetime(2020, 2, 25)
def test_subcategory_max_score_is_updated(self): """ Test if the SubCategory's max score is updated on Challenge creation This is done to capture the fact that sometimes we'll have new challenges added or removed and it needs to reflex the max score in a subcategory """ c1 = Challenge(name='Sub1', difficulty=5, score=200, description=ChallengeDescFactory(), test_case_count=5, category=self.sub1) c2 = Challenge(name='Sub1_2', difficulty=5, score=200, description=ChallengeDescFactory(), test_case_count=5, category=self.sub1) c3 = Challenge(name='Sub2', difficulty=5, score=200, description=ChallengeDescFactory(), test_case_count=5, category=self.sub2) c1.save(); c2.save(); c3.save() self.sub1.refresh_from_db() self.sub2.refresh_from_db() self.sub3.refresh_from_db() self.assertEqual(self.sub1.max_score, 400) self.assertEqual(self.sub2.max_score, 200) self.assertEqual(self.sub3.max_score, 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')
def insertRealChallenges(): connection = r.connect(host=RDB_HOST, port=RDB_PORT) try: with open('challenges.json') as f: data = json.load(f) for c in data: category = Category.objects.filter( name__icontains=c['category']) if c['hosted']: challenge = Challenge(category=category[0], flag=c['flag'], points=c['points'], title=c['title'], description=c['description'], hosted=c['hosted'], fileUpload=c['fileUpload'], imageName=c['imageName'], ports=c['ports'], pathPrefix=c['pathPrefix']) else: challenge = Challenge(category=category[0], flag=c['flag'], points=c['points'], title=c['title'], description=c['description'], hosted=c['hosted'], fileUpload=c['fileUpload']) challenge.save() if c['hosted']: r.db(CTF_DB).table('challenges').insert({ 'sid': challenge.id, 'category': challenge.category.id, 'title': c['title'], 'points': challenge.points, 'description': c['description'], 'solved_count': 0, 'hosted': c['hosted'], 'fileUpload': c['fileUpload'], 'imageName': c['imageName'], 'ports': c['ports'], 'pathPrefix': c['pathPrefix'], 'created': format(challenge.created, 'U') }).run(connection) else: r.db(CTF_DB).table('challenges').insert({ 'sid': challenge.id, 'category': challenge.category.id, 'title': c['title'], 'points': challenge.points, 'description': c['description'], 'solved_count': 0, 'hosted': c['hosted'], 'fileUpload': c['fileUpload'], 'created': format(challenge.created, 'U') }).run(connection) except RqlRuntimeError as e: raise Exception('Error adding challenges to realtime database: %s' % (e)) finally: connection.close()
def insertChallengeBoard(): i = 1 # Push test challenges to rethinkdb database connection = r.connect(host=RDB_HOST, port=RDB_PORT) try: for category in Category.objects.all(): # Save the challenge flag to the database challenge_50 = Challenge(category=category, flag="flag{0}".format(i), points=50, title='Test Title', description='Test Description', hosted=True, fileUpload=False, imageName='tutum/hello-world:latest', ports='80', pathPrefix="path{0}".format(i)) challenge_50.save() i += 1 # Save the challenge flag to the database challenge_100 = Challenge(category=category, flag="flag{0}".format(i), points=100, title='Test Title', description='Test Description', hosted=True, fileUpload=False, imageName='tutum/hello-world:latest', ports='80', pathPrefix="path{0}".format(i)) challenge_100.save() i += 1 # Save the challenge flag to the database challenge_200 = Challenge(category=category, flag="flag{0}".format(i), points=200, title='Test Title', description='Test Description', hosted=True, fileUpload=False, imageName='tutum/hello-world:latest', ports='80', pathPrefix="path{0}".format(i)) challenge_200.save() i += 1 # Save the challenge flag to the database challenge_300 = Challenge(category=category, flag="flag{0}".format(i), points=300, title='Test Title', description='Test Description', hosted=False, fileUpload=True) challenge_300.save() i += 1 # Save the challenge flag to the database challenge_400 = Challenge(category=category, flag="flag{0}".format(i), points=400, title='Test Title', description='Test Description', hosted=False, fileUpload=False) challenge_400.save() i += 1 # Save the challenge flag to the database challenge_500 = Challenge(category=category, flag="flag{0}".format(i), points=500, title='Test Title', description='Test Description', hosted=False, fileUpload=False) challenge_500.save() i += 1 r.db(CTF_DB).table('challenges').insert({ 'sid': challenge_50.id, 'category': challenge_50.category.id, 'title': 'Test Title', 'points': challenge_50.points, 'description': 'Test Description', 'solved_count': 0, 'hosted': True, 'fileUpload': False, 'imageName': 'tutum/hello-world:latest', 'ports': '80', 'pathPrefix': challenge_50.pathPrefix, 'created': format(challenge_50.created, 'U') }).run(connection) r.db(CTF_DB).table('challenges').insert({ 'sid': challenge_100.id, 'category': challenge_100.category.id, 'title': 'Test Title', 'points': challenge_100.points, 'description': 'Test Description', 'solved_count': 0, 'hosted': True, 'fileUpload': False, 'imageName': 'tutum/hello-world:latest', 'ports': '80', 'pathPrefix': challenge_100.pathPrefix, 'created': format(challenge_100.created, 'U') }).run(connection) r.db(CTF_DB).table('challenges').insert({ 'sid': challenge_200.id, 'category': challenge_200.category.id, 'title': 'Test Title', 'points': challenge_200.points, 'description': 'Test Description', 'solved_count': 0, 'hosted': True, 'fileUpload': False, 'imageName': 'tutum/hello-world:latest', 'ports': '80', 'pathPrefix': challenge_200.pathPrefix, 'created': format(challenge_200.created, 'U') }).run(connection) r.db(CTF_DB).table('challenges').insert({ 'sid': challenge_300.id, 'category': challenge_300.category.id, 'title': 'Test Title', 'points': challenge_300.points, 'description': 'Test Description', 'solved_count': 0, 'hosted': False, 'fileUpload': True, 'created': format(challenge_300.created, 'U') }).run(connection) r.db(CTF_DB).table('challenges').insert({ 'sid': challenge_400.id, 'category': challenge_400.category.id, 'title': 'Test Title', 'points': challenge_400.points, 'description': 'Test Description', 'solved_count': 0, 'hosted': False, 'fileUpload': False, 'created': format(challenge_400.created, 'U') }).run(connection) r.db(CTF_DB).table('challenges').insert({ 'sid': challenge_500.id, 'category': challenge_500.category.id, 'title': 'Test Title', 'points': challenge_500.points, 'description': 'Test Description', 'solved_count': 0, 'hosted': False, 'fileUpload': False, 'created': format(challenge_500.created, 'U') }).run(connection) except RqlRuntimeError as e: raise Exception('Error adding challenges to realtime database: %s' % (e)) finally: connection.close()
cap.save() for cat in data['board']['categories']: print(cat['name']) ca = Category(name=cat['name'], description=cat['description']) ca.save() ''' Challenge create. Required: Category, Name, Description, Points, Flag ''' for challenge in cat['challenges']: print(" |--", challenge['name']) if challenge['name'] and challenge['description'] and challenge[ 'points'] and challenge['flag']: chal = Challenge(category=ca, name=challenge['name'], description=challenge['description'], points=challenge['points'], hidden=False) chal.save() flag_v = compute_flag(challenge['flag']) flag = Flag(value=flag_v, hashed=challenge['flag']['hashed'], challenge=chal) flag.save() else: print("Failed", challenge) exit()
def setUp(self): self.ch1_start = date(2020, 2, 1) self.ch1_end = date(2020, 3, 15) ch0 = Challenge(title='Challenge 0', external_id=4, start_date=date(2019, 11, 20), end_date=date(2019, 11, 25)) ch1 = Challenge(title='Challenge 1', external_id=5, start_date=self.ch1_start, end_date=self.ch1_end) ch2 = Challenge(title='Challenge 2', external_id=6, start_date=date(2020, 2, 10), end_date=date(2020, 2, 29)) ch3 = Challenge(title='Challenge 3', external_id=2, start_date=date(2019, 6, 1), end_date=date(2019, 6, 30)) ch0.save() ch1.save() ch2.save() ch3.save() t1 = Team(name='Team A', challenge=ch1) t2 = Team(name='Team B', challenge=ch1) t3 = Team(name='Team C', challenge=ch2) t1.save() t2.save() t3.save() comp1 = Competitor(external_id=10, name='Competitor 1') comp2 = Competitor(external_id=20, name='Competitor 2') comp3 = Competitor(external_id=25, name='Competitor 3', display_name='Competitor C') comp4 = Competitor(external_id=26, name='Competitor 4') comp5 = Competitor(external_id=27, name='Competitor 5') comp6 = Competitor(external_id=28, name='Competitor 6') comp7 = Competitor(external_id=29, name='Competitor 7') comp1.save() comp2.save() comp3.save() comp4.save() comp5.save() comp6.save() comp7.save() comp1.teams.add(t1) comp3.teams.add(t1) comp4.teams.add(t1) comp5.teams.add(t3) comp6.teams.add(t2) comp7.teams.add(t2) comp1.save() comp3.save() comp4.save() comp5.save() comp6.save() comp7.save() comp1_stats = Stats(calories=1001, competitor=comp1, challenge=ch1) comp2_stats = Stats(calories=500, competitor=comp3, challenge=ch1) comp5_stats = Stats(calories=2000, competitor=comp5, challenge=ch2) comp6_stats = Stats(calories=100, competitor=comp6, challenge=ch1) comp7_stats = Stats(calories=20, competitor=comp7, challenge=ch1) comp1_stats.save() comp2_stats.save() comp5_stats.save() comp6_stats.save() comp7_stats.save()
def bulk_update(request: HttpRequest): try: challenges_data = json.loads(request.body.decode()) challenges = challenges_data["challenges"] except Exception: logger.exception("Couldn't load json") return JsonResponse({"message": "Couldn't load json data"}, status=400) try: assert isinstance(challenges, list) assert len(challenges) > 0 and isinstance(challenges[0], dict) except AssertionError: logger.exception( "Expected a list of dict, representing the challenges") return JsonResponse( { "message": "Expected a list of dict, representing the challenges" }, status=400) try: challenge_slugs = {chal["slug"] for chal in challenges} assert len(challenge_slugs) == len(challenges) except (KeyError, AssertionError): return JsonResponse( { "message": "`slug` should be present and unique in all challenges" }, status=400) expected_data = """Challenges should be of this form (following documentation may not be up to date): { "difficulty": 0-4 (0 easier, 4 harder), "name": "bla bla" (len<50), "slug": "bla-bla" (extracted from name, identifies the challenge), "description": "Fun story in html", "category": Any of: "MIC", "WEB", "PPC", "FOR", "REV", "PWN", "CRY", "NET", "flag": "INSA{the flag}" (len<=255), "static_url": null OR "url of the static files for the chal", "company_logo_url": null OR "the URL of the company who wrote the chal, if any", "nb_points_override": integer, if greater then -3, it will override the automagic points calculus }""" for chal in challenges: try: difficulty = chal["difficulty"] name = chal["name"] slug = chal["slug"] description = chal["description"] category = chal["category"] flag = sha256(chal["flag"].encode('utf-8')).hexdigest() static_url = chal["static_url"] company_logo_url = chal["company_logo_url"] nb_points_override = chal["nb_points_override"] except KeyError: logger.exception("Wrong challenge format") return JsonResponse({"message": expected_data}, status=400) try: try: chal = Challenge.all_objects.get(slug=slug) chal.difficulty = difficulty chal.name = name chal.description = description chal.category = category chal.flag = flag chal.static_url = static_url chal.company_logo_url = company_logo_url chal.nb_points_override = nb_points_override chal.full_clean() chal.save() except ObjectDoesNotExist: chal = Challenge(difficulty=difficulty, name=name, slug=slug, description=description, category=category, flag=flag, static_url=static_url, company_logo_url=company_logo_url, nb_points_override=nb_points_override) chal.full_clean() chal.save() except ValidationError as e: logger.exception("Wrong challenge format") return JsonResponse( { "message": "Challenge `{}` doesn't have the right form: {}.\n{}". format(name, e, expected_data) }, status=400) except Exception as e: logger.exception("Exception creating the challenge") return JsonResponse( { "message": "Error while updating {}, please check the serverlogs. err: {}" "\nFor reference: {}".format(name, e, expected_data) }, status=500) Challenge.all_objects.exclude(slug__in=challenge_slugs).delete() return JsonResponse({"message": "OK"}, status=200)