132 lines
4.6 KiB
PHP
132 lines
4.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../app/analytics-relay.php';
|
|
|
|
$failures = 0;
|
|
$assert = static function (string $label, bool $condition) use (&$failures): void {
|
|
if ($condition) {
|
|
echo "OK: {$label}\n";
|
|
return;
|
|
}
|
|
$failures++;
|
|
echo "FEHLER: {$label}\n";
|
|
};
|
|
|
|
$environmentNames = [
|
|
'APP_ENV',
|
|
'APP_HOST',
|
|
'APP_MARKETING_URL',
|
|
'MATOMO_URL',
|
|
'MATOMO_SITE_ID',
|
|
'MATOMO_CONSENT_COOKIE_DOMAIN',
|
|
'MATOMO_PRIVACY_CONFIRMED',
|
|
];
|
|
$previousEnvironment = [];
|
|
foreach ($environmentNames as $name) {
|
|
$previousEnvironment[$name] = getenv($name);
|
|
}
|
|
|
|
putenv('APP_ENV=dev');
|
|
putenv('APP_HOST=app.example.test');
|
|
putenv('APP_MARKETING_URL=http://example.test:8765');
|
|
putenv('MATOMO_URL=http://analytics.example.test/');
|
|
putenv('MATOMO_SITE_ID=7');
|
|
putenv('MATOMO_CONSENT_COOKIE_DOMAIN=.example.test');
|
|
putenv('MATOMO_PRIVACY_CONFIRMED=1');
|
|
|
|
$visitorId = '0123456789abcdef';
|
|
$cookies = [
|
|
APP_ANALYTICS_CONSENT_COOKIE => APP_ANALYTICS_CONSENT_VERSION . ':granted',
|
|
APP_ANALYTICS_VISITOR_COOKIE => $visitorId,
|
|
];
|
|
$server = [
|
|
'HTTP_HOST' => 'example.test:8765',
|
|
'HTTP_ORIGIN' => 'http://example.test:8765',
|
|
'HTTP_SEC_FETCH_SITE' => 'same-origin',
|
|
'SERVER_PORT' => '8765',
|
|
'HTTP_USER_AGENT' => 'Relay-Testbrowser/1.0',
|
|
'REMOTE_ADDR' => '203.0.113.42',
|
|
];
|
|
$payload = [
|
|
'visitorId' => $visitorId,
|
|
'pageUrl' => 'http://example.test:8765/passwort-zuruecksetzen.php?token=GEHEIM#formular',
|
|
'pageTitle' => 'Kaffeeliste Passwort zurücksetzen',
|
|
'referrerUrl' => 'http://app.example.test/login.php?source=GEHEIM',
|
|
'resolution' => '1440x900',
|
|
'language' => 'de-DE',
|
|
'h' => 12,
|
|
'm' => 34,
|
|
's' => 56,
|
|
];
|
|
|
|
$parameters = app_matomo_page_view_parameters($payload, $server, $cookies);
|
|
$assert('Seiten-URL verliert Query und Fragment',
|
|
($parameters['url'] ?? '') === 'http://example.test:8765/passwort-zuruecksetzen.php');
|
|
$assert('Interner Referrer verliert Query und Fragment',
|
|
($parameters['urlref'] ?? '') === 'http://app.example.test/login.php');
|
|
$assert('Zufällige Besucherkennung wird unverändert genutzt', ($parameters['_id'] ?? '') === $visitorId);
|
|
$assert('Browserdaten werden auf erlaubte Angaben begrenzt',
|
|
($parameters['res'] ?? '') === '1440x900'
|
|
&& ($parameters['lang'] ?? '') === 'de-DE'
|
|
&& ($parameters['ua'] ?? '') === 'Relay-Testbrowser/1.0');
|
|
$assert('Client-IP wird nicht an Matomo übergeben',
|
|
!array_key_exists('cip', $parameters)
|
|
&& !in_array('203.0.113.42', $parameters, true));
|
|
|
|
$capturedUrl = '';
|
|
$capturedParameters = [];
|
|
$forwardResult = app_matomo_forward_page_view(
|
|
$parameters,
|
|
static function (string $url, array $values) use (&$capturedUrl, &$capturedParameters): array {
|
|
$capturedUrl = $url;
|
|
$capturedParameters = $values;
|
|
return ['ok' => true, 'status' => 204, 'error' => null];
|
|
}
|
|
);
|
|
$assert('Relay verwendet den fest konfigurierten Matomo-Endpunkt',
|
|
$forwardResult['ok']
|
|
&& $capturedUrl === 'http://analytics.example.test/matomo.php'
|
|
&& ($capturedParameters['idsite'] ?? '') === '7');
|
|
|
|
$mustReject = static function (array $changedPayload, array $changedServer, array $changedCookies): bool {
|
|
try {
|
|
app_matomo_page_view_parameters($changedPayload, $changedServer, $changedCookies);
|
|
return false;
|
|
} catch (Throwable) {
|
|
return true;
|
|
}
|
|
};
|
|
|
|
$deniedCookies = $cookies;
|
|
$deniedCookies[APP_ANALYTICS_CONSENT_COOKIE] = APP_ANALYTICS_CONSENT_VERSION . ':denied';
|
|
$assert('Ohne Einwilligung wird der Aufruf verworfen', $mustReject($payload, $server, $deniedCookies));
|
|
|
|
$foreignServer = $server;
|
|
$foreignServer['HTTP_ORIGIN'] = 'https://evil.example';
|
|
$foreignServer['HTTP_SEC_FETCH_SITE'] = 'cross-site';
|
|
$assert('Fremder Ursprung wird verworfen', $mustReject($payload, $foreignServer, $cookies));
|
|
|
|
$foreignPage = $payload;
|
|
$foreignPage['pageUrl'] = 'https://evil.example/gestohlen?token=1';
|
|
$assert('Fremde Seiten-URL wird verworfen', $mustReject($foreignPage, $server, $cookies));
|
|
|
|
$wrongVisitor = $payload;
|
|
$wrongVisitor['visitorId'] = 'fedcba9876543210';
|
|
$assert('Nicht zum Cookie passende Besucherkennung wird verworfen', $mustReject($wrongVisitor, $server, $cookies));
|
|
|
|
$relaySource = file_get_contents(APP_ROOT . '/app/analytics-relay.php') ?: '';
|
|
$assert('Relay-Code liest die Client-IP nicht', !str_contains($relaySource, "['REMOTE_ADDR']"));
|
|
|
|
foreach ($previousEnvironment as $name => $value) {
|
|
$value === false ? putenv($name) : putenv($name . '=' . $value);
|
|
}
|
|
|
|
if ($failures > 0) {
|
|
echo "\n{$failures} Relay-Prüfung(en) fehlgeschlagen.\n";
|
|
exit(1);
|
|
}
|
|
|
|
echo "\nFirst-Party-Matomo-Relay: alle Prüfungen bestanden.\n";
|