Skip to content

konekoe/konekoe-exercise-server

Repository files navigation

Konekoe exercise server

This server was developed for conducting online exams with konekoe-editor frontend. It is used for fetching exam information from the database, saving exercise submissions and running graders with submitted files.

  1. Installation
  2. Notes about CI runner
  3. Architecture
  4. Configuration
    1. Possible values
    2. Configuring integration tests
  5. Message interface
    1. server_connect
    2. submission_fetch
    3. code_submission

1. Installation

For local development, running npm install and configuring an .env file suffice. However, running the provided tests additionally requires running npm install --only=dev and npm install konekoe-database. The later install is required due to a bug in npm. See here for details.

Docker images can be built with the commands npm run docker:build and npm run docker:build:dev which build images with the latest and dev tags repectively.

2. Notes about CI runner

The project utilizes a local Gitlab runner for CI (Continous Integration) and CD (Continous Deployment). The runner is hosted on the examos-dev.comnet.aalto.fi server and installed inside of docker. Notably, the runner is passed environment parameters and authentication tokens via volume mounts. The authentication tokens are gitlab deploy tokens generated for each private dependency and are mounted inside the container with a local system volume mount. A local system volume mount allows easy access to the token file for updates and additions. These tokens are inserted into the package.json file with the .runner-preinstall.js script.

The runner has two stages: test and deployment. The test stage runs tests defined in the test/ directory. Notably, these test don't require a database connection as the database interface module konekoe-database supports utilization of inmemory mock databases. Additionally, the test job runs an explicit installation of konekoe-database to install all of its dependencies needed for testing. See here for why and explicit npm install call is needed.

The deployment stage builds a docker image based on the branch on which the runner is executed on. Execution on the main branch builds a latest image and execution on the dev branch a dev image. The dev image is utilized for system wide integration tests and the latest image for production. The deployment stage utilizes a shell runner which inserts values into package.json with the .runner-preinstall.py script.

3. Architecture

Diagram of application architecture

The above diagram illustrates the application architecture of the project. The main of the project is server.js represented in the diagram as Server. Server connects to the database and Docker API and makes these interfaces available across the application by adding them to the process object. Server also creates instances of the MessageHandler class whenever a new client connects and a WebSocket is created.

Essentially, a MessageHandler is a wrapper around a WebSocket that adds parsing and handling for data received from the socket. Message parsing and interfacing with the client are handled with the methods inside of MessageHandler. Received data is parsed with parseMsg which passes the results to handleMsg. This method calls resolveMsg and awaits for the result which is then sent to the client.

Notice that MessageHandler binds external handlers to itself. The handlers are utlized by resolveMsg which chooses a handler based on the type field of the received message. In the diagram, received messages are referred to as Requests and sent messages as Responses. Section 5 covers the different message types.

4. Configuration

The application requires some configuration before execution. You can find the different configuration fields in src/utils/Config.js. The config script attempts to find and parse a JSON file containing configuration values. The default path for the JSON file is project_root/.env.json but a custom path can be passed with the ENV_FILE_PATH environment variable.

The table below displays the different configuration options. Some fields are mandatory. The values that are not required have either a static default value set in src/utils/Config.js or are determined dynamically; dynamically. Setting a configuration value that would otherwise be determined dynamically essentially overrides those fields. This is useful for testing. Lastly, PORT is can be set either via a JSON file or an environment variable and is 4000 by default.

4.1. Possible values

