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