Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,76 @@ jobs:
path: |
~/rpmbuild/RPMS/${{ env.ARCH }}/${{ env.AIKIDO_ARTIFACT_RELEASE }}

build_lambda_layers:
name: Build Lambda layers php-${{ matrix.php_version }}
runs-on: ubuntu-24.04
needs: [ build_libs, build_php_extension_nts ]
strategy:
matrix:
php_version: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5']
fail-fast: false

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Get Aikido version
run: |
AIKIDO_VERSION=$(grep '#define PHP_AIKIDO_VERSION' lib/php-extension/include/php_aikido.h | awk -F'"' '{print $2}')
echo "AIKIDO_VERSION=$AIKIDO_VERSION" >> $GITHUB_ENV
echo "AIKIDO_LIBZEN_VERSION=0.1.60" >> $GITHUB_ENV

- name: Download NTS extension
uses: actions/download-artifact@v4
with:
name: aikido-extension-php-${{ matrix.php_version }}-nts-x86_64
path: artifacts/extension

- name: Download agent
uses: actions/download-artifact@v4
with:
name: aikido-agent-x86_64
path: artifacts/agent

- name: Download request processor
uses: actions/download-artifact@v4
with:
name: aikido-request-processor-x86_64
path: artifacts/request-processor

- name: Download Aikido Zen Internals Lib
run: |
curl -L -O https://github.com/AikidoSec/zen-internals/releases/download/v${{ env.AIKIDO_LIBZEN_VERSION }}/libzen_internals_x86_64-unknown-linux-gnu.so

- name: Build Lambda layer zip
run: |
LAYER_DIR=lambda-layer
AIKIDO_DIR=$LAYER_DIR/aikido-${{ env.AIKIDO_VERSION }}
BREF_CONF_DIR=$LAYER_DIR/bref/etc/php/conf.d

mkdir -p $AIKIDO_DIR $BREF_CONF_DIR

find artifacts/extension -name "aikido-extension-php-${{ matrix.php_version }}-nts.so" -exec cp {} $AIKIDO_DIR/ \;
find artifacts/agent -name "aikido-agent" -exec cp {} $AIKIDO_DIR/ \;
find artifacts/request-processor -name "aikido-request-processor.so" -exec cp {} $AIKIDO_DIR/ \;
cp libzen_internals_x86_64-unknown-linux-gnu.so $AIKIDO_DIR/
chmod +x $AIKIDO_DIR/aikido-agent

echo "extension=/opt/aikido-${{ env.AIKIDO_VERSION }}/aikido-extension-php-${{ matrix.php_version }}-nts.so" > $BREF_CONF_DIR/ext-aikido.ini

ls -la $AIKIDO_DIR/

cd $LAYER_DIR
zip -r ../aikido-firewall-bref-lambda-layer-php-${{ matrix.php_version }}-x86_64.zip .

- name: Archive Lambda layer
uses: actions/upload-artifact@v4
with:
name: aikido-firewall-bref-lambda-layer-php-${{ matrix.php_version }}-x86_64
if-no-files-found: error
path: |
aikido-firewall-bref-lambda-layer-php-${{ matrix.php_version }}-x86_64.zip

build_deb:
name: Build deb ${{ matrix.arch == '' && 'x86_64' || 'arm' }}
runs-on: ubuntu-24.04${{ matrix.arch }}
Expand Down
9 changes: 8 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,16 @@ jobs:
with:
pattern: |
aikido-php-firewall*

- name: Download Lambda layer artifacts
uses: actions/download-artifact@v4
with:
pattern: |
aikido-firewall-bref-lambda-layer-*

- name: List Artifacts
run: |
ls -l
ls -lR
pwd

- name: Deploy to GitHub Release (draft)
Expand All @@ -38,3 +44,4 @@ jobs:
draft: true
files: |
./**/aikido-php-firewall*
./**/aikido-firewall-bref-lambda-layer-*
23 changes: 20 additions & 3 deletions lib/agent/constants/constants.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
package constants

import "os"

const Version = "1.5.4"

var SocketPath string
var PidPath string

