at 23.11-pre 4.9 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.dex; 7 fixClient = client: if client ? secretFile then ((builtins.removeAttrs client [ "secretFile" ]) // { secret = client.secretFile; }) else client; 8 filteredSettings = mapAttrs (n: v: if n == "staticClients" then (builtins.map fixClient v) else v) cfg.settings; 9 secretFiles = flatten (builtins.map (c: if c ? secretFile then [ c.secretFile ] else []) (cfg.settings.staticClients or [])); 10 11 settingsFormat = pkgs.formats.yaml {}; 12 configFile = settingsFormat.generate "config.yaml" filteredSettings; 13 14 startPreScript = pkgs.writeShellScript "dex-start-pre" 15 (concatStringsSep "\n" (map (file: '' 16 replace-secret '${file}' '${file}' /run/dex/config.yaml 17 '') 18 secretFiles)); 19in 20{ 21 options.services.dex = { 22 enable = mkEnableOption (lib.mdDoc "the OpenID Connect and OAuth2 identity provider"); 23 24 environmentFile = mkOption { 25 type = types.nullOr types.path; 26 default = null; 27 description = lib.mdDoc '' 28 Environment file (see `systemd.exec(5)` 29 "EnvironmentFile=" section for the syntax) to define variables for dex. 30 This option can be used to safely include secret keys into the dex configuration. 31 ''; 32 }; 33 34 settings = mkOption { 35 type = settingsFormat.type; 36 default = {}; 37 example = literalExpression '' 38 { 39 # External url 40 issuer = "http://127.0.0.1:5556/dex"; 41 storage = { 42 type = "postgres"; 43 config.host = "/var/run/postgres"; 44 }; 45 web = { 46 http = "127.0.0.1:5556"; 47 }; 48 enablePasswordDB = true; 49 staticClients = [ 50 { 51 id = "oidcclient"; 52 name = "Client"; 53 redirectURIs = [ "https://example.com/callback" ]; 54 secretFile = "/etc/dex/oidcclient"; # The content of `secretFile` will be written into to the config as `secret`. 55 } 56 ]; 57 } 58 ''; 59 description = lib.mdDoc '' 60 The available options can be found in 61 [the example configuration](https://github.com/dexidp/dex/blob/v${pkgs.dex-oidc.version}/config.yaml.dist). 62 63 It's also possible to refer to environment variables (defined in [services.dex.environmentFile](#opt-services.dex.environmentFile)) 64 using the syntax `$VARIABLE_NAME`. 65 ''; 66 }; 67 }; 68 69 config = mkIf cfg.enable { 70 systemd.services.dex = { 71 description = "dex identity provider"; 72 wantedBy = [ "multi-user.target" ]; 73 after = [ "networking.target" ] ++ (optional (cfg.settings.storage.type == "postgres") "postgresql.service"); 74 path = with pkgs; [ replace-secret ]; 75 serviceConfig = { 76 ExecStart = "${pkgs.dex-oidc}/bin/dex serve /run/dex/config.yaml"; 77 ExecStartPre = [ 78 "${pkgs.coreutils}/bin/install -m 600 ${configFile} /run/dex/config.yaml" 79 "+${startPreScript}" 80 ]; 81 82 RuntimeDirectory = "dex"; 83 AmbientCapabilities = "CAP_NET_BIND_SERVICE"; 84 BindReadOnlyPaths = [ 85 "/nix/store" 86 "-/etc/dex" 87 "-/etc/hosts" 88 "-/etc/localtime" 89 "-/etc/nsswitch.conf" 90 "-/etc/resolv.conf" 91 "-/etc/ssl/certs/ca-certificates.crt" 92 ]; 93 BindPaths = optional (cfg.settings.storage.type == "postgres") "/var/run/postgresql"; 94 CapabilityBoundingSet = "CAP_NET_BIND_SERVICE"; 95 # ProtectClock= adds DeviceAllow=char-rtc r 96 DeviceAllow = ""; 97 DynamicUser = true; 98 LockPersonality = true; 99 MemoryDenyWriteExecute = true; 100 NoNewPrivileges = true; 101 PrivateDevices = true; 102 PrivateMounts = true; 103 # Port needs to be exposed to the host network 104 #PrivateNetwork = true; 105 PrivateTmp = true; 106 PrivateUsers = true; 107 ProcSubset = "pid"; 108 ProtectClock = true; 109 ProtectHome = true; 110 ProtectHostname = true; 111 # Would re-mount paths ignored by temporary root 112 #ProtectSystem = "strict"; 113 ProtectControlGroups = true; 114 ProtectKernelLogs = true; 115 ProtectKernelModules = true; 116 ProtectKernelTunables = true; 117 ProtectProc = "invisible"; 118 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; 119 RestrictNamespaces = true; 120 RestrictRealtime = true; 121 RestrictSUIDSGID = true; 122 SystemCallArchitectures = "native"; 123 SystemCallFilter = [ "@system-service" "~@privileged @setuid @keyring" ]; 124 TemporaryFileSystem = "/:ro"; 125 # Does not work well with the temporary root 126 #UMask = "0066"; 127 } // optionalAttrs (cfg.environmentFile != null) { 128 EnvironmentFile = cfg.environmentFile; 129 }; 130 }; 131 }; 132 133 # uses attributes of the linked package 134 meta.buildDocsInSandbox = false; 135}