KB CertificateManagementandCashDepositAPI 071124 1539
KB CertificateManagementandCashDepositAPI 071124 1539
Overview
This documentation provides a detailed guide for the implementation of the Certificate Management and Cash Deposit API. The project is split
into two primary modules: CertificateManager for managing certificates and private keys, and CashDepositAPI for handling deposit
functionality to a secure API. This modular structure ensures reusable and maintainable code that can be adapted to different secure API
requirements.
Purpose
The CertificateManager module is designed to manage the creation, storage, and validation of RSA private keys and self-signed SSL
certificates. These certificates are used to authenticate API clients with the Cash Deposit API and other secure endpoints, ensuring secure
communication.
Key Features
RSA Key Generation: Generates a 2048-bit RSA private key for secure signing and encryption.
Self-Signed Certificate Creation: Creates an x.509 self-signed certificate, valid for 1 year, to authenticate against the API server.
File Management: Saves both the private key and certificate to specified file paths, ensuring they are accessible for secure API requests.
Reusable: Can be utilized by any other secure API requiring certificate-based authentication.
Code Walkthrough
1. Initialization: The CertificateManager class is initialized with file paths for the certificate and private key.
2. Key and Certificate Creation:
Generates an RSA private key with a public exponent of 65537 and key size of 2048 bits.
Saves the key to a PEM file for use with other APIs.
Creates a self-signed certificate with metadata like country, state, locality, organization, and common name.
3. Ensure Certificate and Key: Checks if the specified files exist, and if not, generates the required key and certificate.
Example Usage
cert_path = "cert.pem"
key_path = "key.pem"
cert_manager = CertificateManager(cert_path, key_path)
cert_manager.ensure_cert_and_key()
This snippet initializes the CertificateManager and ensures the certificate and key are available.
Purpose
The CashDepositAPI module handles interactions with the Cash Deposit API, specifically making secure deposit transactions. It uses the
certificate and private key generated by CertificateManager to authenticate the client.
Key Features
Secure API Requests: Uses the x.509 certificate and RSA key for secure communication with the deposit server.
Deposit Handling: Manages deposit transactions with the API, including details like the amount, currency, transaction number, and optional
fields like tenant ID and deposit date.
Error Handling: Captures and logs any request-related errors for troubleshooting.
Code Walkthrough
1. Deposit Data Class: The Deposit data class is used to represent the deposit request details, such as id, tenant, amount, currency,
and transaction number.
2. Deposit API Implementation:
The CashDepositAPI class is initialized with paths to the certificate and key files.
Constructs the JSON payload with mandatory and optional fields.
Sends a POST request to the deposit endpoint, securely attaching the certificate and private key.
Handles responses and potential errors.
Example Usage
cert_path = "cert.pem"
key_path = "key.pem"
deposit_api = CashDepositAPI(cert_path, key_path)
test_deposit = Deposit(
id="123",
tenant="ABC",
amount=20000,
currency="EUR",
trans_nr=4,
deposit_date="2013-12-24 20:00:00"
)
result = deposit_api.make_deposit(test_deposit)
if result.new_balance is not None:
print(f"Deposit successful! New balance: {result.new_balance} {result.
currency_code}")
else:
print("Deposit failed.")
This snippet initializes the CashDepositAPI and makes a deposit request using the provided deposit details.
3. Typical Workflow
1. Certificate Generation:
First, generate the certificate and key using CertificateManager.
This ensures that secure communication is established before interacting with any API.
2. Making a Deposit:
Use CashDepositAPI to initialize the deposit client.
Provide the necessary details for the deposit (e.g., amount, tenant, transaction number).
Handle the response, checking for errors or successful deposits.
4. Advantages of Modularization
Reusability: The CertificateManager is now decoupled from any specific API, allowing reuse for different secure API integrations.
Maintainability: Updates to the certificate generation process can be made in a single module, automatically benefiting all API clients.
Security: Centralized management of keys and certificates enhances security by ensuring a consistent approach to encryption and secure
communications.
5. Future Extensions
Extend CertificateManager: Add support for generating certificates with longer validity or certificates signed by an internal CA for production
environments.
Add Unit Tests: Implement unit tests for both CertificateManager and CashDepositAPI to ensure the modules are functioning
correctly under different scenarios.
Dockerize: Package the entire system in a Docker container for easy deployment across environments, ensuring consistency in how
certificates are managed and APIs are consumed.
6. File Structure
# certificate_manager.py
import os
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import hashes
from cryptography.x509 import NameOID
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from datetime import datetime, timedelta
class CertificateManager:
"""
Manages the creation of RSA keys and self-signed certificates.
This is crucial to ensure secure communications with APIs using x.509
certificates.
"""
def __init__(self, cert_path: str, key_path: str):
self.cert_path = cert_path
self.key_path = key_path
def create_key_and_cert(self):
"""Create an RSA private key and a self-signed certificate for
secure API requests."""
def ensure_cert_and_key(self):
"""Ensure that both certificate and key files exist, or create
them if they don't."""
if not os.path.exists(self.cert_path) or not os.path.exists(self.
key_path):
print("Creating new certificate and key...")
self.create_key_and_cert() # Create key and certificate if
they do not exist
print("Certificate and key created successfully.")
else:
print("Certificate and key already exist.")
# cash_deposit_api.py
import requests
from dataclasses import dataclass
from typing import Optional
from certificate_manager import CertificateManager # Import the
Certificate Manager
@dataclass
class Deposit:
# Represents a deposit request
id: str # Unique identifier to assign the deposit to a
driver/entity
tenant: Optional[str] # Optional tenant identifier (useful in multi-
tenant environments)
amount: int # Deposit amount in cents, e.g., 20000 for
€200.00
currency: str # Currency code, e.g., "EUR"
trans_nr: int # Unique transaction number for this deposit
deposit_date: Optional[str] = None # Optional: Date of the deposit (e.
g., "2013-12-24 20:00:00")
@dataclass
class DepositResponse:
# Represents a response to a deposit request
new_balance: Optional[int] = None # The new account balance after
the deposit
currency_code: Optional[str] = None # The currency code of the
balance (e.g., "EUR")
account_trans_nr: Optional[int] = None # The account transaction
number provided in the response
class CashDepositAPI:
"""
Handles the communication with the Cash Deposit API.
The API uses a secure x.509 certificate for authentication, which must
be supplied in each request.
"""
base_url = "https://fare-server:8443/deposit-payment" # Replace with
the actual server address
headers = {
"Content-Type": "application/vnd.de.ivu.fare.deposit.payment.
deposit.v1.0+json" # Media type for the API request
}
try:
# Send the POST request to the deposit API endpoint
response = requests.post(
url, json=payload, headers=self.headers,
cert=(self.cert_path, self.key_path), verify=True #
Attach certificate and key for SSL verification
)
response.raise_for_status() # Raises an HTTPError if the
response code is 4xx or 5xx
except requests.exceptions.RequestException as e:
# Log any request-related errors
print(f"Error making deposit: {e}")
return DepositResponse() # Return an empty response object on
failure
# Ensure that the certificate and private key are available for secure
communications
cert_manager = CertificateManager(cert_path, key_path)
cert_manager.ensure_cert_and_key()