diff --git a/MohamadMahdiReisi/Problem1_PostgreSQL/Dockerfile b/MohamadMahdiReisi/Problem1_PostgreSQL/Dockerfile new file mode 100644 index 00000000..afe6a248 --- /dev/null +++ b/MohamadMahdiReisi/Problem1_PostgreSQL/Dockerfile @@ -0,0 +1,15 @@ +FROM postgres:latest + +ENV POSTGRES_USER=amir +ENV POSTGRES_PASSWORD=barari +ENV POSTGRES_DB=mydatabase +ENV POSTGRES_PORT=5432 + +RUN mkdir -p /docker-entrypoint-initdb.d + +EXPOSE ${POSTGRES_PORT} + +HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \ + CMD pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB} + +VOLUME /var/lib/postgresql/data \ No newline at end of file diff --git a/MohamadMahdiReisi/Problem1_PostgreSQL/README.md b/MohamadMahdiReisi/Problem1_PostgreSQL/README.md index 8b137891..fccb76f0 100644 --- a/MohamadMahdiReisi/Problem1_PostgreSQL/README.md +++ b/MohamadMahdiReisi/Problem1_PostgreSQL/README.md @@ -1 +1,164 @@ +# PostgreSQL Docker Deployment with Persistent Storage + +![PostgreSQL Logo](https://www.postgresql.org/media/img/about/press/elephant.png) + +## Table of Contents +- [Overview](#overview) +- [Features](#features) +- [Quick Start](#quick-start) +- [Detailed Usage](#detailed-usage) +- [Data Persistence Verification](#data-persistence-verification) +- [Maintenance](#maintenance) +- [Troubleshooting](#troubleshooting) +- [Security Considerations](#security-considerations) +- [Contributing](#contributing) +- [License](#license) + +## Overview + +This project provides a complete solution for deploying PostgreSQL in Docker with persistent storage, designed specifically for: +- Development environments +- Learning database concepts +- Capture The Flag (CTF) challenges +- Application prototyping + +## Features + +✔ **Persistent Data Storage** - Uses Docker volumes to maintain data between container restarts +✔ **Pre-configured Environment** - Ready-to-use database with user credentials +✔ **Simple Operations** - Includes sample SQL commands for basic CRUD operations +✔ **Verification Scripts** - Commands to validate data persistence +✔ **Production-ready Foundation** - Can be extended for more complex deployments + +## Quick Start + +### 1. Deploy the Container +```bash +docker run -d \ + --name postgres_ctf \ + -e POSTGRES_USER=ctf_user \ + -e POSTGRES_PASSWORD=ctf_password \ + -e POSTGRES_DB=ctf_db \ + -p 5432:5432 \ + -v postgres_data:/var/lib/postgresql/data \ + postgres:latest +``` + +### 2. Connect and Test +```bash +docker exec -it postgres_ctf psql -U ctf_user -d ctf_db -c "SELECT version();" +``` + +## Detailed Usage + +### Database Initialization +The container automatically: +- Creates the specified user (`ctf_user`) +- Creates the default database (`ctf_db`) +- Sets up the persistent volume + +### Common Operations + +**Create Table:** +```sql +CREATE TABLE challenges ( + id SERIAL PRIMARY KEY, + name VARCHAR(100) NOT NULL, + points INTEGER NOT NULL, + category VARCHAR(50), + is_active BOOLEAN DEFAULT true +); +``` + +**Insert Data:** +```sql +INSERT INTO challenges (name, points, category) VALUES + ('SQL Injection', 100, 'Web'), + ('Buffer Overflow', 200, 'Binary'), + ('Cryptanalysis', 150, 'Crypto'); +``` + +**Query Data:** +```sql +-- Basic query +SELECT * FROM challenges; + +-- Filtered query +SELECT name, points FROM challenges WHERE points > 120; + +-- Aggregation +SELECT category, AVG(points) as avg_points FROM challenges GROUP BY category; +``` + +## Data Persistence Verification + +1. **Stop and remove the container** + ```bash + docker stop postgres_ctf + docker rm postgres_ctf + ``` + +2. **Redeploy with same volume** + ```bash + docker run -d \ + --name postgres_ctf_new \ + -v postgres_data:/var/lib/postgresql/data \ + -p 5432:5432 \ + postgres:latest + ``` + +3. **Verify data integrity** + ```bash + docker exec -it postgres_ctf_new psql -U ctf_user -d ctf_db -c "SELECT * FROM challenges;" + ``` + +## Maintenance + +### Backup Database +```bash +docker exec postgres_ctf pg_dump -U ctf_user -d ctf_db > ctf_backup.sql +``` + +### Restore Database +```bash +cat ctf_backup.sql | docker exec -i postgres_ctf psql -U ctf_user -d ctf_db +``` + +### Monitor Performance +```bash +docker exec -it postgres_ctf psql -U ctf_user -d ctf_db -c "SELECT * FROM pg_stat_activity;" +``` + +## Troubleshooting + +| Issue | Solution | +|-------|----------| +| Connection refused | Check if container is running: `docker ps` | +| Authentication failed | Verify credentials in environment variables | +| Volume not persisting | Confirm volume mount: `docker inspect postgres_ctf` | +| Port conflicts | Change host port mapping (e.g., `-p 5433:5432`) | + +## Security Considerations + +For production environments, we recommend: +1. Using complex passwords +2. Enabling SSL connections +3. Implementing network isolation +4. Regular backups +5. Monitoring access logs + +## Contributing + +We welcome contributions! Please: +1. Fork the repository +2. Create a feature branch +3. Submit a pull request + +## License + +MIT License - See [LICENSE](LICENSE) for details. + +--- + +**Pro Tip**: For advanced configurations, check out the [official PostgreSQL Docker image documentation](https://hub.docker.com/_/postgres). \ No newline at end of file diff --git a/MohamadMahdiReisi/Problem2_Redis/Dockerfile b/MohamadMahdiReisi/Problem2_Redis/Dockerfile new file mode 100644 index 00000000..d3834474 --- /dev/null +++ b/MohamadMahdiReisi/Problem2_Redis/Dockerfile @@ -0,0 +1,3 @@ +FROM redis + +EXPOSE 6379 \ No newline at end of file diff --git a/MohamadMahdiReisi/Problem2_Redis/README.md b/MohamadMahdiReisi/Problem2_Redis/README.md index 8b137891..96045335 100644 --- a/MohamadMahdiReisi/Problem2_Redis/README.md +++ b/MohamadMahdiReisi/Problem2_Redis/README.md @@ -1 +1,117 @@ +# Redis Server Setup with Docker and Python Integration +## Table of Contents +- [Overview](#overview) +- [Prerequisites](#prerequisites) +- [Redis Server Deployment](#redis-server-deployment) +- [Python Programs for Redis Operations](#python-programs-for-redis-operations) +- [Redis Monitoring](#redis-monitoring) +- [Demonstration](#demonstration) +- [Cleanup](#cleanup) +- [Troubleshooting](#troubleshooting) +- [License](#license) + +## Overview + +This solution demonstrates how to: +1. Deploy a Redis server in Docker +2. Implement Python programs for Redis operations +3. Monitor Redis activity using RedisInsight +4. Document the inter-process communication + +## Prerequisites + +- Docker installed +- Python 3.6+ with `redis-py` package (`pip install redis`) +- (Optional) RedisInsight for monitoring + +## Redis Server Deployment + +### 1. Launch Redis Container +```bash +docker run -d --name redis_server -p 6379:6379 redis:latest +``` + +### 2. Verify Connection +```bash +docker exec -it redis_server redis-cli ping +# Should respond with "PONG" +``` + +## Python Programs for Redis Operations + +### Program 1: Redis Writer (`redis_writer.py`) +```python +import redis +import time + +r = redis.Redis(host='localhost', port=6379, db=0) + +# Set key-value pairs +r.set('server:name', 'Redis CTF Server') +r.set('server:uptime', '24 hours') +r.hset('user:1001', mapping={'name': 'Alice', 'score': '850'}) + +# Publish messages +for i in range(3): + r.publish('ctf-channel', f'Message {i+1} from writer') + time.sleep(1) +``` + +### Program 2: Redis Reader (`redis_reader.py`) +```python +import redis + +r = redis.Redis(host='localhost', port=6379, db=0) + +# Retrieve key-value pairs +print("Key-Value Pairs:") +print(f"Server Name: {r.get('server:name').decode('utf-8')}") +print(f"Server Uptime: {r.get('server:uptime').decode('utf-8')}") +print(f"User Data: {r.hgetall('user:1001')}") + +# Subscribe to channel +pubsub = r.pubsub() +pubsub.subscribe('ctf-channel') + +print("\nWaiting for messages...") +for message in pubsub.listen(): + if message['type'] == 'message': + print(f"Received: {message['data'].decode('utf-8')}") +``` + +### Running the Programs +1. First terminal: +```bash +python3 redis_writer.py +``` + +2. Second terminal: +```bash +python3 redis_reader.py +``` + +### Screenshot Checklist +**desierd output** + + + +## Demonstration + +### Video Script (30 seconds) +1. Show Redis container running (`docker ps`) +2. Execute `redis_writer.py` (terminal) +3. Execute `redis_reader.py` (terminal) +4. Show RedisInsight with real-time data +5. Stop container (`docker stop redis_server`) + +## Cleanup + +```bash +docker stop redis_server +docker rm redis_server +``` + +## License + +MIT License - See [LICENSE](LICENSE) for details. \ No newline at end of file diff --git a/MohamadMahdiReisi/Problem2_Redis/redis_reader.py b/MohamadMahdiReisi/Problem2_Redis/redis_reader.py new file mode 100644 index 00000000..b88831ef --- /dev/null +++ b/MohamadMahdiReisi/Problem2_Redis/redis_reader.py @@ -0,0 +1,16 @@ +import redis + +r = redis.Redis(host='localhost', port=6379, decode_responses=True) + +keys = ["amir", "ali", "reza"] +for key in keys: + value = r.get(key) + print(f"Key: {key}, Value: {value}") + +pubsub = r.pubsub() +pubsub.subscribe("task_updates") +print("Subscribed to channel 'task_updates'. Waiting for messages...") + +for message in pubsub.listen(): + if message["type"] == "message": + print(f"Received: {message['data']}") \ No newline at end of file diff --git a/MohamadMahdiReisi/Problem2_Redis/redis_writer.py b/MohamadMahdiReisi/Problem2_Redis/redis_writer.py new file mode 100644 index 00000000..49315989 --- /dev/null +++ b/MohamadMahdiReisi/Problem2_Redis/redis_writer.py @@ -0,0 +1,17 @@ +import redis +import time + +r = redis.Redis(host='localhost', port=6379, decode_responses=True) + +r.set("amir", "healthy") +r.set("ali", "sick") +r.set("reza", "dead") + +print("Set key-value pairs") + +channel = "task_updates" +for i in range(3): + message = f"Task update {i+1}: Processing..." + r.publish(channel, message) + print(f"Published: {message}") + time.sleep(1) \ No newline at end of file diff --git a/MohamadMahdiReisi/Problem3_Celery/.env b/MohamadMahdiReisi/Problem3_Celery/.env new file mode 100644 index 00000000..62fa983e --- /dev/null +++ b/MohamadMahdiReisi/Problem3_Celery/.env @@ -0,0 +1,5 @@ +# .env +REDIS_URL=redis://localhost:6379/0 +DEFAULT_IMAGE=ctg_postgre +DB_PASSWORD=barari +MAX_CONTAINERS=10 \ No newline at end of file diff --git a/MohamadMahdiReisi/Problem3_Celery/README.md b/MohamadMahdiReisi/Problem3_Celery/README.md new file mode 100644 index 00000000..31a6a232 --- /dev/null +++ b/MohamadMahdiReisi/Problem3_Celery/README.md @@ -0,0 +1,113 @@ +# Problem 3: Celery-Based Docker Container Management + +This guide explains how to set up and use the Celery-based system for managing CTF challenge containers in the `Problem3_Celery` folder. + +--- + +## Table of Contents + +- [Overview](#overview) +- [Prerequisites](#prerequisites) +- [Setup Instructions](#setup-instructions) +- [Configuration](#configuration) +- [Running the System](#running-the-system) +- [Usage](#usage) +- [Troubleshooting](#troubleshooting) +- [Cleanup](#cleanup) + +--- + +## Overview + +This solution uses **Celery** (with Redis as a broker) and the **Docker SDK for Python** to start and stop challenge containers asynchronously. +You can trigger container operations by running simple Python scripts. + +--- + +## Prerequisites + +- **Linux** OS +- **Docker** installed and running +- **Python 3.6+** +- **pip** (Python package manager) +- **Redis** server (can be run via Docker) + +--- + +## Setup Instructions + +1. **Install Python dependencies:** + + ```bash + pip install celery docker python-dotenv + ``` + +2. **Start a Redis server** (if not already running): + + ```bash + ddocker run -d -p 6379:6379 --name ctf_redis_db -e REDIS_PASSWORD=12345678 redis:alpine + (i did use the redis container which i create in question 2) + ``` + +--- + +## Configuration + +- Edit the `.env` file to set your desired configuration (Redis URL, default image, DB password, etc.). +- Make sure the Docker network specified in `.env` (default: `ctf-network`) exists, or create it: + + ```bash + docker network create ctf-network + ``` + +--- + +## Running the System + +1. **Start the Celery worker:** + + ```bash + celery -A conf worker --loglevel=info + ``` + + - If you see permission errors, make sure you are in the `docker` group or run with `sudo` (not recommended for regular use). + +2. **Start a challenge container:** + + In a new terminal (with the same environment): + + ```bash + python3 start.py + ``` + +3. **Stop a challenge container:** + + In a new terminal: + + ```bash + python3 end.py + ``` + +--- + +## Usage + +- **start.py**: Triggers a Celery task to start a new challenge container. +- **end.py**: Triggers a Celery task to stop and remove the challenge container. + +Check the output of the Celery worker terminal for task results and error messages. + +**desierd output** + + +--- + + +## Notes + +- You can adjust the maximum number of containers, image name, and other settings in the `.env` file. +- For production, consider securing your Redis instance and using more robust error handling. + +--- + + diff --git a/MohamadMahdiReisi/Problem3_Celery/__pycache__/conf.cpython-310.pyc b/MohamadMahdiReisi/Problem3_Celery/__pycache__/conf.cpython-310.pyc new file mode 100644 index 00000000..11bd2da1 Binary files /dev/null and b/MohamadMahdiReisi/Problem3_Celery/__pycache__/conf.cpython-310.pyc differ diff --git a/MohamadMahdiReisi/Problem3_Celery/conf.py b/MohamadMahdiReisi/Problem3_Celery/conf.py new file mode 100644 index 00000000..bd618870 --- /dev/null +++ b/MohamadMahdiReisi/Problem3_Celery/conf.py @@ -0,0 +1,66 @@ +import os +import docker +from celery import Celery +from dotenv import load_dotenv + +load_dotenv() + +app = Celery('container_management', + broker=os.getenv('REDIS_URL', 'redis://localhost:6379/0'), + broker_connection_retry_on_startup=True) + +client = docker.from_env() + +DEFAULT_IMAGE = os.getenv('DEFAULT_IMAGE', 'docker.arvancloud.ir/postgres:latest') +MAX_CONTAINERS = int(os.getenv('MAX_CONTAINERS', '5')) + +@app.task +def start_container(challenge_name): + """Start a Docker container for a CTF challenge with safety checks""" + try: + print('chanllenge name is ', challenge_name) + existing = client.containers.list(all=True) + if len(existing) >= MAX_CONTAINERS: + raise RuntimeError("Maximum container limit reached") + + container_config = { + "image": DEFAULT_IMAGE, + "environment": {"POSTGRES_PASSWORD": os.getenv('DB_PASSWORD', 'changeme')}, + "detach": True, + "auto_remove": True, + "network": os.getenv('NETWORK_NAME', 'ctf-network'), + "mem_limit": os.getenv('MEM_LIMIT', '512m') + } + + container = client.containers.run( + name=f"ctf-{challenge_name}", + **container_config + ) + + return { + "status": "success", + "container_id": container.id, + "name": container.name + } + + except docker.errors.DockerException as e: + return {"status": "error", "message": f"Docker error: {str(e)}"} + except Exception as e: + return {"status": "error", "message": f"Unexpected error: {str(e)}"} + +@app.task +def stop_container(container_name): + """Stop and clean up container with additional checks""" + try: + container = client.containers.get(container_name) + if not container.name.startswith('ctf-'): + raise PermissionError("Not authorized to stop non-CTF containers") + + container.stop() + container.remove() + return {"status": "success", "message": f"Removed {container_name}"} + + except docker.errors.NotFound: + return {"status": "error", "message": "Container not found"} + except docker.errors.APIError as e: + return {"status": "error", "message": f"API error: {str(e)}"} \ No newline at end of file diff --git a/MohamadMahdiReisi/Problem3_Celery/end.py b/MohamadMahdiReisi/Problem3_Celery/end.py new file mode 100644 index 00000000..fb63ed6e --- /dev/null +++ b/MohamadMahdiReisi/Problem3_Celery/end.py @@ -0,0 +1,2 @@ +from conf import stop_container +stop_container.delay("ctf-web-challenge-1") \ No newline at end of file diff --git a/MohamadMahdiReisi/Problem3_Celery/start.py b/MohamadMahdiReisi/Problem3_Celery/start.py new file mode 100644 index 00000000..6e3145c5 --- /dev/null +++ b/MohamadMahdiReisi/Problem3_Celery/start.py @@ -0,0 +1,2 @@ +from conf import start_container +start_container.delay("ctf_web-challenge-1") \ No newline at end of file diff --git a/MohamadMahdiReisi/Problem4 b/MohamadMahdiReisi/Problem4 new file mode 160000 index 00000000..ad756bb2 --- /dev/null +++ b/MohamadMahdiReisi/Problem4 @@ -0,0 +1 @@ +Subproject commit ad756bb214cc401b4ec181b2c05bcdd2a3162b32 diff --git a/MohamadMahdiReisi/Problem5 b/MohamadMahdiReisi/Problem5 new file mode 160000 index 00000000..ad756bb2 --- /dev/null +++ b/MohamadMahdiReisi/Problem5 @@ -0,0 +1 @@ +Subproject commit ad756bb214cc401b4ec181b2c05bcdd2a3162b32 diff --git a/MohamadMahdiReisi/README.md b/MohamadMahdiReisi/README.md deleted file mode 100644 index 5fd544e5..00000000 --- a/MohamadMahdiReisi/README.md +++ /dev/null @@ -1 +0,0 @@ -Sample diff --git a/shots/q2/Screenshot from 2025-05-12 01-45-19.png b/shots/q2/Screenshot from 2025-05-12 01-45-19.png new file mode 100644 index 00000000..88c19e9f Binary files /dev/null and b/shots/q2/Screenshot from 2025-05-12 01-45-19.png differ diff --git a/shots/q2/Screenshot from 2025-05-12 01-45-47.png b/shots/q2/Screenshot from 2025-05-12 01-45-47.png new file mode 100644 index 00000000..90a3f4ca Binary files /dev/null and b/shots/q2/Screenshot from 2025-05-12 01-45-47.png differ diff --git a/shots/q3/Screenshot from 2025-05-12 15-19-42.png b/shots/q3/Screenshot from 2025-05-12 15-19-42.png new file mode 100644 index 00000000..1a04f622 Binary files /dev/null and b/shots/q3/Screenshot from 2025-05-12 15-19-42.png differ diff --git a/shots/q3/Screenshot from 2025-05-12 15-20-27.png b/shots/q3/Screenshot from 2025-05-12 15-20-27.png new file mode 100644 index 00000000..0ad95539 Binary files /dev/null and b/shots/q3/Screenshot from 2025-05-12 15-20-27.png differ diff --git a/shots/q4/add-teams.png b/shots/q4/add-teams.png new file mode 100644 index 00000000..1c36d0c3 Binary files /dev/null and b/shots/q4/add-teams.png differ diff --git a/shots/q4/all-challenges.png b/shots/q4/all-challenges.png new file mode 100644 index 00000000..20858dbc Binary files /dev/null and b/shots/q4/all-challenges.png differ diff --git a/shots/q4/create-1.png b/shots/q4/create-1.png new file mode 100644 index 00000000..db461166 Binary files /dev/null and b/shots/q4/create-1.png differ diff --git a/shots/q4/create-2.png b/shots/q4/create-2.png new file mode 100644 index 00000000..5d134f8a Binary files /dev/null and b/shots/q4/create-2.png differ diff --git a/shots/q4/remove.png b/shots/q4/remove.png new file mode 100644 index 00000000..586fae39 Binary files /dev/null and b/shots/q4/remove.png differ