diff --git a/README.md b/README.md index 1cf3b0fc..7aff67fb 100644 --- a/README.md +++ b/README.md @@ -39,25 +39,25 @@ Prerequisites: ##### x86_64 ``` -rpm -Uvh --oldpackage https://github.com/AikidoSec/firewall-php/releases/download/v1.5.1/aikido-php-firewall.x86_64.rpm +rpm -Uvh --oldpackage https://github.com/AikidoSec/firewall-php/releases/download/v1.5.2/aikido-php-firewall.x86_64.rpm ``` ##### arm64 / aarch64 ``` -rpm -Uvh --oldpackage https://github.com/AikidoSec/firewall-php/releases/download/v1.5.1/aikido-php-firewall.aarch64.rpm +rpm -Uvh --oldpackage https://github.com/AikidoSec/firewall-php/releases/download/v1.5.2/aikido-php-firewall.aarch64.rpm ``` #### For Debian-based Systems (Debian, Ubuntu) ##### x86_64 ``` -curl -L -O https://github.com/AikidoSec/firewall-php/releases/download/v1.5.1/aikido-php-firewall.x86_64.deb +curl -L -O https://github.com/AikidoSec/firewall-php/releases/download/v1.5.2/aikido-php-firewall.x86_64.deb dpkg -i -E ./aikido-php-firewall.x86_64.deb ``` ##### arm64 / aarch64 ``` -curl -L -O https://github.com/AikidoSec/firewall-php/releases/download/v1.5.1/aikido-php-firewall.aarch64.deb +curl -L -O https://github.com/AikidoSec/firewall-php/releases/download/v1.5.2/aikido-php-firewall.aarch64.deb dpkg -i -E ./aikido-php-firewall.aarch64.deb ``` diff --git a/docs/aws-elastic-beanstalk.md b/docs/aws-elastic-beanstalk.md index fb6f6f12..2adac104 100644 --- a/docs/aws-elastic-beanstalk.md +++ b/docs/aws-elastic-beanstalk.md @@ -4,7 +4,7 @@ ``` commands: aikido-php-firewall: - command: "rpm -Uvh --oldpackage https://github.com/AikidoSec/firewall-php/releases/download/v1.5.1/aikido-php-firewall.x86_64.rpm" + command: "rpm -Uvh --oldpackage https://github.com/AikidoSec/firewall-php/releases/download/v1.5.2/aikido-php-firewall.x86_64.rpm" ignoreErrors: true files: diff --git a/docs/fly-io.md b/docs/fly-io.md index 7dc680cb..ae534f2c 100644 --- a/docs/fly-io.md +++ b/docs/fly-io.md @@ -32,7 +32,7 @@ Create a script to install the Aikido PHP Firewall during deployment: #!/usr/bin/env bash cd /tmp -curl -L -O https://github.com/AikidoSec/firewall-php/releases/download/v1.5.1/aikido-php-firewall.x86_64.deb +curl -L -O https://github.com/AikidoSec/firewall-php/releases/download/v1.5.2/aikido-php-firewall.x86_64.deb dpkg -i -E ./aikido-php-firewall.x86_64.deb ``` diff --git a/docs/laravel-forge.md b/docs/laravel-forge.md index 309849c0..fdb170fa 100644 --- a/docs/laravel-forge.md +++ b/docs/laravel-forge.md @@ -8,7 +8,7 @@ You can get your token from the [Aikido Security Dashboard](https://help.aikido. Go to "Commands" and run the following by replacing the sudo password with the one that Forge displays when the server is created: ``` -curl -L -O https://github.com/AikidoSec/firewall-php/releases/download/v1.5.1/aikido-php-firewall.x86_64.deb && echo "YOUR_SUDO_PASSWORD_HERE" | sudo -S dpkg -i -E ./aikido-php-firewall.x86_64.deb && echo "YOUR_SUDO_PASSWORD_HERE" | sudo -S service php8.4-fpm restart +curl -L -O https://github.com/AikidoSec/firewall-php/releases/download/v1.5.2/aikido-php-firewall.x86_64.deb && echo "YOUR_SUDO_PASSWORD_HERE" | sudo -S dpkg -i -E ./aikido-php-firewall.x86_64.deb && echo "YOUR_SUDO_PASSWORD_HERE" | sudo -S service php8.4-fpm restart ``` ![Forge Commands](./forge-commands.png) diff --git a/lib/agent/constants/constants.go b/lib/agent/constants/constants.go index 51b97f3a..23903b83 100644 --- a/lib/agent/constants/constants.go +++ b/lib/agent/constants/constants.go @@ -1,7 +1,7 @@ package constants const ( - Version = "1.5.1" + Version = "1.5.2" SocketPath = "/run/aikido-" + Version + "/aikido-agent.sock" PidPath = "/run/aikido-" + Version + "/aikido-agent.pid" ConfigUpdatedAtMethod = "GET" diff --git a/lib/php-extension/Aikido.cpp b/lib/php-extension/Aikido.cpp index c66e45b2..295afbf9 100644 --- a/lib/php-extension/Aikido.cpp +++ b/lib/php-extension/Aikido.cpp @@ -4,14 +4,8 @@ ZEND_DECLARE_MODULE_GLOBALS(aikido) PHP_MINIT_FUNCTION(aikido) { - // For FrankenPHP: Set sapi_name but skip rest of LoadEnvironment during MINIT - // Full environment will be loaded in RINIT when Caddyfile env vars are available - if (sapi_module.name == std::string("frankenphp")) { - AIKIDO_GLOBAL(sapi_name) = sapi_module.name; - } else { - // For other SAPIs: Load environment during MINIT as normal - LoadEnvironment(); - } + LoadSystemEnvironment(); + AIKIDO_GLOBAL(logger).Init(); AIKIDO_LOG_INFO("MINIT started!\n"); diff --git a/lib/php-extension/Environment.cpp b/lib/php-extension/Environment.cpp index cbf53a24..bc2903f8 100644 --- a/lib/php-extension/Environment.cpp +++ b/lib/php-extension/Environment.cpp @@ -152,14 +152,19 @@ std::string GetLaravelEnvVariable(const std::string& env_key) { */ using EnvGetterFn = std::string(*)(const std::string&); -EnvGetterFn envGetters[] = { + +const std::vector completeEnvGetters = { &GetSystemEnvVariable, &GetFrankenEnvVariable, &GetPhpEnvVariable, &GetLaravelEnvVariable }; -std::string GetEnvVariable(const std::string& env_key) { +const std::vector systemEnvGetters = { + &GetSystemEnvVariable, +}; + +std::string GetEnvVariable(const std::vector& envGetters, const std::string& env_key) { for (EnvGetterFn envGetter : envGetters) { std::string env_value = envGetter(env_key); if (!env_value.empty()) { @@ -169,8 +174,8 @@ std::string GetEnvVariable(const std::string& env_key) { return ""; } -std::string GetEnvString(const std::string& env_key, const std::string default_value) { - std::string env_value = GetEnvVariable(env_key); +std::string GetEnvString(const std::vector& envGetters, const std::string& env_key, const std::string default_value) { + std::string env_value = GetEnvVariable(envGetters, env_key); if (!env_value.empty()) { return env_value; } @@ -185,12 +190,16 @@ bool GetBoolFromString(const std::string& env, bool default_value) { return default_value; } -bool GetEnvBool(const std::string& env_key, bool default_value) { - return GetBoolFromString(GetEnvVariable(env_key), default_value); +bool GetEnvBool(const std::vector& envGetters, const std::string& env_key, bool default_value) { + return GetBoolFromString(GetEnvVariable(envGetters, env_key), default_value); } -unsigned int GetEnvNumber(const std::string& env_key, unsigned int default_value) { - std::string env_value = GetEnvVariable(env_key.c_str()); +bool GetEnvBoolWithAllGetters(const std::string& env_key, bool default_value) { + return GetBoolFromString(GetEnvVariable(completeEnvGetters, env_key), default_value); +} + +unsigned int GetEnvNumber(const std::vector& envGetters, const std::string& env_key, unsigned int default_value) { + std::string env_value = GetEnvVariable(envGetters, env_key); if (!env_value.empty()) { try { unsigned int number = std::stoi(env_value); @@ -203,26 +212,34 @@ unsigned int GetEnvNumber(const std::string& env_key, unsigned int default_value return default_value; } -void LoadEnvironment() { +void LoadEnvironmentFromGetters(const std::vector& envGetters) { auto& logLevelStr = AIKIDO_GLOBAL(log_level_str); auto& logLevel = AIKIDO_GLOBAL(log_level); - if (GetEnvBool("AIKIDO_DEBUG", false)) { + if (GetEnvBool(envGetters, "AIKIDO_DEBUG", false)) { logLevelStr = "DEBUG"; logLevel = AIKIDO_LOG_LEVEL_DEBUG; } else { - logLevelStr = GetEnvString("AIKIDO_LOG_LEVEL", "WARN"); + logLevelStr = GetEnvString(envGetters, "AIKIDO_LOG_LEVEL", "WARN"); logLevel = Log::ToLevel(logLevelStr); } - AIKIDO_GLOBAL(blocking) = GetEnvBool("AIKIDO_BLOCK", false) || GetEnvBool("AIKIDO_BLOCKING", false);; - AIKIDO_GLOBAL(disable) = GetEnvBool("AIKIDO_DISABLE", false); - AIKIDO_GLOBAL(collect_api_schema) = GetEnvBool("AIKIDO_FEATURE_COLLECT_API_SCHEMA", true); - AIKIDO_GLOBAL(localhost_allowed_by_default) = GetEnvBool("AIKIDO_LOCALHOST_ALLOWED_BY_DEFAULT", true); - AIKIDO_GLOBAL(trust_proxy) = GetEnvBool("AIKIDO_TRUST_PROXY", true); - AIKIDO_GLOBAL(disk_logs) = GetEnvBool("AIKIDO_DISK_LOGS", false); + AIKIDO_GLOBAL(blocking) = GetEnvBool(envGetters, "AIKIDO_BLOCK", false) || GetEnvBool(envGetters, "AIKIDO_BLOCKING", false); + AIKIDO_GLOBAL(disable) = GetEnvBool(envGetters, "AIKIDO_DISABLE", false); + AIKIDO_GLOBAL(collect_api_schema) = GetEnvBool(envGetters,"AIKIDO_FEATURE_COLLECT_API_SCHEMA", true); + AIKIDO_GLOBAL(localhost_allowed_by_default) = GetEnvBool(envGetters, "AIKIDO_LOCALHOST_ALLOWED_BY_DEFAULT", true); + AIKIDO_GLOBAL(trust_proxy) = GetEnvBool(envGetters, "AIKIDO_TRUST_PROXY", true); + AIKIDO_GLOBAL(disk_logs) = GetEnvBool(envGetters, "AIKIDO_DISK_LOGS", false); AIKIDO_GLOBAL(sapi_name) = sapi_module.name; - AIKIDO_GLOBAL(token) = GetEnvString("AIKIDO_TOKEN", ""); - AIKIDO_GLOBAL(endpoint) = GetEnvString("AIKIDO_ENDPOINT", "https://guard.aikido.dev/"); - AIKIDO_GLOBAL(config_endpoint) = GetEnvString("AIKIDO_REALTIME_ENDPOINT", "https://runtime.aikido.dev/"); - AIKIDO_GLOBAL(report_stats_interval_to_agent) = GetEnvNumber("AIKIDO_REPORT_STATS_INTERVAL", 100); -} \ No newline at end of file + AIKIDO_GLOBAL(token) = GetEnvString(envGetters, "AIKIDO_TOKEN", ""); + AIKIDO_GLOBAL(endpoint) = GetEnvString(envGetters, "AIKIDO_ENDPOINT", "https://guard.aikido.dev/"); + AIKIDO_GLOBAL(config_endpoint) = GetEnvString(envGetters, "AIKIDO_REALTIME_ENDPOINT", "https://runtime.aikido.dev/"); + AIKIDO_GLOBAL(report_stats_interval_to_agent) = GetEnvNumber(envGetters, "AIKIDO_REPORT_STATS_INTERVAL", 100); +} + +void LoadEnvironment() { + LoadEnvironmentFromGetters(completeEnvGetters); +} + +void LoadSystemEnvironment() { + LoadEnvironmentFromGetters(systemEnvGetters); +} diff --git a/lib/php-extension/HandleFileCompilation.cpp b/lib/php-extension/HandleFileCompilation.cpp index 91df6a31..a560a02c 100644 --- a/lib/php-extension/HandleFileCompilation.cpp +++ b/lib/php-extension/HandleFileCompilation.cpp @@ -1,6 +1,10 @@ #include "Includes.h" zend_op_array* handle_file_compilation(zend_file_handle* file_handle, int type) { + if(AIKIDO_GLOBAL(disable) == true) { + return original_file_compilation_handler(file_handle, type); + } + auto& eventCacheStack = AIKIDO_GLOBAL(eventCacheStack); // Create a new event context for file compilation diff --git a/lib/php-extension/HookAst.cpp b/lib/php-extension/HookAst.cpp index 659119c7..71268788 100644 --- a/lib/php-extension/HookAst.cpp +++ b/lib/php-extension/HookAst.cpp @@ -114,9 +114,17 @@ void insert_call_to_ast(zend_ast *ast) { } void aikido_ast_process(zend_ast *ast) { + auto& original_ast_process = AIKIDO_GLOBAL(originalAstProcess); + + if(AIKIDO_GLOBAL(disable) == true) { + if(original_ast_process){ + original_ast_process(ast); + } + return; + } + insert_call_to_ast(ast); - auto& original_ast_process = AIKIDO_GLOBAL(originalAstProcess); if(original_ast_process){ original_ast_process(ast); } diff --git a/lib/php-extension/RequestProcessor.cpp b/lib/php-extension/RequestProcessor.cpp index d0f705fc..c728363f 100644 --- a/lib/php-extension/RequestProcessor.cpp +++ b/lib/php-extension/RequestProcessor.cpp @@ -207,6 +207,14 @@ bool RequestProcessorInstance::ReportStats() { bool RequestProcessorInstance::RequestInit() { std::string sapiName = sapi_module.name; + if (sapiName == "frankenphp") { + if (GetEnvBoolWithAllGetters("FRANKENPHP_WORKER", false)) { + AIKIDO_GLOBAL(isWorkerMode) = true; + AIKIDO_LOG_INFO("FrankenPHP worker warm-up request detected, skipping RequestInit\n"); + return true; + } + } + if (sapiName == "apache2handler" || sapiName == "frankenphp") { // Apache-mod-php and FrankenPHP can serve multiple sites per process // We need to reload config each request to detect token changes @@ -222,14 +230,6 @@ bool RequestProcessorInstance::RequestInit() { } } - if (sapiName == "frankenphp") { - if (GetEnvBool("FRANKENPHP_WORKER", false)) { - AIKIDO_GLOBAL(isWorkerMode) = true; - AIKIDO_LOG_INFO("FrankenPHP worker warm-up request detected, skipping RequestInit\n"); - return true; - } - } - // Initialize the request processor only once(lazy) during RINIT because php-fpm forks the main process // for workers and we need to load the library after the worker process is forked because // the request processor is a go library that brings in the Go runtime, which (once initialized) diff --git a/lib/php-extension/include/Environment.h b/lib/php-extension/include/Environment.h index 2c0e0685..0895d503 100644 --- a/lib/php-extension/include/Environment.h +++ b/lib/php-extension/include/Environment.h @@ -2,10 +2,8 @@ void LoadEnvironment(); -bool LoadLaravelEnvFile(); - -bool GetBoolFromString(const std::string& env, bool default_value); +void LoadSystemEnvironment(); -bool GetEnvBool(const std::string& env_key, bool default_value); +bool LoadLaravelEnvFile(); -std::string GetEnvString(const std::string& env_key, const std::string default_value); +bool GetEnvBoolWithAllGetters(const std::string& env_key, bool default_value); diff --git a/lib/php-extension/include/Includes.h b/lib/php-extension/include/Includes.h index 679107d6..eaeef525 100644 --- a/lib/php-extension/include/Includes.h +++ b/lib/php-extension/include/Includes.h @@ -18,6 +18,7 @@ #include #include +#include #include #include #include diff --git a/lib/php-extension/include/php_aikido.h b/lib/php-extension/include/php_aikido.h index 812e56cf..af854f30 100644 --- a/lib/php-extension/include/php_aikido.h +++ b/lib/php-extension/include/php_aikido.h @@ -19,7 +19,7 @@ extern zend_module_entry aikido_module_entry; #define phpext_aikido_ptr &aikido_module_entry -#define PHP_AIKIDO_VERSION "1.5.1" +#define PHP_AIKIDO_VERSION "1.5.2" #if defined(ZTS) && defined(COMPILE_DL_AIKIDO) ZEND_TSRMLS_CACHE_EXTERN() diff --git a/lib/request-processor/globals/globals.go b/lib/request-processor/globals/globals.go index ab88ea99..034fc2cf 100644 --- a/lib/request-processor/globals/globals.go +++ b/lib/request-processor/globals/globals.go @@ -79,6 +79,6 @@ func CreateServer(token string) *ServerData { } const ( - Version = "1.5.1" + Version = "1.5.2" SocketPath = "/run/aikido-" + Version + "/aikido-agent.sock" ) diff --git a/package/rpm/aikido.spec b/package/rpm/aikido.spec index b4d5bba3..e957036e 100644 --- a/package/rpm/aikido.spec +++ b/package/rpm/aikido.spec @@ -1,5 +1,5 @@ Name: aikido-php-firewall -Version: 1.5.1 +Version: 1.5.2 Release: 1 Summary: Aikido PHP Extension License: GPL