VMAUTH: Difference between revisions

From STEMX365-WIKI
Jump to navigationJump to search
No edit summary
No edit summary
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
=VM AUTH=
=VM AUTH=
==Bind VM Usage to Online Authentication using a Flask-based API server==
===Step 1: Flask API Server (STEMX365 Side)===
<pre>
# vm_auth_server.py
from flask import Flask, request, jsonify
from werkzeug.security import check_password_hash
app = Flask(__name__)
# Dummy database (use real DB in prod)
users = {
    "student1@stemx365.org": {
        "name": "Student One",
        "password_hash": "pbkdf2:sha256:260000$...your_hash_here..."
    }
}
@app.route("/api/vm-auth", methods=["POST"])
def vm_auth():
    data = request.json
    email = data.get("email")
    password = data.get("password")
    user = users.get(email)
    if user and check_password_hash(user["password_hash"], password):
        return jsonify({"status": "success", "message": "Authenticated"}), 200
    else:
        return jsonify({"status": "error", "message": "Invalid credentials"}), 401
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)
</pre>
===Step 2: VM Startup Script (Ubuntu Side)===
<pre>
#!/bin/bash
API_URL="https://login.stemx365.org/api/vm-auth"
MAX_ATTEMPTS=3
LOGFILE="/var/log/stemx365_vm_auth.log"
clear
echo "🔐 STEMX365 VM Access Authentication"
for attempt in $(seq 1 $MAX_ATTEMPTS); do
    read -p "Enter your STEMX365 email: " EMAIL
    read -s -p "Enter your password: " PASSWORD
    echo ""
    # Send request
    RESPONSE=$(curl -s -X POST $API_URL \
        -H "Content-Type: application/json" \
        -d "{\"email\":\"$EMAIL\", \"password\":\"$PASSWORD\"}")
    STATUS=$(echo $RESPONSE | jq -r '.status')
    if [[ "$STATUS" == "success" ]]; then
        echo "✅ Access granted. Welcome!"
        echo "$(date): $EMAIL logged in successfully" >> $LOGFILE
        exit 0
    else
        echo "❌ Login failed. Attempt $attempt of $MAX_ATTEMPTS."
    fi
done
echo "$(date): $EMAIL failed authentication" >> $LOGFILE
echo "⚠️ Too many failed attempts. Locking out..."
sleep 3
pkill -KILL -u "$USER"  # logout the session (or use shutdown -h now)
</pre>
===Step 3: Auto-Run Script at Boot===
Place the above script in /usr/local/bin/vm_login.sh, make it executable:
chmod +x /usr/local/bin/vm_login.sh
Then set it as a required login precondition using one of:
====Option A: .bashrc (for single user VM)====
# Add to top of ~/.bashrc
/usr/local/bin/vm_login.sh || exit
Option B: LightDM autologin greeter (more secure)
Modify /etc/lightdm/lightdm.conf:
<pre>
[SeatDefaults]
greeter-setup-script=/usr/local/bin/vm_login.sh
</pre>
#A **Python Flask server** (runs on your central server) to handle login/authentication and token validation.
#A **Python Flask server** (runs on your central server) to handle login/authentication and token validation.
#A **bash script** that runs on **each student's VM during boot**, checks their token, and halts if invalid.
#A **bash script** that runs on **each student's VM during boot**, checks their token, and halts if invalid.
Line 12: Line 115:
##Only continue if authenticated
##Only continue if authenticated


---
==Bash Script for the Student VM (runs on boot)==
 
## 🖥️ 1. Bash Script for the Student VM (runs on boot)


Save this as `/usr/local/bin/stemx365_boot.sh` and make it executable.
Save this as `/usr/local/bin/stemx365_boot.sh` and make it executable.
Line 58: Line 159:
</pre>
</pre>


---
==2. Config File Example (per VM)==
 
## ⚙️ 2. Config File Example (per VM)


Path: `/etc/stemx365.conf`
Path: `/etc/stemx365.conf`


```bash
<pre>
bash
STUDENT_ID="student123"
STUDENT_ID="student123"
VM_TOKEN="a1b2c3d4e5f6"
VM_TOKEN="a1b2c3d4e5f6"
```
</pre>


Generate unique `VM_TOKEN`s for each student when creating the VM.
Generate unique `VM_TOKEN`s for each student when creating the VM.


---
==3. Flask Server to Validate Login==
 
## 🌐 3. Flask Server to Validate Login


Install Flask:
Install Flask:


```bash
<pre>
bash
pip install flask flask-cors
pip install flask flask-cors
```
</pre>


Save this as `stemx365_auth.py` on your server:
Save this as `stemx365_auth.py` on your server:


```python
<pre>
from flask import Flask, request, jsonify
from flask import Flask, request, jsonify
from flask_cors import CORS
from flask_cors import CORS
Line 109: Line 208:
if __name__ == "__main__":
if __name__ == "__main__":
     app.run(host="0.0.0.0", port=5000)
     app.run(host="0.0.0.0", port=5000)
```
</pre>


Run with:
Run with:
```bash
<pre>
python stemx365_auth.py
python stemx365_auth.py
```
</pre>


💡 In production, put behind NGINX with HTTPS.
💡 In production, put behind NGINX with HTTPS.


---
==Bonus: Generate Unique Tokens for Each VM==
 
## ✅ Bonus: Generate Unique Tokens for Each VM


A helper Python snippet to generate:
A helper Python snippet to generate:


```python
<pre>
import uuid
import uuid


Line 131: Line 228:


print(generate_vm_token())
print(generate_vm_token())
```
</pre>
 
---
 
## Want More?
 
Would you like to:
- Store tokens in a MySQL/PostgreSQL DB?
- Add a web dashboard to revoke/block tokens?
- Auto-create `/etc/stemx365.conf` during VM build?
- Convert the server to use Google OAuth instead?
 
