SecurityConfig.php
151 lines
| 1 | <?php |
| 2 | /** |
| 3 | * CommerceBird Security Configuration |
| 4 | * |
| 5 | * @package CommerceBird\Admin\Security |
| 6 | */ |
| 7 | |
| 8 | namespace CommerceBird\Admin\Security; |
| 9 | |
| 10 | if ( ! defined( 'ABSPATH' ) ) { |
| 11 | exit; |
| 12 | } |
| 13 | |
| 14 | final class SecurityConfig { |
| 15 | |
| 16 | /** |
| 17 | * Rate limiting configuration. |
| 18 | */ |
| 19 | const RATE_LIMIT_REQUESTS_PER_MINUTE = 60; |
| 20 | const RATE_LIMIT_REQUESTS_PER_HOUR = 300; |
| 21 | |
| 22 | /** |
| 23 | * Session and nonce configuration. |
| 24 | */ |
| 25 | const NONCE_LIFETIME = 43200; // 12 hours. |
| 26 | const SESSION_TIMEOUT = 1800; // 30 minutes. |
| 27 | |
| 28 | /** |
| 29 | * Security headers configuration. |
| 30 | */ |
| 31 | const SECURITY_HEADERS = array( |
| 32 | 'X-Content-Type-Options' => 'nosniff', |
| 33 | 'X-Frame-Options' => 'SAMEORIGIN', |
| 34 | 'X-XSS-Protection' => '1; mode=block', |
| 35 | 'Referrer-Policy' => 'strict-origin-when-cross-origin', |
| 36 | ); |
| 37 | |
| 38 | /** |
| 39 | * Allowed capabilities for different actions. |
| 40 | */ |
| 41 | const REQUIRED_CAPABILITIES = array( |
| 42 | 'subscription_get' => 'manage_woocommerce', |
| 43 | 'settings_get' => 'manage_woocommerce', |
| 44 | 'settings_set' => 'manage_woocommerce', |
| 45 | 'settings_reset' => 'manage_woocommerce', |
| 46 | ); |
| 47 | |
| 48 | /** |
| 49 | * Input validation patterns. |
| 50 | */ |
| 51 | const VALIDATION_PATTERNS = array( |
| 52 | 'token' => '/^[a-zA-Z0-9_-]{10,}$/', |
| 53 | 'subscription_id' => '/^\d+$/', |
| 54 | 'email' => '/^[^\s@]+@[^\s@]+\.[^\s@]+$/', |
| 55 | ); |
| 56 | |
| 57 | /** |
| 58 | * Data encryption settings. |
| 59 | */ |
| 60 | const ENCRYPTION_METHOD = 'AES-256-CBC'; |
| 61 | const HASH_ALGORITHM = 'sha256'; |
| 62 | |
| 63 | /** |
| 64 | * Security logging configuration. |
| 65 | */ |
| 66 | const LOG_SECURITY_EVENTS = true; |
| 67 | const LOG_RETENTION_DAYS = 30; |
| 68 | const LOG_MAX_ENTRIES = 1000; |
| 69 | |
| 70 | /** |
| 71 | * Get security headers for AJAX responses. |
| 72 | * |
| 73 | * @return array Security headers. |
| 74 | */ |
| 75 | public static function get_security_headers(): array { |
| 76 | return self::SECURITY_HEADERS; |
| 77 | } |
| 78 | |
| 79 | /** |
| 80 | * Check if action requires specific capability. |
| 81 | * |
| 82 | * @param string $action Action name. |
| 83 | * @return string|false Required capability or false if none. |
| 84 | */ |
| 85 | public static function get_required_capability( string $action ) { |
| 86 | return self::REQUIRED_CAPABILITIES[ $action ] ?? false; |
| 87 | } |
| 88 | |
| 89 | /** |
| 90 | * Get validation pattern for field type. |
| 91 | * |
| 92 | * @param string $field_type Field type. |
| 93 | * @return string|false Validation pattern or false if none. |
| 94 | */ |
| 95 | public static function get_validation_pattern( string $field_type ) { |
| 96 | return self::VALIDATION_PATTERNS[ $field_type ] ?? false; |
| 97 | } |
| 98 | |
| 99 | /** |
| 100 | * Generate secure random token. |
| 101 | * |
| 102 | * @param int $length Token length. |
| 103 | * @return string Generated token. |
| 104 | */ |
| 105 | public static function generate_secure_token( int $length = 32 ): string { |
| 106 | return bin2hex( random_bytes( $length / 2 ) ); |
| 107 | } |
| 108 | |
| 109 | /** |
| 110 | * Hash sensitive data. |
| 111 | * |
| 112 | * @param string $data Data to hash. |
| 113 | * @param string $salt Salt for hashing. |
| 114 | * @return string Hashed data. |
| 115 | */ |
| 116 | public static function hash_data( string $data, string $salt = '' ): string { |
| 117 | return hash( self::HASH_ALGORITHM, $data . $salt ); |
| 118 | } |
| 119 | |
| 120 | /** |
| 121 | * Encrypt sensitive data for storage. |
| 122 | * |
| 123 | * @param string $data Data to encrypt. |
| 124 | * @param string $key Encryption key. |
| 125 | * @return string Encrypted data. |
| 126 | */ |
| 127 | public static function encrypt_data( string $data, string $key ): string { |
| 128 | $iv = openssl_random_pseudo_bytes( openssl_cipher_iv_length( self::ENCRYPTION_METHOD ) ); |
| 129 | $encrypted = openssl_encrypt( $data, self::ENCRYPTION_METHOD, $key, 0, $iv ); |
| 130 | return base64_encode( $encrypted . '::' . $iv ); |
| 131 | } |
| 132 | |
| 133 | /** |
| 134 | * Decrypt sensitive data. |
| 135 | * |
| 136 | * @param string $data Encrypted data. |
| 137 | * @param string $key Encryption key. |
| 138 | * @return string|false Decrypted data or false on failure. |
| 139 | */ |
| 140 | public static function decrypt_data( string $data, string $key ) { |
| 141 | $data = base64_decode( $data ); |
| 142 | $parts = explode( '::', $data, 2 ); |
| 143 | |
| 144 | if ( count( $parts ) !== 2 ) { |
| 145 | return false; |
| 146 | } |
| 147 | |
| 148 | return openssl_decrypt( $parts[0], self::ENCRYPTION_METHOD, $key, 0, $parts[1] ); |
| 149 | } |
| 150 | } |
| 151 |