Updating to include systemd timers
Better Makefile layout Improving pytest
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -5,3 +5,4 @@ nodeslist | ||||
| *.tar.xz | ||||
| pkg/ | ||||
| src/ | ||||
| **/__pycache__ | ||||
|   | ||||
							
								
								
									
										77
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,76 +1,25 @@ | ||||
| SHELL := /bin/bash | ||||
| BACKUPDIR := /usr/local/backup | ||||
|  | ||||
| client: user aether.bash | ||||
| 	cp aether.bash /home/aether/aether.bash | ||||
| 	/home/aether/aether.bash | ||||
| 	sudo -u aether crontab -l > /tmp/cronie | ||||
| 	grep aether.bash /tmp/cronie || echo '0 1 * * * /home/aether/aether.bash &>> /var/log/aether.log' >> /tmp/cronie | ||||
| 	sudo -u aether crontab /tmp/cronie | ||||
| 	rm /tmp/cronie | ||||
| 	touch /var/log/aether.log | ||||
| 	chown aether:aether /var/log/aether.log | ||||
| 	make checkperm | ||||
|  | ||||
| compile: | ||||
| 	@echo Nothing to do	 | ||||
|  | ||||
| install: compile | ||||
| 	@echo You must specify client or server in a call to make. | ||||
|  | ||||
| server: keys scripts user ./aether-gen.bash ./aether.pub ./server-backup | ||||
| 	bash ./aether-gen.bash | ||||
| 	cp ./aether.pub /home/aether/.ssh/authorized_keys | ||||
| 	cp ./aether-gen.bash /root/bin/aether-gen.bash | ||||
| 	mkdir -p /usr/local/etc/Aether/backup-entries | ||||
| 	touch /usr/local/etc/Aether/nodeslist | ||||
| 	mkdir -p ${BACKUPDIR};   | ||||
| 	make checkperm | ||||
| 	@echo You have the files. Add aether-gen.bash and server-backup to root\'s crontab. | ||||
| 	@echo Mark services to be backed up by adding a file from examples/ to /usr/local/etc/Aether/backup-entries | ||||
| 	@echo Track client nodes in /usr/local/etc/Aether/nodeslist | ||||
|  | ||||
| user: aether make-user.bash | ||||
| 	/bin/bash ./make-user.bash | ||||
|  | ||||
| node-command:  | ||||
| 	@echo USE THE FOLLOWING COMMANDS TO SET UP A NODE. | ||||
| 	@echo -ne 'git clone https://aninix.net/foundation/Aether;' | ||||
| 	@echo | ||||
| 	@echo -ne 'cd Aether; cat > aether # Paste the private key' | ||||
| 	@echo | ||||
| 	@echo -ne 'make client' | ||||
| 	@echo | ||||
| 	@echo MAKE SURE TO ADD THE NODE TO /usr/local/etc/Aether/nodes.list | ||||
|  | ||||
| keys: | ||||
| 	if [ ! -f ./aether ]; then ssh-keygen -t rsa -P "" -f aether; fi | ||||
|  | ||||
| scripts: ./server-backup ./remote-backup | ||||
| 	cp ./server-backup /root/bin | ||||
| 	cp ./remote-backup /root/bin | ||||
| 	make checkperm | ||||
|  | ||||
| reverse:  | ||||
| 	if [ -f /root/bin/server-backup ]; then cp /root/bin/server-backup .; fi | ||||
| 	if [ -f /root/bin/remote-backup ]; then cp /root/bin/remote-backup .; fi | ||||
| 	if [ -f /root/bin/aether-gen.bash ]; then cp /root/bin/aether-gen.bash .; fi | ||||
| 	if [ -f /home/aether/aether.bash ]; then cp /home/aether/aether.bash .; fi | ||||
|  | ||||
| diff: | ||||
| 	if [ -f /root/bin/server-backup ]; then diff ./server-backup /root/bin/server-backup; fi | ||||
| 	if [ -f /root/bin/remote-backup ]; then diff ./remote-backup /root/bin/remote-backup; fi | ||||
| 	if [ -f /root/bin/aether-gen.bash ]; then diff ./aether-gen.bash /root/bin/aether-gen.bash; fi | ||||
| 	if [ -f /home/aether/aether.bash ]; then diff ./aether.bash /home/aether/aether.bash; fi | ||||
| 	mkdir -p ${pkgdir}/usr/local/sbin | ||||
| 	mkdir -p ${pkgdir}/usr/local/etc | ||||
| 	install -m 0750 -o aether aether.bash ${pkgdir}/usr/local/sbin | ||||
| 	install -m 0750 -o root -g root aether-gen.bash ${pkgdir}/usr/local/sbin | ||||
| 	install -m 0750 -o root -g root remote-backup ${pkgdir}/usr/local/sbin | ||||
| 	install -m 0750 -o aether -d ${pkgdir}/usr/local/etc/Aether | ||||
| 	install -m 0750 -o aether -d ${pkgdir}/usr/local/etc/Aether/backup-entries | ||||
| 	mkdir -p ${pkgdir}/usr/lib/systemd/system | ||||
| 	for i in *.service *.timer; do install -m 0640 -o root -g root "$$i" ${pkgdir}/usr/lib/systemd/system; done | ||||
|  | ||||
| checkperm: | ||||
| 	id aether; | ||||
| 	if [ -d /home/aether ]; then chmod 0600 /home/aether/.ssh/authorized_keys; chmod 0700 /home/aether/.ssh /home/aether; chown -R aether:aether /home/aether; fi | ||||
| 	if [ -f /root/bin/remote-backup ]; then chmod 0700 /root/bin/remote-backup; chown root:root /root/bin/remote-backup; fi | ||||
| 	if [ -f /root/bin/server-backup ]; then chmod 0700 /root/bin/server-backup; chown root:root /root/bin/server-backup; fi  | ||||
| 	if [ -d /usr/local/etc/Aether ]; then chmod -R 0700 /usr/local/etc/Aether; chown -R aether:aether /usr/local/etc/Aether; fi | ||||
| 	if [ -d ${BACKUPDIR} ]; then chmod 0770 ${BACKUPDIR}; chown postgres:root ${BACKUPDIR}; fi | ||||
| 	if [ -f /var/log/aether.log ]; then chown aether:aether /var/log/aether.log; chmod 0750 /var/log/aether.log; fi | ||||
| 	for i in ${pkgdir}/usr/local/sbin/aether.bash ${pkgdir}/usr/local/sbin/aether-gen.bash ${pkgdir}/usr/local/sbin/remote-backup ${pkgdir}/usr/local/etc/Aether; do chmod 0750 "$$i"; done | ||||
| 	for i in ${pkgdir}/usr/local/sbin/aether.bash ${pkgdir}/usr/local/sbin/aether-gen.bash ${pkgdir}/usr/local/sbin/remote-backup ${pkgdir}/usr/local/etc/Aether; do chown root: "$$i"; done | ||||
| 	chown aether: ${pkgdir}/usr/local/sbin/aether.bash | ||||
| 	for i in *.service *.timer; do chown root: ${pkgdir}/usr/lib/systemd/system; chmod 0640 ${pkgdir}/usr/lib/systemd/system; done | ||||
|  | ||||
| clean: | ||||
| 	@bash -c 'printf "This will irreversibly destroy all backups. Confirm? [YES/no]  " ; read answer; [ "$$answer" == "YES" ] && exit 0; exit 1'	 | ||||
|   | ||||
							
								
								
									
										2
									
								
								PKGBUILD
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								PKGBUILD
									
									
									
									
									
								
							| @@ -19,7 +19,7 @@ conflicts=() | ||||
