diff --git a/bouncer/Readme.md b/bouncer/Readme.md index f72c88c..761794f 100644 --- a/bouncer/Readme.md +++ b/bouncer/Readme.md @@ -62,6 +62,7 @@ These environment variables need to be applied to the CONSUMING SERVICE and not | BOUNCER_ALLOW_WEBSOCKETS | Defaults to enabled. Values are "yes" or "true", anything else is false | Enable websocket behaviour | | BOUNCER_ALLOW_LARGE_PAYLOADS | Defaults to disabled. | Allows overriding the default nginx payload size. Related to BOUNCER_MAX_PAYLOADS_MEGABYTES | | BOUNCER_MAX_PAYLOADS_MEGABYTES | numbers | Size of max payload to allow, in megabytes. Requires BOUNCER_ALLOW_LARGE_PAYLOADS to be enabled | +| BOUNCER_CUSTOM_NGINX_CONFIG | Contents of nginx config file, optionally base64 encoded | Allows you to provide a custom nginx config file for this service. This will entirely replace the default config for this service. This is hella dangerous. | ## Security considerations diff --git a/bouncer/src/Bouncer.php b/bouncer/src/Bouncer.php index 0eb4228..ef1d04e 100644 --- a/bouncer/src/Bouncer.php +++ b/bouncer/src/Bouncer.php @@ -280,6 +280,12 @@ class Bouncer $bouncerTarget->setLabel($service['Spec']['Name']); $bouncerTarget = $this->parseContainerEnvironmentVariables($envs, $bouncerTarget); + if ($bouncerTarget->hasCustomNginxConfig()) { + $this->logger->info('Custom nginx config for {label} is provided.', ['emoji' => Emoji::artistPalette(), 'label' => $bouncerTarget->getLabel()]); + $bouncerTargets[] = $bouncerTarget; + + continue; + } if ($bouncerTarget->isPortSet()) { $bouncerTarget->setEndpointHostnameOrIp($service['Spec']['Name']); // $this->logger->info('{label}: Ports for {target_name} has been explicitly set to {host}:{port}.', ['emoji' => Emoji::warning().' ', 'target_name' => $bouncerTarget->getName(), 'host' => $bouncerTarget->getEndpointHostnameOrIp(), 'port' => $bouncerTarget->getPort()]); @@ -300,7 +306,7 @@ class Bouncer $bouncerTarget->setUseGlobalCert($this->isUseGlobalCert()); - if ($bouncerTarget->isEndpointValid()) { + if ($bouncerTarget->isEndpointValid() || $bouncerTarget->hasCustomNginxConfig()) { $bouncerTargets[] = $bouncerTarget; } else { $this->logger->debug( @@ -438,6 +444,16 @@ class Bouncer case 'BOUNCER_PROXY_TIMEOUT_SECONDS': $bouncerTarget->setProxyTimeoutSeconds(is_numeric($envVal) ? intval($envVal) : null); + break; + + case 'BOUNCER_CUSTOM_NGINX_CONFIG': + // If envval is base64 encoded, decode it first + if (base64_encode(base64_decode($envVal, true)) === $envVal) { + $envVal = base64_decode($envVal); + } + $this->logger->info('Custom nginx config for {label} is provided.', ['emoji' => Emoji::artistPalette(), 'label' => $bouncerTarget->getLabel()]); + $bouncerTarget->setCustomNginxConfig($envVal); + break; } } @@ -804,7 +820,7 @@ class Bouncer */ private function generateNginxConfig(Target $target): bool { - $configData = $this->twig->render('NginxTemplate.twig', $target->__toArray()); + $configData = $target->hasCustomNginxConfig() ? $target->getCustomNginxConfig() : $this->twig->render('NginxTemplate.twig', $target->__toArray()); $changed = false; $configFileHash = $this->configFilesystem->fileExists($target->getNginxConfigFileName()) ? sha1($this->configFilesystem->read($target->getNginxConfigFileName())) : null; diff --git a/bouncer/src/Target.php b/bouncer/src/Target.php index ce5c12c..f88477f 100644 --- a/bouncer/src/Target.php +++ b/bouncer/src/Target.php @@ -28,7 +28,8 @@ class Target private ?string $username = null; private ?string $password = null; - private ?string $hostOverride = null; + private ?string $hostOverride = null; + private ?string $customNginxConfig = null; public function __construct( private Logger $logger, @@ -462,4 +463,21 @@ class Target $this->getName() ); } + + public function setCustomNginxConfig(string $config): self + { + $this->customNginxConfig = $config; + + return $this; + } + + public function getCustomNginxConfig(): ?string + { + return $this->customNginxConfig; + } + + public function hasCustomNginxConfig(): bool + { + return $this->customNginxConfig !== null; + } }