Initial commit: CloudOps infrastructure platform

This commit is contained in:
root
2026-04-09 19:58:57 +02:00
commit 1166a52f26
7762 changed files with 839452 additions and 0 deletions

View File

@@ -0,0 +1,105 @@
<?php
namespace Mautic\Middleware\Tests\Dev;
use Mautic\Middleware\Dev\IpRestrictMiddleware;
use PHPUnit\Framework\Assert;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class IpRestrictMiddlewareTest extends \PHPUnit\Framework\TestCase
{
private mixed $originalDdevTldValue;
public function setUp(): void
{
$this->originalDdevTldValue = getenv('DDEV_TLD');
putenv('DDEV_TLD');
parent::setUp();
}
public function tearDown(): void
{
putenv('DDEV_TLD='.$this->originalDdevTldValue);
parent::tearDown();
}
public function testWorkflowWithLocalhostIp(): void
{
$inputRequest = new Request();
$inputRequest->server->set('REMOTE_ADDR', '127.0.0.1'); // 127.0.0.1 is always allowed.
$httpKernel = new class implements HttpKernelInterface {
public function __construct()
{
}
public function handle(Request $request, $type = HttpKernelInterface::MAIN_REQUEST, $catch = true): Response
{
return new Response();
}
};
$middleware = new IpRestrictMiddleware($httpKernel);
$response = $middleware->handle($inputRequest);
Assert::assertSame(Response::HTTP_OK, $response->getStatusCode());
}
public function testWorkflowWithDisallowedIp(): void
{
$inputRequest = new Request();
$inputRequest->server->set('REMOTE_ADDR', 'unallowed.ip.address');
$httpKernel = new class implements HttpKernelInterface {
public $handleWasCalled = false;
public function __construct()
{
}
public function handle(Request $request, $type = HttpKernelInterface::MAIN_REQUEST, $catch = true): Response
{
$this->handleWasCalled = true;
return new Response();
}
};
$middleware = new IpRestrictMiddleware($httpKernel);
$response = $middleware->handle($inputRequest);
Assert::assertSame(Response::HTTP_FORBIDDEN, $response->getStatusCode());
Assert::assertFalse($httpKernel->handleWasCalled);
}
public function testWorkflowWithConfiguredIp(): void
{
// Remember original custom_dev_hosts value so we could return it afterwards.
$originalDevHostsValue = $_SERVER['MAUTIC_CUSTOM_DEV_HOSTS'] ?? '[]';
$_SERVER['MAUTIC_CUSTOM_DEV_HOSTS'] = '["configured.ip.address"]';
$inputRequest = new Request();
$inputRequest->server->set('REMOTE_ADDR', 'configured.ip.address');
$httpKernel = new class($inputRequest) implements HttpKernelInterface {
public function __construct()
{
}
public function handle(Request $request, $type = HttpKernelInterface::MAIN_REQUEST, $catch = true): Response
{
return new Response();
}
};
$middleware = new IpRestrictMiddleware($httpKernel);
$response = $middleware->handle($inputRequest);
Assert::assertSame(Response::HTTP_OK, $response->getStatusCode());
// Set the original value back.
$_SERVER['MAUTIC_CUSTOM_DEV_HOSTS'] = $originalDevHostsValue;
}
}

View File

