Skip to content

Commit 0efa00e

Browse files
authored
Merge pull request #210 from AikidoSec/composer-packages
Added support for extracting composer packages from composer.lock
2 parents 7ee0ca4 + 023b533 commit 0efa00e

File tree

3 files changed

+73
-17
lines changed

3 files changed

+73
-17
lines changed

lib/php-extension/Packages.cpp

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include "Includes.h"
22

3-
std::string GetPackageVersion(const std::string& packageName) {
3+
std::string GetPhpPackageVersion(const std::string& packageName) {
44
zval return_value;
55
CallPhpFunctionWithOneParam("phpversion", packageName, &return_value);
66
if (Z_TYPE(return_value) == IS_STRING) {
@@ -9,7 +9,7 @@ std::string GetPackageVersion(const std::string& packageName) {
99
return "";
1010
}
1111

12-
unordered_map<std::string, std::string> GetPackages() {
12+
unordered_map<std::string, std::string> GetPhpPackages() {
1313
unordered_map<std::string, std::string> packages;
1414

1515
zval extensions_array;
@@ -27,11 +27,67 @@ unordered_map<std::string, std::string> GetPackages() {
2727

2828
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL(extensions_array), index, key, extension) {
2929
if (extension && Z_TYPE_P(extension) == IS_STRING) {
30-
packages[Z_STRVAL_P(extension)] = GetPackageVersion(Z_STRVAL_P(extension));
31-
AIKIDO_LOG_INFO("Found package %s version %s\n", Z_STRVAL_P(extension), packages[Z_STRVAL_P(extension)].c_str());
30+
packages[Z_STRVAL_P(extension)] = GetPhpPackageVersion(Z_STRVAL_P(extension));
3231
}
3332
} ZEND_HASH_FOREACH_END();
3433

3534
zval_ptr_dtor(&extensions_array);
35+
return packages;
36+
}
37+
38+
std::string GetComposerPackageVersion(const std::string& version) {
39+
if (version.empty()) {
40+
return version;
41+
}
42+
43+
if (version[0] == 'v') {
44+
return version.substr(1);
45+
}
46+
47+
return version;
48+
}
49+
50+
unordered_map<std::string, std::string> GetComposerPackages() {
51+
unordered_map<std::string, std::string> packages;
52+
53+
std::string docRoot = server.GetVar("DOCUMENT_ROOT");
54+
if (docRoot.empty()) {
55+
return packages;
56+
}
57+
std::string composerLockPath = docRoot + "/../composer.lock";
58+
59+
std::ifstream composerLockFile(composerLockPath);
60+
if (!composerLockFile.is_open()) {
61+
return packages;
62+
}
63+
64+
try {
65+
json composerLockData = json::parse(composerLockFile);
66+
if (!composerLockData.contains("packages")) {
67+
return packages;
68+
}
69+
70+
const auto& composerLockPackages = composerLockData["packages"];
71+
72+
for (const auto& composerLockPackage : composerLockPackages) {
73+
if (!composerLockPackage.contains("name") || !composerLockPackage.contains("version")) {
74+
continue;
75+
}
76+
packages[composerLockPackage["name"]] = GetComposerPackageVersion(composerLockPackage["version"]);
77+
}
78+
} catch (const std::exception& e) {
79+
AIKIDO_LOG_ERROR("Error parsing composer.lock: %s\n", e.what());
80+
return packages;
81+
}
82+
83+
return packages;
84+
}
85+
86+
unordered_map<std::string, std::string> GetPackages() {
87+
unordered_map<std::string, std::string> packages = GetPhpPackages();
88+
unordered_map<std::string, std::string> composerPackages = GetComposerPackages();
89+
90+
packages.insert(composerPackages.begin(), composerPackages.end());
91+
3692
return packages;
3793
}

lib/request-processor/aikido_types/config.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,24 @@ import (
77
)
88

99
type EnvironmentConfigData struct {
10-
SocketPath string `json:"socket_path"` // '/run/aikido-{version}/aikido-{datetime}-{randint}.sock'
11-
SAPI string `json:"sapi"` // '{php-sapi}'
10+
SocketPath string `json:"socket_path"` // '/run/aikido-{version}/aikido-{datetime}-{randint}.sock'
11+
SAPI string `json:"sapi"` // '{php-sapi}'
12+
TrustProxy bool `json:"trust_proxy"` // default: true
13+
LocalhostAllowedByDefault bool `json:"localhost_allowed_by_default"` // default: true
14+
CollectApiSchema bool `json:"collect_api_schema"` // default: true
15+
}
16+
17+
type AikidoConfigData struct {
18+
Token string `json:"token"` // default: ''
19+
LogLevel string `json:"log_level"` // default: 'WARN'
20+
Blocking bool `json:"blocking"` // default: false
1221
TrustProxy bool `json:"trust_proxy"` // default: true
1322
LocalhostAllowedByDefault bool `json:"localhost_allowed_by_default"` // default: true
1423
CollectApiSchema bool `json:"collect_api_schema"` // default: true
24+
DiskLogs bool `json:"disk_logs"` // default: false
1525
Packages map[string]string `json:"packages"` // default: {}
1626
}
1727

18-
type AikidoConfigData struct {
19-
Token string `json:"token"` // default: ''
20-
LogLevel string `json:"log_level"` // default: 'WARN'
21-
Blocking bool `json:"blocking"` // default: false
22-
TrustProxy bool `json:"trust_proxy"` // default: true
23-
LocalhostAllowedByDefault bool `json:"localhost_allowed_by_default"` // default: true
24-
CollectApiSchema bool `json:"collect_api_schema"` // default: true
25-
DiskLogs bool `json:"disk_logs"` // default: false
26-
}
27-
2828
type RateLimiting struct {
2929
Enabled bool
3030
MaxRequests int

lib/request-processor/grpc/client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ func Init() {
3333
log.Debugf("Current connection state: %s\n", conn.GetState().String())
3434

3535
SendAikidoConfig()
36-
OnPackages(globals.EnvironmentConfig.Packages)
3736
startCloudConfigRoutine()
3837
}
3938

@@ -62,6 +61,7 @@ func SendAikidoConfig() {
6261
}
6362

6463
log.Debugf("Aikido config sent via socket!")
64+
OnPackages(globals.AikidoConfig.Packages)
6565
}
6666

6767
/* Send outgoing domain to Aikido Agent via gRPC */

0 commit comments

Comments
 (0)