From 8afcfba1d9444df221b01cf3ca2365878e91fd97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Krop=C3=A1=C4=8Dek?= Date: Tue, 7 Jan 2025 20:05:09 +0100 Subject: [PATCH] functional HELL --- hosts/bootstrap/default.nix | 5 ++++- nixosModules/users/default.nix | 7 ++++++ scripts/fresh_install.py | 39 ++++++++++++++++++++++++++------- secrets/keys.json | 13 +++++++++++ secrets/mypassword.age | Bin 505 -> 505 bytes secrets/secrets.nix | 19 ++++++---------- 6 files changed, 62 insertions(+), 21 deletions(-) create mode 100644 secrets/keys.json diff --git a/hosts/bootstrap/default.nix b/hosts/bootstrap/default.nix index c36a525..482a431 100644 --- a/hosts/bootstrap/default.nix +++ b/hosts/bootstrap/default.nix @@ -2,6 +2,9 @@ { kropcloud = { networking.enable = false; - admin.password = "changeme"; + admin = { + password = "changeme"; + sudoRequirePassword = false; + }; }; } diff --git a/nixosModules/users/default.nix b/nixosModules/users/default.nix index d19618e..af557f8 100644 --- a/nixosModules/users/default.nix +++ b/nixosModules/users/default.nix @@ -19,12 +19,19 @@ in default = null; description = "Password for the admin user. Should be used only for initial setup."; }; + sudoRequirePassword = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Require password for sudo. Should be used only for initial setup."; + }; }; config = { age.secrets.mypassword.file = ../../secrets/mypassword.age; + security.sudo.wheelNeedsPassword = cfg.sudoRequirePassword; + # Define the admin user users = { mutableUsers = false; diff --git a/scripts/fresh_install.py b/scripts/fresh_install.py index bccf412..a706023 100755 --- a/scripts/fresh_install.py +++ b/scripts/fresh_install.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import argparse import json -import ipaddress +import socket import time from subprocess import check_output @@ -16,10 +16,10 @@ def _get_available_machines() -> list: def _validate_ip(ip: str) -> bool: try: - ipaddress.ip_address(ip) - return True - except ValueError: + socket.inet_aton(ip) return False + except socket.error: + return True def _check_ssh_connection(ip: str) -> bool: @@ -29,6 +29,8 @@ def _check_ssh_connection(ip: str) -> bool: except Exception: return False +def add_key_to_secrets(key: str): + def bootstrap_machine(ip: str): check_output( @@ -50,7 +52,22 @@ def get_ssh_key(ip: str) -> str: """ This function uses machines ssh-keyscan to get the ssh key and then get the ed25519 key """ + ssh_keys = check_output( + [ + "ssh-keyscan", + "-q", + "-t", + "ed25519", + ip, + ] + ).decode("utf-8").strip().splitlines() + if len(ssh_keys) != 1: + raise ValueError("Exactly one key should be returned") + + key = ssh_keys.pop().lstrip(f"{ip} ").strip() + + return key def get_machine_config(machine_name: str) -> dict: output = check_output( @@ -82,18 +99,24 @@ def main() -> int: raise ValueError(f"Invalid IP address {args.machine_ip}") machine_config = get_machine_config(machine_name) - print(machine_config) # We are bootstraping the machine first because we need their ssh keys + print(f"Bootstrapping machine {args.machine_ip}") bootstrap_machine() + print("Machine bootstrapped") + print("Waiting for ssh connection") while not _check_ssh_connection(): time.sleep(5) + print("Machine is up and running") - # # connect and get ssh keys + print("Getting ssh key") + ssh_key = get_ssh_key(args.machine_ip) - # ssh_key = get_ssh_key() + print("Adding ssh key to secrets") + add_key_to_secrets(ssh_key) + rekey_secrets() - # Add the ssh key to keys in secrets/secrets.nix + # Add the ssh key to keys in secrets/keys.json # and rekey the secrets # install_machine() diff --git a/secrets/keys.json b/secrets/keys.json new file mode 100644 index 0000000..9c54dae --- /dev/null +++ b/secrets/keys.json @@ -0,0 +1,13 @@ + +{ + "hosts": { + "wenar-nix": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJl0Rdo2kHliBeIiPuiO4kYO5M0VZFNXw4siepV1p6Pj", + "lenar": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOUnlAjPnMwJYgZb7YuholdTxifOEFnAyXVqI+xFlHw6" + }, + "servers" : { + "test-server": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID4ioqiTzYe6Y6H0YfFkWyDBbCB25wYs3gKNZIufE/Sn" + }, + "secrets": { + "mypassword.age": ["hosts:wenar-nix", "hosts:lenar", "servers:test-server"] + } +} diff --git a/secrets/mypassword.age b/secrets/mypassword.age index 2752c16996c0a2373d2e9df3cedf7e07523e7800..f372b0a799e6f3c51b1c627e60033bda54bee2e8 100644 GIT binary patch delta 451 zcmV;!0X+Ws1Nj4xEPqfhdQEq7R&g>pZ7*XsR&Q%ZGfFr`XH7CNX-Q#bbVou$V{Ug& zGD&S$YYJLPSVLM_YI0{#V_7ybc}8V3XJt`oMQ%ezYj!zzb2Lj~L`-l{Nmy`iGzu*~ zAaiqQEoEdfH8n9gAWdjQM{IW>c2{miNn~PSX*M%yF=0?gWkxntM>0q-aBVY7LU}<{ zVNObDbvHRdVs}VI3NU7GNq9#}F*a{-c2_e*RBK3LY)43JXlz(&Q*~KIV_8X8RylZh zL19c$k?|LQO+i_AG;TpPaCTu(OKo;RRAhHacymTJR!cBSH&bJHMR8a-dTl{jcSKPN zbTV2Hp zL2P(!Q8;64Wp6PxZ!~u}Ms#>>P+3fFVMswwF;-P_H8ylba9S}q3W1vcA#T30P1ZyM zs}QEPxrv5!Ac8e#o`eE>5BC!E;4`+MDd%>-Orc~UZD%u#!{&M1*Z&X;pd0F@{ocj$ t^JII_R*769_bBgj@NUeX@p?j=n#kj&o8{{1|EBE~e?4DEE6#NV!J!l!tQG(O delta 451 zcmV;!0X+Ws1Nj4xEPqXFGIcmkYj{dFW=?ZWZ&Of1Y<72KQbjPIWj{HdIeCRc=XDbapFpX-P~^Ic#A?H*_*qV+t)k zAaiqQEoEdfH8n9gAWdjQM{IW>T3T*1V_8LPS!_d1I5S3WdPZ?8dQ(qALsfQ4Q$tNN zZ8vUlY)@}8GI4A$3N$ZPR#;3jLSk!8P(n;nZDvPPaCTKrR8vw_ZEHeyT1Zkzac*RA zNl`{~k?|LQIAv;CSVu!OIV);pVRKDGFH|sMb4h4&cs5vMN=$KUT3S?2MMZ8Z%O;c=nOhZ>}Nl;ZXT5)bjI7&$|D@Zg|a#}AjSZXy&``R{o7<~Y(mUa9EM7P~d)OP