Skip to content
On this page

Technická specifikace požadavků na úlohu spustitelnou v platformě Haxagon

Základní principy fungování platformy

Systém Haxagon zprostředkovává soutěžícím přístup k soutěžním úlohám. Automatizovaně tyto úlohy spouští a vytváří vzdálené připojení pro soutěžící. Aby byla úloha nasaditelná v systému, je nutné, aby splňovala určité technické specifikace.

Technická specifikace úloh

Virtualizace infrastruktury

V systému Haxagon jsou úlohy spouštěny virtualizací v Dockeru.
Docker-compose je nástroj pro spouštění a správu aplikací pomocí Dockeru. Umožňuje spouštět více kontejnerů jako jeden celek a řídit je pomocí jednoho konfiguračního souboru.

Struktura repozitáře s úlohou

Formát úlohy je velice jednoduchý – stačí systému poskytnout následující soubory v gitovém repozitáři:

  • challenge.yaml - Soubor ve formátu YAML, který definuje základní parametry úlohy.
  • docker-compose.yaml / docker-compose.yml - Instrukce pro sestavení kontejneru(ů) úlohy, viz Docker dokumentace.
  • THEORY.md - Markdown soubor s teoretickou částí úlohy, kde jsou řešiteli předávány teoretické znalosti bez vazby na obsah úlohy.
  • HANDBOOK.md - Markdown soubor obsahující obsah, který slouží jako příručka pro učitele.
  • DESCRIPTION.md - Krátký popis k zadání úlohy.

Tyto soubory jsou detailněji rozebrány v následujících sekcích.

challenge.yaml

název parametrupopis parametrupovinný parametr
titlePojmenování úlohyANO
shortDescriptionKrátký popisek shrnující obsah úlohyANO
difficultyUrčení obtížnosti úlohy. Více o obtížnosti dále.ANO
imageUrl adresa obrázku, který slouží jako thumbnailNE
theoryRelativní cesta k Markdown souboru s teorií k úlozeNE
descriptionRelativní cesta k Markdown souboru s popisem k vlajkámNE
handbookRelativní cesta k Markdown souboru s příručkou pro učiteleNE
typeTyp úlohy. Více o typu úlohy dále.NE
tagsPole definující kategorizaci úlohyNE
accessPole objektů definující možnosti připojení k úloze. Více o přístupu dále.NE
flagsPole objektů definující vlajky, které budou součástí úlohy. Více o vlajkách dále.ANO

difficulty

Vabírat můžete z těchto možností:

  • beginner
  • average
  • skilled
  • expert
  • master
  • unselected

type

Typ úlohy. Tento údaj říká HAXAGONu jakým způsobem má k úloze přístupovat. Výchozí hodnotou je docker. Pokud tvoříte úlohu virtualizovanou pomocí dockeru, tak tento parametr nemusítě vůbec uvádět.

Vabírat můžete z těchto možností:

  • docker: Úloha virtualizovaná pomocí dockeru
  • quiz: Nevirtualizovaná úloha
  • sheets: Úloha v prostředí Google Sheets

access

Základní formát objektů přístupu je tento:

název parametrupopis parametrupříklad
typeTyp připojení, viz dále."ssh"
portPort, na který se mají řešitelé připojit.22
usernameUživatelské jméno použité pro připojení.student
passwordHeslo použité v páru s uživatelským jménem.heslo1234
textNepovinný text s dodatečnými informacemi."Formátovaný *text*"

V parametru type je možné použít jednu z těchto hodnot:

  • ssh
  • http
  • vnc
  • rdp
  • tcp
  • udp
  • other

U typu připojení other není povinné uvádět parametry port, username a password, většinou je ale naopak velmi využíván parametr text k vysvětlení nestandardního připojení.

Parametr text umožňuje využití Markdownu k formátování. Fungování víceřádkových textů v YAML je hezky vysvětleno na stránce YAML-multiline.info.

flags

Vlajky se dělí do celkem 5 typů.

Všechny typy vlajek mají společné tyto parametry:

název parametrupopis parametrupříklad
namePojmenování vlajkyOprávnění souboru file-1
descriptionBližší informace o úkolu. Podporuje Markdown formátování.Změň oprávnění souboru file-1 na 742.
pointsBodové ohodnocení vlajky20
identifierUnikátní (v rámci této úlohy) identifikátor vlajkyfile-perms-check1
typeČíslo označující druh vlajky
Je nutné uvést type jako string v uvozovkách!
"4"

Dynamická vlajka

