This Flask API server provides secure access to a MongoDB database and implements various security measures. This guide covers configuring variables, managing users, building and deploying the Docker image, and deploying the application to a MicroK8s cluster.
- JWT Authentication: Securely manage access using JWT tokens.
- IP Whitelisting: Restrict access to specific IP addresses.
- Blacklist: Prevents access from blacklisted IPs.
- Database Integration: Connects to a MongoDB database for data storage and retrieval.
- Middleware: Custom middleware for logging, honeypot functionality, and blacklisting.
This project focuses on API security, implementing measures directly at the application layer:
-
JWT Authentication:
- Securely manages access by issuing JWT tokens upon successful login.
- Tokens are signed with a secret key to prevent forgery.
- Tokens have an expiry time to prevent reuse.
-
IP Whitelisting and Blacklisting:
- Allows only requests from specific IP addresses listed in
whitelist.txt. - Requests from IP addresses listed in
blacklist.txtare blocked. - IP lists are dynamically refreshed to ensure up-to-date access control.
- Allows only requests from specific IP addresses listed in
-
Honeypot Middleware:
- Logs and blacklists IPs attempting to access non-existent routes.
- Provides mock credentials to these IPs, further trapping potential attackers.
-
Logging Middleware:
- Logs all incoming requests, recording their method, path, and originating IP.
- Helps track unauthorized access attempts and identify patterns.
-
Secure Data Handling:
- Database queries are secured, preventing unauthorized access.
- Passwords are securely hashed and stored, protecting against leaks and misuse.
The security measures provided by this server are implemented at the application layer. For a comprehensive security strategy, additional measures such as network-level firewalls, intrusion detection systems (IDS), and regular security audits should be considered. It's crucial to build a multi-layered security approach when deploying this server in a production environment.
First, clone the repository to your local machine and change into the project directory:
git clone https://github.com/Ilansos/flask_api_server.git
cd flask_api_server.gitInstall Docker on your system by following the instructions on the official Docker website: Install Docker
Install MicroK8s using the following command:
sudo snap install microk8s --classicEnable necessary MicroK8s addons, including DNS and the registry:
sudo microk8s enable dns registryTo ensure secure communication, create a self-signed SSL certificate:
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365This creates a 2048-bit RSA key and a self-signed certificate valid for one year. Follow the prompts to fill in the necessary details.
MicroK8s includes a built-in Docker registry where you can push your images. It is available at localhost:32000. Use this registry to manage local images. Create Docker Image
docker build -t localhost:32000/api_server:v1 .docker push localhost:32000/api_server:v1To manage sensitive information securely, store it as Kubernetes Secrets:
- Users: Store hashed passwords as key-value pairs in
secrets.yaml.
- To hash the users password run `python3 generate_hashed_password.py`
- This script will request an imput of the user password and will print the hashed password.
3- Base64 Encode the Values: Before creating the secrets, encode the values you want to store in Base64 format. For example:
echo -n "YOUR JWT_SECRET_KEY" | base64
echo -n "YOUR secret" | base64
echo -n "YOUR backend_secret" | base64
echo -n "YOUR user1 hashed password" | base64
echo -n "YOUR user2 hashed password" | base644- Define the Secret in the secrets.yaml File replacing the placeholders with the actual Base64-encoded strings:
apiVersion: v1
kind: Secret
metadata:
name: api-secrets
type: Opaque
data:
JWT_SECRET_KEY: <base64-encoded-key>
secret: <base64-encoded-secret>
backend_secret: <base64-encoded-backend-secret>
user1: <base64_encoded_hashed_password_for_user1> # Set the key <user1> with the real username
user2: <base64_encoded_hashed_password_for_user2> # Set the key <user2> with the real username- name: user1
valueFrom:
secretKeyRef:
name: api-secrets
key: user1 # Modify this with the real usernameIP Lists:
Update whitelist.txt and blacklist.txt in ip_lists.yaml with valid IP addresses for access control.
ConfigMap:
Ensure ip_lists.yaml contains valid IP addresses and apply it to the cluster.
Ensure secrets.yaml contains base64-encoded values and apply it:
kubectl apply -f secrets.yamlEnsure ip_lists.yaml is correctly configured and apply it:
kubectl apply -f ip_lists.yamlEnsure deployment.yaml references the correct Docker image and contains necessary environment variables. Apply it:
kubectl apply -f deployment.yamlExpose the server by applying service.yaml:
kubectl apply -f service.yamlTo ensure the server is functioning correctly:
Check the deployment's status with:
kubectl get podsCheck the logs of a specific pod to see request activities and potential errors:
kubectl logs <pod-name>To access the shell of the API server for direct inspection:
kubectl exec -it <pod-name> /bin/bashThis project is licensed under the MIT License - see the LICENSE file for details.