Skip to content
Snippets Groups Projects
Unverified Commit ccf17683 authored by Matt Bovel's avatar Matt Bovel
Browse files

Run student's code as a different user, add timeout

parent 4e3b8653
No related branches found
No related tags found
No related merge requests found
Pipeline #199852 passed
This commit is part of merge request !213. Comments created here will be created in the context of that merge request.
FROM python:3.13.0b3-alpine3.20 FROM python:3.13.0b3-alpine3.20
# Create a less-privileged user to run student's code and install sudo
RUN addgroup -S student && adduser -S student -G student
RUN apk add --no-cache --update sudo
WORKDIR /usr/src/app WORKDIR /usr/src/app
COPY ./grade.sh grade.sh COPY ./grade.sh grade.sh
RUN chmod +x grade.sh RUN chmod +x grade.sh
CMD ["./grade.sh"] CMD ["./grade.sh"]
...@@ -19,8 +19,9 @@ After building the image you can try out the grading image locally, by mounting ...@@ -19,8 +19,9 @@ After building the image you can try out the grading image locally, by mounting
Example submissions are provided in `./test_submissions`. For instance, to grade the correct submission `/test_submissions/correct.py` using the image, run the following command: Example submissions are provided in `./test_submissions`. For instance, to grade the correct submission `/test_submissions/correct.py` using the image, run the following command:
```bash ```bash
rm -rf feedback
mkdir feedback mkdir feedback
docker run -v ./feedback:/data/feedback -v ./test_submissions/correct.py:/data/submission/script.py demo-python3 docker run --rm -v ./feedback:/data/feedback -v ./test_submissions/correct.py:/data/submission/script.py demo-python3
cat feedback/grade.json cat feedback/grade.json
``` ```
......
...@@ -3,32 +3,42 @@ ...@@ -3,32 +3,42 @@
save_feedback() { save_feedback() {
grade=$1 grade=$1
feedback=$2 feedback=$2
# Feedback must be saved in `/data/feedback`. # Feedback must be saved in `/data/feedback`.
# - `grade.json`, must be a JSON file with {"grade": grade_as_a_number} # - `grade.json`, must be a JSON file with {"grade": grade_as_a_number}
# - other file are attached as feedback files # - other file are attached as feedback files
echo "[*] Saving grade $grade and feedback \"$feedback\""
mkdir -p /data/feedback mkdir -p /data/feedback
echo "{\"grade\": $grade}" > /data/feedback/grade.json echo "{\"grade\": $grade}" > /data/feedback/grade.json
echo "$feedback" > /data/feedback/feedback.txt echo "$feedback" > /data/feedback/feedback.txt
exit 0
} }
grade() { grade() {
# Files submitted by the student are mounted in `/data/submission`. # Files submitted by the student are mounted in `/data/submission`.
if [ -f /data/submission/script.py ]; then
output=$(python3 /data/submission/script.py) if [ ! -f /data/submission/script.py ]; then
echo "[*] Python output: $output"
if [ "Hello World!" == "$output" ]; then
save_feedback 100 "The output is correct, well done! :)"
else
save_feedback 0 "The output is not correct :'("
fi
else
save_feedback 0 "I have not found the script.py file :'(" save_feedback 0 "I have not found the script.py file :'("
fi fi
# Run the script under the restricted `student` user with a timeout of 1
# minute, and capture the output.
cp /data/submission/script.py /home/student/script.py
chmod -R 700 /data
chmod 755 /home/student/script.py
output=$(timeout 1m sudo -u student python3 /home/student/script.py 2>&1)
echo "[*] Python output: $output"
if [ "$output" == "Hello World!" ]; then
save_feedback 100 "The output is correct, well done! :)"
else
save_feedback 0 "The output is not correct :'("
fi
} }
handle_internal_error() { handle_internal_error() {
save_feedback 0 "An internal error occurred, please contact your teacher." save_feedback 0 "An internal error occurred, please contact the teaching team."
} }
# Important: always exit with 0 # Important: make sure to always exit with 0
grade || handle_internal_error grade || handle_internal_error
import os
import json
os.system("ls -l /data/submission")
os.system("whoami")
os.makedirs('/data/feedback', exist_ok=True)
with open("/data/feedback/grade.json", "w") as f:
json.dump({"grade": 100}, f)
with open("/data/feedback/ahah.txt", "w") as f:
f.write("Ahah")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment