diff --git a/bundles/backup-server/metadata.py b/bundles/backup-server/metadata.py new file mode 100644 index 0000000..2d3439d --- /dev/null +++ b/bundles/backup-server/metadata.py @@ -0,0 +1,14 @@ +defaults = { + 'users': { + 'backup-receiver': { + 'authorized_keys': [], + }, + }, +} + + +@metadata_reactor.provides( + 'users/backup-receiver/authorized_keys' +) +def backup_authorized_keys(): + return diff --git a/bundles/users/metadata.py b/bundles/users/metadata.py index a8f0e9b..b22786a 100644 --- a/bundles/users/metadata.py +++ b/bundles/users/metadata.py @@ -1,9 +1,31 @@ -# defaults = { -# 'users': { -# 'root': { -# 'home': '/root', -# 'shell': '/bin/bash', -# 'password': repo.vault.human_password_for('root on {}'.format(node.name)), -# }, -# }, -# } +from base64 import b64decode + + +defaults = { + 'users': { + 'root': { + 'home': '/root', + }, + }, +} + + +@metadata_reactor.provides( + 'users', +) +def users(metadata): + users = {} + + for name in metadata.get('users'): + privkey, pubkey = repo.libs.ssh.generate_ad25519_key_pair( + b64decode(str(repo.vault.random_bytes_as_base64_for(metadata.get('id'), length=32))) + ) + users[name] = { + 'home': f'/home/{name}', + 'privkey': privkey, + 'pubkey': pubkey, + } + + return { + 'users': users, + } diff --git a/groups/all.py b/groups/all.py index 6697eee..0318471 100644 --- a/groups/all.py +++ b/groups/all.py @@ -1,6 +1,7 @@ { 'bundles': [ 'backup', + 'users', ], 'metadata': { 'backup': { diff --git a/libs/ssh.py b/libs/ssh.py new file mode 100644 index 0000000..39f765c --- /dev/null +++ b/libs/ssh.py @@ -0,0 +1,27 @@ +from base64 import b64decode, b64encode +from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey +from cryptography.hazmat.primitives import serialization + + +def generate_ad25519_key_pair(secret): + privkey_bytes = Ed25519PrivateKey.from_private_bytes(secret) + + nondeterministic_privatekey = privkey_bytes.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.OpenSSH, + encryption_algorithm=serialization.NoEncryption() + ).decode() + nondeterministic_bytes = b64decode(''.join(nondeterministic_privatekey.split('\n')[1:-2])) + # handle random 32bit number, occuring twice in a row + deterministic_bytes = nondeterministic_bytes[:98] + b'00000000' + nondeterministic_bytes[106:] + deterministic_privatekey = '\n'.join([ + '-----BEGIN OPENSSH PRIVATE KEY-----', + b64encode(deterministic_bytes).decode(), + '-----END OPENSSH PRIVATE KEY-----', + ]) + + public_key = privkey_bytes.public_key().public_bytes( + encoding=serialization.Encoding.OpenSSH, + format=serialization.PublicFormat.OpenSSH, + ).decode() + return (deterministic_privatekey, public_key)