From 4c428b4a6f8793e62889819e7e9877e6cbca6210 Mon Sep 17 00:00:00 2001 From: Volth Date: Tue, 27 Jun 2017 14:54:25 +0000 Subject: vault: run as an unpivileged user --- nixos/modules/services/security/vault.nix | 269 +++++++++++------------------- 1 file changed, 97 insertions(+), 172 deletions(-) (limited to 'nixos/modules/services') diff --git a/nixos/modules/services/security/vault.nix b/nixos/modules/services/security/vault.nix index eae3a8ca6188..dc06f89cce8c 100644 --- a/nixos/modules/services/security/vault.nix +++ b/nixos/modules/services/security/vault.nix @@ -1,207 +1,132 @@ -{ config, lib, pkgs, utils, ... }: +{ config, lib, pkgs, ... }: with lib; let - - inherit (pkgs) vault; - cfg = config.services.vault; - + configFile = pkgs.writeText "vault.hcl" '' listener "tcp" { - address = "${cfg.listener.address}" - - ${optionalString (cfg.listener.cluster_address != null)'' - cluster_address = "${cfg.listener.cluster_address}" - ''} - - ${optionalString (cfg.listener.tls_cert_file != null)'' - tls_cert_file = "${cfg.listener.tls_cert_file}" - ''} - - ${optionalString (cfg.listener.tls_key_file != null)'' - tls_key_file = "${cfg.listener.tls_key_file}" - ''} - - ${if cfg.listener.tls_disable then "tls_disable = \"1\"" else "" } - - tls_min_version = "${cfg.listener.tls_min_version}" - - ${optionalString (cfg.listener.tls_cipher_suites != null)'' - tls_cipher_suites = \"${cfg.listener.tls_cipher_suites}\" - ''} - - tls_prefer_server_cipher_suites = "${boolToString cfg.listener.tls_prefer_server_cipher_suites}" - - tls_require_and_verify_client_cert = "${boolToString cfg.listener.tls_require_and_verify_client_cert}" - + address = "${cfg.address}" + tls_cert_file = "${cfg.tlsCertFile}" + tls_key_file = "${cfg.tlsKeyFile}" + ${cfg.listenerExtraConfig} } - - storage "${cfg.storage.backend}" { - ${cfg.storage.extraConfig} + storage "${cfg.storageBackend}" { + ${cfg.storageConfig} } - - ${if cfg.telemetry.extraConfig != "" then " - telemetry { - ${if cfg.telemetry.disable_hostname then "disable_hostname = \"true\"" else ""} - ${cfg.telemetry.extraConfig} - }" else ""} - + ${optionalString (cfg.telemetryConfig != "") '' + telemetry { + ${cfg.telemetryConfig} + } + ''} ''; - in { options = { services.vault = { - enable = mkOption { - type = types.bool; - default = false; - description = '' - Enables the vault daemon. - ''; - }; - - listener = { - - address = mkOption { - type = types.str; - default = "127.0.0.1:8200"; - description = '' - The name of the ip interface to listen to. - ''; - }; - - cluster_address = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - The name of the address to bind to for cluster server-to-server requests. - ''; - }; - - tls_cert_file = mkOption { - type = types.str; - default = ""; - description = '' - The name of the crt file for the ssl certificate. - ''; - }; - - tls_key_file = mkOption { - type = types.str; - default = ""; - description = '' - The name of the key file for the ssl certificate. - ''; - }; - - tls_disable = mkOption { - type = types.bool; - default = false; - description = '' - Specifies if TLS will be disabled. Vault assumes TLS by default, so you must explicitly disable TLS to opt-in to insecure communication. - ''; - }; - - tls_min_version = mkOption { - type = types.enum [ "tls10" "tls11" "tls12" ]; - default = "tls12"; - description = '' - The minimum supported version of TLS. Accepted values are "tls10", "tls11" or "tls12". - ''; - }; - - tls_cipher_suites = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - The list of supported ciphersuites as a comma-separated-list. - ''; - }; - - tls_prefer_server_cipher_suites = mkOption { - type = types.bool; - default = false; - description = '' - Specifies to prefer the server's ciphersuite over the client ciphersuites. - ''; - }; - - tls_require_and_verify_client_cert = mkOption { - type = types.bool; - default = false; - description = '' - Turns on client authentication for this listener. - ''; - }; + enable = mkEnableOption "Vault daemon"; + address = mkOption { + type = types.str; + default = "127.0.0.1:8200"; + description = "The name of the ip interface to listen to"; }; - storage = { - - backend = mkOption { - type = types.str; - default = "inMemory"; - description = '' - The name of the type of storage backend. - ''; - }; - - extraConfig = mkOption { - type = types.lines; - default = ""; - description = '' - Configuration for storage - ''; - }; - + tlsCertFile = mkOption { + type = types.str; + default = "/etc/vault/cert.pem"; + example = "/path/to/your/cert.pem"; + description = "TLS certificate file. A self-signed certificate will be generated if file not exists"; }; + tlsKeyFile = mkOption { + type = types.str; + default = "/etc/vault/key.pem"; + example = "/path/to/your/key.pem"; + description = "TLS private key file. A self-signed certificate will be generated if file not exists"; + }; - telemetry = { - - disable_hostname = mkOption { - type = types.bool; - default = false; - description = '' - Specifies if gauge values should be prefixed with the local hostname. - ''; - }; + listenerExtraConfig = mkOption { + type = types.lines; + default = '' + tls_min_version = "tls12" + ''; + description = "extra configuration"; + }; - extraConfig = mkOption { - type = types.lines; - default = ""; - description = '' - configuration for telemetry - ''; - }; + storageBackend = mkOption { + type = types.enum ["inmem" "consul" "zookeeper" "file" "s3" "azure" "dynamodb" "etcd" "mssql" "mysql" "postgresql" "swift" "gcs"]; + default = "inmem"; + description = "The name of the type of storage backend"; + }; + storageConfig = mkOption { + type = types.lines; + description = "Storage configuration"; + default = ""; }; + telemetryConfig = mkOption { + type = types.lines; + default = ""; + description = "Telemetry configuration"; + }; }; - }; config = mkIf cfg.enable { - systemd.services.vault = - { description = "Vault server daemon"; - - wantedBy = ["multi-user.target"]; + users.extraUsers.vault = { + name = "vault"; + group = "vault"; + uid = config.ids.uids.vault; + description = "Vault daemon user"; + }; + users.extraGroups.vault.gid = config.ids.gids.vault; - preStart = - '' - mkdir -m 0755 -p /var/lib/vault - ''; + systemd.services.vault = { + description = "Vault server daemon"; - serviceConfig = - { ExecStart = - "${pkgs.vault}/bin/vault server -config ${configFile}"; - KillMode = "process"; - }; - }; + wantedBy = ["multi-user.target"]; + after = [ "network.target" ]; + + preStart = '' + mkdir -m 0755 -p /var/lib/vault + chown -R vault:vault /var/lib/vault + + # generate a self-signed certificate, you will have to set environment variable "VAULT_SKIP_VERIFY=1" in the client + if [ ! -s ${cfg.tlsCertFile} -o ! -s ${cfg.tlsKeyFile} ]; then + mkdir -p $(dirname ${cfg.tlsCertFile}) || true + mkdir -p $(dirname ${cfg.tlsKeyFile }) || true + ${pkgs.openssl.bin}/bin/openssl req -x509 -newkey rsa:2048 -sha256 -nodes -days 99999 \ + -subj /C=US/ST=NY/L=NYC/O=vault/CN=${cfg.address} \ + -keyout ${cfg.tlsKeyFile} -out ${cfg.tlsCertFile} + + chown root:vault ${cfg.tlsKeyFile} ${cfg.tlsCertFile} + chmod 440 ${cfg.tlsKeyFile} ${cfg.tlsCertFile} + fi + ''; + + serviceConfig = { + User = "vault"; + Group = "vault"; + PermissionsStartOnly = true; + ExecStart = "${pkgs.vault}/bin/vault server -config ${configFile}"; + PrivateDevices = true; + PrivateTmp = true; + ProtectSystem = "full"; + ProtectHome = "read-only"; + AmbientCapabilities = "cap_ipc_lock"; + NoNewPrivileges = true; + KillSignal = "SIGINT"; + TimeoutStopSec = "30s"; + Restart = "on-failure"; + StartLimitInterval = "60s"; + StartLimitBurst = 3; + }; + }; }; } -- cgit 1.4.1