From c0767f72840759d0f92b78bbbd3b7a0f7e6af48b Mon Sep 17 00:00:00 2001 From: Marc Scholten Date: Tue, 12 Nov 2024 14:52:04 -0800 Subject: [PATCH] nixos: add sessionSecretFile option Closes https://github.com/digitallyinduced/ihp/issues/1985 --- IHP/Server.hs | 12 ++++++--- NixSupport/nixosModules/app.nix | 1 + NixSupport/nixosModules/options.nix | 15 +++++++++++ .../nixosModules/services/app-keygen.nix | 27 +++++++++++++++++++ NixSupport/nixosModules/services/app.nix | 4 +-- NixSupport/nixosModules/services/worker.nix | 4 +-- flake.nix | 1 + 7 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 NixSupport/nixosModules/services/app-keygen.nix diff --git a/IHP/Server.hs b/IHP/Server.hs index 3103cc4a5..5e37c77a2 100644 --- a/IHP/Server.hs +++ b/IHP/Server.hs @@ -110,11 +110,17 @@ initSessionMiddleware FrameworkConfig { sessionCookie } = do let path = "Config/client_session_key.aes" hasSessionSecretEnvVar <- EnvVar.hasEnvVar "IHP_SESSION_SECRET" + hasSessionSecretFileEnvVar <- EnvVar.hasEnvVar "IHP_SESSION_SECRET_FILE" doesConfigDirectoryExist <- Directory.doesDirectoryExist "Config" store <- clientsessionStore <$> - if hasSessionSecretEnvVar || not doesConfigDirectoryExist - then ClientSession.getKeyEnv "IHP_SESSION_SECRET" - else ClientSession.getKey path + if hasSessionSecretFileEnvVar + then do + path <- EnvVar.env "IHP_SESSION_SECRET_FILE" + ClientSession.getKey path + else + if hasSessionSecretEnvVar || not doesConfigDirectoryExist + then ClientSession.getKeyEnv "IHP_SESSION_SECRET" + else ClientSession.getKey path let sessionMiddleware :: Middleware = withSession store "SESSION" sessionCookie sessionVaultKey pure sessionMiddleware diff --git a/NixSupport/nixosModules/app.nix b/NixSupport/nixosModules/app.nix index 96fa8a22f..7b339577d 100644 --- a/NixSupport/nixosModules/app.nix +++ b/NixSupport/nixosModules/app.nix @@ -9,6 +9,7 @@ in ihp.nixosModules.services_app ihp.nixosModules.services_worker ihp.nixosModules.services_migrate + ihp.nixosModules.services_appKeygen ]; # Pin the nixpkgs to the IHP nixpkgs diff --git a/NixSupport/nixosModules/options.nix b/NixSupport/nixosModules/options.nix index 952d571f6..d1b24dc55 100644 --- a/NixSupport/nixosModules/options.nix +++ b/NixSupport/nixosModules/options.nix @@ -68,6 +68,21 @@ with lib; sessionSecret = mkOption { type = types.str; + descriptiom = '' + It's recommended to use sessionSecretFile instead + ''; + }; + + sessionSecretFile = mkOption { + type = types.path; + default = "/var/ihp/session.aes"; + descriptiom = '' + The session secret is stored here. + + If the file doesn't exists, the service will generate a new key automatically. + + When the key changes all users need to relogin. + ''; }; additionalEnvVars = mkOption { diff --git a/NixSupport/nixosModules/services/app-keygen.nix b/NixSupport/nixosModules/services/app-keygen.nix new file mode 100644 index 000000000..9664c1a8f --- /dev/null +++ b/NixSupport/nixosModules/services/app-keygen.nix @@ -0,0 +1,27 @@ +{ config, pkgs, modulesPath, lib, self, ... }: +let + cfg = config.services.ihp; + openssl = "${pkgs.openssl}/bin/openssl"; + base64 = "${pkgs.coreutils}/bin/base64"; +in +{ + systemd.services.app-keygen = { + description = "App Session Key Generation"; + wantedBy = [ "multi-user.target" ]; + before = [ "app.service" ]; + script = '' + mkdir -p "$(dirname "${cfg.sessionSecretFile}")" + + if [ -n "${cfg.sessionSecret or ""}" ]; then + # If sessionSecret is set, decode and write it to the file + echo "${cfg.sessionSecret}" | ${base64} -d > "${cfg.sessionSecretFile}" + elif [ ! -f "${cfg.sessionSecretFile}" ]; then + # If sessionSecret is not set, generate a new secret + ${openssl} rand 96 > "${cfg.sessionSecretFile}" + fi + + chmod 600 "${cfg.sessionSecretFile}" + ''; + serviceConfig.Type = "oneshot"; + }; +} \ No newline at end of file diff --git a/NixSupport/nixosModules/services/app.nix b/NixSupport/nixosModules/services/app.nix index 8311dc629..bbba77299 100644 --- a/NixSupport/nixosModules/services/app.nix +++ b/NixSupport/nixosModules/services/app.nix @@ -6,7 +6,7 @@ in systemd.services.app = { description = "IHP App"; enable = true; - after = [ "network.target" ]; + after = [ "network.target" "app-keygen.service" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "simple"; @@ -22,7 +22,7 @@ in IHP_BASEURL = cfg.baseUrl; IHP_REQUEST_LOGGER_IP_ADDR_SOURCE = cfg.requestLoggerIPAddrSource; DATABASE_URL = cfg.databaseUrl; - IHP_SESSION_SECRET = cfg.sessionSecret; + IHP_SESSION_SECRET_FILE = cfg.sessionSecretFile; GHCRTS = cfg.rtsFlags; }; in diff --git a/NixSupport/nixosModules/services/worker.nix b/NixSupport/nixosModules/services/worker.nix index c0ba77dda..84e1eea8b 100644 --- a/NixSupport/nixosModules/services/worker.nix +++ b/NixSupport/nixosModules/services/worker.nix @@ -5,7 +5,7 @@ in { systemd.services.worker = { enable = true; - after = [ "network.target" ]; + after = [ "network.target" "app-keygen.service" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "simple"; @@ -21,7 +21,7 @@ in IHP_BASEURL = cfg.baseUrl; IHP_REQUEST_LOGGER_IP_ADDR_SOURCE = cfg.requestLoggerIPAddrSource; DATABASE_URL = cfg.databaseUrl; - IHP_SESSION_SECRET = cfg.sessionSecret; + IHP_SESSION_SECRET_FILE = cfg.sessionSecretFile; GHCRTS = cfg.rtsFlags; }; in diff --git a/flake.nix b/flake.nix index 3301cee59..42441f16c 100644 --- a/flake.nix +++ b/flake.nix @@ -47,6 +47,7 @@ services_worker = ./NixSupport/nixosModules/services/worker.nix; services_migrate = ./NixSupport/nixosModules/services/migrate.nix; services_loadSchema = ./NixSupport/nixosModules/services/loadSchema.nix; + services_appKeygen = ./NixSupport/nixosModules/services/app-keygen.nix; options = ./NixSupport/nixosModules/options.nix; binaryCache = ./NixSupport/nixosModules/binaryCache.nix; };