Skip to content
Snippets Groups Projects
Unverified Commit fe3cc85d authored by Marco Emilio "sphakka" Poleggi's avatar Marco Emilio "sphakka" Poleggi
Browse files

README: added data schemas and test instructions

parent cee2baf4
No related branches found
No related tags found
No related merge requests found
README.html
...@@ -52,9 +52,9 @@ Buttons: 4, named as the routes above. ...@@ -52,9 +52,9 @@ Buttons: 4, named as the routes above.
### Back-end ### Back-end
:construction: Session management subsystem written in Python/FlaskGunicorn/??? :construction: Session management subsystem written in Python/Flask
:hammer_and_wrench: This part requires some development by the students. :tools: This part requires some development by the students.
### Storage ### Storage
...@@ -62,22 +62,110 @@ Buttons: 4, named as the routes above. ...@@ -62,22 +62,110 @@ Buttons: 4, named as the routes above.
:construction: S3-like object storage composed of 1 buckets with two directories: one for :construction: S3-like object storage composed of 1 buckets with two directories: one for
*enrollment* data, one for *session* data. *enrollment* data, one for *session* data.
Objects shall be written as JSON data based on the following proposed schema.
#### Enrollment objects
An enrollment object:
* is named after the user e-mail
* is unique in the system
* is created when a new user subscribes to the system via the `enroll` function
* is never updated (assume that users' passwords cannot be changed)
* is deleted when a subscribed (== existing) user unsubscribes from the
system via the `unenroll` function
Minimum schema (you're free to extend it):
``` json
{
"title": "Enrollment",
"type": "object",
"properties": {
"password": {
"type": "string",
"description": "The user's password."
},
"timestamp": {
"description": "The UNIX epoch time of object's creation",
"type": "integer",
"minimum": 0
}
}
}
```
Example data for object named `foo@bar.com`:
``` json
{
"password": "SECRET",
"timestamp": 1733330967
}
```
#### Session objects
A session object:
* is named after the user e-mail
* is unique in the system -- multiple sessions are not permitted
* is created at the first user's connection to the system via the `login`
function
* is never updated
* is deleted when a logged-in user disconnects from the system via the
`logout` function
Minimum schema (you're free to extend it):
``` json
{
"title": "Session",
"type": "object",
"properties": {
"client": {
"description": "The client host's IPv4 address",
"type": "string",
"format": "ipv4"
},
"timestamp": {
"description": "The UNIX epoch time of object's creation",
"type": "integer",
"minimum": 0
}
}
}
```
Example data for object named `foo@bar.com`:
``` json
{
"timestamp": 1733330967
}
```
### Workflows ### Workflows
The following workflows correspond to the front-end routes discussed above. The following workflows correspond to the application "routes" discussed
above. Additional information is provided in the boilerplate files. All
involved data are in JSON format.
Conventions: Conventions:
* KEYWORDS are capitalized. * KEYWORDS are capitalized.
* **Actors** are in boldface. * **Actors** are in boldface.
* 'CONSTANTS' are capitalized and single-quoted. * 'CONSTANTS' are capitalized and single-quoted.
* *data* items are lower-case and italicized. * *data* items are lower-case and italicized.
* all times are represented as [UNIX epoch
timestamps](https://en.wikipedia.org/wiki/Unix_time)
:bulb: This is a fake SSO ;-) For the sake of simplicity: :bulb: For the sake of simplicity:
* Sessions never expire. * Sessions never expire.
* No cookies are stored at the client. * No cookies are stored at the client.
* The e-mail address is used as authentication token. * The e-mail address is used as authentication token.
All operations are *stateless*: apart from enrollment and session data,
nothing else is recorded by the back-end.
#### Enroll #### Enroll
...@@ -90,7 +178,7 @@ A new user subscribes to the system via the `enroll` function: ...@@ -90,7 +178,7 @@ A new user subscribes to the system via the `enroll` function:
- IF user exists THEN returns 'KO:ALREADY_ENROLLED' - IF user exists THEN returns 'KO:ALREADY_ENROLLED'
- ELSE - ELSE
1. Writes enrollment data to storage 1. Writes enrollment data to storage
2. Returns 'OK' to the front-end 2. Returns 'OK:ENROLLED' to the front-end
4. **Front-end** receives response from the back-end and shows it to the user. 4. **Front-end** receives response from the back-end and shows it to the user.
...@@ -102,10 +190,10 @@ An enrolled unsubscribes from the system with the `unenroll` function: ...@@ -102,10 +190,10 @@ An enrolled unsubscribes from the system with the `unenroll` function:
front-end. front-end.
2. **Front-end** sends enrollment data to the back-end. 2. **Front-end** sends enrollment data to the back-end.
3. **Back-end** verifies enrollment data: 3. **Back-end** verifies enrollment data:
- IF user does not exists THEN returns 'KO:NO_SUCH_USER' - IF user does not exists THEN returns 'KO:NO\_SUCH\_USER'
- ELSE - ELSE
1. Removes enrollment data and any active sessions from the storage 1. Removes enrollment data and any active sessions from the storage
2. Returns 'OK' to the front-end 2. Returns 'OK:UNENROLLED' to the front-end
4. **Front-end** receives response from the back-end and shows it to the user. 4. **Front-end** receives response from the back-end and shows it to the user.
...@@ -116,22 +204,22 @@ An enrolled user authenticates to the system with the `login` function: ...@@ -116,22 +204,22 @@ An enrolled user authenticates to the system with the `login` function:
1. **User** provides *e-mail* via the the front-end. 1. **User** provides *e-mail* via the the front-end.
2. **Front-end** sends *e-mail* to the back-end. 2. **Front-end** sends *e-mail* to the back-end.
3. **Back-end** verifies the *e-mail*: 3. **Back-end** verifies the *e-mail*:
- IF user does not exists THEN returns 'KO:NO_SUCH_USER' - IF user does not exists THEN returns 'KO:NO\_SUCH\_USER'
- ELSE verifies sessions: - ELSE verifies sessions:
1. IF an active session exists THEN returns 'OK' 1. IF an active session exists THEN returns 'OK:SESSION_EXISTS'
2. ELSE returns 'NEED_PASSWORD'. 2. ELSE returns 'OK:NEED_PASSWORD'.
4. **Front-end** receives first response from the back-end: 4. **Front-end** receives first response from the back-end:
- IF response == 'NEED_PASSWORD' THEN - IF response == 'OK:NEED_PASSWORD' THEN
1. Prompts the user for their *password*. 1. Prompts the user for their *password*.
2. **User** provides *password*. 2. **User** provides *password*.
3. **Front-end** sends *e-mail* and *password* to the back-end. 3. **Front-end** sends *e-mail* and *password* to the back-end.
4. **Back-end** verifies the *password*: 4. **Back-end** verifies the *password*:
- IF *password* matches THEN - IF *password* matches THEN
1. Writes session to storage. 1. Writes a new session to storage.
2. Returns 'OK' to the front-end. 2. Returns 'OK:LOGGED_IN' to the front-end.
- ELSE returns 'KO:WRONG_PASSWORD' to the front-end. - ELSE returns 'KO:WRONG_PASSWORD' to the front-end.
- ELSE shows 'OK' response to the user and terminates. - ELSE shows other response to the user and terminates.
5. **Front-end** receives second response 'OK/KO' from the back-end and 5. **Front-end** receives second response from the back-end and
shows it to the user. shows it to the user.
...@@ -142,12 +230,12 @@ An enrolled user deauthenticates to the system with the `logout` function: ...@@ -142,12 +230,12 @@ An enrolled user deauthenticates to the system with the `logout` function:
1. **User** provides *e-mail* via the the front-end. 1. **User** provides *e-mail* via the the front-end.
2. **Front-end** sends *e-mail* to the back-end. 2. **Front-end** sends *e-mail* to the back-end.
3. **Back-end** verifies the *e-mail*: 3. **Back-end** verifies the *e-mail*:
- IF user does not exists THEN returns 'KO' - IF user does not exists THEN returns 'KO:NO\_SUCH\_USER'
- ELSE verifies sessions: - ELSE verifies sessions:
- IF an active session exists THEN - IF an active session exists THEN
1. Removes session from storage. 1. Removes session from storage.
2. Returns 'OK'. 2. Returns 'OK:LOGGED_OUT'.
- ELSE returns 'KO'. - ELSE returns 'KO:NO\_ACTIVE\_SESSION'.
4. **Front-end** receives response from the back-end and shows it to the user. 4. **Front-end** receives response from the back-end and shows it to the user.
...@@ -186,18 +274,53 @@ whenever its image is updated. ...@@ -186,18 +274,53 @@ whenever its image is updated.
## Tasks ## Tasks
:construction: **To be finalized**
You shall: You shall:
0. Fork this repository.
1. Complete the Python back-end file(s) in folder `Application/back-end.py`. 1. Complete the Python back-end file(s) in folder `Application/back-end.py`.
2. Rebuild the application Docker image, and store it :question: somewhere -- 2. Rebuild the application Docker image, and store it (somewhere) --
**(TO-DO: We should provide instructions. Build on the student's **(:question: TO-DO - We should provide instructions + Dockerfile:
workstation?)**. - Build image on the student's workstation
3. Complete the `Terraform/main.tf` recipe to handle the provisioning of the S3 storage - What's better: push to Dockerhub vs to scp to VM + import?
bucket. )**. This task shall be automated via Ansible -- see below.
4. Complete the `Ansible/deploy.yml` playbook to handle: 3. Complete your Terraform files from the version you developed in
- exposure of the application portal IP (e.g., load-balancer IP) to the [Lab-Terraform](https://gitedu.hesge.ch/lsds/teaching/bachelor/cloud-and-deployment/lab-terraform/-/blob/main/SwitchEngines/README.md)
up to Task #8. Your recipe shall handle only the provisioning of the VM
plus an S3 storage bucket -- no KinD/Kubectl package installation. Commit
your recipe files (included Cloud-init) and in directory `Terraform/`.
4. Complete your Ansible playbook, starting from the version you developed in
[Lab-Ansible](https://gitedu.hesge.ch/lsds/teaching/bachelor/cloud-and-deployment/lab-ansible)
Task #10, to:
- expose the application portal IP (e.g., load-balancer IP) to the
Internet via `socat` or other mechanism of your choice; Internet via `socat` or other mechanism of your choice;
- :question: **(TO-DO: What's better? Local or registry [Helm/Docker])?** - :question: **(TO-DO: What's better? Local or registry [Docker])?**
transfer/download of the application image to your VM instance. rebuild and transfer/download the application image to your VM instance.
Commit these files in directory `Ansible/`.
Tests: :construction: **TO-DO**
### Tests
The following tests shall be passed by your implementation:
* Starting with a non-provisioned infrastructure:
1. Terraform apply shall provision a bare-bone VM and an S3 bucket
2. Ansible-playbook shall install KinD/Kubectl and deploy your
load-balanced application
3. Your application shall be reachable on port 80 (or another of your
choice) from any host outside the Cloud network.
* Once your application is installed, you shall exercise all the branch
conditions described by the above workflows:
1. Enroll a new user: shall succeed
2. Enroll an existing: user shall fail
3. Unenroll a new user: shall fail
4. Unenroll an existing user: shall succeed
5. Login an enrolled user: shall succeed and ask for the password
* with a valid password: shall succeed
* with an invalid password: shall fail
6. Login a non-enrolled user: shall fail
7. Logout a non-enrolled user: shall fail
8. Logout an enrolled user
* with an active session: shall succeed
* without an active session: shall fail
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment