From cd820411c4f00f5338d6c0a8bfd519150464d183 Mon Sep 17 00:00:00 2001 From: cswimr Date: Mon, 2 Dec 2024 20:50:24 -0500 Subject: [PATCH] use `sops` for secret management --- .sops.yaml | 9 +++++++++ .sops.yml | 7 ------- flake.lock | 21 +++++++++++++++++++++ flake.nix | 7 +++++++ nixos/sops.nix | 13 +++++++++++++ scripts/py/common/common.py | 15 +++++++++++---- scripts/py/spectacle-screenshot.py | 2 +- scripts/py/zipline.py | 16 +++------------- secrets/secrets.yaml | 30 ++++++++++++++++++++++++++++++ 9 files changed, 95 insertions(+), 25 deletions(-) create mode 100644 .sops.yaml delete mode 100644 .sops.yml create mode 100644 nixos/sops.nix create mode 100644 secrets/secrets.yaml diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..25db5dd --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,9 @@ +keys: + - &cswimr age1q9f9zhkfjn2c3a8qtmfqh0rtls3542jukqpt7t93jca6hc947f3sm9ujhx + - &eclipse age184ude6fyak8z4nnndq4nzcpe2d89zxf3r4paty7j2tenkwa6zgtqrz60lq +creation_rules: + - path_regex: secrets/[^/]+\.(yaml|json|env|ini)$ + key_groups: + - age: + - *cswimr + - *eclipse diff --git a/.sops.yml b/.sops.yml deleted file mode 100644 index 11233dc..0000000 --- a/.sops.yml +++ /dev/null @@ -1,7 +0,0 @@ -keys: - - $eclipse age1q9f9zhkfjn2c3a8qtmfqh0rtls3542jukqpt7t93jca6hc947f3sm9ujhx -creation_rules: - - path_regex: secrets/[^/]+\.(yaml|json|env|ini|sops)$ - key_groups: - - age: - - *eclipse diff --git a/flake.lock b/flake.lock index 9f18703..2b59fce 100644 --- a/flake.lock +++ b/flake.lock @@ -532,9 +532,30 @@ "nixpkgs": "nixpkgs_3", "nixvim": "nixvim", "plasma-manager": "plasma-manager", + "sops-nix": "sops-nix", "zen-browser": "zen-browser" } }, + "sops-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1733128155, + "narHash": "sha256-m6/qwJAJYcidGMEdLqjKzRIjapK4nUfMq7rDCTmZajc=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "c6134b6fff6bda95a1ac872a2a9d5f32e3c37856", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" + } + }, "systems": { "locked": { "lastModified": 1681028828, diff --git a/flake.nix b/flake.nix index 12a1957..da479d0 100644 --- a/flake.nix +++ b/flake.nix @@ -11,6 +11,10 @@ inputs.nixpkgs.follows = "nixpkgs"; inputs.home-manager.follows = "home-manager"; }; + sops-nix = { + url = "github:Mic92/sops-nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; nix-flatpak.url = "github:gmodena/nix-flatpak"; nixvim = { url = "github:nix-community/nixvim"; @@ -44,6 +48,7 @@ inherit pkgs; system = system; hostname = "eclipse"; + user = user; }; modules = [ # imports @@ -60,6 +65,7 @@ ./nixos/nvim.nix ./nixos/pkg.nix ./nixos/shell.nix + ./nixos/sops.nix ./nixos/sudo.nix ./nixos/symlinks.nix ./nixos/tailscale.nix @@ -69,6 +75,7 @@ hardware.bluetooth.enable = true; } + inputs.sops-nix.nixosModules.sops inputs.nixvim.nixosModules.nixvim inputs.nix-flatpak.nixosModules.nix-flatpak diff --git a/nixos/sops.nix b/nixos/sops.nix new file mode 100644 index 0000000..fd2b726 --- /dev/null +++ b/nixos/sops.nix @@ -0,0 +1,13 @@ +{ user, ... }: +{ + sops = { + defaultSopsFile = ../secrets/secrets.yaml; + age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; + secrets = { + "zipline" = { + owner = user; + path = "/home/${user}/.secrets/zipline"; + }; + }; + }; +} diff --git a/scripts/py/common/common.py b/scripts/py/common/common.py index 84906d7..762e42a 100644 --- a/scripts/py/common/common.py +++ b/scripts/py/common/common.py @@ -13,6 +13,8 @@ def notify( icon: Path | None = None, desktop_entry: str | None = None, ) -> None: + if not which("notify-send"): + raise FileNotFoundError("notify-send is not installed.") args = ["notify-send", "-a", application_name, "-u", urgency] if category: args.append("-c") @@ -21,6 +23,8 @@ def notify( args.append("-i") args.append(str(icon)) if desktop_entry: + if not does_desktop_entry_exist(desktop_entry=desktop_entry): + raise FileNotFoundError("Desktop entry does not exist.") args.append("-h") args.append(f"string:desktop-entry:{desktop_entry}") args.append(title) @@ -29,12 +33,15 @@ def notify( subprocess.run(args) -def read_secret_file(secret: str) -> str: - path = f"/var/secrets/{secret}" +def read_secret_file(secret: str, home: bool = False) -> str: + if home: + path = os.path.expanduser(f"~/.secrets/{secret}") + else: + path = f"/var/secrets/{secret}" if not os.path.exists(path): raise FileNotFoundError(f"Secret file {path} does not exist or cannot be read.") - with open(f"/var/secrets/{secret}", "r") as f: - secret = f.read().strip() + with open(file=path, mode="r") as secret_file: + secret = secret_file.read().strip() if not secret: raise ValueError(f"Secret file {path} is empty.") return secret diff --git a/scripts/py/spectacle-screenshot.py b/scripts/py/spectacle-screenshot.py index 0c94b16..e9f9d94 100755 --- a/scripts/py/spectacle-screenshot.py +++ b/scripts/py/spectacle-screenshot.py @@ -60,7 +60,7 @@ def spectacle_screenshot( try: opts = [ - "zipline.py", + "/etc/nixos/scripts/py/zipline.py", file_path, "--application-name", "Spectacle", diff --git a/scripts/py/zipline.py b/scripts/py/zipline.py index d17f745..6178f03 100755 --- a/scripts/py/zipline.py +++ b/scripts/py/zipline.py @@ -5,12 +5,10 @@ import argparse import mimetypes import os from pathlib import Path -from shutil import which from typing import Any import requests # type: ignore from common.common import ( # type: ignore - does_desktop_entry_exist, notify, read_secret_file, ) @@ -23,19 +21,11 @@ def zipline( application_name: str | None = None, desktop_entry: str | None = None, ) -> Any: - token = read_secret_file("zipline") + token = read_secret_file(secret="zipline", home=True) if not os.path.isfile(file_path): raise FileNotFoundError(f"File at {file_path} does not exist.") - use_notify_send = False - if application_name and desktop_entry: - if not does_desktop_entry_exist(desktop_entry=desktop_entry): - raise FileNotFoundError("Desktop entry does not exist.") - if not which("notify-send"): - raise FileNotFoundError("notify-send is not installed.") - use_notify_send = True - content_type = mimetypes.guess_type(file_path)[0] or "application/octet-stream" try: @@ -55,7 +45,7 @@ def zipline( copy(text=link) print(f"Link copied to clipboard: {link}") - if use_notify_send: + if application_name and desktop_entry: notify( application_name=application_name, title="Upload Successful", @@ -71,7 +61,7 @@ def zipline( raise Exception(error_message) except BaseException as e: - if use_notify_send: + if application_name and desktop_entry: notify( application_name=application_name, title="Upload Failed", diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml new file mode 100644 index 0000000..ec1042b --- /dev/null +++ b/secrets/secrets.yaml @@ -0,0 +1,30 @@ +zipline: ENC[AES256_GCM,data:YQMdw1cJy9wFnJsX6fPWBXK0rPEnuJJwJysVh0vggcnySFjl5Dmolaqxhw==,iv:RKB+rNz76ZxqzmyATLcpHmaap1f6aWWm7smBTieMZ8M=,tag:GN967VhwqZwMA6uzshKBmQ==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1q9f9zhkfjn2c3a8qtmfqh0rtls3542jukqpt7t93jca6hc947f3sm9ujhx + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBabXF4b2dBelo1THZHOG9u + UWxNaEMwTlErTU1ZYmhISnVubXBBY3JaZkFjClFpblNFeWtwN0hrOGVTdThaQzFE + R0lqS2lYcDBWck9Pb3dmTk1yRS9rNFUKLS0tIFRUaUx2QlRmb0NFRlV3RndYbUpn + RHlURzRGL0grRFRDVGlVMTNpMlU5eUkKWzoCPqrcJBqM0H+Ap0v5Jsf69y7xV9gA + d9ubH84yMrOjLPs/K2FmLm+0zr7/epGE02nceiGzgWDHczQGp7qhzA== + -----END AGE ENCRYPTED FILE----- + - recipient: age184ude6fyak8z4nnndq4nzcpe2d89zxf3r4paty7j2tenkwa6zgtqrz60lq + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1ZVdIRkMzMjErTjRpSC82 + Rk04SmxVM3FiUys1VVViUmhQTkJKTW1MSjNNClg2KzA1M3lXTjVqVm52aXlxNDE1 + cHl0VDB1MCtpdnVabStZRkoxQjlHQmcKLS0tIGs5WTZMUFNKcU5qQXVqUjFNTGVF + b1JvNi9YODZPN1FObWpOVHN3aU85NFEK1dN5pV8g3nG3D2l482z1JCRzmJ/9m495 + YEobjXbEqQDhvA47ueWojoMjvQ3CgrPyiL6v+DLj7VfI5cyuo+89IQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-12-03T01:29:28Z" + mac: ENC[AES256_GCM,data:NzE6V3kb9hiA9WAs7GFK5GqFoOUP5U/EOskWq0qdCo6GMewkK8TqrY+lFgjkEhY39PobgVTICBT8MGhY9eiEINYdBl7DuQGb3cR/puV+iCPEgUemzVcmcGkd24ktzUO2DsWet1EFC84oOu50XzYfR9VqW3z7+7UbpzWuOxIdvAA=,iv:pxNCxKPevqg8QxsIfL6+2pEB5cUmKhmLhmdiO+nB/Ac=,tag:uFA84z0XjzNgp3NLBu8AfQ==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.1