Field name Requirement Description Example value
PORT STATIC DEFAULT Port that the web socket server attempts to start listening. 4000
EXERCISE_DATABASE_URI REQUIRED Location of the database storing exercise and submission information. mongodb://example.com/exercises
DATABASE_AUTH REQUIRED Name of database used for database authentication AdminDb
DATABASE_USER REQUIRED Username for database authentication Test User
DATABASE_PASS REQUIRED Password for database authentication Password
JWT_PUBLIC REQUIRED Path to public key used for JWT authentication /project/root/data/public.key
JWT_PUBLIC STATIC DEFAULT Path to private key used for creating JWTs during testing. Not required by application but required by tests. /project/root/data/pricate.key
JWT_ISSUER REQUIRED String indetifier of the principal that issued the JWT Test Issuer
JWT_SUBJECT REQUIRED String indetifier of the subject of the JWT Exam
JWT_AUDIENCE REQUIRED String indetifier of the indended audience of the JWT My project
JWT_EXPIRESIN REQUIRED Lifetime of the JWT 60 for 60 seconds or 12h for 12 hours.
JWT_ALGORITHM REQUIRED Algorithm used for encryption ([supported options](https://www.npmjs.com/package/jsonwebtoken#algorithms-supported) RS256
DOCKER_HOST STATIC DEFAULT The application utilizes the Docker API for running grader containers. This field should be the host name of the targeted Docker daemon. localhost
DOCKER_CA_CERT REQUIRED Path to CA certificate used for self-signed certificate. /project/root/data/docker_ca.pem
DOCKER_CLIENT_CERT REQUIRED Path to certificate used for client certificate authentication. /project/root/data/client.pem
DOCKER_CLIENT_KEY REQUIRED Path to key used for client certificate authentication. /project/root/data/client.key
GRADER_CONTAINER_IMAGE REQUIRED Name of image used for grader containers. examos/grader-c
GRADER_INTERNAL_TIMEOUT REQUIRED Used by our grader implementations for producing a timeout inside of the grader container. Expressed in milliseconds. 10000 (10 seconds)
GRADER_EXTERNAL_TIMEOUT REQUIRED How long the application will wait for the grader to finish before shutting it down. Expressed in milliseconds. 20000 (20 seconds)
GRADER_CMD DYNAMIC DEFAULT Command run when the grader container starts. Passed as an array of strings. By default, set dynamically in src/services/containers.js ["/bin/bash/", "/home/student/grader/test_runner.sh"]
GRADER_WORKING_DIR DYNAMIC DEFAULT Work directory inside of grader container. By default, set dynamically in src/services/containers.js /home/student/
GRADER_RESULT_DIR DYNAMIC DEFAULT The application expects to find a result.json file detailing the results of grading inside of the grader container in this directory. By default, set dynamically in src/services/containers.js /home/student/
GRADER_ERROR_DIR STATIC DEFAULT If result.json file is not found, look for error.json in this directory. /home/student/
GRADER_PATH STATIC DFEAULT On disk location of grader template files. /var/grader/
GRADER_CONTAINER_VOLUME_TARGETS REQUIRED Paths to which grader volumes are mounted inside of the grader container. [/some/path/, /another/path/]
GRADER_CONTAINER_VOLUME_SOURCES REQUIRED Which volumes to mount. Ordering should match the targets. A volume can either be a docker volume or a bind mount. [/some/path/, my-data-volume]
GRADER_CONTAINER_VOLUME_PERMISSIONS REQUIRED Array of booleans indicating which volumes have write permissions. [true, false]
GRADER_CONTAINER_VOLUME_TYPES STATIC DEFAULT Array of strings indicating mount types. Defaults to an empty array and as a result all mounts default to volume mounts. Note that the source needs to match the type. Therefore, if you assign a path as a source for some mount, you need to specify that it is a bind mount. [bind, volume]

4.2. Configuring integration tests

The test file test/submission.test.js runs test cases utilizing an actual connection to a Docker host. Therefore, to run the tests a Docker instance needs to be running at the host defined by DOCKER_HOST. Furthermore, the tests function by submitting shell script files that are then run by the grader. In principle, the test can be configured in a variety of ways but here are the configuration options we used during development. Note that these are just the fields integral for the integration tests and required field not listed here should be defined as well.

"GRADER_CONTAINER_IMAGE": "busybox", "GRADER_CMD": ["/bin/sh", "/home/student/grader/test_runner.sh"], "GRADER_CONTAINER_VOLUME_TARGETS": ["/var/grader/","/home/student/grader/"], "GRADER_CONTAINER_VOLUME_SOURCES": ["/home/student/konekoe-exercise-server/test_temp/","/home/student/konekoe-exercise-server/test_temp-EXAMCODE-STUDENTID-backup/"], "GRADER_RESULT_DIR": "/home/student/grader/", "GRADER_ERROR_DIR": "/home/student/grader/", "GRADER_WORKING_DIR": "/home/student/grader/", "GRADER_CONTAINER_VOLUME_TYPES": ["bind","bind"], "GRADER_CONTAINER_VOLUME_PERMISSIONS": [true,false], "DOCKER_CLIENT_KEY": "/home/student/.certs/client-key.pem", "DOCKER_CLIENT_CERT": "/home/student/.certs/client-cert.pem", "DOCKER_CA_CERT": "/home/student/.docker/ca.pem", "GRADER_INTERNAL_TIMEOUT": 300, "GRADER_EXTERNAL_TIMEOUT": 600, "GRADER_PATH": "./test_temp/"

Note that the tests in test/connection.test.js attempt to create authorization tokens with a private key. Therefore, an encryption key pair should be provided for testing.

5. Message interface

5.1. server_connect

Diagram of server connection

5.3. code_submission

Diagram of submission

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published