rework
This commit is contained in:
+47
-34
@@ -16,14 +16,6 @@ in
|
|||||||
default = [ ];
|
default = [ ];
|
||||||
description = "A list of master keys for encrypting secrets.";
|
description = "A list of master keys for encrypting secrets.";
|
||||||
};
|
};
|
||||||
homeIdentities = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [ ];
|
|
||||||
example = [
|
|
||||||
"laptop-home"
|
|
||||||
"wawa-wawa-home"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
secretsDir = mkOption {
|
secretsDir = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = null;
|
default = null;
|
||||||
@@ -56,47 +48,68 @@ in
|
|||||||
config =
|
config =
|
||||||
let
|
let
|
||||||
secrets = builtins.fromJSON (builtins.readFile "${inputs.self}/${cfg.secretsDir}/secrets.json");
|
secrets = builtins.fromJSON (builtins.readFile "${inputs.self}/${cfg.secretsDir}/secrets.json");
|
||||||
all_keys = lib.flatten (lib.concatAttrValues per_host_keys);
|
|
||||||
per_host_keys = lib.mergeAttrsList (
|
toKeyList =
|
||||||
lib.flatten (
|
v:
|
||||||
map (
|
if builtins.isString v then
|
||||||
x:
|
|
||||||
builtins.mapAttrs (
|
|
||||||
name: value:
|
|
||||||
let
|
|
||||||
v = value.sopsPublic or [ ];
|
|
||||||
type = builtins.typeOf v;
|
|
||||||
vv =
|
|
||||||
if type == "string" then
|
|
||||||
[ v ]
|
[ v ]
|
||||||
else if type == "list" then
|
else if builtins.isList v then
|
||||||
v
|
v
|
||||||
else
|
else
|
||||||
throw "Unexpected type ${type} for sopsPublic in host ${name}";
|
throw "Unexpected type ${builtins.typeOf v} for sopsPublic";
|
||||||
in
|
|
||||||
vv
|
# Every host across every system: hostName -> [host pubkeys].
|
||||||
) x
|
host_keys = lib.mergeAttrsList (
|
||||||
|
lib.flatten (
|
||||||
|
map (
|
||||||
|
perSystem:
|
||||||
|
lib.mapAttrsToList (_: host: { ${host.hostName} = toKeyList (host.sopsPublic or [ ]); }) perSystem
|
||||||
) (builtins.attrValues den.hosts)
|
) (builtins.attrValues den.hosts)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
# Every user on every host is a home identity "<hostName>@<userName>".
|
||||||
|
home_keys = lib.mergeAttrsList (
|
||||||
|
lib.flatten (
|
||||||
|
map (
|
||||||
|
perSystem:
|
||||||
|
lib.mapAttrsToList (
|
||||||
|
_: host:
|
||||||
|
lib.mapAttrsToList (
|
||||||
|
_: user: { "${host.hostName}@${user.userName}" = toKeyList (user.sopsPublic or [ ]); }
|
||||||
|
) (host.users or { })
|
||||||
|
) perSystem
|
||||||
|
) (builtins.attrValues den.hosts)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
# Replaces the old hand-maintained `homeIdentities` option.
|
||||||
|
homeIdentities = builtins.attrNames home_keys;
|
||||||
|
|
||||||
|
# A secret's `hosts` may target either a host or a home identity.
|
||||||
|
identity_keys = host_keys // home_keys;
|
||||||
|
all_host_keys = lib.flatten (lib.attrValues host_keys);
|
||||||
|
all_home_keys = lib.flatten (lib.attrValues home_keys);
|
||||||
secret_map = lib.mapAttrs (
|
secret_map = lib.mapAttrs (
|
||||||
name: value:
|
name: value:
|
||||||
let
|
let
|
||||||
sopskeys = lib.unique (
|
sopskeys = lib.unique (
|
||||||
lib.flatten (map (k: per_host_keys.${k}) value.hosts)
|
lib.flatten (map (k: identity_keys.${k}) value.hosts)
|
||||||
++ (lib.optionals value.global all_keys)
|
++ (lib.optionals value.globalHosts all_host_keys)
|
||||||
|
++ (lib.optionals value.globalHomes all_home_keys)
|
||||||
++ cfg.masterKeys
|
++ cfg.masterKeys
|
||||||
);
|
);
|
||||||
# Descriptive flag: is this secret consumed by a home-manager user?
|
# Descriptive flag: is this secret consumed by a home-manager user?
|
||||||
# True when it is global or targets any identity in `homeIdentities`.
|
# True when it is global to homes or targets any home identity.
|
||||||
home = value.global || lib.any (h: lib.elem h cfg.homeIdentities) value.hosts;
|
home = value.globalHomes || lib.any (h: lib.elem h homeIdentities) value.hosts;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
inherit (value)
|
inherit (value)
|
||||||
format
|
format
|
||||||
neededForUsers
|
neededForUsers
|
||||||
hosts
|
hosts
|
||||||
global
|
globalHosts
|
||||||
|
globalHomes
|
||||||
;
|
;
|
||||||
keys = value.keys or [ ];
|
keys = value.keys or [ ];
|
||||||
inherit sopskeys home;
|
inherit sopskeys home;
|
||||||
@@ -114,7 +127,7 @@ in
|
|||||||
lib.mapAttrsToList (
|
lib.mapAttrsToList (
|
||||||
name: value:
|
name: value:
|
||||||
let
|
let
|
||||||
hasHost = (lib.elem host value.hosts) || value.global;
|
hasHost = (lib.elem host value.hosts) || value.globalHosts;
|
||||||
isYamlOrJson = value.format == "yaml" || value.format == "json";
|
isYamlOrJson = value.format == "yaml" || value.format == "json";
|
||||||
in
|
in
|
||||||
(
|
(
|
||||||
@@ -158,7 +171,7 @@ in
|
|||||||
lib.mapAttrsToList (
|
lib.mapAttrsToList (
|
||||||
name: value:
|
name: value:
|
||||||
let
|
let
|
||||||
hasHost = (lib.elem identity value.hosts) || value.global;
|
hasHost = (lib.elem identity value.hosts) || value.globalHomes;
|
||||||
isYamlOrJson = value.format == "yaml" || value.format == "json";
|
isYamlOrJson = value.format == "yaml" || value.format == "json";
|
||||||
in
|
in
|
||||||
(
|
(
|
||||||
@@ -193,8 +206,8 @@ in
|
|||||||
flake.secretsManifest = {
|
flake.secretsManifest = {
|
||||||
secretsDir = cfg.secretsDir;
|
secretsDir = cfg.secretsDir;
|
||||||
masterKeys = cfg.masterKeys;
|
masterKeys = cfg.masterKeys;
|
||||||
hosts = lib.mapAttrs (_: keys: { inherit keys; }) per_host_keys;
|
hosts = lib.mapAttrs (_: keys: { inherit keys; }) host_keys;
|
||||||
homeIdentities = cfg.homeIdentities;
|
inherit homeIdentities;
|
||||||
secrets = secret_map;
|
secrets = secret_map;
|
||||||
};
|
};
|
||||||
secrets.nixosModule = {
|
secrets.nixosModule = {
|
||||||
|
|||||||
+4
-1
@@ -25,7 +25,10 @@ pub struct HostInfo {
|
|||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
pub struct SecretInfo {
|
pub struct SecretInfo {
|
||||||
pub format: SecretFormat,
|
pub format: SecretFormat,
|
||||||
pub global: bool,
|
#[serde(rename = "globalHosts")]
|
||||||
|
pub global_hosts: bool,
|
||||||
|
#[serde(rename = "globalHomes")]
|
||||||
|
pub global_homes: bool,
|
||||||
pub hosts: Vec<String>,
|
pub hosts: Vec<String>,
|
||||||
#[serde(rename = "neededForUsers")]
|
#[serde(rename = "neededForUsers")]
|
||||||
pub needed_for_users: bool,
|
pub needed_for_users: bool,
|
||||||
|
|||||||
@@ -81,16 +81,17 @@ fn render_secret_detail(state: &App, area: Rect, buf: &mut Buffer) {
|
|||||||
]));
|
]));
|
||||||
|
|
||||||
// Scope
|
// Scope
|
||||||
let scope = if secret.global {
|
let scope = match (secret.global_hosts, secret.global_homes) {
|
||||||
"global".to_string()
|
(true, true) => "global (hosts + homes)".to_string(),
|
||||||
} else {
|
(true, false) => "global (hosts)".to_string(),
|
||||||
"host-specific".to_string()
|
(false, true) => "global (homes)".to_string(),
|
||||||
|
(false, false) => "host-specific".to_string(),
|
||||||
};
|
};
|
||||||
lines.push(Line::from(vec![
|
lines.push(Line::from(vec![
|
||||||
Span::styled(" Scope: ", Style::default().fg(Color::DarkGray)),
|
Span::styled(" Scope: ", Style::default().fg(Color::DarkGray)),
|
||||||
Span::styled(scope, Style::default().fg(Color::White)),
|
Span::styled(scope, Style::default().fg(Color::White)),
|
||||||
]));
|
]));
|
||||||
if !secret.global {
|
if !(secret.global_hosts && secret.global_homes) {
|
||||||
// Hosts / identities. Home-manager identities are coloured distinctly
|
// Hosts / identities. Home-manager identities are coloured distinctly
|
||||||
// so it is obvious which targets are user (home) rather than system.
|
// so it is obvious which targets are user (home) rather than system.
|
||||||
let mut host_spans: Vec<Span> = vec![Span::styled(
|
let mut host_spans: Vec<Span> = vec![Span::styled(
|
||||||
|
|||||||
Reference in New Issue
Block a user