### Install uv or pip Source: https://github.com/alanbato/tlacacoca/blob/main/docs/quickstart.md Instructions for installing the 'uv' package manager or using pip to install Tlacacoca. ```bash curl -LsSf https://astral.sh/uv/install.sh | sh # Add to your project uv add tlacacoca # Or with pip pip install tlacacoca ``` -------------------------------- ### Install Tlacacoca from Source Source: https://github.com/alanbato/tlacacoca/blob/main/docs/installation.md Guides users on installing Tlacacoca directly from its source repository using git and uv. This method is intended for developers and provides the latest development version. ```bash # Clone the repository git clone https://github.com/alanbato/tlacacoca.git cd tlacacoca # Install with development dependencies uv sync ``` -------------------------------- ### Create Server TLS Contexts in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/quickstart.md Shows how to create TLS server contexts using Tlacacoca. Examples include a basic server setup and a server configured to request client certificates with trusted CAs. ```python from tlacacoca import create_server_context # Basic server context = create_server_context( certfile="server.pem", keyfile="server-key.pem" ) # Server requesting client certificates context = create_server_context( certfile="server.pem", keyfile="server-key.pem", request_client_cert=True, client_ca_certs=["trusted_client1.pem", "trusted_client2.pem"] ) ``` -------------------------------- ### Setup Pre-commit Hooks and Verify Setup Source: https://github.com/alanbato/tlacacoca/blob/main/CONTRIBUTING.md This snippet demonstrates how to install and use pre-commit hooks for automatic code quality checks and verification of your development setup by running tests and linting. ```bash # Set up pre-commit hooks for automatic code quality checks uv run pre-commit install # Run the test suite uv run pytest # Run linting uv run ruff check src/ tests/ # Run type checking uv run ty check src/ ``` -------------------------------- ### Install Tlacacoca Package Source: https://github.com/alanbato/tlacacoca/blob/main/docs/installation.md Checks if tlacacoca is installed and installs it if not found. It supports both 'uv' and 'pip' as package managers. ```shell pip list | grep tlacacoca # If not found, install it uv add tlacacoca # or: pip install tlacacoca ``` -------------------------------- ### Privacy-Preserving IP Logging Setup in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/quickstart.md Shows the initial import for privacy-preserving IP logging. This snippet likely precedes further configuration or usage of the `hash_ip_processor` with a logging library like `structlog`. ```python from tlacacoca import hash_ip_processor import structlog ``` -------------------------------- ### Install Tlacacoca with pip Source: https://github.com/alanbato/tlacacoca/blob/main/docs/installation.md Shows how to install Tlacacoca using pip, emphasizing the use of a virtual environment for better project isolation. Includes activation commands for different operating systems. ```bash # In a virtual environment (recommended) python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate pip install tlacacoca ``` -------------------------------- ### Install uv Package Manager Source: https://github.com/alanbato/tlacacoca/blob/main/docs/installation.md Provides commands to install the 'uv' package manager, recommended for faster Python package installations. Includes methods for Linux/macOS, Windows, and installation via pip. ```bash curl -LsSf https://astral.sh/uv/install.sh | sh ``` ```powershell powershell -c "irm https://astral.sh/uv/install.ps1 | iex" ``` ```bash pip install uv ``` -------------------------------- ### Generate Self-Signed Certificates in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/quickstart.md Illustrates generating self-signed TLS certificates using Tlacacoca. Includes examples for basic localhost certificates and generating certificates with custom options like hostname, key size, validity, and organization. ```python from pathlib import Path from tlacacoca import generate_self_signed_cert # Generate certificate for localhost cert_pem, key_pem = generate_self_signed_cert("localhost") # Save to files Path("cert.pem").write_bytes(cert_pem) Path("key.pem").write_bytes(key_pem) # Generate with custom options cert_pem, key_pem = generate_self_signed_cert( hostname="example.com", key_size=4096, valid_days=365, organization="My Organization" ) ``` -------------------------------- ### Create Client TLS Contexts in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/quickstart.md Demonstrates how to create TLS client contexts using Tlacacoca. Covers development/testing with default settings, production with certificate verification, and client certificate authentication. ```python import ssl from tlacacoca import create_client_context # Development/testing - accept all certificates context = create_client_context() # Production - with certificate verification # (Combine with TOFU for full validation) context = create_client_context( verify_mode=ssl.CERT_REQUIRED, check_hostname=True ) # With client certificate authentication context = create_client_context( verify_mode=ssl.CERT_REQUIRED, check_hostname=True, certfile="client.pem", keyfile="client-key.pem" ) ``` -------------------------------- ### Tlacacoca Middleware Integration Example in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/how-to/logging.md Provides an example of integrating Tlacacoca logging with middleware, specifically demonstrating the use of a `RateLimiter`. It shows how to log request reception, denial, and allowance, incorporating privacy features like IP hashing. ```python from tlacacoca import ( configure_logging, get_logger, MiddlewareChain, RateLimiter, RateLimitConfig, DenialReason, ) configure_logging(level="INFO", hash_ips=True) log = get_logger("myserver") rate_limiter = RateLimiter(RateLimitConfig(capacity=10, refill_rate=1.0)) async def handle_request(url: str, client_ip: str): log.info("request_received", url=url, client_ip=client_ip) result = await rate_limiter.process_request(url, client_ip) if not result.allowed: log.warning("request_denied", url=url, client_ip=client_ip, reason=result.denial_reason, retry_after=result.retry_after ) return deny_response(result) log.info("request_allowed", url=url, client_ip=client_ip) return process_request(url) ``` -------------------------------- ### Add Tlacacoca to Project with uv Source: https://github.com/alanbato/tlacacoca/blob/main/docs/installation.md Demonstrates how to add Tlacacoca as a dependency to a new or existing Python project using the 'uv' package manager. This is the recommended installation method. ```bash # Create a new project uv init my-protocol-server cd my-protocol-server # Add tlacacoca as a dependency uv add tlacacoca ``` ```bash # Add to your existing project uv add tlacacoca ``` -------------------------------- ### Load and Inspect Certificates in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/quickstart.md Provides Python code for loading TLS certificates, getting their fingerprints (useful for TOFU), retrieving detailed information, and checking for expiration using Tlacacoca. ```python from tlacacoca import ( load_certificate, get_certificate_fingerprint, get_certificate_info, is_certificate_expired, ) # Load certificate cert = load_certificate(Path("cert.pem")) # Get fingerprint (for TOFU) fingerprint = get_certificate_fingerprint(cert) print(f"SHA-256: {fingerprint}") # Get detailed information info = get_certificate_info(cert) print(f"Subject: {info['subject']}") print(f"Valid until: {info['not_after']}") # Check expiration if is_certificate_expired(cert): print("Certificate has expired!") ``` -------------------------------- ### Install Tlacacoca Pre-commit Hooks Source: https://github.com/alanbato/tlacacoca/blob/main/docs/installation.md Instructions to install pre-commit hooks for Tlacacoca development. These hooks automate code quality checks before each commit, helping maintain code consistency. ```bash uv run pre-commit install ``` -------------------------------- ### Integrate Tlacacoca Middleware into a TLS Server (Python) Source: https://github.com/alanbato/tlacacoca/blob/main/docs/quickstart.md Demonstrates a full integration of Tlacacoca into a Python asyncio TLS server. It includes TLS context creation, middleware setup (Access Control and Rate Limiter), request handling, and logging. ```python import asyncio import ssl from pathlib import Path from tlacacoca import ( create_server_context, generate_self_signed_cert, MiddlewareChain, RateLimiter, RateLimitConfig, AccessControl, AccessControlConfig, DenialReason, configure_logging, get_logger, ) # Configure logging configure_logging(level="INFO", hash_ips=True) log = get_logger("myserver") # Generate certificates (in production, use proper certs) cert_pem, key_pem = generate_self_signed_cert("localhost") Path("cert.pem").write_bytes(cert_pem) Path("key.pem").write_bytes(key_pem) # Create TLS context ssl_context = create_server_context("cert.pem", "key.pem") # Configure middleware middleware = MiddlewareChain([ AccessControl(AccessControlConfig(default_allow=True)), RateLimiter(RateLimitConfig(capacity=10, refill_rate=1.0)), ]) async def handle_client(reader, writer): """Handle a client connection.""" # Get client IP peername = writer.get_extra_info('peername') client_ip = peername[0] if peername else "unknown" try: # Read request data = await reader.readline() url = data.decode().strip() log.info("request_received", url=url, client_ip=client_ip) # Process through middleware result = await middleware.process_request(url, client_ip) if not result.allowed: # Send protocol-specific denial response response = f"Error: {result.denial_reason}\r\n" writer.write(response.encode()) log.warning("request_denied", reason=result.denial_reason, client_ip=client_ip) else: # Handle request response = "20 text/plain\r\nHello, World!\r\n" writer.write(response.encode()) log.info("request_handled", url=url, client_ip=client_ip) except Exception as e: log.error("request_error", error=str(e), client_ip=client_ip) finally: writer.close() await writer.wait_closed() async def main(): server = await asyncio.start_server( handle_client, 'localhost', 1965, ssl=ssl_context ) log.info("server_started", host="localhost", port=1965) async with server: await server.serve_forever() if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Basic Logging Setup in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/how-to/logging.md Demonstrates the fundamental steps to configure Tlacacoca logging, including setting the logging level and obtaining a logger instance. It shows how to log events at various levels (INFO, DEBUG, WARNING, ERROR) with associated context. ```python from tlacacoca import configure_logging, get_logger # Basic configuration configure_logging(level="INFO") # Get a logger log = get_logger("myapp.server") # Log events log.info("server_started", host="localhost", port=1965) log.debug("connection_received", client_ip="192.168.1.100") log.warning("rate_limited", client_ip="203.0.113.50") log.error("connection_failed", error="timeout") ``` -------------------------------- ### Complete Asynchronous Server with Middleware (Python) Source: https://github.com/alanbato/tlacacoca/blob/main/docs/how-to/logging.md This example demonstrates how to set up a complete asynchronous server using tlacacoca. It includes logging configuration, middleware for access control and rate limiting, and handles client connections by processing requests and enforcing security policies. The server uses TLS/SSL and listens on a specified host and port. ```python import asyncio from tlacacoca import ( configure_logging, get_logger, create_server_context, MiddlewareChain, RateLimiter, RateLimitConfig, AccessControl, AccessControlConfig, ) # Configure logging configure_logging(level="INFO", format="json", hash_ips=True) log = get_logger("myserver") # Create middleware middleware = MiddlewareChain([ AccessControl(AccessControlConfig(default_allow=True)), RateLimiter(RateLimitConfig(capacity=10, refill_rate=1.0)), ]) async def handle_client(reader, writer): peername = writer.get_extra_info('peername') client_ip = peername[0] if peername else "unknown" # Bind client IP to logger for this connection conn_log = log.bind(client_ip=client_ip) try: data = await reader.readline() url = data.decode().strip() conn_log.info("request_received", url=url) result = await middleware.process_request(url, client_ip) if not result.allowed: conn_log.warning("request_denied", reason=result.denial_reason) writer.write(b"Error\r\n") else: conn_log.info("request_processed", url=url, status=20) writer.write(b"20 text/plain\r\nOK\r\n") except Exception as e: conn_log.error("request_failed", error=str(e)) finally: writer.close() await writer.wait_closed() conn_log.debug("connection_closed") async def main(): ssl_context = create_server_context("cert.pem", "key.pem") server = await asyncio.start_server( handle_client, 'localhost', 1965, ssl=ssl_context ) log.info("server_started", host="localhost", port=1965) async with server: await server.serve_forever() asyncio.run(main()) ``` -------------------------------- ### Check Python Version Source: https://github.com/alanbato/tlacacoca/blob/main/docs/installation.md Verifies if the installed Python version meets the minimum requirement of 3.10. ```bash python --version ``` -------------------------------- ### Logging Log Levels Examples (Python) Source: https://github.com/alanbato/tlacacoca/blob/main/docs/how-to/logging.md This snippet illustrates the usage of different log levels provided by the tlacacoca logging utility. It shows examples for DEBUG, INFO, WARNING, ERROR, and CRITICAL levels, demonstrating how to log specific events and diagnostic information. This helps in understanding how to effectively use log levels for different scenarios. ```python # DEBUG: Detailed diagnostic information log.debug("parsing_request", raw_bytes=len(data)) # INFO: Normal operation events log.info("request_processed", url=url, status=20) # WARNING: Unexpected but handled log.warning("rate_limited", client_ip=ip, retry_after=30) # ERROR: Operation failures log.error("database_connection_failed", error=str(e)) # CRITICAL: System-level failures log.critical("certificate_expired", cert_path=path) ``` -------------------------------- ### Configuring Log Levels in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/how-to/logging.md Illustrates how to set different logging verbosity levels using `configure_logging`. It shows examples for development (DEBUG) and production (WARNING) environments, highlighting the impact on the detail of logged messages. ```python # Development - verbose logging configure_logging(level="DEBUG") # Production - only warnings and errors configure_logging(level="WARNING") ``` -------------------------------- ### Install Tlacacoca Library or from Source Source: https://github.com/alanbato/tlacacoca/blob/main/README.md Installs the tlacacoca library using uv or sets up the project from source for development by cloning the repository and synchronizing dependencies. ```bash # As a library uv add tlacacoca # From source (for development) git clone https://github.com/alanbato/tlacacoca.git cd tlacacoca && uv sync ``` -------------------------------- ### Run Tlacacoca Quick Test Source: https://github.com/alanbato/tlacacoca/blob/main/docs/installation.md Executes a test script that generates a self-signed certificate, saves and loads it, calculates its fingerprint, and creates a TLS client context. This verifies core functionalities of Tlacacoca. ```python from tlacacoca import ( create_client_context, generate_self_signed_cert, get_certificate_fingerprint, load_certificate, ) from pathlib import Path import tempfile # Generate a test certificate cert_pem, key_pem = generate_self_signed_cert("localhost") print(f"Generated certificate: {len(cert_pem)} bytes") # Save and load certificate with tempfile.NamedTemporaryFile(suffix=".pem", delete=False) as f: f.write(cert_pem) cert_path = Path(f.name) cert = load_certificate(cert_path) fingerprint = get_certificate_fingerprint(cert) print(f"Certificate fingerprint: {fingerprint[:32]}...") # Create TLS context context = create_client_context() print(f"TLS context created: {context.minimum_version}") ``` -------------------------------- ### Manage TOFU Known Hosts in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/quickstart.md Shows how to manage known hosts within the TOFU database using Tlacacoca. This includes listing all known hosts, revoking trust for a specific host, and exporting/importing the TOFU database. ```python async def manage_tofu(): async with TOFUDatabase(app_name="myapp") as tofu: # List all known hosts hosts = await tofu.list_hosts() for host in hosts: print(f"{host['hostname']}:{host['port']}") # Revoke trust for a host await tofu.revoke("old-server.com", 1965) # Export database for backup await tofu.export_toml(Path("tofu-backup.toml")) # Import from backup await tofu.import_toml(Path("tofu-backup.toml")) ``` -------------------------------- ### Verify Tlacacoca Import Source: https://github.com/alanbato/tlacacoca/blob/main/docs/installation.md A Python snippet to verify the Tlacacoca installation by importing the library and printing its available components. This helps confirm that the package has been correctly installed and is accessible. ```python # In a Python shell or script import tlacacoca # Check available components print(dir(tlacacoca)) ``` -------------------------------- ### Standalone Token Bucket Implementation in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/quickstart.md Shows how to use the `TokenBucket` class for custom rate limiting logic. It allows checking if a request can be consumed from the bucket and retrieves the current token count. ```python from tlacacoca import TokenBucket # Create bucket bucket = TokenBucket(capacity=10, refill_rate=1.0) # Check if request is allowed if bucket.consume(): # Request allowed pass else: # Request denied - bucket empty pass # Get current token count tokens = bucket.tokens ``` -------------------------------- ### Complete TLS Server Example with Certificate Authentication (Python) Source: https://github.com/alanbato/tlacacoca/blob/main/docs/how-to/client-certificates.md This Python example sets up a complete TLS server using `asyncio` and `tlacacoca`. It configures TLS context to request client certificates, integrates certificate authentication middleware for specific paths, and handles incoming client connections. The server listens on localhost:1965 and responds to requests, enforcing certificate checks for the /private/ path. ```python import asyncio from tlacacoca import ( create_server_context, get_certificate_fingerprint, MiddlewareChain, CertificateAuth, CertificateAuthConfig, CertificateAuthPathRule, DenialReason, ) from cryptography import x509 # Configure certificate authentication cert_config = CertificateAuthConfig( rules=[ CertificateAuthPathRule( path_prefix="/private/", require_cert=True, allowed_fingerprints=[ "sha256:abc123...", "sha256:def456...", ] ), ] ) cert_auth = CertificateAuth(cert_config) # Create TLS context with client cert support ssl_context = create_server_context( certfile="server.pem", keyfile="server.key", request_client_cert=True, client_ca_certs=["client1.pem", "client2.pem"] ) async def handle_client(reader, writer): # Get client info peername = writer.get_extra_info('peername') client_ip = peername[0] if peername else "unknown" # Get client certificate fingerprint ssl_object = writer.get_extra_info('ssl_object') cert_fingerprint = None if ssl_object: cert_der = ssl_object.getpeercert(binary_form=True) if cert_der: cert = x509.load_der_x509_certificate(cert_der) cert_fingerprint = get_certificate_fingerprint(cert) try: # Read request data = await reader.readline() url = data.decode().strip() # Check certificate authentication result = await cert_auth.process_request(url, client_ip, cert_fingerprint) if not result.allowed: if result.denial_reason == DenialReason.CERT_REQUIRED: writer.write(b"60 Client certificate required\r\n") elif result.denial_reason == DenialReason.CERT_NOT_AUTHORIZED: writer.write(b"61 Certificate not authorized\r\n") else: # Process request writer.write(b"20 text/plain\r\nWelcome!\r\n") finally: writer.close() await writer.wait_closed() async def main(): server = await asyncio.start_server( handle_client, 'localhost', 1965, ssl=ssl_context ) async with server: await server.serve_forever() asyncio.run(main()) ``` -------------------------------- ### Configure Console Output Format in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/how-to/logging.md Demonstrates configuring Tlacacoca logging for a human-readable, colored console output format, ideal for development environments. An example log message is shown with its console representation. ```python configure_logging(level="DEBUG", format="console") log = get_logger("myapp") log.info("request_received", url="/index.gmi", status=20) ``` -------------------------------- ### Upgrade Tlacacoca Package Source: https://github.com/alanbato/tlacacoca/blob/main/docs/installation.md Upgrades the tlacacoca package to the latest version using 'uv' or 'pip'. Also includes instructions for upgrading from source by pulling the latest changes and syncing dependencies. ```shell uv add tlacacoca --upgrade ``` ```shell pip install --upgrade tlacacoca ``` ```shell cd tlacacoca git pull origin main uv sync ``` -------------------------------- ### Basic TOFU Certificate Validation in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/quickstart.md Demonstrates a basic Trust-On-First-Use (TOFU) certificate validation workflow in Python using Tlacacoca's TOFUDatabase. It covers checking known hosts, verifying fingerprints, and trusting new certificates on the first connection. ```python import asyncio from tlacacoca import TOFUDatabase, CertificateChangedError async def verify_server_certificate(hostname: str, port: int, fingerprint: str): """Verify a server's certificate using TOFU.""" async with TOFUDatabase(app_name="myapp") as tofu: # Check if we know this host if await tofu.is_known(hostname, port): # Verify fingerprint matches stored = await tofu.get_fingerprint(hostname, port) if stored != fingerprint: raise CertificateChangedError( hostname, port, stored, fingerprint ) print(f"Certificate verified for {hostname}:{port}") else: # First connection - trust and store await tofu.trust(hostname, port, fingerprint) print(f"First connection to {hostname}:{port} - certificate trusted") # Use it asyncio.run(verify_server_certificate("example.com", 1965, "sha256:abc123...")) ``` -------------------------------- ### Basic Rate Limiting with Token Bucket in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/quickstart.md Demonstrates how to use the RateLimiter class for token bucket rate limiting. It configures capacity, refill rate, and retry-after periods. The `process_request` method checks if a request is allowed and returns a denial message if not. ```python from tlacacoca import RateLimiter, RateLimitConfig, DenialReason # Configure rate limiter config = RateLimitConfig( capacity=10, # Burst size refill_rate=1.0, # Tokens per second retry_after=30, # Seconds to wait when limited ) # Create rate limiter rate_limiter = RateLimiter(config) # Process a request async def handle_request(client_ip: str, url: str): result = await rate_limiter.process_request(url, client_ip) if not result.allowed: # Map to protocol-specific response # Gemini: "44 SLOW DOWN. Retry after 30 seconds\r\n" # Scroll: "44 SLOW_DOWN 30\r\n" return f"Rate limited. Retry after {result.retry_after} seconds" # Handle request normally return "OK" ``` -------------------------------- ### Clone Repository and Install Dependencies Source: https://github.com/alanbato/tlacacoca/blob/main/CONTRIBUTING.md This snippet shows how to clone the Tlacacoca repository and install its dependencies using 'uv'. Ensure you have Git and Python 3.10+ installed. ```bash git clone https://github.com/YOUR_USERNAME/tlacacoca.git cd tlacacoca # Install all dependencies including dev dependencies uv sync ``` -------------------------------- ### Python Type Hinting Example Source: https://github.com/alanbato/tlacacoca/blob/main/CONTRIBUTING.md This Python snippet demonstrates the correct use of type hints for function signatures, following PEP 8 guidelines. It shows a 'good' example with type hints and a 'bad' example missing them. ```python # Good def get_fingerprint(cert: bytes, algorithm: str = "sha256") -> str: ... # Bad - missing type hints def get_fingerprint(cert, algorithm="sha256"): ... ``` -------------------------------- ### Lazy Formatting for Expensive Computations (Python) Source: https://github.com/alanbato/tlacacoca/blob/main/docs/how-to/logging.md This example demonstrates a performance best practice in logging: using lazy formatting for expensive computations. It shows the difference between a good approach (using a lambda function) where the computation is only performed if the log level is enabled, and a bad approach where the computation is always executed, regardless of the log level. ```python # Good - only computed if DEBUG level is enabled log.debug("computed_value", result=lambda: expensive_computation()) # Bad - always computed log.debug("computed_value", result=expensive_computation()) ``` -------------------------------- ### Common IPv4 CIDR Notation Examples Source: https://github.com/alanbato/tlacacoca/blob/main/docs/how-to/access-control.md Provides common examples of IPv4 addresses and networks represented using CIDR notation, including single IPs, /24, /16, /8 networks, and the localhost range. These are used for configuring access control lists. ```text # Single IP address "192.168.1.50/32" # or just "192.168.1.50" # /24 network (256 addresses) "192.168.1.0/24" # 192.168.1.0 - 192.168.1.255 # /16 network (65,536 addresses) "10.0.0.0/16" # 10.0.0.0 - 10.0.255.255 # /8 network (16,777,216 addresses) "10.0.0.0/8" # 10.0.0.0 - 10.255.255.255 # Localhost range "127.0.0.0/8" # 127.0.0.0 - 127.255.255.255 ``` -------------------------------- ### Bash: Install Tlacacoca Package Source: https://github.com/alanbato/tlacacoca/blob/main/docs/index.md This snippet provides instructions for installing the tlacacoca library using common package managers like `uv` and `pip`. It assumes a Python 3.10 or higher environment. ```bash # Add to your project uv add tlacacoca # Or with pip pip install tlacacoca ``` -------------------------------- ### Python Docstring Example (Google Style) Source: https://github.com/alanbato/tlacacoca/blob/main/CONTRIBUTING.md This Python snippet illustrates the Google style for docstrings, which is required for all public classes, methods, and functions in the Tlacacoca project. It includes sections for arguments, return values, raised exceptions, and an example. ```python def verify_certificate( hostname: str, port: int, fingerprint: str, ) -> bool: """Verify a certificate fingerprint against stored value. Args: hostname: The server hostname. port: The server port. fingerprint: SHA-256 fingerprint to verify. Returns: True if fingerprint matches stored value, False otherwise. Raises: CertificateChangedError: If fingerprint doesn't match stored value. Example: >>> db = TOFUDatabase() >>> db.verify_certificate("example.com", 1965, fingerprint) True """ ... ``` -------------------------------- ### Integrate Custom Middleware with MiddlewareChain in Python Source: https://context7.com/alanbato/tlacacoca/llms.txt Demonstrates how to use the custom MaintenanceMiddleware within a Tlacacoca MiddlewareChain. This example shows the instantiation of the middleware with configuration and its inclusion in a chain for processing requests. ```python # Use custom middleware from tlacacoca import MiddlewareChain maintenance_config = MaintenanceConfig( enabled=True, allowed_ips=["192.168.1.1"] ) chain = MiddlewareChain([ MaintenanceMiddleware(maintenance_config), # ... other middleware ]) result = await chain.process_request("gemini://example.com/", "192.168.1.100") if not result.allowed: print(f"Access denied: {result.denial_reason}") ``` -------------------------------- ### Install Cryptography Build Dependencies Source: https://github.com/alanbato/tlacacoca/blob/main/docs/installation.md Installs necessary build dependencies for the 'cryptography' Python package on Debian/Ubuntu, Fedora/RHEL, and macOS systems to resolve build errors during installation. ```shell sudo apt-get install build-essential libssl-dev libffi-dev python3-dev ``` ```shell sudo dnf install gcc openssl-devel libffi-devel python3-devel ``` ```shell brew install openssl ``` -------------------------------- ### Tlacacoca Development Setup and Testing Source: https://github.com/alanbato/tlacacoca/blob/main/README.md Provides commands for setting up the Tlacacoca development environment by cloning the repository and synchronizing dependencies using `uv sync`. It also includes the command to run the project's tests using `pytest`. ```bash # Setup git clone https://github.com/alanbato/tlacacoca.git cd tlacacoca && uv sync # Test uv run pytest ``` -------------------------------- ### TOFU: Verify and Manage Certificates and Hosts Source: https://context7.com/alanbato/tlacacoca/llms.txt Demonstrates how to verify TLS certificates on first connection using the TOFU (Trust On First Use) mechanism, list known hosts, retrieve host information, revoke hosts, and manage the TOFU database by exporting to and importing from TOML files. ```python import tofu from pathlib import Path # Assuming 'cert' is a valid certificate object # cert = ... # Verify certificate on subsequent connections is_valid, message = tofu.verify("example.com", 1965, cert) if not is_valid: print(f"Certificate verification failed: {message}") if message == "changed": print("WARNING: Certificate has changed - possible MITM attack!") # List all known hosts hosts = tofu.list_hosts() for host in hosts: print(f"{host['hostname']}:{host['port']} - {host['fingerprint']}") # Get specific host information info = tofu.get_host_info("example.com", 1965) if info: print(f"First seen: {info['first_seen']}") print(f"Last seen: {info['last_seen']}") # Revoke a specific host if tofu.revoke("example.com", 1965): print("Host removed from TOFU database") # Export TOFU database to TOML count = tofu.export_toml(Path("tofu-backup.toml")) print(f"Exported {count} hosts") # Import TOFU database from TOML (merge with existing) added, updated, skipped = tofu.import_toml(Path("tofu-backup.toml"), merge=True) print(f"Added: {added}, Updated: {updated}, Skipped: {skipped}") ``` -------------------------------- ### Uninstall Tlacacoca Package Source: https://github.com/alanbato/tlacacoca/blob/main/docs/installation.md Provides instructions for uninstalling the tlacacoca package using 'pip' or by deleting the source code directory if installed from source. ```shell pip uninstall tlacacoca ``` ```shell rm -rf tlacacoca ``` -------------------------------- ### Run Tlacacoca Test Suite Source: https://github.com/alanbato/tlacacoca/blob/main/docs/installation.md Command to execute the Tlacacoca test suite using 'uv run pytest'. This ensures that all tests pass, confirming the library's integrity after installation or development changes. ```bash uv run pytest ``` -------------------------------- ### Example Configuration with Both Lists (Python) Source: https://github.com/alanbato/tlacacoca/blob/main/docs/how-to/access-control.md Illustrates Tlacacoca's AccessControl configuration using both an allow list and a deny list, demonstrating how the deny list takes precedence. Sets the default policy to deny. Requires Tlacacoca. ```python config = AccessControlConfig( allow_list=["192.168.1.0/24"], deny_list=["192.168.1.50"], default_allow=False ) ``` -------------------------------- ### Run Tlacacoca Code Quality Checks Source: https://github.com/alanbato/tlacacoca/blob/main/docs/installation.md Commands to perform code quality checks on Tlacacoca, including linting with Ruff, type checking with Ty, and running tests with coverage reporting. ```bash # Run linting uv run ruff check src/ tests/ # Run type checking uv run ty check src/ # Run tests with coverage uv run pytest --cov=src/tlacacoca --cov-report=html ``` -------------------------------- ### Token Bucket Rate Limiting Logic Source: https://github.com/alanbato/tlacacoca/blob/main/docs/explanation/security-model.md Illustrates the core logic of the token bucket algorithm for rate limiting. It involves tracking client IP buckets with capacity, current tokens, and a refill rate. Requests are allowed if a token is available, otherwise denied. ```plaintext Each client IP has a bucket with: - capacity: Maximum tokens (e.g., 10) - tokens: Current tokens (starts at capacity) - refill_rate: Tokens per second (e.g., 1.0) On each request: 1. Refill bucket based on time elapsed 2. If tokens >= 1: consume token, allow request 3. Else: deny request ``` -------------------------------- ### Create Access Control Middleware (Python) Source: https://github.com/alanbato/tlacacoca/blob/main/docs/how-to/access-control.md Demonstrates how to initialize Tlacacoca's AccessControl middleware with different default policies (allow all or deny all). Requires the Tlacacoca library. ```python from tlacacoca import AccessControl, AccessControlConfig # Allow all connections (default) config = AccessControlConfig(default_allow=True) # Or deny all connections by default config = AccessControlConfig(default_allow=False) # Create access control access_control = AccessControl(config) ``` -------------------------------- ### Configure Logging and Hash IPs with Tlacacoca (Python) Source: https://github.com/alanbato/tlacacoca/blob/main/docs/quickstart.md Configures Tlacacoca logging to hash IP addresses, enabling privacy-preserving tracking and analysis. This function sets the logging level and enables IP hashing. ```python from tlacacoca import configure_logging, get_logger # Configure logging configure_logging(level="INFO", hash_ips=True) log = get_logger("myserver") ``` -------------------------------- ### Structured Event Logging Example (Python) Source: https://github.com/alanbato/tlacacoca/blob/main/docs/reference/api/logging.md Demonstrates how to perform structured event logging using Tlacacoca's `configure_logging` and `get_logger`. This pattern allows for logging events with associated key-value context, useful for application monitoring and debugging. ```python from tlacacoca import configure_logging, get_logger configure_logging(level="INFO") log = get_logger("myserver") # Log events with context log.info("server_started", host="localhost", port=1965) log.info("request_received", url="/index.gmi", client_ip="192.168.1.100") log.error("upstream_failed", upstream="backend.example.com", error="timeout") ``` -------------------------------- ### Configure JSON Output Format in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/how-to/logging.md Illustrates how to configure Tlacacoca logging to output messages in a structured JSON format, suitable for log aggregation systems. It shows an example log message and its corresponding JSON output. ```python configure_logging(level="INFO", format="json") log = get_logger("myapp") log.info("request_received", url="/index.gmi", status=20) ``` -------------------------------- ### Create TOFU Database with Tlacacoca Source: https://github.com/alanbato/tlacacoca/blob/main/docs/how-to/tofu.md Demonstrates how to initialize the TOFUDatabase, which stores known host certificates for Trust-On-First-Use (TOFU) validation. You can specify an application name to create a default database location or provide a custom path for the database file. ```python from tlacacoca import TOFUDatabase # Create database with app-specific location # Database stored at ~/.myapp/tofu.db async with TOFUDatabase(app_name="myapp") as tofu: # Use TOFU database pass # Or with custom path from pathlib import Path async with TOFUDatabase(db_path=Path("/var/lib/myapp/tofu.db")) as tofu: pass ``` -------------------------------- ### IP Access Control Lists in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/quickstart.md Demonstrates configuring `AccessControl` with `allow_list` (whitelist) or `deny_list` (blacklist) modes. The `process_request` method determines if a client IP is permitted access based on the configured lists and default policy. ```python from tlacacoca import AccessControl, AccessControlConfig # Whitelist mode - only allow specific IPs config = AccessControlConfig( allow_list=["192.168.1.0/24", "10.0.0.0/8"], default_allow=False ) # Blacklist mode - allow all except specific IPs config = AccessControlConfig( deny_list=["203.0.113.0/24", "198.51.100.50"], default_allow=True ) # Create access control access_control = AccessControl(config) # Check access async def check_client_access(client_ip: str, url: str): result = await access_control.process_request(url, client_ip) if not result.allowed: # Gemini: "53 PROXY REFUSED\r\n" return "Access denied" return "Access granted" ``` -------------------------------- ### Add Context to Log Events in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/how-to/logging.md Shows how to enrich log messages with structured contextual data in Tlacacoca. It provides examples of logging events with multiple key-value pairs, such as request details, response status, and error information. ```python log = get_logger("myapp.server") # Log with structured context log.info("request_received", url="/index.gmi", client_ip="192.168.1.100", method="GET" ) log.info("response_sent", url="/index.gmi", status=20, content_type="text/gemini", bytes_sent=1234 ) log.warning("rate_limited", client_ip="203.0.113.50", retry_after=30, requests_per_minute=100 ) log.error("upstream_failed", upstream="backend.example.com", error="connection_timeout", retry_count=3 ) ``` -------------------------------- ### TLS Integration with TOFU Verification Source: https://github.com/alanbato/tlacacoca/blob/main/docs/how-to/tofu.md Demonstrates a complete example of integrating TOFU with TLS connections. It includes creating a client context, fetching a resource, verifying the certificate fingerprint against the TOFU database, and handling first-time connections or certificate changes. ```python import asyncio import ssl from tlacacoca import ( create_client_context, TOFUDatabase, CertificateChangedError, get_certificate_fingerprint, ) async def fetch_with_tofu(hostname: str, port: int, path: str): """Fetch a resource with TOFU certificate validation.""" # Create TLS context (we'll do our own verification) ssl_context = create_client_context( verify_mode=ssl.CERT_NONE, check_hostname=False ) # Connect reader, writer = await asyncio.open_connection( hostname, port, ssl=ssl_context ) try: # Get peer certificate ssl_object = writer.get_extra_info('ssl_object') cert_der = ssl_object.getpeercert(binary_form=True) # Get fingerprint from cryptography import x509 cert = x509.load_der_x509_certificate(cert_der) fingerprint = get_certificate_fingerprint(cert) # TOFU verification async with TOFUDatabase(app_name="myapp") as tofu: if await tofu.is_known(hostname, port): stored = await tofu.get_fingerprint(hostname, port) if stored != fingerprint: raise CertificateChangedError( hostname, port, stored, fingerprint ) await tofu.update_last_seen(hostname, port) else: # Prompt user for first-time trust print(f"First connection to {hostname}:{port}") print(f"Fingerprint: {fingerprint}") response = input("Trust this certificate? [y/N]: ") if response.lower() != 'y': raise ValueError("Certificate not trusted") await tofu.trust(hostname, port, fingerprint) # Send request request = f"protocol://{hostname}:{port}{path}\r\n" writer.write(request.encode()) await writer.drain() # Read response response = await reader.read() return response.decode('utf-8') finally: writer.close() await writer.wait_closed() ``` -------------------------------- ### Structured Logging Configuration in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/quickstart.md Configures structured logging using `configure_logging` with options for log level, format ('json' or 'console'), and privacy-preserving IP hashing. It then demonstrates obtaining a logger and logging structured events at different levels. ```python from tlacacoca import configure_logging, get_logger # Configure logging configure_logging( level="INFO", format="json", # or "console" for development hash_ips=True # Privacy-preserving IP hashing ) # Get a logger log = get_logger("myapp.server") # Log structured events log.info("server_started", host="localhost", port=1965) log.info("request_received", url="/index.gmi", client_ip="192.168.1.100") log.warning("rate_limited", client_ip="203.0.113.50", retry_after=30) log.error("connection_failed", error="timeout", host="upstream.example.com") ``` -------------------------------- ### Basic Tlacacoca Usage: TLS Contexts and Middleware Source: https://github.com/alanbato/tlacacoca/blob/main/README.md Demonstrates the basic usage of Tlacacoca, including creating TLS client and server contexts, setting up Trust-On-First-Use (TOFU) certificate validation, and configuring a middleware chain for access control and rate limiting. It shows how to process requests through the chain and handle denial reasons. ```python import ssl from tlacacoca import ( create_client_context, create_server_context, TOFUDatabase, RateLimiter, RateLimitConfig, AccessControl, AccessControlConfig, MiddlewareChain, ) # Create TLS contexts client_ctx = create_client_context(verify_mode=ssl.CERT_REQUIRED) server_ctx = create_server_context("cert.pem", "key.pem") # Set up TOFU certificate validation async with TOFUDatabase(app_name="myapp") as tofu: # First connection - certificate is stored await tofu.verify_or_trust("example.com", 1965, cert_fingerprint) # Subsequent connections - certificate is verified await tofu.verify_or_trust("example.com", 1965, cert_fingerprint) # Configure middleware chain rate_config = RateLimitConfig(capacity=10, refill_rate=1.0) access_config = AccessControlConfig( allow_list=["192.168.1.0/24"], default_allow=False ) chain = MiddlewareChain([ AccessControl(access_config), RateLimiter(rate_config), ]) # Process requests through middleware result = await chain.process_request( request_url="protocol://example.com/path", client_ip="192.168.1.100" ) if result.allowed: # Handle request pass else: # Map denial_reason to protocol-specific response if result.denial_reason == "rate_limit": # e.g., Gemini: "44 SLOW DOWN\r\n" pass ``` -------------------------------- ### Middleware Chain for Request Processing in Python Source: https://github.com/alanbato/tlacacoca/blob/main/docs/quickstart.md Illustrates combining multiple middleware components like `AccessControl`, `RateLimiter`, and `CertificateAuth` into a `MiddlewareChain`. The order of middleware in the chain is crucial for request processing. The `process_request` method iterates through the chain, handling denial reasons. ```python from tlacacoca import ( MiddlewareChain, RateLimiter, RateLimitConfig, AccessControl, AccessControlConfig, CertificateAuth, CertificateAuthConfig, DenialReason, ) # Configure each middleware access_config = AccessControlConfig( deny_list=["203.0.113.0/24"], default_allow=True ) rate_config = RateLimitConfig( capacity=10, refill_rate=1.0, retry_after=30 ) # Create middleware chain # Order matters: access control → rate limiting → cert auth chain = MiddlewareChain([ AccessControl(access_config), RateLimiter(rate_config), ]) # Process requests async def process_request(url: str, client_ip: str, cert_fingerprint: str = None): result = await chain.process_request(url, client_ip, cert_fingerprint) if not result.allowed: # Map denial reason to protocol-specific response match result.denial_reason: case DenialReason.ACCESS_DENIED: return "53 Access denied\r\n" case DenialReason.RATE_LIMIT: return f"44 Rate limited. Retry after {result.retry_after}s\r\n" case DenialReason.CERT_REQUIRED: return "60 Client certificate required\r\n" case DenialReason.CERT_NOT_AUTHORIZED: return "61 Certificate not authorized\r\n" case _: return "50 Server error\r\n" # Request allowed - continue processing return handle_request(url) ```