Skip to content

YHWong20/secure-banking-app

 
 

Repository files navigation

IFS4205 Team 1: Project AIMS - Account Intelligent Management System

Monorepo for a simple banking system

Setting up the environment

1. Python environment

This project uses uv for managing dependencies and virtual environments.

  1. Install uv based on installation guide

  2. Create and sync the environment:

    uv venv
    # https://github.com/astral-sh/uv/issues/13664
    uv sync [--all-packages]
  3. Running scripts can be done 2 ways

    1. Using uv uv run <app.py> OR
    2. Activate virtual environment uv venv and run python <app.py>, flask --app hello run etc.

uv dev dependencies

NOTE: Dev dependencies can be

  • Installed: uv sync --group dev
  • Uninstalled: uv sync --no-dev

Additional info on uv

2. Docker environment

This project uses Docker to provide the following services:

  1. Postgres: Database Management System
  2. pgAdmin: Administration platform for Postgres
  3. Redis: In-memory key-value database for session management
  4. Caddy: Reverse Proxy
  5. step-ca: Certificate Authority for certificate management

Steps to setup docker:

  1. Install docker based on installation guide for Docker Engine and Docker Compose
  2. Spin up the containers for the above 3 services using docker compose up -d in the project root directory
  3. Check the container status using docker ps and container logs using docker logs <container_name>

This project also uses Docker to containerise each of the microservices. Below are some essential info about it:

  • Each of the microservices (account, auth, loan, profile & signup) are containerised
    • Their Dockerfile can be located at services/<service_name>/
    • They utilise the same base image that can be built using the Dockerfile.base located at the project root
      • Development build has additional private CA baked in so it uses Dockerfile.dev.base, which adds on to the Dockerfile.base image
      • The entrypoint.sh script for each microservice can be found in scripts/ (with or without db versions)
  • All services defined in compose.yaml with their appropriate configurations
    • Development setup has an override configuration compose.dev.yaml
  • Multi-stage build (stepca -> base -> services)
  • Makefile commands (Inspect for Docker commands)
    • Rebuild stepca, base and services: make rebuild-all
    • Rebuild base and services: make rebuild-base
    • Rebuild services: make rebuild-svcs

Additional info on docker

3. Project environment

This project's folder structure is as follows:

banking-system/
├── config: Contains additional configurations used in the project
└── services: Contains all microservices for project
    └── <service_name>
        ├── app: Contains service source code
        └── migrations: Contains database change management scripts

Precommit hooks

This project utilises pre-commit and should be enabled as follows:

  1. Ensure uv dev dependencies has been installed (Refer to Python environment)
  2. Enable pre-commit hooks using: pre-commit install
  3. To bypass pre-commit hooks when committing: git commit -m <commit message> --no-verify
  4. To run checks outside of pre-commit hooks: pre-commit run --all-files

Database info

This project utilises flask-sqlalchemy (sqlalchemy) and flask-migrate (alembic) to provision the Postgres database.

  1. When setting up the project environment:
    1. Ensure that the docker containers are running: docker ps and docker logs <container_name>
    2. Enter each services directory: cd services/<service_name>/
    3. Setup the database schemas and tables: flask --app app:create_app db upgrade
    4. Login to pgAdmin and verify that the database schemas and tables have been setup: Servers > Banking DB > Databases > bankingdb > Schemas > SERVICE_NAME
  2. When updating the service database schema:
    1. Enter the service directory: cd services/<service_name>/
    2. Modify or add your SQLAlchemy models as needed in app/models.py
    3. Generate a new migration: flask --app app:create_app db migrate -m "Describe your migration here"
    4. Apply the migration to the database: flask --app app:create_app db upgrade
    5. Verify the changes in pgAdmin: Servers > Banking DB > Databases > bankingdb > Schemas > SERVICE_NAME

Redis

