- docker-compose.server.yml: app on APP_BIND for an existing nginx proxy, QLO_SSL passed to the container - docker/setup-testserver.ps1: one-shot setup for Docker Desktop/WSL (random .env secrets, CLI install that never reinstalls over an existing shop, German texts, optional demo content, hardening) - docker/harden-test-server.php: delete demo customer pub@qloapps.com, disable webservice API keys, set SSL mode, deny module log folders - docker/nginx-qloapps.conf: HTTPS + basic auth + X-Forwarded-Proto - apache: deny /modules/*/logs/ (qlocmconnector logs API secrets) - docker/TESTSERVER.md: Windows Server guide (German) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
68 lines
2.4 KiB
PHP
68 lines
2.4 KiB
PHP
<?php
|
|
/**
|
|
* Clean up demo leftovers before a QloApps install is reachable from the network.
|
|
* Idempotent; safe to run again.
|
|
* docker compose exec -u www-data app php docker/harden-test-server.php
|
|
*
|
|
* - deletes the demo customer pub@qloapps.com (its password is public in the QloApps fixtures)
|
|
* - disables the webservice API and every API key (the installer creates an active key)
|
|
* - makes sure developer mode is off and the shop runs in the expected SSL mode
|
|
* - protects module log folders (qlocmconnector logs API secrets) with a deny file
|
|
* QLO_SSL=1 in the environment (docker-compose.server.yml) switches the shop to HTTPS.
|
|
*/
|
|
if (PHP_SAPI !== 'cli') {
|
|
exit("CLI only\n");
|
|
}
|
|
define('_PS_ADMIN_DIR_', __DIR__);
|
|
require __DIR__.'/../config/config.inc.php';
|
|
|
|
$ok = function ($msg) { echo ' [ok] '.$msg.PHP_EOL; };
|
|
$warn = function ($msg) { echo ' [!!] '.$msg.PHP_EOL; };
|
|
|
|
echo "Demo customer\n";
|
|
$ids = Db::getInstance()->executeS('SELECT id_customer FROM '._DB_PREFIX_."customer WHERE email = 'pub@qloapps.com'");
|
|
foreach ($ids as $row) {
|
|
$c = new Customer((int)$row['id_customer']);
|
|
$c->delete();
|
|
}
|
|
$ok(count($ids) ? 'pub@qloapps.com deleted' : 'no demo customer present');
|
|
|
|
echo "Webservice API\n";
|
|
Configuration::updateValue('PS_WEBSERVICE', 0);
|
|
Db::getInstance()->update('webservice_account', array('active' => 0));
|
|
$ok('API disabled, all keys deactivated');
|
|
|
|
echo "Developer mode\n";
|
|
if (_PS_MODE_DEV_) {
|
|
$warn('_PS_MODE_DEV_ is on: set it to false in config/defines.inc.php');
|
|
} else {
|
|
$ok('off');
|
|
}
|
|
|
|
echo "SSL\n";
|
|
$ssl = getenv('QLO_SSL') === '1';
|
|
Configuration::updateValue('PS_SSL_ENABLED', (int)$ssl);
|
|
Configuration::updateValue('PS_SSL_ENABLED_EVERYWHERE', (int)$ssl);
|
|
$ok($ssl ? 'HTTPS everywhere' : 'HTTP (LAN test, no certificate)');
|
|
|
|
echo "Module log folders\n";
|
|
$deny = "<IfModule mod_authz_core.c>\n Require all denied\n</IfModule>\n";
|
|
foreach (glob(_PS_MODULE_DIR_.'*', GLOB_ONLYDIR) as $dir) {
|
|
$logs = $dir.'/logs';
|
|
if (basename($dir) === 'qlocmconnector' && !is_dir($logs)) {
|
|
@mkdir($logs, 0755, true);
|
|
}
|
|
if (is_dir($logs) && !is_file($logs.'/.htaccess')) {
|
|
file_put_contents($logs.'/.htaccess', $deny);
|
|
$ok(basename($dir).'/logs protected');
|
|
}
|
|
}
|
|
|
|
echo "Admin accounts\n";
|
|
foreach (Db::getInstance()->executeS('SELECT email, active FROM '._DB_PREFIX_.'employee') as $e) {
|
|
echo ' - '.$e['email'].($e['active'] ? '' : ' (inactive)').PHP_EOL;
|
|
}
|
|
|
|
Tools::clearSmartyCache();
|
|
echo "Done.\n";
|