Finish remaining code
This commit is contained in:
86
README.md
86
README.md
@@ -1,12 +1,82 @@
|
||||
# jss-devsecops-challenge
|
||||
|
||||
This is a practical test for a DevSecOps Engineer candidate at Bank J. Safra Sarasin. Instructions received (on 09.02.2025) from the recruiter are attached to this repo.
|
||||
DevSecOps assessment - device registration and statistics API built with Python (Flask) and MariaDB.
|
||||
|
||||
### On 09.02.2026
|
||||
I created repo on https://git.harshanu.space. I'll work on code changes tomorrow as I will be free in the afternoon (Fashing Tuesday, half day work)
|
||||
## What it does
|
||||
|
||||
### On 10.02.2026
|
||||
- Defined the database schema for the API endpoints in `init.sql`.
|
||||
- Pulled the `docker.io/library/mariadb:12` Docker image.
|
||||
- Tested the schema by spinning up a MariaDB container and verifying the table creation.
|
||||
- Python will be used to write API endpoints
|
||||
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:
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
docker compose up --build -d
|
||||
```
|
||||
|
||||
This starts MariaDB, runs the init SQL script, and launches the API on port 5000.
|
||||
|
||||
To stop:
|
||||
|
||||
```bash
|
||||
docker compose down -v
|
||||
```
|
||||
|
||||
## Running tests
|
||||
|
||||
```bash
|
||||
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`
|
||||
|
||||
Reference in New Issue
Block a user