Skip to content

Commit

Permalink
+
Browse files Browse the repository at this point in the history
+

+
  • Loading branch information
oluceps committed Nov 1, 2024
1 parent 5ebd836 commit ec49259
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 165 deletions.
9 changes: 6 additions & 3 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
- [ ] remote machine, compare hash, needs host priv key
- [ ] [edit] extra encrypt key
- [ ] deploy to other directory
- [ ] check command
- [x] vaultix.d in ramfs
- [x] vaultix{,.d} permission
- [x] age plugin
- [ ] check command
- [x] rage plugin support
- [x] should get entire `Secret` when deploy
- [x] [renc] calc hash and skip unchanged
- [x] remove renced path while renc
- [x] apply `Secret` metadata
- [x] nix integration
- [ ] feed the toml after renced, thus store path changed
- [ ] ~~feed the toml after renced, thus store path changed~~
- [ ] ~~eval in vaultix to json, reduce requirement~~
4 changes: 2 additions & 2 deletions apps/renc.nix
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
nodes,
userFlake',
pkgs,
system,
package,
...
}:
let
Expand All @@ -11,7 +11,7 @@ let
inherit (builtins) attrValues;

vaultixs = map (n: n.config.vaultix) (attrValues nodes);
bin = pkgs.lib.getExe userFlake'.packages.${system}.default;
bin = pkgs.lib.getExe package;