func isRunDirWritable() bool {
return os.WriteFile("/run/aikido-probe", nil, 0644) == nil && os.Remove("/run/aikido-probe") == nil
}

func init() {
runDir := "/run/aikido-" + Version
if !isRunDirWritable() {
runDir = "/tmp/aikido-" + Version
}
SocketPath = runDir + "/aikido-agent.sock"
PidPath = runDir + "/aikido-agent.pid"
}

const (
Version = "1.5.4"
SocketPath = "/run/aikido-" + Version + "/aikido-agent.sock"
PidPath = "/run/aikido-" + Version + "/aikido-agent.pid"
ConfigUpdatedAtMethod = "GET"
ConfigUpdatedAtAPI = "/config"
ConfigAPIMethod = "GET"
Expand Down
23 changes: 21 additions & 2 deletions lib/php-extension/Agent.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
#include "Includes.h"

static std::string GetRuntimeDir() {
if (getenv("AWS_LAMBDA_FUNCTION_NAME") != nullptr) {
return "/tmp/aikido-" + std::string(PHP_AIKIDO_VERSION);
}
return "/run/aikido-" + std::string(PHP_AIKIDO_VERSION);
}

vector<pid_t> Agent::GetPIDsFromRunningProcesses(const std::string& aikidoAgentPath) {
vector<pid_t> agentPIDs;

Expand Down Expand Up @@ -105,7 +112,7 @@ bool Agent::IsRunning(const std::string& aikidoAgentPath, const std::string& aik

AIKIDO_LOG_INFO("Found socket file \"%s\" on disk! Checking if Aikido Agent process is running...\n", aikidoAgentSocketPath.c_str());

std::string aikidoAgentPidPath = "/run/aikido-" + std::string(PHP_AIKIDO_VERSION) + "/aikido-agent.pid";
std::string aikidoAgentPidPath = GetRuntimeDir() + "/aikido-agent.pid";
pid_t agentPIDFromFile = this->GetPIDFromFile(aikidoAgentPidPath);
vector<pid_t> agentPIDsFromRunningProcesses = this->GetPIDsFromRunningProcesses(aikidoAgentPath);
if (agentPIDFromFile == -1 ||
Expand All @@ -126,7 +133,8 @@ bool Agent::IsRunning(const std::string& aikidoAgentPath, const std::string& aik

bool Agent::Init() {
std::string aikidoAgentPath = "/opt/aikido-" + std::string(PHP_AIKIDO_VERSION) + "/aikido-agent";
std::string aikidoAgentSocketPath = "/run/aikido-" + std::string(PHP_AIKIDO_VERSION) + "/aikido-agent.sock";
std::string runtimeDir = GetRuntimeDir();
std::string aikidoAgentSocketPath = runtimeDir + "/aikido-agent.sock";

if (this->IsRunning(aikidoAgentPath, aikidoAgentSocketPath)) {
AIKIDO_LOG_INFO("Aikido Agent is already running! Skipping init...\n");
Expand All @@ -140,6 +148,17 @@ bool Agent::Init() {
return false;
}

// Wait for the agent to bind its Unix socket (max ~1s) so the first
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agent::Init adds an inlined polling loop that returns from inside the loop; extract or convert this wait into a guard/helper (early-return) to flatten Init's control flow and improve readability.

Details

✨ AI Reasoning
​Agent::Init was modified to add a polling loop that waits for the agent socket to appear, returning from inside the loop when ready or logging a warning after the loop. This increases nesting and mixes startup orchestration with waiting logic, which could be clearer if the wait were a separate guard/helper or inverted into an early-return check. The change makes the control flow less linear and slightly harder to follow, so a guard/early-return or small helper function would improve maintainability.

🔧 How do I fix it?
Place parameter validation and guard clauses at the function start. Use early returns to reduce nesting levels and improve readability.

Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

// request doesn't race against agent startup. This matters on Lambda
// cold starts where MINIT and the first invoke happen back-to-back.
for (int i = 0; i < 200; i++) {
if (FileExists(aikidoAgentSocketPath)) {
AIKIDO_LOG_INFO("Aikido Agent socket ready after %d ms\n", i * 5);
return true;
}
usleep(5000);
}
AIKIDO_LOG_WARN("Aikido Agent socket did not appear within 1s\n");
return true;
}

Expand Down
19 changes: 15 additions & 4 deletions lib/request-processor/globals/globals.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,18 @@ func CreateServer(token string) *ServerData {
return Servers[token]
}

const (
Version = "1.5.4"
SocketPath = "/run/aikido-" + Version + "/aikido-agent.sock"
)
const Version = "1.5.4"

var SocketPath string

func isRunDirWritable() bool {
return os.WriteFile("/run/aikido-probe", nil, 0644) == nil && os.Remove("/run/aikido-probe") == nil
}

func init() {
runDir := "/run/aikido-" + Version
if !isRunDirWritable() {
runDir = "/tmp/aikido-" + Version
}
SocketPath = runDir + "/aikido-agent.sock"
}
20 changes: 11 additions & 9 deletions package/rpm/aikido.spec
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ if command -v php -v >/dev/null 2>&1; then
fi

# Check common PHP installation paths
for php_path in /usr/bin/php* /usr/local/bin/php*; do
for php_path in /usr/bin/php* /usr/local/bin/php* /opt/bin/php*; do
if [[ -x "$php_path" && "$php_path" =~ php([0-9]+\.[0-9]+)$ ]]; then
version=$("$php_path" -v | grep -oP 'PHP \K\d+\.\d+' | head -n 1)
if [[ ! " ${PHP_VERSIONS[@]} " =~ " ${version} " ]]; then
Expand Down Expand Up @@ -133,9 +133,10 @@ for PHP_VERSION in "${PHP_VERSIONS[@]}"; do
fi
else
# RedHat-based system
if [ -d "$PHP_MOD_DIR" ]; then
echo "Installing new Aikido mod in $PHP_MOD_DIR/zz-aikido-%{version}.ini..."
ln -sf /opt/aikido-%{version}/aikido.ini $PHP_MOD_DIR/zz-aikido-%{version}.ini
PHP_MOD_DIR_FIRST="${PHP_MOD_DIR%%:*}"
if [ -d "$PHP_MOD_DIR_FIRST" ]; then
echo "Installing new Aikido mod in $PHP_MOD_DIR_FIRST/zz-aikido-%{version}.ini..."
ln -sf /opt/aikido-%{version}/aikido.ini $PHP_MOD_DIR_FIRST/zz-aikido-%{version}.ini
else
echo "No mod dir for PHP $PHP_VERSION! Skipping..."
continue
Expand Down Expand Up @@ -198,7 +199,7 @@ if command -v php -v >/dev/null 2>&1; then
fi

# Check common PHP installation paths
for php_path in /usr/bin/php* /usr/local/bin/php*; do
for php_path in /usr/bin/php* /usr/local/bin/php* /opt/bin/php*; do
if [[ -x "$php_path" && "$php_path" =~ php([0-9]+\.[0-9]+)$ ]]; then
version=$("$php_path" -v | grep -oP 'PHP \K\d+\.\d+' | head -n 1)
if [[ ! " ${PHP_VERSIONS[@]} " =~ " ${version} " ]]; then
Expand Down Expand Up @@ -252,10 +253,11 @@ for PHP_VERSION in "${PHP_VERSIONS[@]}"; do
rm -f $PHP_DEBIAN_MOD_DIR_APACHE2/zz-aikido-%{version}.ini
fi
else
# RedHat-based system
if [ -d "$PHP_MOD_DIR" ]; then
echo "Uninstalling Aikido mod from $PHP_MOD_DIR/zz-aikido-%{version}.ini..."
rm -f $PHP_MOD_DIR/zz-aikido-%{version}.ini
# RedHat-based system (take first dir if colon-separated)
PHP_MOD_DIR_FIRST="${PHP_MOD_DIR%%:*}"
if [ -f "$PHP_MOD_DIR_FIRST/zz-aikido-%{version}.ini" ]; then
echo "Uninstalling Aikido mod from $PHP_MOD_DIR_FIRST/zz-aikido-%{version}.ini..."
rm -f $PHP_MOD_DIR_FIRST/zz-aikido-%{version}.ini
fi
fi

Expand Down
Loading