From 54bb672d9ef8da3aa213966029227141506daf8c Mon Sep 17 00:00:00 2001 From: Ryan Yin Date: Fri, 14 Jul 2023 17:09:47 +0800 Subject: [PATCH] feat: harden my private secrets --- flake.lock | 18 ++++++ flake.nix | 4 ++ home/base/server/bash.nix | 3 +- home/base/server/nushell/default.nix | 4 +- hosts/harmonica/default.nix | 2 + secrets/README.md | 93 ++++++++++++++++++--------- secrets/default.nix | 19 +++++- secrets/encrypt/smb-credentials.age | 10 --- secrets/encrypt/wg-business.conf.age | Bin 676 -> 0 bytes secrets/secrets.nix | 20 ------ 10 files changed, 108 insertions(+), 65 deletions(-) delete mode 100644 secrets/encrypt/smb-credentials.age delete mode 100644 secrets/encrypt/wg-business.conf.age delete mode 100644 secrets/secrets.nix diff --git a/flake.lock b/flake.lock index f5f3625e..e3a3e09c 100644 --- a/flake.lock +++ b/flake.lock @@ -239,6 +239,23 @@ "type": "github" } }, + "mysecrets": { + "flake": false, + "locked": { + "lastModified": 1689326736, + "narHash": "sha256-wVfvr9bEDkuivJbdtbLC6l82QZnc2dW4Nl3ExY6/oaA=", + "ref": "refs/heads/main", + "rev": "cd37f1a4f8543b6e272809c75f84ed674ac0e4d3", + "shallow": true, + "type": "git", + "url": "ssh://git@github.com/ryan4yin/nix-secrets.git" + }, + "original": { + "shallow": true, + "type": "git", + "url": "ssh://git@github.com/ryan4yin/nix-secrets.git" + } + }, "nix-eval-jobs": { "inputs": { "flake-parts": "flake-parts", @@ -449,6 +466,7 @@ "darwin": "darwin_2", "home-manager": "home-manager_2", "hyprland": "hyprland", + "mysecrets": "mysecrets", "nixos-generators": "nixos-generators", "nixpkgs": "nixpkgs_3", "nixpkgs-darwin": "nixpkgs-darwin", diff --git a/flake.nix b/flake.nix index 77f28991..2185f362 100644 --- a/flake.nix +++ b/flake.nix @@ -74,6 +74,10 @@ # AstroNvim is an aesthetic and feature-rich neovim config. astronvim = { url = "github:AstroNvim/AstroNvim/v3.32.0"; flake = false; }; + + # my private secrets, it's a private repository, you need to replace it with your own. + # use ssh protocol to authenticate via ssh-agent/ssh-key, and shallow clone to save time + mysecrets = { url = "git+ssh://git@github.com/ryan4yin/nix-secrets.git?shallow=1"; flake = false; }; }; # The `outputs` function will return all the build results of the flake. diff --git a/home/base/server/bash.nix b/home/base/server/bash.nix index 80faca62..53827dad 100644 --- a/home/base/server/bash.nix +++ b/home/base/server/bash.nix @@ -1,10 +1,11 @@ -{ ... }: { +{ config, builtins, ... }: { programs.bash = { enable = true; enableCompletion = true; bashrcExtra = '' export PATH="$PATH:$HOME/bin:$HOME/.local/bin:$HOME/go/bin" ''; + # ++ (builtins.readFile config.age.secrets."alias-for-work.bash".path); shellAliases = { k = "kubectl"; diff --git a/home/base/server/nushell/default.nix b/home/base/server/nushell/default.nix index 41fa49ec..3d37f1a7 100644 --- a/home/base/server/nushell/default.nix +++ b/home/base/server/nushell/default.nix @@ -1,4 +1,4 @@ -{ ... }: { +{ config, builtins, ... }: { programs.nushell = { enable = true; configFile.source = ./config.nu; @@ -9,6 +9,8 @@ # envFile.source = ./env.nu; # environmentVariables = { FOO="bar"; }; + # extraConfig = builtins.readFile config.age.secrets."alias-for-work.nushell".path; + shellAliases = { k = "kubectl"; diff --git a/hosts/harmonica/default.nix b/hosts/harmonica/default.nix index 11fd0f8b..1c8c0491 100644 --- a/hosts/harmonica/default.nix +++ b/hosts/harmonica/default.nix @@ -10,5 +10,7 @@ imports = [ ../../modules/darwin/core.nix ../../modules/darwin/apps.nix + + ../../secrets ]; } diff --git a/secrets/README.md b/secrets/README.md index da987b8d..dc91a7e0 100644 --- a/secrets/README.md +++ b/secrets/README.md @@ -1,27 +1,20 @@ -# secrets management -This directory contains my secret files, encrypt by agenix: +# Secrets Management -- my wireguard configuration files, which is used by `wg-quick` -- github token, used by nix flakes to query and downloads flakes from github - - without this, you may reach out github api rate limit. -- ssh key pairs for my homelab and other servers -- ... +This directory contains my encrypted secret files managed by agenix. -## TODO +All these secrets are stored in a separate private GitHub repository and referenced as a flake input of this repository. -- a better way to manage all these secrets, is to used a separate private github repository to store all these secrets, and use it as a flakes input this this repo. - - e.g. +## Adding or Updating Secrets -## Add or Update Secrets +> All the operations in this section should be performed in my private repository: `nix-secrets`. -This job is done by `agenix` CLI tool with the `./secrets.nix` file. +This task is accomplished using the `agenix` CLI tool with the `./secrets.nix` file. -Pretend you want to add a new secret file `xxx.age`, then: +Suppose you want to add a new secret file `xxx.age`. Follow these steps: -1. `cd` to this directory -1. edit `secrets.nix`, add a new entry for `xxx.age`, which defines the - encryption keys and the secret file path, e.g. +1. Navigate to your private `nix-secrets` repository. +2. Edit `secrets.nix` and add a new entry for `xxx.age`, defining the encryption keys and the secret file path, for example: ```nix # This file is not imported into your NixOS configuration. It is only used for the agenix CLI. @@ -42,32 +35,69 @@ let systems = [ ai ]; in { - "./encrypt/xxx.age".publicKeys = users ++ systems; + "./xxx.age".publicKeys = users ++ systems; } ``` -2. create and edit the secret file `xxx.age` interactively by command: +3. Create and edit the secret file `xxx.age` interactively using the following command: ```shell -agenix -e ./encrypt/xxx.age +agenix -e ./xxx.age ``` -3. or you can also encrypt an existing file to `xxx.age` by command: +Alternatively, you can encrypt an existing file to `xxx.age` using the following command: ```shell -cat /path/to/xxx | agenix -e ./encrypt/xxx.age +cat /path/to/xxx | agenix -e ./xxx.age ``` -the agenix use `~/.ssh/id_ed25519.pub` or `~/.ssh/id_rsa.pub` as encrypt key by default, you need to pass `--identity /path/to/key` to use a custom `/path/to/key.pub` for enctypt. +By default, agenix uses `~/.ssh/id_ed25519.pub` or `~/.ssh/id_rsa.pub` as the encryption key. +If you want to use a custom key located at `/path/to/key.pub` for encryption, pass `--identity /path/to/key`. -## Deploy Secrets +## Deploying Secrets -This job is done by `nixos-rebuild` with the `./default.nix` file. +> All the operations in this section should be performed in this repository. -An nixos module exmaple(need to set agenix as flake inputs first...): +First, add the private `nix-secrets` repository and `agenix` as flake inputs: ```nix -{ config, pkgs, agenix, ... }: +{ + inputs = { + # ...... + + # secrets management, lock with git commit at 2023/5/15 + agenix.url = "github:ryantm/agenix/db5637d10f797bb251b94ef9040b237f4702cde3"; + + # my private secrets, it's a private repository, you need to replace it with your own. + mysecrets = { url = "github:ryan4yin/nix-secrets"; flake = false; }; + }; + + outputs = inputs@{ self, nixpkgs, ... }: { + nixosConfigurations = { + nixos-test = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + + # Set all input parameters as specialArgs of all sub-modules + # so that we can use the `agenix` & `mysecrets` in sub-modules + specialArgs = inputs; + modules = [ + # ...... + + # import & decrypt secrets in `mysecrets` in this module + ./secrets/default.nix + ]; + }; + }; + }; +} +} +``` + +Then, create `./secrets/default.nix` with the following content: + +```nix +# import & decrypt secrets in `mysecrets` in this module +{ config, pkgs, agenix, mysecrets, ... }: { imports = [ @@ -84,7 +114,7 @@ An nixos module exmaple(need to set agenix as flake inputs first...): # target path for decrypted file path = "/etc/xxx/"; # encrypted file path - file = ./encrypt/xxx.age; + file = "${mysecrets}/xxx.age"; # refer to ./xxx.age located in `mysecrets` repo mode = "0400"; owner = "root"; group = "root"; @@ -92,7 +122,10 @@ An nixos module exmaple(need to set agenix as flake inputs first...): } ``` -`nixos-rebuild` will decrypt the secrets using the private keys defined by argument `age.identityPaths`, -And then symlink the secrets to the path defined by argument `age.secrets..path`, it defaults to `/etc/secrets`. +From now on, every time you run `nixos-rebuild switch`, it will decrypt the secrets using the private keys defined by the `age.identityPaths` argument. +It will then symlink the secrets to the path defined by the `age.secrets..path` argument, which defaults to `/etc/secrets`. + +NOTE: By default, `age.identityPaths` is set to `~/.ssh/id_ed25519` and `~/.ssh/id_rsa`, +so make sure to place your decryption keys there. +If you're deploying to the same machine from which you encrypted the secrets, it should work out of the box. -NOTE: `age.identityPaths` it defaults to `~/.ssh/id_ed25519` and `~/.ssh/id_rsa`, so you should put your decrypt keys there. if you're deploying to the same machine as you're encrypting from, it should work out of the box. diff --git a/secrets/default.nix b/secrets/default.nix index c50ec452..9b1af0a7 100644 --- a/secrets/default.nix +++ b/secrets/default.nix @@ -1,4 +1,4 @@ -{ pkgs, agenix, ... }: +{ pkgs, agenix, mysecrets, ... }: { imports = [ @@ -19,7 +19,7 @@ # target path for decrypted file path = "/etc/wireguard/"; # encrypted file path - file = ./encrypt/wg-business.conf.age; + file = "${mysecrets}/wg-business.conf.age"; mode = "0400"; owner = "root"; group = "root"; @@ -30,6 +30,19 @@ # wether secrets are symlinked to age.secrets..path symlink = true; # encrypted file path - file = ./encrypt/smb-credentials.age; + file = "${mysecrets}/smb-credentials.age"; + }; + + age.secrets."alias-for-work.nushell" = { + # wether secrets are symlinked to age.secrets..path + symlink = false; + # encrypted file path + file = "${mysecrets}/alias-for-work.nushell.age"; + }; + age.secrets."alias-for-work.bash" = { + # wether secrets are symlinked to age.secrets..path + symlink = false; + # encrypted file path + file = "${mysecrets}/alias-for-work.bash.age"; }; } diff --git a/secrets/encrypt/smb-credentials.age b/secrets/encrypt/smb-credentials.age deleted file mode 100644 index ec70dcd7..00000000 --- a/secrets/encrypt/smb-credentials.age +++ /dev/null @@ -1,10 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 epfRpA jNJBiC/XF/yZK+l5KoQiP9Q4Fd3DmkDy+g4NqFsoe3I -k1lFpYcTki0wjwFBDoAwRNZED1bbZI563fFs6wF6cQI --> ssh-ed25519 Q4ARMQ A5e3ifhn8G+XS16KqT0xtSZVwfE6IXgfN4mP0sr+wQ0 -dKHy5WGc8OxFhlDNEd/ZXPbDcvC7JcFChyK3vkquKjo --> b9bIm-grease -Y+K1G8OK/DI2E0cCD27xOPeneAZ/hFkw8bvNBZRYmQ0kTLf017wNDrLcIbyYTjpa -/HrKBATlWanuLhzhUFWyBxaJMCqtP35j5TPRCTh7 ---- rSOSvyrgXuiNAx8P3gDV7VaTcbOzwnufTnjhVvsMS7k -3&'6a(@O2'h&SUÅ[@h=Fz̨_DeLE{ds%K \ No newline at end of file diff --git a/secrets/encrypt/wg-business.conf.age b/secrets/encrypt/wg-business.conf.age deleted file mode 100644 index dfb15e4fbd42ae0e7479f326f380683e1328b198..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 676 zcmV;V0$crIXJsvAZewzJaCB*JZZ2?FFICfKcHa1W+WjJ+CRZBBf3TbsR zO*D68dPO&IP)u%OaxY?KNn|- zb7dfCYBgyfbR;7nawBmpZXix93S&h}V{c7&3N0-yAU1MxS7t(ZPB2zEGj3KzNOo~= zPHmO~pa?vJfX0zYTo0n_$>9(th%f_VGSP0C}Aqu@IWXYe$w z94rsG6W)3s;fbj8^j0Y#%)ixc;7*Y));Ilifl8lV8N)}#pMhImDJ(2|)M6B992d00 zP>hz|riUwA9s|~FcP=w4TIKKlZ-V|lIVItkIpH`jkdyc37gHM1QL{SZ`3N6lsVzdi K6M)QirofLU0u&Yi diff --git a/secrets/secrets.nix b/secrets/secrets.nix deleted file mode 100644 index 120a1eac..00000000 --- a/secrets/secrets.nix +++ /dev/null @@ -1,20 +0,0 @@ -# This file is not imported into your NixOS configuration. It is only used for the agenix CLI. - -let - # get my ssh public key for agenix by command: - # cat ~/.ssh/juliet-age.pub - # if you do not have one, you can generate it by command: - # ssh-keygen -t ed25519 - ryan = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP7FbSWehHoOWCZMDEHLiPCa1ZJ5c6hYMzhKdXssPpE9 ryan@juliet-age"; - users = [ ryan ]; - - # get system's ssh public key by command: - # cat /etc/ssh/ssh_host_ed25519_key.pub - ai = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICGeXNCazqiqxn8TmbCRjA+pLWrxwenn+CFhizBMP6en root@ai"; - systems = [ ai ]; -in -{ - "./encrypt/wg-business.conf.age".publicKeys = users ++ systems; - "./encrypt/smb-credentials.age".publicKeys = users ++ systems; - # "./encrypt/secret123.age".publicKeys = [ user1 system1 ]; -}