Harshavardhan Musanalli d720f43439 Finish remaining code
2026-02-13 09:48:41 +01:00
2026-02-13 09:48:41 +01:00
2026-02-13 09:48:41 +01:00
2026-02-13 09:48:41 +01:00
2026-02-13 09:48:41 +01:00
2026-02-13 09:48:41 +01:00
2026-02-10 21:09:13 +01:00
2026-02-09 18:12:18 +00:00
2026-02-13 09:48:41 +01:00
2026-02-13 09:48:41 +01:00
2026-02-13 09:48:41 +01:00

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 type
  • GET /log/auth/statistics?deviceType=iOS - returns count of registrations for a given device type
  • POST /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

Description
This is a practical test for a DevSecOps Engineer candidate at Bank J. Safra Sarasin.
Readme MIT 136 KiB
Languages
Python 97%
Dockerfile 3%