Merge pull request #17 from numtide/ci

flake.lock: Update
main
Jörg Thalheim 2 years ago committed by GitHub
commit d01702db6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,6 +1,7 @@
# systemd-vaultd - load vault credentials with systemd units
> Mostly written in a train
- Jörg Thalheim
systemd-vaultd is a proxy between systemd and [vault agent](https://vaultproject.io).

@ -1,7 +1,10 @@
cut_body_after = "" # don't include text from the PR body in the merge commit message
status = [
"Evaluate flake.nix",
"package %",
"check %",
"devShell %",
"check systemd-vaultd [x86_64-linux]",
"check treefmt [x86_64-linux]",
"check unittests [x86_64-linux]",
"check vault-agent [x86_64-linux]",
"devShell default [x86_64-linux]",
"package default [x86_64-linux]"
]

@ -1,4 +1,4 @@
{pkgs ? import <nixpkgs> {}}:
{ pkgs ? import <nixpkgs> { } }:
pkgs.buildGoModule {
name = "systemd-vaultd";
src = ./.;
@ -7,7 +7,7 @@ pkgs.buildGoModule {
description = "A proxy for secrets between systemd services and vault";
homepage = "https://github.com/numtide/systemd-vaultd";
license = licenses.mit;
maintainers = with maintainers; [mic92];
maintainers = with maintainers; [ mic92 ];
platforms = platforms.unix;
};
}

@ -7,11 +7,11 @@
]
},
"locked": {
"lastModified": 1671322946,
"narHash": "sha256-J8Qj+ITV+eti+irTK9Zn2LZVYoIW2g7irPUckU8yZvU=",
"lastModified": 1673362319,
"narHash": "sha256-Pjp45Vnj7S/b3BRpZEVfdu8sqqA6nvVjvYu59okhOyI=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "3f7172646953bf86dad5953bc45f0edae62ac445",
"rev": "82c16f1682cf50c01cb0280b38a1eed202b3fe9f",
"type": "github"
},
"original": {
@ -22,15 +22,16 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1671537075,
"narHash": "sha256-lAejYRUtM2SDTmHxcFLnx4W/P0URejhkl9DyqJ++PIc=",
"lastModified": 1673606088,
"narHash": "sha256-wdYD41UwNwPhTdMaG0AIe7fE1bAdyHe6bB4HLUqUvck=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "eb37a7f66312e845fba0b3cc7c36e727012b3dae",
"rev": "37b97ae3dd714de9a17923d004a2c5b5543dfa6d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
@ -38,7 +39,23 @@
"root": {
"inputs": {
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs"
"nixpkgs": "nixpkgs",
"treefmt-nix": "treefmt-nix"
}
},
"treefmt-nix": {
"locked": {
"lastModified": 1672931382,
"narHash": "sha256-lgtc2Sct/xtvqkdzlJ4AL3Vesw0Wz/fxqNGOBFS7YXU=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "6717065d6a432bc3f5b827007ad959e6032d5856",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
}
},

@ -4,30 +4,40 @@
inputs = {
flake-parts.url = "github:hercules-ci/flake-parts";
flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs";
nixpkgs.url = "github:NixOS/nixpkgs";
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
treefmt-nix.url = "github:numtide/treefmt-nix";
};
outputs = inputs @ {flake-parts, ...}:
flake-parts.lib.mkFlake {inherit inputs;} {
systems = ["x86_64-linux" "aarch64-linux"];
perSystem = {
config,
self',
inputs',
pkgs,
system,
...
outputs = inputs @ { flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
systems = [ "x86_64-linux" "aarch64-linux" ];
imports = [
./nix/checks/flake-module.nix
];
perSystem =
{ config
, pkgs
, ...
}: {
packages.default = pkgs.callPackage ./default.nix {};
devShells.default = pkgs.callPackage ./shell.nix {};
checks = let
nixosTests = pkgs.callPackages ./nix/checks/nixos-test.nix {
makeTest = import (pkgs.path + "/nixos/tests/make-test-python.nix");
};
in {
treefmt = pkgs.callPackage ./nix/checks/treefmt.nix {};
inherit (nixosTests) unittests vault-agent systemd-vaultd;
packages.default = pkgs.callPackage ./default.nix { };
packages.systemd = pkgs.callPackage ./nix/pkgs/systemd.nix { };
devShells.default = pkgs.mkShellNoCC {
buildInputs = with pkgs; [
python3.pkgs.pytest
python3.pkgs.mypy
golangci-lint
vault
systemd
hivemind
go
just
config.packages.treefmt
config.packages.systemd
];
};
};
flake.nixosModules = {
vaultAgent = ./nix/modules/vault-agent.nix;

@ -1,10 +1,8 @@
{
config,
lib,
pkgs,
...
{ config
, pkgs
, ...
}: {
environment.systemPackages = [pkgs.vault];
environment.systemPackages = [ pkgs.vault ];
services.vault = {
enable = true;
dev = true;
@ -14,8 +12,8 @@
environment.variables.VAULT_TOKEN = config.services.vault.devRootTokenID;
systemd.services.setup-vault-agent-approle = {
path = [pkgs.jq pkgs.vault pkgs.systemd];
wantedBy = ["multi-user.target"];
path = [ pkgs.jq pkgs.vault pkgs.systemd ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
@ -51,7 +49,7 @@
# Make sure our setup service is started before our vault-agent
systemd.services.vault-agent-test = {
wants = ["setup-vault-agent-approle.service"];
after = ["setup-vault-agent-approle.service"];
wants = [ "setup-vault-agent-approle.service" ];
after = [ "setup-vault-agent-approle.service" ];
};
}

@ -0,0 +1,57 @@
{ inputs, ... }: {
imports = [
inputs.treefmt-nix.flakeModule
];
perSystem =
{ pkgs
, ...
}: {
treefmt = {
# Used to find the project root
projectRootFile = "flake.lock";
programs.gofumpt.enable = true;
programs.prettier.enable = true;
settings.formatter = {
nix = {
command = "sh";
options = [
"-eucx"
''
# First deadnix
${pkgs.lib.getExe pkgs.deadnix} --edit "$@"
# Then nixpkgs-fmt
${pkgs.lib.getExe pkgs.nixpkgs-fmt} "$@"
''
"--"
];
includes = [ "*.nix" ];
};
python = {
command = "sh";
options = [
"-eucx"
''
${pkgs.lib.getExe pkgs.ruff} --fix "$@"
${pkgs.lib.getExe pkgs.python3.pkgs.black} "$@"
''
"--" # this argument is ignored by bash
];
includes = [ "*.py" ];
};
};
};
checks =
let
nixosTests = pkgs.callPackages ./nixos-test.nix {
makeTest = import (pkgs.path + "/nixos/tests/make-test-python.nix");
};
in
{
inherit (nixosTests) unittests vault-agent systemd-vaultd;
};
};
}

@ -1,13 +1,15 @@
{
makeTest ? import <nixpkgs/nixos/tests/make-test-python.nix>,
pkgs ? (import <nixpkgs> {}),
}: let
{ makeTest ? import <nixpkgs/nixos/tests/make-test-python.nix>
, pkgs ? (import <nixpkgs> { })
,
}:
let
makeTest' = args:
makeTest args {
inherit pkgs;
inherit (pkgs) system;
};
in {
in
{
vault-agent = makeTest' (import ./vault-agent-test.nix);
systemd-vaultd = makeTest' (import ./systemd-vaultd-test.nix);
unittests = makeTest' {

@ -1,9 +1,9 @@
{
name = "systemd-vaultd";
nodes.server = {
config,
pkgs,
...
nodes.server =
{ config
, pkgs
, ...
}: {
imports = [
../modules/vault-agent.nix
@ -12,7 +12,7 @@
];
systemd.services.service1 = {
wantedBy = ["multi-user.target"];
wantedBy = [ "multi-user.target" ];
script = ''
cat $CREDENTIALS_DIRECTORY/foo > /tmp/service1
echo -n "$SECRET_ENV" > /tmp/service1-env
@ -24,7 +24,7 @@
template = ''
{{ with secret "secret/my-secret" }}{{ .Data.data | toJSON }}{{ end }}
'';
secrets.foo = {};
secrets.foo = { };
environmentTemplate = ''
{{ with secret "secret/my-secret" }}
SECRET_ENV={{ .Data.data.foo }}
@ -34,7 +34,7 @@
};
systemd.services.service2 = {
wantedBy = ["multi-user.target"];
wantedBy = [ "multi-user.target" ];
script = ''
set -x
while true; do
@ -43,13 +43,13 @@
done
'';
serviceConfig.ExecReload = "${pkgs.coreutils}/bin/true";
serviceConfig.LoadCredential = ["secret:/run/systemd-vaultd/sock"];
serviceConfig.LoadCredential = [ "secret:/run/systemd-vaultd/sock" ];
vault = {
template = ''
{{ with secret "secret/blocking-secret" }}{{ scratch.MapSet "secrets" "secret" .Data.data.foo }}{{ end }}
{{ scratch.Get "secrets" | explodeMap | toJSON }}
'';
secrets.secret = {};
secrets.secret = { };
};
};

@ -1,22 +0,0 @@
{
runCommand,
gofumpt,
alejandra,
python3,
treefmt,
}:
runCommand "treefmt" {
nativeBuildInputs = [
gofumpt
treefmt
alejandra
python3.pkgs.flake8
python3.pkgs.black
];
} ''
# keep timestamps so that treefmt is able to detect mtime changes
cp --no-preserve=mode --preserve=timestamps -r ${../..} source
cd source
HOME=$TMPDIR treefmt --no-cache --fail-on-change
touch $out
''

@ -1,14 +1,15 @@
{
writeShellScript,
python3,
pkgs,
lib,
coreutils,
}: let
systemd-vaultd = pkgs.callPackage ../../default.nix {};
systemd = pkgs.callPackage ../pkgs/systemd.nix {};
{ writeShellScript
, python3
, pkgs
, lib
, coreutils
,
}:
let
systemd-vaultd = pkgs.callPackage ../../default.nix { };
systemd = pkgs.callPackage ../pkgs/systemd.nix { };
in
writeShellScript "unittests" ''
writeShellScript "unittests" ''
set -eu -o pipefail
export PATH=${lib.makeBinPath [python3.pkgs.pytest coreutils systemd]}
export SYSTEMD_VAULTD_BIN=${systemd-vaultd}/bin/systemd-vaultd
@ -19,4 +20,4 @@ in
pytest -s ./tests
# we need this in our nixos tests
touch /tmp/success
''
''

@ -1,9 +1,8 @@
{
name = "vault-agent";
nodes.server = {
config,
pkgs,
...
nodes.server =
{ config
, ...
}: {
imports = [
./dev-vault-server.nix

@ -1,20 +1,19 @@
{ pkgs
, ...
}:
let
systemd-vaultd = pkgs.callPackage ../../default.nix { };
in
{
config,
lib,
pkgs,
...
}: let
systemd-vaultd = pkgs.callPackage ../../default.nix {};
in {
imports = [
./vault-secrets.nix
];
systemd.package = pkgs.callPackage ../pkgs/systemd.nix {};
systemd.package = pkgs.callPackage ../pkgs/systemd.nix { };
systemd.sockets.systemd-vaultd = {
description = "systemd-vaultd socket";
wantedBy = ["sockets.target"];
wantedBy = [ "sockets.target" ];
socketConfig = {
ListenStream = "/run/systemd-vaultd/sock";
@ -24,8 +23,8 @@ in {
};
systemd.services.systemd-vaultd = {
description = "systemd-vaultd daemon";
requires = ["systemd-vaultd.socket"];
after = ["systemd-vaultd.socket"];
requires = [ "systemd-vaultd.socket" ];
after = [ "systemd-vaultd.socket" ];
# Restarting can break services waiting for secrets
stopIfChanged = false;
serviceConfig = {

@ -1,11 +1,11 @@
{
config,
lib,
pkgs,
...
}: let
{ config
, lib
, pkgs
, ...
}:
let
cfg = config.services.vault;
settingsFormat = pkgs.formats.json {};
settingsFormat = pkgs.formats.json { };
autoAuthMethodModule = lib.types.submodule {
freeformType = lib.types.attrsOf lib.types.unspecified;
@ -27,7 +27,7 @@
options = {
method = lib.mkOption {
type = lib.types.listOf autoAuthMethodModule;
default = [];
default = [ ];
};
};
};
@ -49,18 +49,19 @@
options = {
auto_auth = lib.mkOption {
type = autoAuthModule;
default = {};
default = { };
};
template_config = lib.mkOption {
type = templateConfigModule;
default = {};
default = { };
};
};
};
in {
in
{
options.services.vault.agents = lib.mkOption {
default = {};
default = { };
description = "Instances of vault agent";
type = lib.types.attrsOf (lib.types.submodule {
options = {
@ -72,17 +73,18 @@ in {
});
};
config = {
systemd.services = lib.mapAttrs' (name: instanceCfg:
systemd.services = lib.mapAttrs'
(name: instanceCfg:
lib.nameValuePair "vault-agent-${name}" {
after = ["network.target"];
wantedBy = ["multi-user.target"];
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
# Services that also have `stopIfChanged = false` might wait for secrets
# while `vault-agent` is still stopped. This for example happens with nginx.service.
stopIfChanged = false;
# Needs getent in PATH
path = [pkgs.glibc];
path = [ pkgs.glibc ];
serviceConfig = {
Restart = "on-failure";
ExecStart = "${pkgs.vault}/bin/vault agent -config=${settingsFormat.generate "agent.json" instanceCfg.settings}";

@ -1,11 +1,11 @@
{
lib,
config,
pkgs,
...
}: let
{ lib
, config
, pkgs
, ...
}:
let
secretType = serviceName:
lib.types.submodule ({config, ...}: {
lib.types.submodule ({ config, ... }: {
options = {
name = lib.mkOption {
type = lib.types.str;
@ -59,19 +59,22 @@
vaultTemplates = config:
(lib.mapAttrsToList
(serviceName: service:
(serviceName: _service:
getSecretTemplate serviceName services.${serviceName}.vault)
(lib.filterAttrs (n: v: v.vault.secrets != {} && v.vault.agent == config._module.args.name) services))
(lib.filterAttrs (_n: v: v.vault.secrets != { } && v.vault.agent == config._module.args.name) services))
++ (lib.mapAttrsToList
(serviceName: service:
(serviceName: _service:
getEnvironmentTemplate serviceName services.${serviceName}.vault)
(lib.filterAttrs (n: v: v.vault.environmentTemplate != null && v.vault.agent == config._module.args.name) services));
in {
(lib.filterAttrs (_n: v: v.vault.environmentTemplate != null && v.vault.agent == config._module.args.name) services));
in
{
options = {
systemd.services = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({config, ...}: let
type = lib.types.attrsOf (lib.types.submodule ({ config, ... }:
let
serviceName = config._module.args.name;
in {
in
{
options.vault = {
changeAction = lib.mkOption {
description = ''
@ -110,29 +113,31 @@ in {
secrets = lib.mkOption {
type = lib.types.attrsOf (secretType serviceName);
default = {};
default = { };
description = "List of secrets to load from vault agent template";
example = {
some-secret.template = ''{{ with secret "secret/some-secret" }}{{ .Data.data.some-key }}{{ end }}'';
};
};
};
config = let
config =
let
mkIfHasEnv = lib.mkIf (config.vault.environmentTemplate != null);
in {
after = mkIfHasEnv ["${serviceName}-envfile.service"];
bindsTo = mkIfHasEnv ["${serviceName}-envfile.service"];
in
{
after = mkIfHasEnv [ "${serviceName}-envfile.service" ];
bindsTo = mkIfHasEnv [ "${serviceName}-envfile.service" ];
serviceConfig = {
LoadCredential = lib.mapAttrsToList (_: config: "${config.name}:/run/systemd-vaultd/sock") config.vault.secrets;
EnvironmentFile = mkIfHasEnv ["/run/systemd-vaultd/secrets/${serviceName}.service.EnvironmentFile"];
EnvironmentFile = mkIfHasEnv [ "/run/systemd-vaultd/secrets/${serviceName}.service.EnvironmentFile" ];
};
};
}));
};
services.vault.agents = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({config, ...}: {
type = lib.types.attrsOf (lib.types.submodule ({ config, ... }: {
config.settings.template = vaultTemplates config;
}));
};
@ -140,14 +145,17 @@ in {
config = {
# we cannot use `systemd.services` here since this would create infinite recursion
systemd.packages = let
servicesWithEnv = builtins.attrNames (lib.filterAttrs (n: v: v.vault.environmentTemplate != null) services);
in [
(pkgs.runCommand "env-services" {}
systemd.packages =
let
servicesWithEnv = builtins.attrNames (lib.filterAttrs (_n: v: v.vault.environmentTemplate != null) services);
in
[
(pkgs.runCommand "env-services" { }
(''
mkdir -p $out/lib/systemd/system
''
+ (lib.concatMapStringsSep "\n" (service: ''
+ (lib.concatMapStringsSep "\n"
(service: ''
cat > $out/lib/systemd/system/${service}-envfile.service <<EOF
[Unit]
Before=${service}.service

@ -1,6 +1,6 @@
{
systemd,
fetchpatch,
{ systemd
, fetchpatch
,
}:
systemd.overrideAttrs (old: {
patches =

@ -0,0 +1,20 @@
[tool.ruff]
line-length = 88
select = ["E", "F", "I"]
ignore = [ "E501" ]
[tool.mypy]
python_version = "3.10"
warn_redundant_casts = true
disallow_untyped_calls = true
disallow_untyped_defs = true
no_implicit_optional = true
[[tool.mypy.overrides]]
module = "setuptools.*"
ignore_missing_imports = true
[[tool.mypy.overrides]]
module = "pytest.*"
ignore_missing_imports = true

@ -1,20 +0,0 @@
{pkgs ? import <nixpkgs> {}}:
with pkgs;
mkShellNoCC {
buildInputs = [
python3.pkgs.pytest
python3.pkgs.flake8
python3.pkgs.black
python3.pkgs.mypy
gofumpt
golangci-lint
alejandra
vault
systemd
hivemind
go
treefmt
just
];
}

@ -3,8 +3,8 @@
import os
import signal
import subprocess
from typing import IO, Any, Dict, Iterator, List, Union
from pathlib import Path
from typing import IO, Any, Dict, Iterator, List, Union
import pytest

@ -1,8 +1,8 @@
#!/usr/bin/env python3
import json
import random
import string
import json
from dataclasses import dataclass
from pathlib import Path

@ -1,9 +1,10 @@
#!/usr/bin/env python3
import os
import pytest
from pathlib import Path
from typing import Optional
import pytest
from command import run
BIN: Optional[Path] = None

@ -1,10 +1,11 @@
#!/usr/bin/env python3
import pytest
from tempfile import TemporaryDirectory
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Iterator
import pytest
@pytest.fixture
def tempdir() -> Iterator[Path]:

@ -1,6 +1,6 @@
import subprocess
from pathlib import Path
import time
from pathlib import Path
from command import Command
from random_service import random_service

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import time
import subprocess
import time
from pathlib import Path
from command import Command, run

@ -1,21 +0,0 @@
[formatter.nix]
command = "alejandra"
includes = ["*.nix"]
[formatter.python]
command = "sh"
options = [
"-eucx",
"""
flake8 "$@"
black "$@"
"""
]
includes = ["*.py"]
excludes = []
[formatter.go]
command = "gofumpt"
options = ["-w"]
includes = ["*.go"]
excludes = []
Loading…
Cancel
Save