add docker-socket-proxy as option

Signed-off-by: Simon L <szaimen@e.mail.de>
This commit is contained in:
Simon L 2023-08-24 14:09:21 +02:00
parent 7e5fe5ac8e
commit 6685791427
14 changed files with 236 additions and 7 deletions

View file

@ -120,7 +120,8 @@
"nextcloud-aio-clamav",
"nextcloud-aio-fulltextsearch",
"nextcloud-aio-talk-recording",
"nextcloud-aio-imaginary"
"nextcloud-aio-imaginary",
"nextcloud-aio-docker-socket-proxy"
],
"display_name": "Nextcloud",
"image": "nextcloud/aio-nextcloud",
@ -203,7 +204,8 @@
"TALK_RECORDING_ENABLED=%TALK_RECORDING_ENABLED%",
"RECORDING_SECRET=%RECORDING_SECRET%",
"TALK_RECORDING_HOST=nextcloud-aio-talk-recording",
"FULLTEXTSEARCH_PASSWORD=%FULLTEXTSEARCH_PASSWORD%"
"FULLTEXTSEARCH_PASSWORD=%FULLTEXTSEARCH_PASSWORD%",
"DOCKER_SOCKET_PROXY_ENABLED=%DOCKER_SOCKET_PROXY_ENABLED%"
],
"restart": "unless-stopped",
"devices": [
@ -639,6 +641,29 @@
"secrets": [
"FULLTEXTSEARCH_PASSWORD"
]
},
{
"container_name": "nextcloud-aio-docker-socket-proxy",
"display_name": "Docker Socket Proxy",
"image": "nextcloud/aio-docker-socket-proxy",
"init": true,
"internal_port": "2375",
"environment": [
"TZ=%TIMEZONE%"
],
"volumes": [
{
"source": "%WATCHTOWER_DOCKER_SOCKET_PATH%",
"destination": "/var/run/docker.sock",
"writeable": false
}
],
"restart": "unless-stopped",
"read_only": true,
"tmpfs": [
"/run/",
"/var/lib/haproxy"
]
}
]
}

View file

@ -0,0 +1,4 @@
document.addEventListener("DOMContentLoaded", function(event) {
// Docker socket proxy
document.getElementById("docker-socket-proxy").disabled = true;
});

View file

@ -121,6 +121,7 @@ $app->get('/containers', function (Request $request, Response $response, array $
'nextcloud_memory_limit' => $configurationManager->GetNextcloudMemoryLimit(),
'is_dri_device_enabled' => $configurationManager->isDriDeviceEnabled(),
'is_talk_recording_enabled' => $configurationManager->isTalkRecordingEnabled(),
'is_docker_socket_proxy_enabled' => $configurationManager->isDockerSocketProxyEnabled(),
]);
})->setName('profile');
$app->get('/login', function (Request $request, Response $response, array $args) use ($container) {

View file

@ -14,6 +14,13 @@ function handleTalkVisibility() {
}
}
function handleDockerSocketProxyWarning() {
let dockerSocketProxy = document.getElementById("docker-socket-proxy");
if (dockerSocketProxy.checked) {
alert('⚠️ Warning! Enabling this container comes with possible Security problems since you are exposing the docker socket and all its privileges to the Nextcloud container. Enable this only if you are sure what you are doing!')
}
}
document.addEventListener("DOMContentLoaded", function(event) {
// handle submit button for options form
let optionsFormSubmit = document.getElementById("options-form-submit");
@ -52,4 +59,9 @@ document.addEventListener("DOMContentLoaded", function(event) {
// Fulltextsearch
let fulltextsearch = document.getElementById("fulltextsearch");
fulltextsearch.addEventListener('change', makeOptionsFormSubmitVisible);
// Docker socket proxy
let dockerSocketProxy = document.getElementById("docker-socket-proxy");
dockerSocketProxy.addEventListener('change', makeOptionsFormSubmitVisible);
dockerSocketProxy.addEventListener('change', handleDockerSocketProxyWarning);
});

View file

@ -93,6 +93,10 @@ class ContainerDefinitionFetcher
if (!$this->configurationManager->isFulltextsearchEnabled()) {
continue;
}
} elseif ($entry['container_name'] === 'nextcloud-aio-docker-socket-proxy') {
if (!$this->configurationManager->isDockerSocketProxyEnabled()) {
continue;
}
}
$ports = new ContainerPorts();
@ -195,6 +199,10 @@ class ContainerDefinitionFetcher
if (!$this->configurationManager->isFulltextsearchEnabled()) {
continue;
}
} elseif ($value === 'nextcloud-aio-docker-socket-proxy') {
if (!$this->configurationManager->isDockerSocketProxyEnabled()) {
continue;
}
}
$dependsOn[] = $value;
}

View file