Let me know and I’ll expand on it!

Latest revision as of 19:13, 11 April 2025

VM AUTH

Bind VM Usage to Online Authentication using a Flask-based API server

Step 1: Flask API Server (STEMX365 Side)

# vm_auth_server.py
from flask import Flask, request, jsonify
from werkzeug.security import check_password_hash

app = Flask(__name__)

# Dummy database (use real DB in prod)
users = {
    "student1@stemx365.org": {
        "name": "Student One",
        "password_hash": "pbkdf2:sha256:260000$...your_hash_here..."
    }
}

@app.route("/api/vm-auth", methods=["POST"])
def vm_auth():
    data = request.json
    email = data.get("email")
    password = data.get("password")

    user = users.get(email)
    if user and check_password_hash(user["password_hash"], password):
        return jsonify({"status": "success", "message": "Authenticated"}), 200
    else:
        return jsonify({"status": "error", "message": "Invalid credentials"}), 401

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

Step 2: VM Startup Script (Ubuntu Side)

#!/bin/bash

API_URL="https://login.stemx365.org/api/vm-auth"
MAX_ATTEMPTS=3
LOGFILE="/var/log/stemx365_vm_auth.log"

clear
echo "🔐 STEMX365 VM Access Authentication"

for attempt in $(seq 1 $MAX_ATTEMPTS); do
    read -p "Enter your STEMX365 email: " EMAIL
    read -s -p "Enter your password: " PASSWORD
    echo ""

    # Send request
    RESPONSE=$(curl -s -X POST $API_URL \
        -H "Content-Type: application/json" \
        -d "{\"email\":\"$EMAIL\", \"password\":\"$PASSWORD\"}")

    STATUS=$(echo $RESPONSE | jq -r '.status')

    if [[ "$STATUS" == "success" ]]; then
        echo "✅ Access granted. Welcome!"
        echo "$(date): $EMAIL logged in successfully" >> $LOGFILE
        exit 0
    else
        echo "❌ Login failed. Attempt $attempt of $MAX_ATTEMPTS."
    fi
done

echo "$(date): $EMAIL failed authentication" >> $LOGFILE
echo "⚠️ Too many failed attempts. Locking out..."
sleep 3
pkill -KILL -u "$USER"  # logout the session (or use shutdown -h now)

Step 3: Auto-Run Script at Boot

Place the above script in /usr/local/bin/vm_login.sh, make it executable:


chmod +x /usr/local/bin/vm_login.sh

Then set it as a required login precondition using one of:

Option A: .bashrc (for single user VM)

  1. Add to top of ~/.bashrc

/usr/local/bin/vm_login.sh || exit Option B: LightDM autologin greeter (more secure) Modify /etc/lightdm/lightdm.conf:

[SeatDefaults]
greeter-setup-script=/usr/local/bin/vm_login.sh



  1. A **Python Flask server** (runs on your central server) to handle login/authentication and token validation.
  2. A **bash script** that runs on **each student's VM during boot**, checks their token, and halts if invalid.

OVERVIEW

Each VM has:

  1. A file `/etc/stemx365.conf` containing a unique `STUDENT_ID` and `VM_TOKEN`
  2. On boot, a script will:
    1. Read this config
    2. Ping your Flask server to validate the ID+token
    3. Only continue if authenticated

Bash Script for the Student VM (runs on boot)

Save this as `/usr/local/bin/stemx365_boot.sh` and make it executable.

#!/bin/bash

CONFIG_FILE="/etc/stemx365.conf"
API_URL="https://auth.stemx365.org/api/validate"

if [ ! -f "$CONFIG_FILE" ]; then
    echo "Missing configuration. Please contact STEMX365 support."
    exit 1
fi

source "$CONFIG_FILE"

# Check if required variables exist
if [ -z "$STUDENT_ID" ] || [ -z "$VM_TOKEN" ]; then
    echo "Invalid config file. Aborting."
    exit 1
fi

# Call central API to verify
response=$(curl -s -X POST "$API_URL" \
    -H "Content-Type: application/json" \
    -d "{\"student_id\": \"$STUDENT_ID\", \"vm_token\": \"$VM_TOKEN\"}")

if [[ "$response" == *"valid":true* ]]; then
    echo "✅ Welcome, $STUDENT_ID"
else
    echo "❌ Authentication failed. Access denied."
    exit 1
fi

Add this to the crontab or systemd to run on boot:

bash
sudo crontab -e
@reboot /usr/local/bin/stemx365_boot.sh

2. Config File Example (per VM)

Path: `/etc/stemx365.conf`

bash
STUDENT_ID="student123"
VM_TOKEN="a1b2c3d4e5f6"

Generate unique `VM_TOKEN`s for each student when creating the VM.

3. Flask Server to Validate Login

Install Flask:

bash
pip install flask flask-cors

Save this as `stemx365_auth.py` on your server:

from flask import Flask, request, jsonify
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

# Example: store valid tokens in a dictionary (use DB in production)
valid_tokens = {
    "student123": "a1b2c3d4e5f6",
    "student456": "z9y8x7w6v5"
}

@app.route('/api/validate', methods=['POST'])
def validate():
    data = request.get_json()
    student_id = data.get('student_id')
    token = data.get('vm_token')

    if student_id in valid_tokens and valid_tokens[student_id] == token:
        return jsonify({"valid": True})
    else:
        return jsonify({"valid": False}), 401

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

Run with:

python stemx365_auth.py

💡 In production, put behind NGINX with HTTPS.

Bonus: Generate Unique Tokens for Each VM

A helper Python snippet to generate:

import uuid

def generate_vm_token():
    return uuid.uuid4().hex

print(generate_vm_token())