This project uses Redis for session management. To see the data inside redis:

  1. apt install redis-tools
  2. If Redis has its port exposed, connect via redis-cli -h localhost -p 6379
  3. The following commands can be run
    • SELECT <db_number> to switch between logical databases in Redis
    • KEYS * (List all the keys)
    • GET <key> (Get a string key)
    • HGETALL <key> (Returns key-value of a key as a flat list)
    • SCAN 0

When creating the Redis session with the Redis database, follow the following format: Redis(host="redis", port=6379, db=0, decode_responses=True), where

  • host="redis" is the location of your redis service
  • port=6379 is the port the redis service is listening to
  • db=x, where x is the database number to connect to
  • decode_responses=True returns responses as strings instead as bytes for easier processing

Note that the current implementation has 3 database sessions

  • db=0 for sessID -> dict data mapping. sessID is sent to client upon login. Used to check for a valid session (after login).
  • db=1 for userID -> dict data mapping. Request ID in the dict is given to client. Internal use to ensure only one active session.
  • db=2 for sessID -> dict data mapping. Similar to db=0, except this is meant for registration workflow for use by 2FA signup.

Caddy

This project uses Caddy as a reverse proxy. There are currently 2 different configurations for Caddy, 1 for production and 1 for development.

Configuration Production Development
Caddyfile Caddyfile Caddyfile.dev
Dockerfile Dockerfile Dockerfile.dev
Entrypoint - entrypoint.sh
  • Production setup will route via HTTP only
  • Development setup will route via HTTPS only
  • If changes were made to Caddyfile.dev, run make misc-caddy-reload to reload Caddy
  • Documentation

Step-CA

This project uses Step-CA as a private Certificate Authority. This is currently enabled for development setup only.

  • There are 2 core components to this setup
    • step-ca: Creates the root and intermediate certificates to issue and sign certificates
    • step-cli: Communicate with the private CA to provision the certificate and private key
  • You will need to setup 3 password files before running the private CA for the first time (Run make misc-stepca-init)
  • Next, you will need to setup the full build stages (Run make rebuild-all. See details on Makefile commands)
    • You will probably need to run make rebuild-all once only
    • Subsequently, running make rebuild-base or make rebuild-svcs will suffice
    • Running make rebuild-all will reinitialise a new CA which will then reinstall to the base image
  • Provisioning of the service certificate and private key
    • Additional script scripts/stepca-provision.sh has been included inside each service image
    • It will provision the service certificate and private key
    • An auto-renewal daemon has been setup as well to run automatically
    • When renewal is complete, it will kill the existing Gunicorn process so it will start with the new certificate and private key
  • Documention:

Testing

Unit tests

This project uses pytest for unit tests. Below are the recommended steps to run tests and troubleshoot common issues when using uv to manage the Python environment.

  • Ensure the virtual environment exists and dependencies are installed: uv sync --all-packages

  • Run tests using uv (preferred) or by activating the venv manually.

# run the whole test suite
uv run pytest

# run only the signup tests (example)
uv run pytest tests/signup/test_signup.py -q

# or activate the venv and run directly
uv venv
source .venv/bin/activate
pytest -q tests/signup/test_signup.py

Seeding the database

This project includes a small seeder utility to generate fake data and Alembic-style seed files for each service.

Basic workflow :

  1. Generate a seed
python3 seeder/seed_generator.py --service auth --name auth
  1. Apply the seed to the database. The Makefile target will invoke the Flask CLI seed command for the chosen service.
# using Makefile (recommended)
make seed SERVICE=auth

Notes

  • The auth faker factory creates HR users by default. The seeded HR account has the a default password
  • The default password can be found or changed at seeder/faker_factories/auth.py
  • Seeding will modify the target schema in your Postgres instance. Only run against a development database. (ensure it is running before seeding)

About

A secure microservice banking application built on AWS.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Python 72.9%
  • HCL 10.9%
  • HTML 9.1%
  • Dockerfile 1.7%
  • Shell 1.5%
  • Makefile 1.5%
  • Other 2.4%