diff --git a/bundles/archive/README.md b/bundles/archive/README.md index acf574a..4a23ef0 100644 --- a/bundles/archive/README.md +++ b/bundles/archive/README.md @@ -1,10 +1,12 @@ ``` defaults = { 'archive': { - 'exclude': [ - '\.cache/', - '\.log$', - ], + '/var/important': { + 'exclude': [ + '\.cache/', + '\.log$', + ], + }, }, } ``` diff --git a/bundles/archive/files/archive b/bundles/archive/files/archive index b476b18..1c31590 100644 --- a/bundles/archive/files/archive +++ b/bundles/archive/files/archive @@ -20,7 +20,7 @@ gsutil ${'\\'} -r ${'\\'} -d ${'\\'} -e ${'\\'} - -x '${'|'.join(conf['exclude'])}' ${'\\'} + -x '${'|'.join(conf.get('exclude', []))}' ${'\\'} '${dir}' ${'\\'} 'gs://${bucket}/${node.name}${dir}' ${'\\'} 2>&1 | tee | logger -t gsutil diff --git a/bundles/archive/metadata.py b/bundles/archive/metadata.py index b0c5a0d..8e03fad 100644 --- a/bundles/archive/metadata.py +++ b/bundles/archive/metadata.py @@ -4,17 +4,19 @@ defaults = { @metadata_reactor.provides( - 'gocryptfs', + 'gocryptfs/paths', ) def gocryptfs(metadata): - gocryptfs = {} + paths = {} - for path in metadata.get('archive'): - gocryptfs[path] = { + for path in metadata.get('archive/paths'): + paths[path] = { 'mountpoint': f'/mnt/gocryptfs{path}', 'reverse': True, } return { - 'gocryptfs': gocryptfs, + 'gocryptfs': { + 'paths': paths, + }, } diff --git a/bundles/gocryptfs/items.py b/bundles/gocryptfs/items.py index 0acf942..0032762 100644 --- a/bundles/gocryptfs/items.py +++ b/bundles/gocryptfs/items.py @@ -1,19 +1,11 @@ -from hashlib import sha3_256 -from base64 import b64decode, b64encode -from binascii import hexlify -from uuid import UUID from json import dumps -id = node.metadata.get('id') - directories['/etc/gocryptfs'] = { 'purge': True, } files['/etc/gocryptfs/masterkey'] = { - 'content': hexlify(b64decode( - str(repo.vault.random_bytes_as_base64_for(id, length=32)) - )), + 'content': node.metadata.get('gocryptfs/masterkey'), 'mode': '500', } @@ -22,9 +14,7 @@ files['/etc/gocryptfs/gocryptfs.conf'] = { 'Version': 2, 'Creator': 'gocryptfs 1.6.1', 'ScryptObject': { - 'Salt': b64encode( - sha3_256(UUID(id).bytes).digest() - ).decode(), + 'Salt': node.metadata.get('gocryptfs/salt'), 'N': 65536, 'R': 8, 'P': 1, @@ -38,3 +28,10 @@ files['/etc/gocryptfs/gocryptfs.conf'] = { ] }, indent=4, sort_keys=True) } + +for path, options in node.metadata.get('gocryptfs/paths').items(): + directories[options['mountpoint']] = { + 'needed_by': [ + f'svc_systemd:gocryptfs-{options["id"]}', + ], + } diff --git a/bundles/gocryptfs/metadata.py b/bundles/gocryptfs/metadata.py index a987e70..e95f6d4 100644 --- a/bundles/gocryptfs/metadata.py +++ b/bundles/gocryptfs/metadata.py @@ -1,18 +1,103 @@ +from hashlib import sha3_256 +from base64 import b64decode, b64encode +from binascii import hexlify +from uuid import UUID + defaults = { - 'gocryptfs': {}, + 'apt': { + 'packages': { + 'gocryptfs': {}, + 'fuse': {}, + 'socat': {}, + }, + }, + 'gocryptfs': { + 'paths': {}, + }, } @metadata_reactor.provides( 'gocryptfs', ) -def gocryptfs(metadata): - gocryptfs = {} +def config(metadata): + return { + 'gocryptfs': { + 'masterkey': hexlify(b64decode( + str(repo.vault.random_bytes_as_base64_for(metadata.get('id'), length=32)) + )).decode(), + 'salt': b64encode( + sha3_256(UUID(metadata.get('id')).bytes).digest() + ).decode(), + }, + } + + +@metadata_reactor.provides( + 'gocryptfs', +) +def paths(metadata): + paths = {} - for path, options in metadata.get('gocryptfs'): - gocryptfs[path] = { - } + for path, options in metadata.get('gocryptfs/paths').items(): + paths[path] = { + 'id': hexlify(sha3_256(path.encode()).digest()[:8]).decode(), + } + + return { + 'gocryptfs': { + 'paths': paths, + }, + } + + + +@metadata_reactor.provides( + 'systemd/services', +) +def systemd(metadata): + services = {} + + for path, options in metadata.get('gocryptfs/paths').items(): + services[f'gocryptfs-{options["id"]}'] = { + 'content': { + 'Unit': { + 'Description': f'gocryptfs@{path} ({options["id"]})', + 'After': { + 'filesystem.target', + 'zfs.target', + }, + }, + 'Service': { + 'RuntimeDirectory': 'gocryptfs', + 'Environment': { + 'MASTERKEY': metadata.get('gocryptfs/masterkey'), + 'SOCKET': f'/var/run/gocryptfs/{options["id"]}', + 'PLAIN': path, + 'CIPHER': options["mountpoint"] + }, + 'ExecStart': [ + '/usr/bin/gocryptfs -fg -reverse -masterkey $MASTERKEY -ctlsock $SOCKET $PLAIN $CIPHER', + ], + 'ExecStopPost': [ + '/usr/bin/umount $CIPHER' + ], + }, + }, + 'needs': [ + 'pkg_apt:gocryptfs', + 'pkg_apt:fuse', + 'pkg_apt:socat', + 'file:/etc/gocryptfs/masterkey', + 'file:/etc/gocryptfs/gocryptfs.conf', + ], + 'triggers': [ + f'svc_systemd:gocryptfs-{options["id"]}:restart', + ], + } return { - 'gocryptfs': gocryptfs, + 'systemd': { + 'services': services, + }, } diff --git a/bundles/systemd/items.py b/bundles/systemd/items.py index 8bc32f2..f282162 100644 --- a/bundles/systemd/items.py +++ b/bundles/systemd/items.py @@ -12,13 +12,7 @@ actions = { }, } -for name, service in node.metadata.get('systemd', {}).get('services', {}).items(): - # use set() in metadata - for enumerator in [ - 'preceded_by', 'needs', 'needed_by', 'triggers', 'triggered_by' - ]: - assert isinstance(service.get(enumerator, set()), set) - +for name, service in node.metadata.get('systemd/services').items(): # dont call a service 'service' explicitly if name.endswith('.service'): raise Exception(name) @@ -46,7 +40,9 @@ for name, service in node.metadata.get('systemd', {}).get('services', {}).items( } # service depends on unit file - service.setdefault('needs', set()).add(f'file:{unit_path}') + service\ + .setdefault('needs', [])\ + .append(f'file:{unit_path}') # service svc_systemd[name] = service diff --git a/bundles/systemd/metadata.py b/bundles/systemd/metadata.py new file mode 100644 index 0000000..883127b --- /dev/null +++ b/bundles/systemd/metadata.py @@ -0,0 +1,5 @@ +defaults = { + 'systemd': { + 'services': {}, + } +} diff --git a/nodes/htz.mails.py b/nodes/htz.mails.py index 8401262..4bf6164 100644 --- a/nodes/htz.mails.py +++ b/nodes/htz.mails.py @@ -88,5 +88,10 @@ }, }, }, + 'archive': { + 'paths': { + '/var/test': {}, + }, + }, }, }