jss-devsecops-challenge
DevSecOps assessment - device registration and statistics API built with Python (Flask) and MariaDB.
What it does
A single API server that tracks device type registrations per user. It exposes three endpoints:
POST /log/auth- logs a user login event by storing the device typeGET /log/auth/statistics?deviceType=iOS- returns count of registrations for a given device typePOST /device/register- directly registers a device type for a user
Accepted device types: iOS, Android, Watch, TV, Tablet, Desktop, IoT. In contrast to API endpoints asked in pdf file, I used smaller case here.
Project structure
app/server.py - Flask application with all endpoints
tests/test_app.py - unit tests (mocked DB)
init.sql - MariaDB schema initialization
Dockerfile - container image for the API
docker-compose.yml - full stack (MariaDB + API)
requirements.txt - Python dependencies
Docker Hub
The API image is published to Docker Hub:
docker.io/harshavmb/jss-devsecops-api:latest
To pull it directly:
docker pull harshavmb/jss-devsecops-api:latest
MariaDB is used from the official registry (docker.io/library/mariadb:12) and does not need a custom image. The schema is applied at startup via the init SQL script mounted in docker-compose.
Running locally with Docker Compose
docker compose up --build -d
This starts MariaDB, runs the init SQL script, and launches the API on port 5000.
To stop:
docker compose down -v
Running tests
pip install -r requirements.txt
pytest tests/ -v
Security controls
- Input validation on userKey (regex whitelist) and deviceType (enum whitelist)
- Parameterized SQL queries to prevent injection
- Rate limiting (30 req/min per endpoint, 60 req/min global)
- Non-root container user
- No secrets hardcoded (configurable via DATABASE_URL env var)
- No docker/podman container is run as root user (that depends on how docker/podman are configured on host)
- Authentication of endpoints is left out for brevity
Configuration
The API reads DATABASE_URL from the environment. Format:
mysql://user:password@host:port/database
Default: mysql://root:my-secret-pw@localhost:3306/devsecops_db