@ -110,6 +110,11 @@ class ConfigurationController
} else {
$this->configurationManager->SetFulltextsearchEnabledState(0);
}
if (isset($request->getParsedBody()['docker-socket-proxy'])) {
$this->configurationManager->SetDockerSocketProxyEnabledState(1);
} else {
$this->configurationManager->SetDockerSocketProxyEnabledState(0);
}
}
if (isset($request->getParsedBody()['delete_collabora_dictionaries'])) {

View file

@ -149,6 +149,21 @@ class ConfigurationManager
}
}
public function isDockerSocketProxyEnabled() : bool {
$config = $this->GetConfig();
if (isset($config['isDockerSocketProxyEnabled']) && $config['isDockerSocketProxyEnabled'] === 1) {
return true;
} else {
return false;
}
}
public function SetDockerSocketProxyEnabledState(int $value) : void {
$config = $this->GetConfig();
$config['isDockerSocketProxyEnabled'] = $value;
$this->WriteConfig($config);
}
public function SetClamavEnabledState(int $value) : void {
$config = $this->GetConfig();
$config['isClamavEnabled'] = $value;

View file

@ -346,6 +346,12 @@ class DockerActionManager
} else {
$replacements[1] = '';
}
} elseif ($out[1] === 'DOCKER_SOCKET_PROXY_ENABLED') {
if ($this->configurationManager->isDockerSocketProxyEnabled()) {
$replacements[1] = 'yes';
} else {
$replacements[1] = '';
}
} elseif ($out[1] === 'NEXTCLOUD_UPLOAD_LIMIT') {
$replacements[1] = $this->configurationManager->GetNextcloudUploadLimit();
} elseif ($out[1] === 'NEXTCLOUD_MEMORY_LIMIT') {
@ -406,7 +412,11 @@ class DockerActionManager
$portWithProtocol = $value->port . '/' . $value->protocol;
$exposedPorts[$portWithProtocol] = null;
}
$requestBody['HostConfig']['NetworkMode'] = 'nextcloud-aio';
if ($container->GetIdentifier() !== 'nextcloud-aio-docker-socket-proxy') {
$requestBody['HostConfig']['NetworkMode'] = 'nextcloud-aio';
} else {
$requestBody['HostConfig']['NetworkMode'] = 'nextcloud-aio-docker-socket-proxy-network';
}
} else {
$requestBody['HostConfig']['NetworkMode'] = 'host';
}
@ -763,13 +773,12 @@ class DockerActionManager
}
}
private function ConnectContainerIdToNetwork(string $id, string $internalPort) : void
private function ConnectContainerIdToNetwork(string $id, string $internalPort, string $network = 'nextcloud-aio') : void
{
if ($internalPort === 'host') {
return;
}
$network = 'nextcloud-aio';
$url = $this->BuildApiUrl('networks/create');
try {
$this->guzzleClient->request(
@ -777,7 +786,7 @@ class DockerActionManager
$url,
[
'json' => [
'Name' => 'nextcloud-aio',
'Name' => $network,
'CheckDuplicate' => true,
'Driver' => 'bridge',
'Internal' => false,
@ -815,13 +824,17 @@ class DockerActionManager
public function ConnectMasterContainerToNetwork() : void
{
$this->ConnectContainerIdToNetwork('nextcloud-aio-mastercontainer', '');
$this->ConnectContainerIdToNetwork('nextcloud-aio-mastercontainer', '', 'nextcloud-aio-docker-socket-proxy-network');
// Don't disconnect here since it slows down the initial login by a lot. Is getting done during cron.sh instead.
// $this->DisconnectContainerFromBridgeNetwork('nextcloud-aio-mastercontainer');
}
public function ConnectContainerToNetwork(Container $container) : void
{
$this->ConnectContainerIdToNetwork($container->GetIdentifier(), $container->GetInternalPort());
$this->ConnectContainerIdToNetwork($container->GetIdentifier(), $container->GetInternalPort());
if ($container->GetIdentifier() === 'nextcloud-aio-nextcloud' || $container->GetIdentifier() === 'nextcloud-aio-docker-socket-proxy') {
$this->ConnectContainerIdToNetwork($container->GetIdentifier(), $container->GetInternalPort(), 'nextcloud-aio-docker-socket-proxy-network');
}
}
public function StopContainer(Container $container) : void {

View file

@ -574,6 +574,11 @@
{% else %}
{#<input type="checkbox" id="onlyoffice" name="onlyoffice"><label for="onlyoffice">OnlyOffice</label><br>#}
{% endif %}
{% if is_docker_socket_proxy_enabled == true %}
<input type="checkbox" id="docker-socket-proxy" name="docker-socket-proxy" checked="checked"><label for="docker-socket-proxy">Docker Socket Proxy (needed for app-ecosystem v2)</label><br><br>
{% else %}
<input type="checkbox" id="docker-socket-proxy" name="docker-socket-proxy"><label for="docker-socket-proxy">Docker Socket Proxy (needed for app-ecosystem v2)</label><br><br>
{% endif %}
<input id="options-form-submit" class="button" type="submit" value="Save changes" />
<script type="text/javascript" src="options-form-submit.js"></script>
</form>