#!/usr/bin/env python """ Test script for API security. This script tests the security features of the API by attempting to access endpoints with and without proper authentication. """ import requests import argparse import logging import json # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) logger = logging.getLogger(__name__) def test_api_security(base_url): """ Test API security features. Args: base_url: Base URL of the API """ logger.info("Testing API security...") # Test health endpoint (should be accessible without authentication) logger.info("\nTesting health endpoint (public)...") health_url = f"{base_url}/health" response = requests.get(health_url) logger.info(f"Status code: {response.status_code}") if response.status_code == 200: logger.info("Success! Health endpoint is publicly accessible as expected.") else: logger.error("Error: Health endpoint should be publicly accessible.") # Test token endpoint logger.info("\nTesting token endpoint...") token_url = f"{base_url}/auth/token" # Test with invalid credentials logger.info("Testing with empty username...") response = requests.post(token_url, json={"username": "", "password": "password"}) logger.info(f"Status code: {response.status_code}") if response.status_code == 400: logger.info("Success! Token endpoint rejected empty username as expected.") else: logger.error("Error: Token endpoint should reject empty username.") # Test with valid credentials logger.info("Testing with valid username...") response = requests.post(token_url, json={"username": "admin", "password": "password"}) logger.info(f"Status code: {response.status_code}") if response.status_code == 200: token_data = response.json() access_token = token_data.get("access_token") logger.info("Success! Received valid token.") # Test protected endpoint without token logger.info("\nTesting protected endpoint without token...") patients_url = f"{base_url}/fhir/Patient" response = requests.get(patients_url) logger.info(f"Status code: {response.status_code}") if response.status_code in (401, 403): logger.info("Success! Access denied without token as expected.") else: logger.error("Error: Protected endpoint should deny access without token.") # Test protected endpoint with token logger.info("\nTesting protected endpoint with token...") headers = {"Authorization": f"Bearer {access_token}"} response = requests.get(patients_url, headers=headers) logger.info(f"Status code: {response.status_code}") if response.status_code == 200: logger.info("Success! Access granted with token as expected.") else: logger.error("Error: Protected endpoint should grant access with token.") # Test admin-only endpoint with user token logger.info("\nTesting role-based access control...") # For this POC, we use a generic endpoint that requires admin role delete_url = f"{base_url}/fhir/Patient/non-existent-id" response = requests.delete(delete_url, headers=headers) if response.status_code == 403: logger.info("Success! Regular user denied access to admin endpoint as expected.") elif response.status_code == 404: logger.info("Success! Admin user granted access to admin endpoint as expected.") else: logger.error(f"Unexpected response code: {response.status_code}") else: logger.error("Error: Could not obtain token for testing.") logger.info("\nAPI security testing completed.") if __name__ == "__main__": parser = argparse.ArgumentParser(description='Test API security') parser.add_argument('--url', default='http://localhost:8000', help='Base URL of the API') args = parser.parse_args() test_api_security(args.url)