Každá instance úlohy má unikátně vygenerované vlajky tak, aby se zamezilo podvádění. Jejich unikátnost je zaručena vygenerováním náhodného řetězce, kterým jsou nahrazeny všechny výskyty placeholderu ve všech souborech v repozitáři scénáře. Aby nedošlo k nechtěné záměně, jsou všechna místa určená k nahrazení ohraničena znaky #@{{ a }}@#. Právě placeholder slouží autorovi úlohy k označení a odlišení jednotlivých míst.

Při zpuštění se tedy z #@{{vlajka1}}@# stane např. haxagon{897316929176464ebc9ad085f31e7284} a v jiné instanci úlohy s úplně stejným scénářem zase haxagon{99bd2e29f6b569bb880f601815cd77ef}.

POZOR

K nahrazení řetězců dochází až v runtime instance. To znamená, že nahrazení probíhá těsně před tím, než systém zavolá docker compose up.

Je potřeba rozdělit build fázi kontejnerů a jejich runtime fázi. Například tento kód v souboru Dockerfile některého z kontejnerů úlohy (RUN echo #@{{vlajka1}}@# > /tmp/test) nesplní očekávání, protože příkaz RUN v Dockerfile je spouštěn při sestavování (build) obrazů kontejnerů.

Pro zpřístupnění dynamické vlajky v runtime fázi kontejneru je potřeba vytvořit složku, v ní vytvořit soubor s placeholderem a tu složkou připojit (mount) pomocí volumes definice v docker compose.

Specifika pro vlajky tohoto typu:

název parametrupopis parametrupříklad
type"1", označuje tento typ vlajky"1"
placeholderZástupný řetězec znaků sloužící pro označení místa, do kterého se vloží unikátní vlajkaflag2
maximumTriesMaximální možný počet pokusů pro odpověď3

Statická vlajka

Tento druh vlajky mám pro všechny uživatele a ve všech instancích stejnou hodnotu.

Specifika pro vlajky tohoto typu:

název parametrupopis parametrupříklad
type"2", označuje tento typ vlajky"2"
answerOdpověď na úkolflag{1234}
maximumTriesMaximální možný počet pokusů pro odpověď3

Vlajka s možností výběru odpovědi

Specifika pro vlajky tohoto typu:

název parametrupopis parametrupříklad
type"3", označuje tento typ vlajky"3"
maximumTriesMaximální možný počet pokusů pro odpověď3
optionsPole objektů možných odpovědíviz níže

Objekty odpovědí mají tuto strukturu:

yaml
- value: "chybná odpověď"
  correct: false # nebo true pro správnou odpověď

Automaticky vyhodnocující se vlajka

Pomocí docker compose exec se v definovaném intervalu spouští definovaný příkaz command a podle návratové hodnoty exitCode procesu se určí, zda byla vlajka splněna. Možnost container určuje, ve kterém z možných kontejnerů se proces spustí.

název parametrupopis parametrupříklad
type"4", označuje tento typ vlajky"4"
commandPříkaz, který se spustí pro ověření splnění úkolubash -c '[ "$(cat /tmp/test.txt)" == "ahoj" ]'
containerCílový kontejner, ve kterém se příkaz bude spouštětserver
shellShell, ve kterém je příkaz spouštěnsh
userUživatel, pod kterým se příkaz spouštíroot
intervalInterval, ve kterém dochází ke spuštění příkazu2000
exitCodeNávratový kód commandu, který bude považován za úspěch pro splnění vlajky0
requiredFlagsVolitelné pole identifierů vlajek, které musí být splněny, než se vyhodnotí příkaz této vlajky.file-perms-check1

Parametr interval je měřen v milisekundách.

Pokud bude jako hodnota interval uvedena 0, command nebude prováděn automaticky, ale v zadání úlohy se objeví tlačítko, kterým si ho řešitelé mohou spustit manuálně. Toto je vhodné pro náročné příkazy, jejichž vyhodnocení trvá dlouho nebo vyžaduje hodně prostředků.

Pokud pole requiredFlags obsahuje pouze jeden prvek, zapisuje se jako requiredFlags: "file-perms-check1". Pokud obsahuje více prvků, je třeba hodnoty zapsat jako YAML sekvenci. Pokud není třeba splnění vlajky podmiňovat jinou vlajkou, requiredFlags se neuvádí vůbec.

Vlajka automatické kontroly tabulek

Skrze Google API se získají data z dokumentu tabulek. Ty jsou následně předány do izolovaného sandboxu, kde se provede kontrola úkolu.

název parametrupopis parametrupříklad
type"5", označuje tento typ vlajky"5"
letObjekt proměnných, do kterých jsou uloženy hodnoty z odpovědi z Google APIa: sheets.0.data.0.rowData.5.values.5.userEnteredValue.formulaValue
conditionJS kod, který v sandboxu vyhodnotí splnění úkolu. Úkol je vyhodnocen jako splněný v případě, že návratová hodnota bude true."a == 1"
requiredFlagsVolitelné pole identifierů vlajek, které musí být splněny, než se vyhodnotí příkaz této vlajky.file-perms-check1

googleSpreadSheetId

Google sheets document ID zdrojového dokumentu. Zdrojový dokument musí mít nastavené oprávnění čtení pro kohokoli s odkazem. Samotné ID pak lze získat z URL dokumentu.

Pokud by url vypadala následnovně:

https://docs.google.com/spreadsheets/d/16yi2Nc9gwddlPhFxJBhHSm2_wo4U9lI-D6Okt0Xw_iI/edit?gid=0#gid=0

Pak je ID: 16yi2Nc9gwddlPhFxJBhHSm2_wo4U9lI-D6Okt0Xw_iI.

Tento paramert zadávejte jen v případě, že úloha je typu sheets

Ukázkový soubor challenge.yaml

yaml
# název úlohy
title: Ukázková úloha

# krátký popisek shrnující obsah úlohy
shortDescription: Ukázková úloha

# obtížnost úlohy
difficulty: beginner

# relativní cesta k souboru obsahující teorii k látce v úloze
theory: './THEORY.md'

# relativní cesta k souboru obsahující popis k řešení vlajek
description: ./DESCRIPTION.md

# relativní cesta k souboru obsahující učitelskou příručku k úloze
handbook: ./HANDBOOK.md

# informace o možnostech připojení na úlohu
access:
  - type: "ssh"
    port: 22
    username: student
    password: heslo1234

  - type: "http"
    port: 80
    username: student
    password: heslo1234

# vlajky, ktere jsou s ulohou spojeny
flags:
  - name: Obsah souboru /tmp/file1
    description: 
    points: 10
    type: "1"
    identifier: "file-content-1"
    placeholder: flag1
    maximumTries: 3
  - name: Heslo uživatele adam
    description: Najdi způsob, jak získat heslo uživatele `adam` v plaintextu.
    points: 20
    type: "2"
    identifier: "password-dump1"
    answer: flag{adamisbest}
    maximumTries: 2
  - name: Vyber správnou odpověď
    description: 
    points: 30
    type: "3"
    identifier: "choice-flag1"
    maximumTries: 2
    options:
      - value: správná odpověď
        correct: true
      - value: chybná odpověď
        correct: false
  - name: /tmp/test.txt
    description: Do souboru /tmp/test.txt zapiš text "ahoj".
    points: 30
    type: "4"
    identifier: "file-content-check1"
    command: "sh -c '[ \"$(cat /tmp/test.txt)\" == \"ahoj\" ]'"
    interval: 1000
    container: "server"
    exitCode: 0


docker-compose.yaml

Tímto souborem jsme schopni definovat, jaká infrastruktura se pro úlohu spustí. Dokumentace formátu je dostupná na https://docs.docker.com/compose/.

Limity

V souboru docker-compose není možné

  • Eskalovat práva kontejneru
    • Vytvářet privilegované kontejnery
    • Přidávat kontejnerům systémové schopnosti (system capabilities)
  • Mountovat adresáře a soubory (vše potřebné by mělo být do kontejneru přidáno v build fázi)

Signalizace úspěšného nastartování scénáře

Je nutné systém informovat o tom, že je scénář spuštěný a vše je připraveno. Tuto informaci je možné systému sdělit tím, že do stdout entrypointu/commandu libovolného commandu definovaného v docker-compose souboru vypíšete řetězec SCENARIO_IS_READY.

Ukázkový docker-compose.yml

yaml
services:
    webserver:
        image: nonbusybox
        container_name: webserver
        command: sh -c '/setup.sh && echo SCENARIO_IS_READY && sleep infinity'
        ports:
            - "80:80"


THEORY.md

Zde jsou předávány teoretické znalosti bez vazby na obsah úlohy.

Je důrazně doporučeno používat správné Markdown formátování pro zvýšení přehlednosti.

DESCRIPTION.md

Úvod k řešení vlajek. Často zde bývá zopakování příběhu úlohy (pokud nějaký je), nebo poznámka o speciálních nestandardních nástrojích, které je možné při řešení využít.

HANDBOOK.md

Do Příručky patří návod k vyřešení celé úlohy, je viditelná pouze pro učitele.

Také je možné uvést poznámky pro učitele, jak dobře vysvětlit danou látku či na co poukázat.


Další konvence pro tvorbu zadání

Technické informace a formátování

Části textu obsahující nějakou technickou informaci, např.:

  • definici subnetu - 192.168.40.0/24
  • příkazy - find --name file
  • parametr - --sevice-scan a podobné zaobalíme do code highlight bloku pomocí znaku `

Další tipy k formátování naleznete na dedikované stránce.