@@ -0,0 +1,183 @@
<?php
declare(strict_types=1);
namespace Mautic\Middleware\Tests;
use Mautic\CoreBundle\Test\AbstractMauticTestCase;
use Mautic\Middleware\HSTSMiddleware;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\ExpectationFailedException as PHPUnitException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class HSTSMiddlewareTest extends AbstractMauticTestCase
{
public const HSTS_KEY = 'strict-transport-security';
protected \ReflectionProperty $addHSTS;
protected \ReflectionProperty $includeDubDomains;
protected \ReflectionProperty $preload;
protected HSTSMiddleware $middleware;
protected \ReflectionClass $middlewareReflection;
/**
* @throws \ReflectionException
*/
protected function setUp(): void
{
parent::setUp();
$this->middleware = new HSTSMiddleware($this->client->getKernel());
$this->middlewareReflection = new \ReflectionClass($this->middleware);
$this->addHSTS = $this->middlewareReflection->getProperty('enableHSTS');
$this->addHSTS->setAccessible(true);
$this->includeDubDomains = $this->middlewareReflection->getProperty('includeDubDomains');
$this->includeDubDomains->setAccessible(true);
$this->preload = $this->middlewareReflection->getProperty('preload');
$this->preload->setAccessible(true);
}
protected function testResponseHeaders(): void
{
$response = $this->getMiddlewareResponse();
Assert::assertNotEmpty($response->headers);
}
public function testHSTSEnabled(): void
{
$this->setHSTS(true);
$response = $this->getMiddlewareResponse();
Assert::assertTrue(
$response->headers->has(self::HSTS_KEY),
'Strict-Transport-Security is enabled but is missing from the response headers'
);
}
public function testHSTSDisabled(): void
{
$this->setHSTS(false);
$response = $this->getMiddlewareResponse();
Assert::assertFalse(
$response->headers->has(self::HSTS_KEY),
'Strict-Transport-Security is disabled but is present in response headers'
);
}
public function testIncludeSubdomainsEnabled(): void
{
$needle = 'includeSubDomains';
$this->setHSTS(true);
$this->setIncludeDubDomainsValue(true);
$response = $this->getMiddlewareResponse();
Assert::assertStringContainsString(
$needle,
$response->headers->get(self::HSTS_KEY),
'Option include Subdomains is enabled but is missing from the HSTS value'
);
}
public function testIncludeSubdomainsDisabled(): void
{
$needle = 'includeSubDomains';
$this->setHSTS(true);
$this->setIncludeDubDomainsValue(false);
$response = $this->getMiddlewareResponse();
Assert::assertStringNotContainsStringIgnoringCase(
$needle,
$this->getHSTSValue($response),
'Option include Subdomains is disabled but is present in HSTS value'
);
}
public function testPreloadEnabled(): void
{
$needle = 'preload';
$this->setHSTS(true);
$this->setPreloadValue(true);
$response = $this->getMiddlewareResponse();
Assert::assertStringContainsString(
$needle,
$response->headers->get(self::HSTS_KEY),
'Option preload is enabled but is missing from the HSTS value'
);
}
public function testPreloadDisabled(): void
{
$needle = 'preload';
$this->setHSTS(true);
$this->setPreloadValue(false);
$response = $this->getMiddlewareResponse();
Assert::assertStringNotContainsStringIgnoringCase(
$needle,
$this->getHSTSValue($response),
'Option preload is disabled but is present in HSTS value'
);
}
/**
* @throws \ReflectionException
*/
public function testExpireTime(): void
{
$this->setHSTS(true);
$expireTimeValue = 12345;
$expireTime = $this->middlewareReflection->getProperty('expireTime');
$expireTime->setAccessible(true);
$expireTime->setValue($this->middleware, $expireTimeValue);
$response = $this->getMiddlewareResponse();
Assert::assertMatchesRegularExpression(
'/max-age='.$expireTimeValue.'(; includeSubDomains)?/',
$this->getHSTSValue($response),
'Expire time does not match the configuration'
);
}
private function setHSTS(bool $value): void
{
$this->addHSTS->setValue($this->middleware, $value);
}
private function setIncludeDubDomainsValue(bool $value): void
{
$this->includeDubDomains->setValue($this->middleware, $value);
}
private function setPreloadValue(bool $value): void
{
$this->preload->setValue($this->middleware, $value);
}
private function getHSTSValue(Response $response): string
{
return $response->headers->get(self::HSTS_KEY) ?? '';
}
private function getMiddlewareResponse(): Response
{
try {
return $this->middleware->handle(Request::create('s/login', Request::METHOD_GET));
} catch (\Exception $e) {
throw new PHPUnitException($e->getMessage());
}
}
}