functional HELL
This commit is contained in:
parent
6b54f0bc42
commit
8afcfba1d9
6 changed files with 62 additions and 21 deletions
|
@ -2,6 +2,9 @@
|
||||||
{
|
{
|
||||||
kropcloud = {
|
kropcloud = {
|
||||||
networking.enable = false;
|
networking.enable = false;
|
||||||
admin.password = "changeme";
|
admin = {
|
||||||
|
password = "changeme";
|
||||||
|
sudoRequirePassword = false;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,19 @@ in
|
||||||
default = null;
|
default = null;
|
||||||
description = "Password for the admin user. Should be used only for initial setup.";
|
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 = {
|
config = {
|
||||||
|
|
||||||
age.secrets.mypassword.file = ../../secrets/mypassword.age;
|
age.secrets.mypassword.file = ../../secrets/mypassword.age;
|
||||||
|
|
||||||
|
security.sudo.wheelNeedsPassword = cfg.sudoRequirePassword;
|
||||||
|
|
||||||
# Define the admin user
|
# Define the admin user
|
||||||
users = {
|
users = {
|
||||||
mutableUsers = false;
|
mutableUsers = false;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
import ipaddress
|
import socket
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from subprocess import check_output
|
from subprocess import check_output
|
||||||
|
@ -16,10 +16,10 @@ def _get_available_machines() -> list:
|
||||||
|
|
||||||
def _validate_ip(ip: str) -> bool:
|
def _validate_ip(ip: str) -> bool:
|
||||||
try:
|
try:
|
||||||
ipaddress.ip_address(ip)
|
socket.inet_aton(ip)
|
||||||
return True
|
|
||||||
except ValueError:
|
|
||||||
return False
|
return False
|
||||||
|
except socket.error:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _check_ssh_connection(ip: str) -> bool:
|
def _check_ssh_connection(ip: str) -> bool:
|
||||||
|
@ -29,6 +29,8 @@ def _check_ssh_connection(ip: str) -> bool:
|
||||||
except Exception:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def add_key_to_secrets(key: str):
|
||||||
|
|
||||||
|
|
||||||
def bootstrap_machine(ip: str):
|
def bootstrap_machine(ip: str):
|
||||||
check_output(
|
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
|
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:
|
def get_machine_config(machine_name: str) -> dict:
|
||||||
output = check_output(
|
output = check_output(
|
||||||
|
@ -82,18 +99,24 @@ def main() -> int:
|
||||||
raise ValueError(f"Invalid IP address {args.machine_ip}")
|
raise ValueError(f"Invalid IP address {args.machine_ip}")
|
||||||
|
|
||||||
machine_config = get_machine_config(machine_name)
|
machine_config = get_machine_config(machine_name)
|
||||||
print(machine_config)
|
|
||||||
# We are bootstraping the machine first because we need their ssh keys
|
# We are bootstraping the machine first because we need their ssh keys
|
||||||
|
print(f"Bootstrapping machine {args.machine_ip}")
|
||||||
bootstrap_machine()
|
bootstrap_machine()
|
||||||
|
print("Machine bootstrapped")
|
||||||
|
|
||||||
|
print("Waiting for ssh connection")
|
||||||
while not _check_ssh_connection():
|
while not _check_ssh_connection():
|
||||||
time.sleep(5)
|
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
|
# and rekey the secrets
|
||||||
|
|
||||||
# install_machine()
|
# install_machine()
|
||||||
|
|
13
secrets/keys.json
Normal file
13
secrets/keys.json
Normal file
|
@ -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"]
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
|
@ -1,17 +1,12 @@
|
||||||
let
|
let
|
||||||
wenar-nix = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJl0Rdo2kHliBeIiPuiO4kYO5M0VZFNXw4siepV1p6Pj";
|
keyfile = builtins.fromJSON (builtins.readFile ./keys.json);
|
||||||
lenar = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOUnlAjPnMwJYgZb7YuholdTxifOEFnAyXVqI+xFlHw6";
|
|
||||||
users = [
|
|
||||||
wenar-nix
|
|
||||||
lenar
|
|
||||||
];
|
|
||||||
|
|
||||||
test-server = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID4ioqiTzYe6Y6H0YfFkWyDBbCB25wYs3gKNZIufE/Sn";
|
splitString = delim: str: builtins.filter builtins.isString (builtins.split delim str);
|
||||||
systems = [
|
|
||||||
test-server
|
getKey = pair: keyfile.${builtins.elemAt pair 0}.${builtins.elemAt pair 1};
|
||||||
];
|
|
||||||
allKeys = users ++ systems;
|
getKeys = secretName: builtins.map (x: getKey (splitString ":" x)) keyfile.secrets.${secretName};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
"mypassword.age".publicKeys = allKeys;
|
"mypassword.age".publicKeys = getKeys "mypassword.age";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue