at 23.11-pre 5.1 kB view raw
1{ config, lib, pkgs, ... }: 2let 3 cfg = config.services.step-ca; 4 settingsFormat = (pkgs.formats.json { }); 5in 6{ 7 meta.maintainers = with lib.maintainers; [ mohe2015 ]; 8 9 options = { 10 services.step-ca = { 11 enable = lib.mkEnableOption (lib.mdDoc "the smallstep certificate authority server"); 12 openFirewall = lib.mkEnableOption (lib.mdDoc "opening the certificate authority server port"); 13 package = lib.mkOption { 14 type = lib.types.package; 15 default = pkgs.step-ca; 16 defaultText = lib.literalExpression "pkgs.step-ca"; 17 description = lib.mdDoc "Which step-ca package to use."; 18 }; 19 address = lib.mkOption { 20 type = lib.types.str; 21 example = "127.0.0.1"; 22 description = lib.mdDoc '' 23 The address (without port) the certificate authority should listen at. 24 This combined with {option}`services.step-ca.port` overrides {option}`services.step-ca.settings.address`. 25 ''; 26 }; 27 port = lib.mkOption { 28 type = lib.types.port; 29 example = 8443; 30 description = lib.mdDoc '' 31 The port the certificate authority should listen on. 32 This combined with {option}`services.step-ca.address` overrides {option}`services.step-ca.settings.address`. 33 ''; 34 }; 35 settings = lib.mkOption { 36 type = with lib.types; attrsOf anything; 37 description = lib.mdDoc '' 38 Settings that go into {file}`ca.json`. See 39 [the step-ca manual](https://smallstep.com/docs/step-ca/configuration) 40 for more information. The easiest way to 41 configure this module would be to run `step ca init` 42 to generate {file}`ca.json` and then import it using 43 `builtins.fromJSON`. 44 [This article](https://smallstep.com/docs/step-cli/basic-crypto-operations#run-an-offline-x509-certificate-authority) 45 may also be useful if you want to customize certain aspects of 46 certificate generation for your CA. 47 You need to change the database storage path to {file}`/var/lib/step-ca/db`. 48 49 ::: {.warning} 50 The {option}`services.step-ca.settings.address` option 51 will be ignored and overwritten by 52 {option}`services.step-ca.address` and 53 {option}`services.step-ca.port`. 54 ::: 55 ''; 56 }; 57 intermediatePasswordFile = lib.mkOption { 58 type = lib.types.path; 59 example = "/run/keys/smallstep-password"; 60 description = lib.mdDoc '' 61 Path to the file containing the password for the intermediate 62 certificate private key. 63 64 ::: {.warning} 65 Make sure to use a quoted absolute path instead of a path literal 66 to prevent it from being copied to the globally readable Nix 67 store. 68 ::: 69 ''; 70 }; 71 }; 72 }; 73 74 config = lib.mkIf config.services.step-ca.enable ( 75 let 76 configFile = settingsFormat.generate "ca.json" (cfg.settings // { 77 address = cfg.address + ":" + toString cfg.port; 78 }); 79 in 80 { 81 assertions = 82 [ 83 { 84 assertion = !lib.isStorePath cfg.intermediatePasswordFile; 85 message = '' 86 <option>services.step-ca.intermediatePasswordFile</option> points to 87 a file in the Nix store. You should use a quoted absolute path to 88 prevent this. 89 ''; 90 } 91 ]; 92 93 systemd.packages = [ cfg.package ]; 94 95 # configuration file indirection is needed to support reloading 96 environment.etc."smallstep/ca.json".source = configFile; 97 98 systemd.services."step-ca" = { 99 wantedBy = [ "multi-user.target" ]; 100 restartTriggers = [ configFile ]; 101 unitConfig = { 102 ConditionFileNotEmpty = ""; # override upstream 103 }; 104 serviceConfig = { 105 User = "step-ca"; 106 Group = "step-ca"; 107 UMask = "0077"; 108 Environment = "HOME=%S/step-ca"; 109 WorkingDirectory = ""; # override upstream 110 ReadWriteDirectories = ""; # override upstream 111 112 # LocalCredential handles file permission problems arising from the use of DynamicUser. 113 LoadCredential = "intermediate_password:${cfg.intermediatePasswordFile}"; 114 115 ExecStart = [ 116 "" # override upstream 117 "${cfg.package}/bin/step-ca /etc/smallstep/ca.json --password-file \${CREDENTIALS_DIRECTORY}/intermediate_password" 118 ]; 119 120 # ProtectProc = "invisible"; # not supported by upstream yet 121 # ProcSubset = "pid"; # not supported by upstream yet 122 # PrivateUsers = true; # doesn't work with privileged ports therefore not supported by upstream 123 124 DynamicUser = true; 125 StateDirectory = "step-ca"; 126 }; 127 }; 128 129 users.users.step-ca = { 130 home = "/var/lib/step-ca"; 131 group = "step-ca"; 132 isSystemUser = true; 133 }; 134 135 users.groups.step-ca = {}; 136 137 networking.firewall = lib.mkIf cfg.openFirewall { 138 allowedTCPPorts = [ cfg.port ]; 139 }; 140 } 141 ); 142}