Manage secrets with sops

This commit is contained in:
clerie 2025-02-15 18:25:36 +01:00
parent 1ccc129bb6
commit 6e080e67ec
5 changed files with 124 additions and 0 deletions

4
.sops.yaml Normal file
View File

@ -0,0 +1,4 @@
creation_rules:
- pgp: 0C982F87B7AFBA0F504F90A2629E741947C87928

View File

@ -1,5 +1,23 @@
uberspaceify = repo.libs.uberspace.Uberspaceify(node) uberspaceify = repo.libs.uberspace.Uberspaceify(node)
repo_config_files = {}
for repo, repo_config in node.metadata.get("clerie-backup/repos").items():
repo_config_files[f'/home/{node.username}/.config/clerie-backup/{repo}/repo_password'] = {
"content": repo_config["repo_password"],
"mode": "0600",
}
repo_config_files[f'/home/{node.username}/.config/clerie-backup/{repo}/repo_url'] = {
"content": repo_config["repo_url"],
}
repo_config_files[f'/home/{node.username}/.config/clerie-backup/{repo}/auth_username'] = {
"content": repo_config["auth_username"],
}
repo_config_files[f'/home/{node.username}/.config/clerie-backup/{repo}/auth_password'] = {
"content": repo_config["auth_password"],
"mode": "0600",
}
files = uberspaceify.files({ files = uberspaceify.files({
f'/home/{node.username}/.bwdownloads/clerie-backup.sh': { f'/home/{node.username}/.bwdownloads/clerie-backup.sh': {
"content_type": "download", "content_type": "download",
@ -14,6 +32,7 @@ files = uberspaceify.files({
"action:install_restic", "action:install_restic",
], ],
}, },
**repo_config_files,
}) })
actions = { actions = {

50
libs/bwsops.py Normal file
View File

@ -0,0 +1,50 @@
from bundlewrap.exceptions import FaultUnavailable
from bundlewrap.utils import Fault
import json
from pathlib import Path
import subprocess
class BwSops:
def __init__(self, file):
self.file = Path(file)
self._secrets = None
def _fetch_secrets(self):
try:
p = subprocess.run(["sops", "decrypt", str(self.file)], capture_output=True, check=True)
except subprocess.CalledProcessError as e:
raise FaultUnavailable(f"SOPS: \n{e.stderr}")
self._secrets = json.loads(p.stdout)
def _get(self, path):
if self._secrets is None:
self._fetch_secrets()
out = self._secrets
_path_traversed = []
try:
for name in path:
if not isinstance(out, dict):
raise KeyError(name)
out = out[name]
_path_traversed.append(name)
except KeyError as e:
raise FaultUnavailable(
f"SOPS secret not found: {self.file}:{'/'.join(path)}\n"
f" {e.args[0]} not in {'/'.join(_path_traversed)}"
)
return out
def get(self, path):
if isinstance(path, str):
path = path.split("/")
return Fault(
f"SOPS {self.file}:{'/'.join(path)}",
self._get,
path=path,
)

View File

@ -1,3 +1,4 @@
bws = libs.bwsops.BwSops("secrets.json")
uberspaceify = libs.uberspace.Uberspaceify() uberspaceify = libs.uberspace.Uberspaceify()
nodes = uberspaceify.nodes({ nodes = uberspaceify.nodes({
@ -6,6 +7,24 @@ nodes = uberspaceify.nodes({
"uberspace-redirect-clerie", "uberspace-redirect-clerie",
"uberspace-clerie-backup", "uberspace-clerie-backup",
), ),
"metadata": {
"clerie-backup": {
"repos": {
"main-cyan": {
"repo_password": bws.get("clerie.uber.space/clerie-backup/main-cyan/repo_password"),
"repo_url": "https://cyan.backup.clerie.de/clerie.uber.space/main",
"auth_username": "clerie.uber.space",
"auth_password": bws.get("clerie.uber.space/clerie-backup/main-cyan/auth_password"),
},
"main-magenta": {
"repo_password": bws.get("clerie.uber.space/clerie-backup/main-magenta/repo_password"),
"repo_url": "https://magenta.backup.clerie.de/clerie.uber.space/main",
"auth_username": "clerie.uber.space",
"auth_password": bws.get("clerie.uber.space/clerie-backup/main-magenta/auth_password"),
},
},
},
},
}, },
"cleriewi.uber.space": { "cleriewi.uber.space": {
"bundles": ( "bundles": (

32
secrets.json Normal file
View File

@ -0,0 +1,32 @@
{
"clerie.uber.space": {
"clerie-backup": {
"main-cyan": {
"repo_password": "ENC[AES256_GCM,data:BjyMOOGFdcT6e/zuQKPW88XiKhL26KYKebP0dsevMHmKoxQdIw9R/KS/GIlMlJKsz2wwH6nk5adiLBVD9+7TCA==,iv:1/iT4/QwRuZL3pq2D9nYiqTEpMHtf29r1mAYOzkxQeA=,tag:4LxvLRwfJYd9erPhBKb1Bw==,type:str]",
"auth_password": "ENC[AES256_GCM,data:j6QJeJ7SKKoEnpiO+YxvHfcP38KVop0bfAScRk0mWeBr+8S+3sYMGnPcVbhoHcqJsWyeeEDomhm/GniGza2zLA==,iv:bxL7Hh9jVZ4wc4/69qSmRZZHcCxlEpllIu9zKA4tRy0=,tag:W4cNmbJgDZlqshUN39ieLw==,type:str]"
},
"main-magenta": {
"repo_password": "ENC[AES256_GCM,data:nDPphjFK0gY77Vq+QLhWRhUM+IxgPD+rIgYS99HCDLS5YVLiPK56kizXRWlOPpq/uUr9bdhLnQAJ8FOBbhvBKA==,iv:HE/v/cVfIrjEXdb820pGJe2hqpYaXiIqDTBr0qTg7AY=,tag:yFpn+0rI9mzGv7vdxUBKjQ==,type:str]",
"auth_password": "ENC[AES256_GCM,data:I3NbXg6Gk4/7z2Ct7L10/mASKxInAFbKN9s9O5Lz6mTfbL35n+cu58H2xP/Nxqu/AJMCcOoXwNHhA/iLGH24RQ==,iv:TwdUR7jnVYK0PnQmMs5P+TrXEtyCxQXbxWPDsmdEPbc=,tag:Sat2Wlb4vYMoH+VRgKjaFQ==,type:str]"
}
}
},
"sops": {
"kms": null,
"gcp_kms": null,
"azure_kv": null,
"hc_vault": null,
"age": null,
"lastmodified": "2025-02-15T17:21:10Z",
"mac": "ENC[AES256_GCM,data:mYmefpdMExQz5PQ9ksHnlfHdPLWrsHLBPxBpghSyMxQgLNuope1D8FiGXPrFq/98MS9X82f326YddmDgGXylfm3URMHCWVtpiPnVIsKNGIknFQDMk2pDtfdkLd+7/FImRu/5xWrDLmpZ1Wtugpoc1831Jx9ouSqFUdwXeUoVeYA=,iv:q7JZGJYalu264UmOk8nD1+orHIa7tnWWK8IGNsuDE2o=,tag:NOTC8SUwBPvtsDVB1lPyhQ==,type:str]",
"pgp": [
{
"created_at": "2025-02-15T16:00:02Z",
"enc": "-----BEGIN PGP MESSAGE-----\n\n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\ncwQ6WxacmA==\n=e0B2\n-----END PGP MESSAGE-----",
"fp": "0C982F87B7AFBA0F504F90A2629E741947C87928"
}
],
"unencrypted_suffix": "_unencrypted",
"version": "3.9.2"
}
}