Dokumentacja AlgoJudge0.1

Podłączenie platformy kursowej

Podpięcie Moodle do instalacji, ustawienie przeglądarki, które decyduje o tym, czy to w ogóle zadziała, oraz co zostało sprawdzone, a co nie.

Platforma kursowa może otworzyć aktywność swoim studentom, a ich oceny wracają do jej dziennika. Mechanizmem jest LTI 1.3; platformą, na której to sprawdzono, jest Moodle.

Ta strona to połowa administratora. To, co robi potem prowadzący — umieszczenie aktywności w kursie, odczytanie listy uczestników — opisuje Logowania zewnętrzne i platformy LTI.

Jeśli tą platformą jest Moodle, całą drogę przechodzi ze zrzutami ekranu Instalacja narzędzia w Moodle, na 5.2 i 5.3. Ta strona opisuje mechanizm, który za tym stoi.

Najpierw przeczytaj sekcję o przeglądarce

O ciasteczko trzeciej strony rozbija się więcej instalacji niż o cokolwiek innego na tej stronie — i rozbija się dopiero wtedy, gdy wszystko wygląda już na poprawnie skonfigurowane. Jeśli Twoja instalacja nie serwuje HTTPS, osadzone uruchomienie nie może zadziałać w ogóle.

Zanim zaczniesz

Trzy warunki muszą być spełnione.

Instalacja jest osiągalna po HTTPS, pod adresem, który platforma potrafi rozwiązać. Tutaj nie jest to opcjonalne — powód jest w sekcji W przeglądarce poniżej.

Server zna swój publiczny adres. Każdy adres podawany platformie jest z niego budowany. Stos celowo zostawia AJ_PublicApiUrl nieustawione i bez tego działa zarówno uruchomienie, jak i platforma wypisana ręcznie — biorą adres z żądania. Wyjątkiem jest oczekiwana rejestracja: odmawia wydania zaproszenia, dopóki wartość nie rozwija się w bezwzględny adres http(s), bo właśnie ma go podać cudzemu serwerowi.

Ustaw ją w nakładce, a nie edytując compose.yaml:

# state/lti.compose.yaml
services:
  server:
    environment:
      AJ_PublicApiUrl: https://twoja.domena/api/v1

Nakładkę wymień w .env, jako COMPOSE_FILE=compose.yaml:state/lti.compose.yaml, a nie w jednym wywołaniu w wierszu poleceń. Tylko stamtąd dowiadują się o niej update.sh, rollback.sh i preflight.sh: składają stos, nie wymieniając plików, więc nakładka podana raz przez -f jest dla każdego z nich niewidzialna — a najbliższa aktualizacja złoży stos bez niej i zabierze jej usługi przez --remove-orphans.

Ktoś ma uprawnienie provider:manage. Zarejestrowanie platformy to decyzja tej samej klasy co zarejestrowanie dostawcy tożsamości i stoi za tym samym uprawnieniem.

Dwie drogi

Platforma rejestruje się sama

Krótsza i tę warto wybrać. W AlgoJudge otwórz Logowania zewnętrzne i platformy LTI, naciśnij Oczekuj rejestracji, wpisz notatkę mówiącą, co to za platforma, i skopiuj podany adres.

Przekaż ten adres osobie administrującej platformą. Po jej stronie trafia tam, gdzie platforma przyjmuje adres URL narzędzia zewnętrznego, które ma samo się skonfigurować — w Moodle jest to ekran zarządzania narzędziami wtyczki narzędzia zewnętrznego. Wkleja adres; niczego więcej nie wpisuje ręcznie.

Zaproszenie jest ważne raz, przez trzydzieści minut. Można je odwołać, zanim zostanie użyte, a platforma, która odpowie źle, go nie zużywa — nie musisz wydawać drugiego dlatego, że pierwsza próba się nie udała.

To, co przychodzi, jest wyłączone

Platforma, która zarejestruje się sama, trafia do Ciebie wyłączona i bez prawa mówienia, kim ktokolwiek jest. To jest zamierzone: ktoś udowodnił, że ma żywe zaproszenie, a nie że prowadzi uczelniany Moodle. Włączenie jej i osobne zdecydowanie, czy może potwierdzać tożsamości, to dwie osobne decyzje, które ktoś podejmuje ze świadomością, co z nich wynika.

Wpisujesz ją ręcznie

Zarejestruj platformę i formularz. Administrator platformy podaje wydawcę, identyfikator klienta, identyfikator wdrożenia oraz trzy adresy — jej zestaw kluczy, punkt wydawania tokenów i punkt autoryzacji.

Trzech z nich nie da się już zmienić: wydawcy, identyfikatora klienta i identyfikatora wdrożenia. Na tej trójce wisi każde uruchomienie i każde powiązanie tożsamości, więc formularz blokuje je przy edycji, zamiast pozwolić Ci odkryć to później.

Potem naciśnij Co w niej wpisać, co wypisze cztery adresy do wklejenia z powrotem do platformy oraz dwa parametry własne. Trzeci parametr własny dochodzi przy każdym osadzeniuactivity=<slug> — i to on mówi uruchomieniu, którą aktywność otwiera. Bez niego uruchomienie zostaje odrzucone z kodem noActivity.