in
writeShellScriptBin "renc" (
Expand Down
9 changes: 2 additions & 7 deletions flake-module.nix
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
localFlake:
{
lib,
self,
Expand Down Expand Up @@ -29,6 +30,7 @@ in
app:
import ./apps/${app}.nix {
inherit (config'.vaultix) nodes pkgs;
package = localFlake.packages.${system}.default;
userFlake' = self;
inherit system;
}
Expand Down Expand Up @@ -60,13 +62,6 @@ in
default = pkgs;
defaultText = lib.literalExpression "pkgs # (module argument)";
};
package = mkOption {
type = types.package;
default = config.vaultix.pkgs.callPackage self.packages.${pkgs.system}.default;
# defaultText = "<agenix script derivation from agenix-rekey>";
readOnly = true;
description = '''';
};
};
}
);
Expand Down
156 changes: 85 additions & 71 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -22,87 +22,101 @@
crane,
...
}:
flake-parts.lib.mkFlake { inherit inputs; } {
imports = with inputs; [
pre-commit-hooks.flakeModule
flake-parts.lib.mkFlake { inherit inputs; } (
{ flake-parts-lib, withSystem, ... }:
let
inherit (flake-parts-lib) importApply;
flakeModules.default = importApply ./flake-module.nix {
inherit (self) packages;
inherit withSystem;
};
in
{
imports = with inputs; [
pre-commit-hooks.flakeModule
flakeModules.default
./test
];
systems = [
"x86_64-linux"
"aarch64-linux"
];
perSystem =
{
# config,
self',
# inputs',
pkgs,
system,
...
}:
{
_module.args.pkgs = import inputs.nixpkgs {
inherit system;
overlays = with inputs; [
rust-overlay.overlays.default
self.overlays.default
];
};

./flake-module.nix
./test
];
systems = [
"x86_64-linux"
"aarch64-linux"
];
perSystem =
{
# config,
self',
# inputs',
pkgs,
system,
...
}:
{
_module.args.pkgs = import inputs.nixpkgs {
inherit system;
overlays = with inputs; [
rust-overlay.overlays.default
self.overlays.default
];
};
vaultix = {
nodes = self.nixosConfigurations;
};
apps = {
default = {
type = "app";
program = pkgs.lib.getExe self'.packages.default;
};
};

vaultix = {
nodes = self.nixosConfigurations;
};
apps.default = {
type = "app";
program = pkgs.lib.getExe self'.packages.default;
};
packages = rec {
default =
let
toolchain = pkgs.rust-bin.nightly.latest.minimal;
craneLib = (crane.mkLib pkgs).overrideToolchain toolchain;
inherit (craneLib) buildPackage;
in
(buildPackage {
src = craneLib.cleanCargoSource ./.;
nativeBuildInputs = [
pkgs.rustPlatform.bindgenHook
];
meta.mainProgram = "vaultix";
});
vaultix = default;
};

packages.default =
let
toolchain = pkgs.rust-bin.nightly.latest.minimal;
craneLib = (crane.mkLib pkgs).overrideToolchain toolchain;
inherit (craneLib) buildPackage;
in
(buildPackage {
src = craneLib.cleanCargoSource ./.;
nativeBuildInputs = [
pkgs.rustPlatform.bindgenHook
formatter = pkgs.nixfmt-rfc-style;

devShells.default = pkgs.mkShell {
inputsFrom = [
pkgs.vaultix
];
meta.mainProgram = "vaultix";
});

formatter = pkgs.nixfmt-rfc-style;
RUST_SRC_PATH = "${pkgs.rustPlatform.rustLibSrc}";
buildInputs = with pkgs; [
just
nushell
];
};

devShells.default = pkgs.mkShell {
inputsFrom = [
pkgs.vaultix
];
pre-commit = {
check.enable = true;
settings.hooks = {
nixfmt-rfc-style.enable = true;
};
};

RUST_SRC_PATH = "${pkgs.rustPlatform.rustLibSrc}";
buildInputs = with pkgs; [
just
nushell
];
};
flake = {
inherit flakeModules;

pre-commit = {
check.enable = true;
settings.hooks = {
nixfmt-rfc-style.enable = true;
};
overlays.default = final: prev: {
vaultix = inputs.self.packages.${prev.system}.default;
};
nixosModules.default = import ./module self;

};
flake = {
flakeModule = ./flake-module.nix;

overlays.default = final: prev: {
vaultix = inputs.self.packages.${prev.system}.default;
};
nixosModules.default = ./module;

};
};
}
);
}
90 changes: 11 additions & 79 deletions module/default.nix
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
vaultixSelf:
{
config,
options,
Expand All @@ -13,7 +14,6 @@ let
isAttrs
isPath
readFile
mkPackageOption
literalExpression
mkEnableOption
mkIf
Expand All @@ -29,7 +29,7 @@ let
) "`systemd.sysusers` or `services.userborn` must be enabled.";

storagePath = self + "/" + cfg.settings.storageDirRelative;
storageExist = assertMsg (builtins.pathExists (storagePath)) "${storagePath} doesn't exist plz manually create and add to git first (may need a placeholder for git to recognize it)";
storageExist = assertMsg (builtins.pathExists storagePath) "${storagePath} doesn't exist plz manually create and add to git first (may need a placeholder for git to recognize it)";

settingsType = types.submodule (submod: {
options = {
Expand Down Expand Up @@ -61,7 +61,7 @@ let

hostKeys = mkOption {
type = types.listOf (
types.submodule ({
types.submodule {
options = {
path = mkOption {
type = types.path;
Expand All @@ -70,7 +70,7 @@ let
type = types.str;
};
};
})
}
);
default = config.services.openssh.hostKeys;
readOnly = true;
Expand Down Expand Up @@ -139,53 +139,6 @@ let
};
})
);
description = ''
The list of age identities that will be presented to `rage` when decrypting the stored secrets
to rekey them for your host(s). If multiple identities are given, they will be tried in-order.
The recommended options are:
- Use a split-identity ending in `.pub`, where the private part is not contained (a yubikey identity)
- Use an absolute path to your key outside of the nix store ("/home/myuser/age-master-key")
- Or encrypt your age identity and use the extension `.age`. You can encrypt an age identity
using `rage -p -o privkey.age privkey` which protects it in your store.
If you are using YubiKeys, you can specify multiple split-identities here and use them interchangeably.
You will have the option to skip any YubiKeys that are not available to you in that moment.
To prevent issues with master keys that may be sometimes unavailable during encryption,
an alternate syntax is possible:
```nix
age.rekey.masterIdentities = [
{
# This has the same type as the other ways to specify an identity.
identity = ./password-encrypted-identity.pub;
# Optional; This has the same type as `age.rekey.hostPubkey`
# and allows explicit association of a pubkey with the identity.
pubkey = "age1qyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqs3290gq";
}
];
```
If a pubkey is explicitly specified, it will be used
in place of the associated identity during encryption. This prevents additional prompts
in the case of a password encrypted key file or prompts for identities that can only be accessed
by certain people in a multi-user scenario. For Yubikey identities the pubkey can be automatically
extracted from the identity file, if there is a comment of the form `Recipient: age1yubikey1<key>`
present in the identity file.
This should be the case for identity files generated by the `age-plugin-yubikey` CLI.
See the description of [pull request #28](https://github.com/oddlama/agenix-rekey/pull/28)
for more information on the exact criteria for automatic pubkey extraction.
For setups where the primary identity may change depending on the situation, e.g. in a multi-user setup,
where each person only has access to their own personal Yubikey, check out the
`AGENIX_REKEY_PRIMARY_IDENTITY` environment variable.
Be careful when using paths here, as they will be copied to the nix store. Using
split-identities is fine, but if you are using plain age identities, make sure that they
are password protected.
'';
default = [ ];
example = [
./secrets/my-public-yubikey-identity.txt.pub
Expand All @@ -196,17 +149,9 @@ let
];
};

extraEncryptionPubkeys = mkOption {
extraReceipients = mkOption {
type = with types; listOf (coercedTo path toString str);
description = ''
When using `agenix edit FILE`, the file will be encrypted for all identities in
rekey.masterIdentities by default. Here you can specify an extra set of pubkeys for which
all secrets should also be encrypted. This is useful in case you want to have a backup indentity
that must be able to decrypt all secrets but should not be used when attempting regular decryption.

If the coerced string is an absolute path, it will be used as if it was a recipient file.
Otherwise, the string will be interpreted as a public key.
'';
default = [ ];
example = [
./backup-key.pub
Expand All @@ -216,22 +161,6 @@ let

hostPubkey = mkOption {
type = with types; coercedTo path (x: if isPath x then readFile x else x) str;
description = ''
The age public key to use as a recipient when rekeying. This either has to be the
path to an age public key file, or the public key itself in string form.
HINT: If you want to use a path, make sure to use an actual nix path, so for example
`./host.pub`, otherwise it will be interpreted as the content and cause errors.
Alternatively you can use `readFile "/path/to/host.pub"` yourself.
If you are managing a single host only, you can use `"/etc/ssh/ssh_host_ed25519_key.pub"`
here to allow the rekey app to directly read your pubkey from your system.
If you are managing multiple hosts, it's recommended to either store a copy of each
host's pubkey in your flake and use refer to those here `./secrets/host1-pubkey.pub`,
or directly set the host's pubkey here by specifying `"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI..."`.
Make sure to NEVER use a private key here, as it will end up in the public nix store!
'';
default = # This pubkey is just binary 0x01 in each byte, so you can be sure there is no known private key for this
"age1qyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqs3290gq";

Expand Down Expand Up @@ -311,7 +240,10 @@ in
{
options.vaultix = {

package = mkPackageOption pkgs "vaultix" { };
package = mkOption {
type = types.package;
default = vaultixSelf.packages.${pkgs.system}.vaultix;
};

settings = mkOption {
type = settingsType;
Expand All @@ -333,12 +265,12 @@ in

config =
let
profile = (pkgs.formats.toml { }).generate "secretsMetadata" (cfg);
profile = (pkgs.formats.toml { }).generate "secretsMetadata" cfg;
in
mkIf (sysusers && storageExist) {
test = profile;

systemd.services.agenix-install-secrets = {
systemd.services.vaultix-install-secrets = {
wantedBy = [ "sysinit.target" ];
after = [ "systemd-sysusers.service" ];
unitConfig.DefaultDependencies = "no";
Expand Down
Loading

0 comments on commit ec49259

Please sign in to comment.