diff options
author | Maximilian Bosch <maximilian@mbosch.me> | 2022-11-20 18:32:41 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-20 18:32:41 +0100 |
commit | 2580440389de71ae590fbb3b9cfeee8a8743eebb (patch) | |
tree | ea4ad72cb635d52579f63931b94a1de092477a73 /nixos | |
parent | 8c6c94de4cf1d529079113efda85ad43a0d1556d (diff) | |
parent | 35b146ca31ea5f6cfdeee11dc7ca737fa9fbc1dd (diff) |
Merge pull request #198470 from RaitoBezarius/nc25-openssl
nextcloud25: use openssl 1.1 as a PHP extension to fix RC4 encryption
Diffstat (limited to 'nixos')
-rw-r--r-- | nixos/doc/manual/from_md/release-notes/rl-2211.section.xml | 17 | ||||
-rw-r--r-- | nixos/doc/manual/release-notes/rl-2211.section.md | 7 | ||||
-rw-r--r-- | nixos/modules/services/web-apps/nextcloud.nix | 58 | ||||
-rw-r--r-- | nixos/modules/services/web-apps/nextcloud.xml | 14 | ||||
-rw-r--r-- | nixos/tests/nextcloud/basic.nix | 7 | ||||
-rw-r--r-- | nixos/tests/nextcloud/default.nix | 4 | ||||
-rw-r--r-- | nixos/tests/nextcloud/openssl-sse.nix | 105 |
7 files changed, 211 insertions, 1 deletions
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml index a1e01bd92921e..c56cfb10538bb 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml @@ -631,6 +631,23 @@ </listitem> <listitem> <para> + The <literal>openssl</literal>-extension for the PHP + interpreter used by Nextcloud is built against OpenSSL 1.1 if + <xref linkend="opt-system.stateVersion" /> is below + <literal>22.11</literal>. This is to make sure that people + using + <link xlink:href="https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/encryption_configuration.html">server-side + encryption</link> don’t loose access to their files. + </para> + <para> + In any other case it’s safe to use OpenSSL 3 for PHP’s openssl + extension. This can be done by setting + <xref linkend="opt-services.nextcloud.enableBrokenCiphersForSSE" /> + to <literal>false</literal>. + </para> + </listitem> + <listitem> + <para> The <literal>coq</literal> package and versioned variants starting at <literal>coq_8_14</literal> no longer include CoqIDE, which is now available through diff --git a/nixos/doc/manual/release-notes/rl-2211.section.md b/nixos/doc/manual/release-notes/rl-2211.section.md index 642009e9f44e4..5daafa8e986b4 100644 --- a/nixos/doc/manual/release-notes/rl-2211.section.md +++ b/nixos/doc/manual/release-notes/rl-2211.section.md @@ -204,6 +204,13 @@ Available as [services.patroni](options.html#opt-services.patroni.enable). - The `p4` package now only includes the open-source Perforce Helix Core command-line client and APIs. It no longer installs the unfree Helix Core Server binaries `p4d`, `p4broker`, and `p4p`. To install the Helix Core Server binaries, use the `p4d` package instead. +- The `openssl`-extension for the PHP interpreter used by Nextcloud is built against OpenSSL 1.1 if + [](#opt-system.stateVersion) is below `22.11`. This is to make sure that people using [server-side encryption](https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/encryption_configuration.html) + don't loose access to their files. + + In any other case it's safe to use OpenSSL 3 for PHP's openssl extension. This can be done by setting + [](#opt-services.nextcloud.enableBrokenCiphersForSSE) to `false`. + - The `coq` package and versioned variants starting at `coq_8_14` no longer include CoqIDE, which is now available through `coqPackages.coqide`. It is still possible to get CoqIDE as part of diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix index 04599884f139c..da621573f2a26 100644 --- a/nixos/modules/services/web-apps/nextcloud.nix +++ b/nixos/modules/services/web-apps/nextcloud.nix @@ -13,7 +13,12 @@ let phpPackage = cfg.phpPackage.buildEnv { extensions = { enabled, all }: (with all; - enabled + # disable default openssl extension + (lib.filter (e: e.pname != "php-openssl") enabled) + # use OpenSSL 1.1 for RC4 Nextcloud encryption if user + # has acknowledged the brokeness of the ciphers (RC4). + # TODO: remove when https://github.com/nextcloud/server/issues/32003 is fixed. + ++ (if cfg.enableBrokenCiphersForSSE then [ cfg.phpPackage.extensions.openssl-legacy ] else [ cfg.phpPackage.extensions.openssl ]) ++ optional cfg.enableImagemagick imagick # Optionally enabled depending on caching settings ++ optional cfg.caching.apcu apcu @@ -80,6 +85,40 @@ in { options.services.nextcloud = { enable = mkEnableOption (lib.mdDoc "nextcloud"); + + enableBrokenCiphersForSSE = mkOption { + type = types.bool; + default = versionOlder stateVersion "22.11"; + defaultText = literalExpression "versionOlder system.stateVersion \"22.11\""; + description = lib.mdDoc '' + This option enables using the OpenSSL PHP extension linked against OpenSSL 1.1 + rather than latest OpenSSL (≥ 3), this is not recommended unless you need + it for server-side encryption (SSE). SSE uses the legacy RC4 cipher which is + considered broken for several years now. See also [RFC7465](https://datatracker.ietf.org/doc/html/rfc7465). + + This cipher has been disabled in OpenSSL ≥ 3 and requires + a specific legacy profile to re-enable it. + + If you deploy Nextcloud using OpenSSL ≥ 3 for PHP and have + server-side encryption configured, you will not be able to access + your files anymore. Enabling this option can restore access to your files. + Upon testing we didn't encounter any data corruption when turning + this on and off again, but this cannot be guaranteed for + each Nextcloud installation. + + It is `true` by default for systems with a [](#opt-system.stateVersion) below + `22.11` to make sure that existing installations won't break on update. On newer + NixOS systems you have to explicitly enable it on your own. + + Please note that this only provides additional value when using + external storage such as S3 since it's not an end-to-end encryption. + If this is not the case, + it is advised to [disable server-side encryption](https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/encryption_configuration.html#disabling-encryption) and set this to `false`. + + In the future, Nextcloud may move to AES-256-GCM, by then, + this option will be removed. + ''; + }; hostName = mkOption { type = types.str; description = lib.mdDoc "FQDN for the nextcloud instance."; @@ -649,6 +688,23 @@ in { ++ (optional (versionOlder cfg.package.version "23") (upgradeWarning 22 "22.05")) ++ (optional (versionOlder cfg.package.version "24") (upgradeWarning 23 "22.05")) ++ (optional (versionOlder cfg.package.version "25") (upgradeWarning 24 "22.11")) + ++ (optional cfg.enableBrokenCiphersForSSE '' + You're using PHP's openssl extension built against OpenSSL 1.1 for Nextcloud. + This is only necessary if you're using Nextcloud's server-side encryption. + Please keep in mind that it's using the broken RC4 cipher. + + If you don't use that feature, you can switch to OpenSSL 3 and get + rid of this warning by declaring + + services.nextcloud.enableBrokenCiphersForSSE = false; + + If you need to use server-side encryption you can ignore this waring. + Otherwise you'd have to disable server-side encryption first in order + to be able to safely disable this option and get rid of this warning. + See <https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/encryption_configuration.html#disabling-encryption> on how to achieve this. + + For more context, here is the implementing pull request: https://github.com/NixOS/nixpkgs/pull/198470 + '') ++ (optional isUnsupportedMariadb '' You seem to be using MariaDB at an unsupported version (i.e. at least 10.6)! Please note that this isn't supported officially by Nextcloud. You can either diff --git a/nixos/modules/services/web-apps/nextcloud.xml b/nixos/modules/services/web-apps/nextcloud.xml index a0b69dbd606ce..ca57692fc16a8 100644 --- a/nixos/modules/services/web-apps/nextcloud.xml +++ b/nixos/modules/services/web-apps/nextcloud.xml @@ -170,6 +170,20 @@ </listitem> </itemizedlist> </listitem> + <listitem> + <formalpara> + <title>Server-side encryption</title> + <para> + Nextcloud supports <link xlink:href="https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/encryption_configuration.html">server-side encryption (SSE)</link>. + This is not an end-to-end encryption, but can be used to encrypt files that will be persisted + to external storage such as S3. Please note that this won't work anymore when using OpenSSL 3 + for PHP's openssl extension because this is implemented using the legacy cipher RC4. + If <xref linkend="opt-system.stateVersion" /> is <emphasis>above</emphasis> <literal>22.05</literal>, + this is disabled by default. To turn it on again and for further information please refer to + <xref linkend="opt-services.nextcloud.enableBrokenCiphersForSSE" />. + </para> + </formalpara> + </listitem> </itemizedlist> </section> diff --git a/nixos/tests/nextcloud/basic.nix b/nixos/tests/nextcloud/basic.nix index eb37470a4c7bb..a475049e7b264 100644 --- a/nixos/tests/nextcloud/basic.nix +++ b/nixos/tests/nextcloud/basic.nix @@ -37,6 +37,8 @@ in { "d /var/lib/nextcloud-data 0750 nextcloud nginx - -" ]; + system.stateVersion = "22.11"; # stateVersion >=21.11 to make sure that we use OpenSSL3 + services.nextcloud = { enable = true; datadir = "/var/lib/nextcloud-data"; @@ -99,6 +101,10 @@ in { # This is just to ensure the nextcloud-occ program is working nextcloud.succeed("nextcloud-occ status") nextcloud.succeed("curl -sSf http://nextcloud/login") + # Ensure that no OpenSSL 1.1 is used. + nextcloud.succeed( + "${nodes.nextcloud.services.phpfpm.pools.nextcloud.phpPackage}/bin/php -i | grep 'OpenSSL Library Version' | awk -F'=>' '{ print $2 }' | awk '{ print $2 }' | grep -v 1.1" + ) nextcloud.succeed( "${withRcloneEnv} ${copySharedFile}" ) @@ -108,5 +114,6 @@ in { "${withRcloneEnv} ${diffSharedFile}" ) assert "hi" in client.succeed("cat /mnt/dav/test-shared-file") + nextcloud.succeed("grep -vE '^HBEGIN:oc_encryption_module' /var/lib/nextcloud-data/data/root/files/test-shared-file") ''; })) args diff --git a/nixos/tests/nextcloud/default.nix b/nixos/tests/nextcloud/default.nix index 7dbdff9882387..b8d3ba75b51a9 100644 --- a/nixos/tests/nextcloud/default.nix +++ b/nixos/tests/nextcloud/default.nix @@ -8,6 +8,10 @@ with pkgs.lib; foldl (matrix: ver: matrix // { "basic${toString ver}" = import ./basic.nix { inherit system pkgs; nextcloudVersion = ver; }; + "openssl-sse${toString ver}" = import ./openssl-sse.nix { + inherit system pkgs; + nextcloudVersion = ver; + }; "with-postgresql-and-redis${toString ver}" = import ./with-postgresql-and-redis.nix { inherit system pkgs; nextcloudVersion = ver; diff --git a/nixos/tests/nextcloud/openssl-sse.nix b/nixos/tests/nextcloud/openssl-sse.nix new file mode 100644 index 0000000000000..7595ee2c67e31 --- /dev/null +++ b/nixos/tests/nextcloud/openssl-sse.nix @@ -0,0 +1,105 @@ +args@{ pkgs, nextcloudVersion ? 25, ... }: + +(import ../make-test-python.nix ({ pkgs, ...}: let + adminuser = "root"; + adminpass = "notproduction"; + nextcloudBase = { + networking.firewall.allowedTCPPorts = [ 80 ]; + system.stateVersion = "22.05"; # stateVersions <22.11 use openssl 1.1 by default + services.nextcloud = { + enable = true; + config.adminpassFile = "${pkgs.writeText "adminpass" adminpass}"; + package = pkgs.${"nextcloud" + (toString nextcloudVersion)}; + }; + }; +in { + name = "nextcloud-openssl"; + meta = with pkgs.lib.maintainers; { + maintainers = [ ma27 ]; + }; + nodes.nextcloudwithopenssl1 = { + imports = [ nextcloudBase ]; + services.nextcloud.hostName = "nextcloudwithopenssl1"; + }; + nodes.nextcloudwithopenssl3 = { + imports = [ nextcloudBase ]; + services.nextcloud = { + hostName = "nextcloudwithopenssl3"; + enableBrokenCiphersForSSE = false; + }; + }; + testScript = { nodes, ... }: let + withRcloneEnv = host: pkgs.writeScript "with-rclone-env" '' + #!${pkgs.runtimeShell} + export RCLONE_CONFIG_NEXTCLOUD_TYPE=webdav + export RCLONE_CONFIG_NEXTCLOUD_URL="http://${host}/remote.php/webdav/" + export RCLONE_CONFIG_NEXTCLOUD_VENDOR="nextcloud" + export RCLONE_CONFIG_NEXTCLOUD_USER="${adminuser}" + export RCLONE_CONFIG_NEXTCLOUD_PASS="$(${pkgs.rclone}/bin/rclone obscure ${adminpass})" + "''${@}" + ''; + withRcloneEnv1 = withRcloneEnv "nextcloudwithopenssl1"; + withRcloneEnv3 = withRcloneEnv "nextcloudwithopenssl3"; + copySharedFile1 = pkgs.writeScript "copy-shared-file" '' + #!${pkgs.runtimeShell} + echo 'hi' | ${withRcloneEnv1} ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file + ''; + copySharedFile3 = pkgs.writeScript "copy-shared-file" '' + #!${pkgs.runtimeShell} + echo 'bye' | ${withRcloneEnv3} ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file2 + ''; + openssl1-node = nodes.nextcloudwithopenssl1.config.system.build.toplevel; + openssl3-node = nodes.nextcloudwithopenssl3.config.system.build.toplevel; + in '' + nextcloudwithopenssl1.start() + nextcloudwithopenssl1.wait_for_unit("multi-user.target") + nextcloudwithopenssl1.succeed("nextcloud-occ status") + nextcloudwithopenssl1.succeed("curl -sSf http://nextcloudwithopenssl1/login") + + with subtest("With OpenSSL 1 SSE can be enabled and used"): + nextcloudwithopenssl1.succeed("nextcloud-occ app:enable encryption") + nextcloudwithopenssl1.succeed("nextcloud-occ encryption:enable") + + with subtest("Upload file and ensure it's encrypted"): + nextcloudwithopenssl1.succeed("${copySharedFile1}") + nextcloudwithopenssl1.succeed("grep -E '^HBEGIN:oc_encryption_module' /var/lib/nextcloud/data/root/files/test-shared-file") + nextcloudwithopenssl1.succeed("${withRcloneEnv1} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file | grep hi") + + with subtest("Switch to OpenSSL 3"): + nextcloudwithopenssl1.succeed("${openssl3-node}/bin/switch-to-configuration test") + nextcloudwithopenssl1.wait_for_open_port(80) + nextcloudwithopenssl1.succeed("nextcloud-occ status") + + with subtest("Existing encrypted files cannot be read, but new files can be added"): + nextcloudwithopenssl1.fail("${withRcloneEnv3} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file >&2") + nextcloudwithopenssl1.succeed("nextcloud-occ encryption:disable") + nextcloudwithopenssl1.succeed("${copySharedFile3}") + nextcloudwithopenssl1.succeed("grep bye /var/lib/nextcloud/data/root/files/test-shared-file2") + nextcloudwithopenssl1.succeed("${withRcloneEnv3} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file2 | grep bye") + + with subtest("Switch back to OpenSSL 1.1 and ensure that encrypted files are readable again"): + nextcloudwithopenssl1.succeed("${openssl1-node}/bin/switch-to-configuration test") + nextcloudwithopenssl1.wait_for_open_port(80) + nextcloudwithopenssl1.succeed("nextcloud-occ status") + nextcloudwithopenssl1.succeed("nextcloud-occ encryption:enable") + nextcloudwithopenssl1.succeed("${withRcloneEnv1} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file2 | grep bye") + nextcloudwithopenssl1.succeed("${withRcloneEnv1} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file | grep hi") + nextcloudwithopenssl1.succeed("grep -E '^HBEGIN:oc_encryption_module' /var/lib/nextcloud/data/root/files/test-shared-file") + nextcloudwithopenssl1.succeed("grep bye /var/lib/nextcloud/data/root/files/test-shared-file2") + + with subtest("Ensure that everything can be decrypted"): + nextcloudwithopenssl1.succeed("echo y | nextcloud-occ encryption:decrypt-all >&2") + nextcloudwithopenssl1.succeed("${withRcloneEnv1} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file2 | grep bye") + nextcloudwithopenssl1.succeed("${withRcloneEnv1} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file | grep hi") + nextcloudwithopenssl1.succeed("grep -vE '^HBEGIN:oc_encryption_module' /var/lib/nextcloud/data/root/files/test-shared-file") + + with subtest("Switch to OpenSSL 3 ensure that all files are usable now"): + nextcloudwithopenssl1.succeed("${openssl3-node}/bin/switch-to-configuration test") + nextcloudwithopenssl1.wait_for_open_port(80) + nextcloudwithopenssl1.succeed("nextcloud-occ status") + nextcloudwithopenssl1.succeed("${withRcloneEnv3} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file2 | grep bye") + nextcloudwithopenssl1.succeed("${withRcloneEnv3} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file | grep hi") + + nextcloudwithopenssl1.shutdown() + ''; +})) args |