W przeglądarce

Uruchomienie działa w ramce na stronie z innej witryny, więc ciasteczko sesji jest ciasteczkiem trzeciej strony, a współczesne przeglądarki domyślnie takie odrzucają.

Server na to odpowiada: sesja założona przez uruchomienie dostaje ciasteczko oznaczone SameSite=None; Secure; Partitioned — i tylko taka sesja. To jest zmierzone, a nie założone: Chrome 141 i Firefox 153 bez tego odrzucają ciasteczko w ramce, własnymi słowami przeglądarki.

Wynikają z tego dwie rzeczy, a pierwsza jest powodem ostrzeżenia na początku tej strony:

  • Secure nie jest opcjonalne. Instalacja serwująca zwykłe HTTP nie może mieć osadzonych sesji w ogóle. Ciasteczko zostanie odrzucone, każde uruchomienie wyląduje na stronie zapasowej, a w konfiguracji nic nie będzie wyglądało źle.
  • Safari nie jest sprawdzone. Nie ma tu sprzętu Apple, na którym dałoby się to zrobić.

Kiedy ciasteczko i tak zostanie odrzucone, uczestnik nie zostaje bez wyjaśnienia: strona mówi, że przeglądarka blokuje logowanie dla tej ramki, proponuje Otwórz w nowej karcie i podaje zdanie do przekazania osobie administrującej kursem. Po stronie platformy naprawia się to, ustawiając narzędzie tak, żeby otwierało się w nowym oknie zamiast w ramce.

Własne reverse proxy opisuje drugą połowę tego — dlaczego X-Frame-Options to SAMEORIGIN, a nie DENY, i co to znaczy, jeśli ustawiasz własne nagłówki przed instalacją.

Co zostało sprawdzone, a co nie

Napisane wprost, bo dla kogoś, kto zaraz to wdroży, liczy się właśnie luka.

Moodle 4.5.13 LTSuruchomienia i tożsamość
Moodle 5.2.2wszystko, łącznie z deep linkingiem i samorejestracją
Moodle 5.3devuruchomienia i tożsamość
Safarinie sprawdzone

Deep linking i samorejestracja były prowadzone wyłącznie na 5.2, a 4.5.13 to wersja, którą uczelnia najprawdopodobniej ma uruchomioną. Cała reszta była sprawdzona na wszystkich trzech.

Dwa zachowania Moodle kształtują to, czego można się spodziewać, i żadne nie jest usterką po naszej stronie:

  • Skopiowany kurs jest rozpoznawany jako kopia, ale tylko na poziomie kursu. Moodle podstawia historię kursu, a nie pojedynczego osadzenia, we wszystkich wspieranych wersjach — więc wygląda na kopię… jest mocną poszlaką, a nie faktem.
  • Ramka nie zmienia wysokości. Moodle nie implementuje zmiany rozmiaru ramki, więc uruchomienie ma tę wysokość, którą prowadzący wpisał w ustawieniach aktywności. Osadzony interfejs jest pod to zbudowany — jeden rząd nagłówka, a treść przewija się w środku.

Kiedy to nie działa

Odrzucone uruchomienie ląduje na stronie nazywającej to, co poszło źle, z surowym kodem obok, żeby dało się go zacytować w zgłoszeniu. Te, które spotyka administrator:

unknownPlatformuruchomienie nie pasowało do żadnej rejestracji — albo pasowało do kilku i nie powiedziało, do której
platformDisabledzarejestrowana i nigdy niewłączona. Najczęstszy wynik po samorejestracji
noActivityosadzeniu brakuje activity=<slug>
notPublishedaktywność nie jest opublikowana, a osoba, która ją otworzyła, nie prowadzi kursu
sharingNotAcknowledgedaktywność jest osadzona w drugim kursie i nikt jeszcze tego nie zaakceptował
platformUnreachablenie udało się stąd pobrać zestawu kluczy platformy

badState i badToken wyglądają groźnie, a zwykle nie są niczym groźnym: przeterminowana karta przeglądarki, uruchomienie powtórzone z historii albo zegary rozjechane o więcej niż dwie minuty.

Zupełnie pusta ramka to żaden z tych przypadków. Jeśli uruchomienie dociera do przeglądarki, ale ramka pozostaje pusta, a w konsoli przeglądarki pojawia się odmowa wyświetlenia strony — odrzuca ją polityka ramek, nie Server. Dołączony nginx wysyła X-Frame-Options: SAMEORIGIN, który pozwala osadzić stronę wyłącznie wtedy, gdy osadza ją ten sam origin, więc LMS pod inną nazwą zostaje odrzucony dokładnie tak, jak odrzuciłby go DENY. Czym to zastąpić, mówi Własne reverse proxy; tutaj ten nagłówek leży w nginx/snippets/security-headers.conf.

Model, który za tym wszystkim stoi — endpointy, klucze i to, do czego Server odmawia otwarcia połączenia — opisuje LTI.

Na tej stronie