| replaces=("${pkgname,,}", "aninix-${pkgname,,}") | ||||
| backup=() | ||||
| options=() | ||||
| install= | ||||
| install=installscript | ||||
| changelog= | ||||
| source=() | ||||
| noextract=() | ||||
|   | ||||
							
								
								
									
										15
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								README.md
									
									
									
									
									
								
							| @@ -10,20 +10,27 @@ You have two options to install this project: | ||||
| * Arch Linux and related distros: Run `makepkg -sri` | ||||
| * Other operating systems: Run `make install` | ||||
|  | ||||
| # Initial setup | ||||
| ## Initial setup | ||||
| To create the aether and aether.pub files, run "make keys". This should not be repeated. | ||||
|  | ||||
| # Adding backup configurations | ||||
| ## Adding backup configurations | ||||
| Individual projects wanting to be backed up by the Aether system should add a file to their package into `/usr/local/etc/Aether/backups/`. | ||||
|  | ||||
| ## Tracking Nodes | ||||
| A SIEM filter should be set up to search for successful logins of the `aether` user. | ||||
|  | ||||
| # Relevant Files and Software | ||||
| Aether installs a script for rsync-based remote backups. We implement this policy through the two 4TB hard-drives, at least one of which is always off-site, that can be plugged into the [Maat](/Wiki/Hosts/Maat.md) hotswap bay along with a virtual machine that mounts the ArchLinux iso and the drive in the bay. | ||||
| Aether installs a script for rsync-based remote backups. We implement this policy through the two 8TB hard-drives, at least one of which is always off-site, that can be plugged into a hotswap bay of a hypervisor along with a virtual machine that mounts the ArchLinux iso and the drive. Admins use the included ssh daemon in the iso to present the drive as a backup target,  | ||||
|  | ||||
| An additional backup is the generated `/home/aether/aether.enc` file. This is a more targeted backup of databases and file indexes. | ||||
|  | ||||
| Keep in mind that all of [AniNIX/Foundation](https://foundation.aninix.net) is naturally a backup solution -- so long as anyone has a clone of the repo, the data survives. | ||||
|  | ||||
| # Available Clients | ||||
| The only client is direct server access on one of the client nodes. | ||||
|  | ||||
| # Equivalents or Competition | ||||
| Equivalent services are DropBox, Google Drive, or Barracuda. | ||||
| Equivalent services are DropBox, Google Drive, iCloud, or OneDrive. | ||||
|  | ||||
| # Notes | ||||
| Those deploying Aether should maintain a nodeslist file that only root can read. | ||||
|   | ||||
| @@ -1,31 +1,29 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| export LOGFILE="/var/log/aether-gen.log" | ||||
| # File: aether-gen.bash | ||||
| #  | ||||
| # Description: This file generates the backup in an encrypted format. | ||||
| #  | ||||
| # Package: AniNIX/HelloWorld | ||||
| # Copyright: WTFPL | ||||
| #  | ||||
| # Author: DarkFeather <ircs://aninix.net:6697/DarkFeather> | ||||
|  | ||||
| export BACKUPDIR="/usr/local/backup" | ||||
| export BACKUPCMD="rsync -avzl --delete-after"; | ||||
|  | ||||
| date >> "$LOGFILE" | ||||
| chown root:root "$BACKUPDIR" | ||||
| chmod 0770 "$BACKUPDIR" | ||||
|  | ||||
| for i in `find /usr/local/etc/Aether/backup-entries/ -type f`; do | ||||
|     bash "${i}" &>> "$LOGFILE" | ||||
|     bash "${i}"  | ||||
| done | ||||
|  | ||||
| date > "$BACKUPDIR"/lastbackup.date | ||||
|  | ||||
| cd /home/aether | ||||
|  | ||||
| echo Creating and compressing archive... | ||||
| tar cvf aether.tar /usr/local/backup | ||||
| gzip -f aether.tar | ||||
|  | ||||
| echo Encrypting archive | ||||
| openssl enc -aes256 -pass file:/usr/local/etc/Aether/pass.txt -in aether.tar.gz -out aether.enc | ||||
| rm aether.tar.gz | ||||
| echo Creating and encrypting archive... | ||||
| tar cvzf - /usr/local/backup | openssl enc -aes256 -pass file:/usr/local/etc/Aether/pass.txt -in aether.tar.gz -out aether.enc | ||||
|  | ||||
| echo Created aether archive. | ||||
|  | ||||
| date >> "$LOGFILE" | ||||
| echo >> "$LOGFILE" | ||||
|   | ||||
							
								
								
									
										11
									
								
								aether-gen.service
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								aether-gen.service
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| [Unit] | ||||
| Description=AniNIX/Aether | Generation | ||||
|  | ||||
| [Service] | ||||
| Nice=19 | ||||
| IOSchedulingClass=best-effort | ||||
| IOSchedulingPriority=7 | ||||
| Type=simple | ||||
| ExecStart=/usr/local/sbin/aether-gen.bash | ||||
|  | ||||
| #EOF | ||||
							
								
								
									
										11
									
								
								aether-gen.timer
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								aether-gen.timer
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| [Unit] | ||||
| Description=AniNIX/Aether | Generation | ||||
|  | ||||
| [Timer] | ||||
| OnCalendar=01:00 | ||||
| Persistent=false | ||||
|  | ||||
| [Install] | ||||
| WantedBy=timers.target | ||||
|  | ||||
| #EOF | ||||
							
								
								
									
										12
									
								
								aether.service
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								aether.service
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| [Unit] | ||||
| Description=AniNIX/Aether | Pull-back | ||||
|  | ||||
| [Service] | ||||
| Nice=19 | ||||
| IOSchedulingClass=best-effort | ||||
| IOSchedulingPriority=7 | ||||
| Type=simple | ||||
| ExecStart=/usr/local/sbin/aether | ||||
| User=aether | ||||
|  | ||||
| #EOF | ||||
							
								
								
									
										11
									
								
								aether.timer
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								aether.timer
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| [Unit] | ||||
| Description=AniNIX/Aether | Pull-back | ||||
|  | ||||
| [Timer] | ||||
| OnCalendar=05:00 | ||||
| Persistent=false | ||||
|  | ||||
| [Install] | ||||
| WantedBy=timers.target | ||||
|  | ||||
| #EOF | ||||
							
								
								
									
										9
									
								
								installscript
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								installscript
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| pre_install() { | ||||
|   groupadd aether &>/dev/null | ||||
|   useradd -g aether -d /srv/aether -s /bin/false aether &> /dev/null | ||||
|   chown -R aether:aether /srv/aether &> /dev/null | ||||
| } | ||||
|  | ||||
| pre_remove() { | ||||
|   getent passwd aether &>/dev/null && userdel aether &> /dev/null | ||||
| } | ||||
| @@ -1,17 +1,44 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| # File: HelloWorld.bash | ||||
| #  | ||||
| # Description: This file exemplifies printing 'Hello world!' in bash.  | ||||
| #  | ||||
| # Package: AniNIX/HelloWorld | ||||
| # Copyright: WTFPL | ||||
| #  | ||||
| # Author: DarkFeather <ircs://aninix.net:6697/DarkFeather> | ||||
|  | ||||
| # Should only be done as root. | ||||
| if [ "$(whoami)" != "root" ]; then | ||||
|     echo Needs to be run as root. | ||||
|     exit 1; | ||||
| fi | ||||
|  | ||||
| if (ping -c 4 "$1" | grep -c ' 0% packet loss,'); then | ||||
|     printf "Are you sure you want to back everything up to %s?\nIs the root password set and all storage mounted?\nDo you have time for this backup to complete?\nEnter YES in all capitals to continue..." "$1" | ||||
| # Default the host to the Aether host in whatever domain this host lives in. | ||||
| host="$1" | ||||
| if [ -z "$host" ]; then | ||||
|     host=Aether | ||||
| fi | ||||
|  | ||||
| # Default the path to / | ||||
| path="$2" | ||||
| if [ -z "$path" ]; then | ||||
|     path='/' | ||||
| fi | ||||
|  | ||||
| # Try to contract the host | ||||
| if (nmap --open -p 22 "$host" | grep -E '22/tcp\s+open' &>/dev/null); then | ||||
|  | ||||
|     # Confirm with the user | ||||
|     printf "Are you sure you want to back everything up to %s?\n* Is the root password set and backup volume mounted on '/mnt'?\n* Do you have time for this backup to complete?\n* Does \`ssh-keyscan -D localhost\` on the server match this? `ssh-keyscan -D "$host" 2>/dev/null | grep 4\ 2`\nEnter YES in all capitals to continue..." "$host" | ||||
|  | ||||
|     read answer | ||||
|     if [ "$answer" != "YES" ]; then | ||||
|         echo User did not confirm. | ||||
|         exit 1; | ||||
|     else | ||||
|         rsync -aAXv --delete --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} / root@"$1":/mnt/ | ||||
|         rsync -aAXv --delete --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} "$path" root@"$host":/mnt"$path" | ||||
|         status="$?" | ||||
|         echo rsync exited with status $status | ||||
|         exit $status | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import subprocess | ||||
| # TODO Still need to devise a testing strategy (https://foundation.aninix.net/AniNIX/Aether/issues/1) | ||||
| def test_aether(): | ||||
|     print(os.getcwd()) | ||||
|     fh = os.popen("echo bye | sftp -o IdentityFile=./aether aether@aninix.net", mode='r', buffering=-1) | ||||
|     fh = os.popen("echo bye | timeout 3 sftp -o IdentityFile=./aether aether@aninix.net", mode='r', buffering=-1) | ||||
|     output = fh.read() | ||||
|     retcode = fh.close() | ||||
|     assert retcode == None and CheckOutput(output) | ||||
|     assert retcode == None | ||||
|   | ||||
		Reference in New Issue
	
	Block a user