AniNIX/Wiki#21 -- effecting renames for policy

This commit is contained in:
DarkFeather 2024-04-01 00:44:23 -05:00
parent 323b4dd306
commit 6f36d515e3
Signed by: DarkFeather
GPG Key ID: 1CC1E3F4ED06F296
46 changed files with 509 additions and 368 deletions

4
.gitignore vendored
View File

@ -1,7 +1,7 @@
# Generated files
roles/Node/files/*-vm.service
roles/Nazara/files/dns
roles/Nazara/files/dhcp
roles/Chappaai/files/dns
roles/Chappaai/files/dhcp
roles/Node/files/vm-definitions/**
roles/ShadowArch/files/mirrorlist
roles/Sharingan/files/monit/checks/availability

View File

@ -11,6 +11,7 @@
import os
import subprocess
import sys
import re
import yaml
rolepath='../roles/Sharingan/files'

View File

@ -1,51 +1,46 @@
#!/usr/bin/env python3
# File: generate-pihole-dns-dhcp.py
#
#
# Description: This file generates the DNS and DHCP files for pihole.
#
# It expects that the inventory has two levels of grouping.
#
# Package: AniNIX/Ubiqtorate
# Copyright: WTFPL
#
#
# Author: DarkFeather <darkfeather@aninix.net>
import os
import re
import subprocess
import sys
import yaml
from kapisi_lib import *
rolepath='../roles/Nazara/files'
rolepath='../roles/Chappaai/files'
dnsfilepath=rolepath+"/dns"
dhcpfilepath=rolepath+"/dhcp"
entryset={}
def WriteDHCPEntry(content,hosttype,hostclass):
def WriteDHCPEntries(replica_domain,dhcpfile):
### Create the DHCP entry
# param content: the yaml content to parse
# param hosttype: managed or unmanaged
# param hostclass: the type of host as classified in the yaml
global dhcpfile
global entryset
for host in entryset:
# Entries should be:
# dhcp-host=mac,ip,fqdn
dhcpfile.write('dhcp-host=' + entryset[host][1] + ',' + entryset[host][0] + ',' + host + '.' + replica_domain + '\n')
with open(dhcpfilepath,'a') as dhcpfile:
for host in content['all']['children'][hosttype]['children'][hostclass]['hosts']:
try:
dhcpfile.write('dhcp-host=' + content['all']['children'][hosttype]['children'][hostclass]['hosts'][host]['mac'] + ',' + content['all']['children'][hosttype]['children'][hostclass]['hosts'][host]['ip'] + ',' + host + '.' + content['all']['vars']['replica_domain'] + '\n')
except:
print(host + ' is not complete for DHCP.')
def WriteDNSEntry(content,hosttype,hostclass):
def WriteDNSEntries(replica_domain,dnsfile):
### Create the DNS entry
# param content: the yaml content to parse
# param hosttype: managed or unmanaged
# param hostclass: the type of host as classified in the yaml
global dnsfile
with open(dnsfilepath,'a') as dnsfile:
# Write host entries
for host in content['all']['children'][hosttype]['children'][hostclass]['hosts']:
try:
dnsfile.write(content['all']['children'][hosttype]['children'][hostclass]['hosts'][host]['ip'] + ' ' + host + '.' + content['all']['vars']['replica_domain'] + ' ' + host + '\n')
except:
print(host + ' is not complete for DNS.')
global entryset
for host in entryset:
# Entries should be:
# ip host fqdn
dnsfile.write(entryset[host][0] + ' ' + host + '.' + replica_domain + ' ' + host + '\n')
def GenerateFiles(file):
### Open the file and parse it
@ -58,29 +53,30 @@ def GenerateFiles(file):
# Parse the yaml
with open(file, 'r') as stream:
content = yaml.safe_load(stream)
replica_domain = content['all']['vars']['replica_domain']
external_domain = content['all']['vars']['external_domain']
# Clear the DNS file
with open(dhcpfilepath,'w') as dhcpfile:
dhcpfile.write('dhcp-range='+content['all']['vars']['dhcprange']+'\n')
dhcpfile.write('dhcp-option=option:dns-server,'+content['all']['vars']['dns']+'\n\n')
dhcpfile.write('dhcp-range='+content['all']['vars']['staticrange']+'\n')
WriteDHCPEntries(replica_domain,dhcpfile)
with open(dnsfilepath,'w') as dnsfile:
vips=subprocess.run(["/bin/bash", "-c", "echo | openssl s_client -connect "+content['all']['vars']['external_domain']+":443 | openssl x509 -text -noout | grep DNS: | tr ',' '\n' | sed 's/\s\+DNS://' | grep -ivE ^"+content['all']['vars']['external_domain']+" | tr '\n' ' '"], capture_output=True).stdout.decode("utf-8")
dnsfile.write(content['all']['vars']['webfront']+' '+content['all']['vars']['external_domain']+' '+vips+"\n")
# Add DNS entries for each host
hosttype = 'managed'
for hostclass in ['physical','virtual','geth_hubs']:
WriteDNSEntry(content,hosttype,hostclass)
WriteDHCPEntry(content,hosttype,hostclass)
hosttype = 'unmanaged'
for hostclass in ['ovas','test_ovas','appliances','adhoc_appliances','iot']:
WriteDNSEntry(content,hosttype,hostclass)
WriteDHCPEntry(content,hosttype,hostclass)
dnsfile.write(content['all']['vars']['webfront']+' '+external_domain+' '+content['all']['vars']['external_subdomains'].replace(' ','.'+external_domain+' ')+'.'+external_domain+' '+content['all']['vars']['hosted_domains']+"\n")
WriteDNSEntries(replica_domain,dnsfile)
print('Files should be in '+rolepath);
### Main function
# param sys.argv: Input arguments
if __name__ == '__main__':
if len(sys.argv) != 2:
if len(sys.argv) < 2:
print("You need to supply an inventory file.")
sys.exit(1)
if len(sys.argv) == 3:
entryset = TrackIPEntries(sys.argv[1],sys.argv[2])
else:
entryset = TrackIPEntries(sys.argv[1])
GenerateFiles(sys.argv[1])
#dumper.dump(entryset)
sys.exit(0)

View File

@ -1,6 +1,6 @@
#!/bin/bash
# File: gen-ssh-keyscan
# File: ./generate-ssh-keyscan
#
# Description: This file generates a known_host block for the inventory.
#

63
bin/kapisi_lib.py Normal file
View File

@ -0,0 +1,63 @@
import re
import yaml
from types import SimpleNamespace
from yamlpath.common import Parsers
from yamlpath.wrappers import ConsolePrinter
from yamlpath import Processor
from yamlpath import YAMLPath
from yamlpath.exceptions import YAMLPathException
def TrackIPEntries(yaml_file,searchstring='all.children.**.ip'):
### Try to parse an Ansible inventory for hosts with the 'ip' attribute.
# param file: the file to parse
# return: a populated entry set in form [{Host,[ip,mac]},...]
# Borrowing from upstream author's example at https://pypi.org/project/yamlpath/
entryset = {}
# The various classes of this library must be able to write messages somewhere
# when things go bad.
#logging_args = SimpleNamespace(quiet=True, verbose=False, debug=False)
logging_args = SimpleNamespace(quiet=True, verbose=True, debug=True)
log = ConsolePrinter(logging_args)
# Prep the YAML parser
yaml = Parsers.get_yaml_editor()
(yaml_data, doc_loaded) = Parsers.get_yaml_data(yaml, log, yaml_file)
if not doc_loaded:
exit(1)
processor = Processor(log, yaml_data)
yaml_path = YAMLPath(searchstring)
# Create a regex pattern to remove the end of the path
ippattern = re.compile('\.ip$')
try:
for node_coordinate in processor.get_nodes(yaml_path, mustexist=True):
# Strip the path to the host entry.
path = ippattern.sub("",str(node_coordinate.path))
# Pull the IP
ip = str(node_coordinate.node)
# Pull the hosname
splitpath = path.split('.')
hostname = splitpath[len(splitpath)-1]
#print("Got {} from '{}''.".format(ip,path))
# Path the MAC
mac_yaml_path = YAMLPath(path+".mac")
mac=""
try:
for node_coordinate in processor.get_nodes(mac_yaml_path, mustexist=True):
mac = str(node_coordinate.node)
except YAMLPathException as ex:
log.error(ex)
# Add the host to the entryset.
entryset.update({ hostname : [ip,mac] })
except YAMLPathException as ex:
log.error(ex)
finally:
return entryset

View File

@ -17,11 +17,11 @@ group=all
offset=0
unset inventory
function usage() {
function usage() {
# Show helptext
# param retcode: what to exit
retcode="$1"
echo "Usage: $0 [ -o offset ] [-g group ] -i inventory.yml"
echo "Usage: $0 [ -o offset ] [-g group ] [-i inventory.yml]"
echo " $0 -h"
echo "Group is optional -- add it if you only want to look at a specific subset."
echo "Add -v for verbosity."
@ -41,7 +41,7 @@ function tmuxHosts() {
name="$group-$offset"
# If no TMUX session started, then add one with four panes.
if [ -z "$TMUX" ]; then
if [ -z "$TMUX" ]; then
tmux new-session -s "$name" -d "/bin/bash -l -c ssh\\ $host1"
tmux select-window -t "$name":0
tmux split-window "/bin/bash -l -c ssh\\ $host2"
@ -51,7 +51,7 @@ function tmuxHosts() {
tmux setw synchronize-panes
tmux a -d -t "$name"
# Otherwise, add a new window to the current session with all four sessions.
else
else
tmux new-window -n "$name" "/bin/bash -l -c ssh\\ $host1"
tmux select-window -t "$name"
tmux split-window "/bin/bash -l -c ssh\\ $host2"
@ -76,12 +76,11 @@ if [ "$(basename $0)" == "tmux-hosts" ]; then
*) usage 1 ;;
esac
done
if [ -z "$inventory" ]; then
echo Need an inventory.
usage 2;
inventory=$(grep -E ^inventory ~/.ansible.cfg | cut -f 2 -d '=')
fi
tmuxHosts $(ansible -i "$inventory" --list-hosts "$group"\
| grep -v hosts\ \( \
| sed 's/\s\+//g' \

View File

@ -1,7 +1,9 @@
all:
vars:
# Environment-wide data
external_domain: aninix.net
external_domain: "aninix.net"
external_subdomains: "cyberbrain foundation irc lykos maat password sharingan singularity superintendent www yggdrasil"
hosted_domains: "travelpawscvt.com"
replica_domain: "MSN0.AniNIX.net"
time_zone: "America/Chicago"
# Services used by all
@ -19,7 +21,7 @@ all:
ansible_become_method: sudo
ansible_become_user: root
static: false
wireless_ssid: 'Shadowfeed'
wireless_ssid: 'Shadownet'
ansible_python_interpreter: auto_silent
ldap:
server: "10.0.1.3"
@ -32,66 +34,83 @@ all:
displayname: 'AniNIX'
gpgkey: '904DE6275579CB589D85720C1CC1E3F4ED06F296'
ssl: # Standard SSL cryptographic standards
identity: 'aninix.net-0001' # The Let's Encrypt identity to use
identity: 'aninix.net-0002' # The Let's Encrypt identity to use
ciphersuite: "!NULL:!SSLv2:!SSLv3:!TLSv1:EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"
children:
managed:
children:
physical: # 10.0.1.0/28
hosts:
Nazara:
Chappaai:
ipinterface: eth0
ip: 10.0.1.2
mac: B8:27:EB:B6:AA:0C
static: true
Node1:
ipinterface: enp1s0
ip: 10.0.1.5
mac: FA:EC:43:87:4D:2D
tap: true
ups: 'aps'
Node2:
ipinterface: enp1s0
ip: 10.0.1.7
mac: 56:02:ef:2c:1f:7c
tap: true
ups: 'cyberpower'
Node3:
ipinterface: enp1s0
ip: 10.0.1.8
mac: B2:C6:2C:02:B2:6E
tap: true
Nodelet0:
Maker:
ipinterface: eth0
ip: 10.0.1.9
mac: b8:27:eb:9a:73:dd
static: true
k3s_primary: true
Nodelet1:
ipinterface: eth0
ip: 10.0.1.10
mac: E4:5F:01:01:FF:9C
static: true
Nodelet2:
ipinterface: eth0
ip: 10.0.1.11
mac: E4:5F:01:01:FF:D5
static: true
Nodelet3:
ipinterface: eth0
ip: 10.0.1.12
mac: E4:5F:01:01:FF:96
static: true
Nodelet4:
ipinterface: eth0
ip: 10.0.1.13
mac: E4:5F:01:01:FF:E4
ip: 10.0.1.14
mac: B8:27:EB:B6:AA:0D
static: true
children:
Node:
hosts:
Node1:
ipinterface: enp1s0
ip: 10.0.1.5
mac: FA:EC:43:87:4D:2D
tap: true
ups: 'aps'
active_vms:
- Yggdrasil
Node2:
ipinterface: enp1s0
ip: 10.0.1.7
mac: 56:02:ef:2c:1f:7c
tap: true
active_vms:
- DarkNet
- Maat
- Sharingan
- Superintendent
Node3:
ipinterface: enp1s0
ip: 10.0.1.8
mac: B2:C6:2C:02:B2:6E
tap: true
active_vms:
- TDS-Jump
Geth:
hosts:
Geth0:
ipinterface: eth0
ip: 10.0.1.9
mac: 84:16:F9:14:15:C5
static: true
k3s_primary: true
Geth1:
ipinterface: eth0
ip: 10.0.1.10
mac: E4:5F:01:01:FF:9C
static: true
Geth2:
ipinterface: eth0
ip: 10.0.1.11
mac: E4:5F:01:01:FF:D5
static: true
Geth3:
ipinterface: eth0
ip: 10.0.1.12
mac: E4:5F:01:01:FF:96
static: true
Geth4:
ipinterface: eth0
ip: 10.0.1.13
mac: E4:5F:01:01:FF:E4
static: true
virtual: # 10.0.1.16/28
vars:
hosts:
Sharingan:
node: Node2
ip: 10.0.1.16
ipinterface: ens3
mac: 00:15:5D:01:02:10
@ -106,7 +125,6 @@ all:
# On hold because of https://aninix.net/DarkFeather/MSN0/issues/6
holdpkg: "elasticsearch graylog mongodb44-bin mongodb-tools-bin"
DarkNet:
node: Node2
ipinterface: ens3
ip: 10.0.1.17
mac: 00:15:5D:01:02:05
@ -118,19 +136,18 @@ all:
- '-drive format=raw,index=0,media=disk,file=/dev/sdb'
wolfpack_config: 'gitea@foundation.aninix.net:DarkFeather/WolfPack-Config.git'
Maat:
node: Node2
ip: 10.0.1.18
ipinterface: ens3
mac: 00:15:5d:01:02:07
cores: 2
memory: 2
bridge: br0
vscan_enabled: true
vnc: 7
disks:
- '-drive format=qcow2,l2-cache-size=8M,file=/mnt/cage2/vm/Maat.qcow2'
Yggdrasil:
node: Node1
ipinterface: enp1s0f0
ipinterface: ens3
ip: 10.0.1.3
mac: 00:25:90:0d:6e:86
static: true
@ -142,6 +159,7 @@ all:
memory: 16
bridge: br0
vnc: 1
vscan_enabled: true
disks:
- '-drive format=raw,index=0,media=disk,file=/dev/sda'
- '-drive format=raw,index=0,media=disk,file=/dev/sdb'
@ -151,18 +169,18 @@ all:
vars:
motion_enabled: yes
hosts:
Geth-Hub-1:
Vergil1:
ip: 10.0.1.32
mac: 84:16:F9:14:15:C5
mac: b8:27:eb:9a:73:dd
rotate: 0
remote: NS-RC4NA-14
Geth-Hub-2:
Vergil2:
ip: 10.0.1.33
mac: 84:16:F9:13:B6:E6
motion_enabled: no
rotate: 180
remote: NS-RC4NA-14
Geth-Hub-3:
Vergil3:
ip: 10.0.1.34
mac: b8:27:eb:60:73:68
rotate: 90
@ -172,8 +190,7 @@ all:
# Both OVA groups are in the same subnet -- test_ovas aren't monitored
ovas: # 10.0.1.48/28
hosts:
Geth:
node: Node2
Superintendent:
ip: 10.0.1.49
mac: DE:8B:9E:19:55:1E
cores: 2
@ -186,7 +203,6 @@ all:
test_ovas: # 10.0.1.48/28
hosts:
TDS-Jump:
node: Node2
ip: 10.0.1.48
mac: 00:15:5d:01:02:08
cores: 2
@ -194,7 +210,7 @@ all:
vnc: 4
bridge: br0
disks:
- '-drive format=qcow2,l2-cache-size=8M,file=/mnt/cage2/vm/TDSJump.qcow2'
- '-drive format=qcow2,l2-cache-size=8M,file=/srv/node/vm/TDSJump.qcow2'
DedNet:
ip: 10.0.1.50
mac: 00:15:5d:01:02:09
@ -248,7 +264,7 @@ all:
# appliances are monitored -- adhoc_appliances are convenience only and not monitored.
appliances:
hosts: # 10.0.1.64/27
Shadowfeed: # Router must be at root
Shadownet: # Router must be at root
ip: 10.0.1.1
mac: 2c:30:33:64:f4:03
Print: # Print is excepted for legacy setup reasons before we laid out subnets.
@ -267,11 +283,11 @@ all:
hosts: # 10.0.1.64/27
DarkFeather:
ip: 10.0.1.64
mac: D0:40:EF:D4:14:CF
mac: f4:2b:8c:10:31:44
Lykos:
ip: 10.0.1.65
mac: 70:74:14:4F:8E:42
Games:
Node0:
ip: 10.0.1.66
mac: E0:BE:03:77:0E:88
LivingRoomTV:
@ -283,25 +299,25 @@ all:
TrainingRoomTV:
ip: 10.0.1.71
mac: 80:D2:1D:17:63:10
Tachikoma:
BT:
ip: 10.0.1.72
mac: 90:0f:0c:1a:d3:23
mac: 8A:00:AA:7F:DF:D1
DedSec:
ip: 10.0.1.73
mac: 34:F6:4B:36:12:8F
# dhcp build space: 10.0.1.224/27
iot: # 10.0.2.0/24
hosts:
LinKeuei:
LivingRoomRegulator:
ip: 10.0.2.2
mac: 64:16:66:08:57:F5
Canary:
Monitor:
ip: 10.0.2.3
mac: 18:B4:30:2F:F1:37
Charon:
Gatekeeper:
ip: 10.0.2.4
mac: 64:52:99:14:28:2B
# CanoptekAleph: physical, no network
CanoptekBek:
# CaretakerAlpha has no network
CaretakerBravo:
ip: 10.0.2.5
mac: 40:9F:38:95:06:34

View File

@ -9,36 +9,23 @@
# Patch then restart a node
#
#
- hosts: physical,virtual
order: sorted
serial: 4
vars:
ansible_become: yes
ansible_become_method: sudo
tasks:
- package:
name: archlinux-keyring
state: latest
- hosts: virtual,geth-hubs
- hosts: "{{ targets | default('virtual') }}"
order: sorted
serial: 4
vars:
ansible_become: yes
ansible_become_method: sudo
vars_files:
- "{{ lookup('env', 'ANSIBLE_VAULT_FILE') }}"
roles:
- patching
- hosts: physical
order: sorted
ignore_unreachable: true
serial: 4
vars:
ansible_become: yes
ansible_become_method: sudo
vars_files:
- "{{ lookup('env', 'ANSIBLE_VAULT_FILE') }}"
roles:
- patching
tasks:
- include_role:
name: patching
when: targets is unset

18
roles/Chappaai/README.md Normal file
View File

@ -0,0 +1,18 @@
A Chappaai host is a gateway to accessing other hosts. It is a safeguard against admin error.
## Etymology
Chappaai hosts are named to follow the non-English naming of the Stargate network by the other denizens of the galaxy.
They are the first line of defense against administrative error -- similar to the way that [Stargate Command](https://stargate.fandom.com/wiki/Stargate_Command) was for Earth. They prevent admins from being locked out of correcting their changes and are connected to everything in the ecosystem. They also control DNS, which allows a sort of subliminal control of the entire ecosystem. This prevents infiltration by infections (similar to Goauld) and in fact can be the extinction of any DNS-enabled malware in the ecosystem by sinkholing the Command-and-Control.
## Capacity and Components
A Chappaai host needs minimal CPU or memory.
## Hosted Services and Entities
Chappaai should host a Pihole installation and [SSH](../Services/SSH.md). It should be linked by NAT to an obscure port to the outside world.
## Connections
Any host should be able to connect to a Chappaai with SSH and X11, and it should be able to dial to any service provider.
## Additional Reference
Chappaai hosts should be deployed alongside any Hypervisor. They can be as simple as a Pi-hole with SSH access, and they should be allowed to receive SSH connections from a non-tcp/22/ssh port.

View File

@ -17,7 +17,7 @@
- name: Ensure pihole web admin password
become: yes
command: "pihole -a -p {{ passwords['Nazara'] }}"
command: "pihole -a -p {{ passwords['Chappaai'] }}"
# when: pihole_install.changed
- name: Generate DNS/DHCP from inventory
@ -25,7 +25,7 @@
run_once: true
command: "python3 ../bin/generate-pihole-dns-dhcp.py {{ inventory_file }}"
- name: Nazara DNS
- name: Chappaai DNS
become: yes
register: dns_updated
copy:
@ -35,7 +35,7 @@
group: pihole
mode: 0644
- name: Nazara DHCP
- name: Chappaai DHCP
become: yes
register: dhcp_updated
copy:
@ -45,7 +45,7 @@
group: root
mode: 0644
- name: Nazara Configuration
- name: Chappaai Configuration
become: yes
register: conf_updated
copy:
@ -56,7 +56,7 @@
mode: 0644
- name: Nazara DHCP Leases dir
- name: Chappaai DHCP Leases dir
become: yes
file:
path: /var/lib/misc/
@ -65,7 +65,7 @@
group: root
mode: 0777
- name: Nazara DHCP Leases
- name: Chappaai DHCP Leases
become: yes
file:
path: /var/lib/misc/dnsmasq.leases

View File

@ -1,16 +0,0 @@
A Nazara host is a gateway to accessing other hosts. It is a safeguard against admin error.
## Etymology
Nazara hosts are named because they are the first line of defense against administrative error -- they prevent admins from being locked out of correcting their changes and are connected to everything in the ecosystem. They also control DNS, which allows a sort of subliminal control of the entire ecosystem. This is akin to the mastermind [Reaper AI](https://masseffect.fandom.com/wiki/Sovereign) from the Mass Effect franchise, and in fact can be the extinction of any DNS-enabled malware in the ecosystem by sinkholing the Command-and-Control.
## Capacity and Components
A Nazara host needs minimal CPU or memory.
## Hosted Services and Entities
Nazara should host a Pihole installation and [SSH](../Services/SSH.md). It should be NAT'ed to an obscure port to the outside world.
## Connections
Any host should be able to connect to a Nazara with SSH and X11, and it should be able to dial to any service provider.
## Additional Reference
Nazara hosts should be deployed alongside any Hypervisor. They can be as simple as a Pi-hole with SSH access, and they should be allowed to receive SSH connections from a non-tcp/22/ssh port.

View File

@ -37,30 +37,20 @@
group: http
mode: 2755
- name: Copy TLSA script
- name: Remove old TLSA script
become: yes
file:
path: /usr/local/sbin/tlsa-generation.bash
state: absent
- name: Copy record generator script
become: yes
template:
src: tlsa-generation.bash.j2
dest: /usr/local/sbin/tlsa-generation.bash
src: record-generation.bash.j2
dest: /usr/local/sbin/record-generation.bash
owner: root
group: root
mode: 0700
- name: Get proposed TLSA records
become: yes
command: /usr/local/sbin/tlsa-generation.bash
register: tlsa_records
- name: Show proposed TLSA records
debug:
msg: "{{ tlsa_records.stdout_lines }}"
- name: Get TLSA records
delegate_to: localhost
run_once: yes
command: "/bin/bash -c 'printf _443._tcp\\ ; dig _443._tcp.{{ external_domain }} TLSA +short; printf _6697._tcp\\ ; dig _6697._tcp.{{ external_domain }} TLSA +short'"
register: ext_tlsa_records
- name: Show TLSA records
debug:
msg: "{{ ext_tlsa_records.stdout_lines }}"
- debug:
msg: 'Run `sudo /usr/local/sbin/record-generation.bash` to generate a zonefile for import into a DNS provider.'

View File

@ -0,0 +1,44 @@
#!/bin/bash
ttl=86400
externalip="$(curl -s ident.me)"
for domain in {{ hosted_domains }} {{ external_domain }}; do
echo
# NS/MX/A -- basic orientation to the world for names, mail, and address
cat <<EOM
\$ORIGIN ${domain}.
@ $ttl IN SOA ns51.cloudns.net. support.cloudns.net. 2024040128 7200 1800 1209600 86400
@ $ttl IN NS ns51.cloudns.net.
@ $ttl IN NS ns52.cloudns.net.
@ $ttl IN NS ns53.cloudns.net.
@ $ttl IN NS ns54.cloudns.net.
@ $ttl IN MX 10 mailforward51.cloudns.net.
@ $ttl IN MX 10 mailforward52.cloudns.net.
@ $ttl IN A ${externalip}
EOM
# CAA -- who can issue certs for this domain
# https://letsencrypt.org/docs/caa/
echo 'CAA 128 issue "letsencrypt.org"'
# TLSA -- TLS fingerprints for certs & chain
for i in _443._tcp _6697._tcp; do
printf "$i $ttl IN ";
openssl x509 -in /etc/letsencrypt/live/{{ sslidentity }}/chain.pem -noout -pubkey 2>/dev/null | openssl rsa -pubin -outform DER 2>/dev/null | openssl dgst -sha256 -hex 2>/dev/null | awk '{print "TLSA 2 1 1", $NF}'
printf "$i $ttl IN ";
openssl x509 -in /etc/letsencrypt/live/{{ sslidentity }}/cert.pem -noout -pubkey 2>/dev/null | openssl rsa -pubin -outform DER 2>/dev/null | openssl dgst -sha256 -hex 2>/dev/null | awk '{print "TLSA 3 1 1", $NF}'
done
# SSHFP -- SFTP/SSH fingerprints
ssh-keygen -r '@ $ttl' | grep -E '4 2|1 2' # Only take RSA & Ed25519 keys
done
# CNAME -- Add CNAMES for various subdomains
for i in {{ external_subdomains }}; do
printf "%-20s %-10s %-10s %-10s %s\n" "$i" "$ttl" IN CNAME {{ external_domain }}.
done

View File

@ -1,4 +0,0 @@
#!/bin/bash
openssl x509 -in /etc/letsencrypt/live/{{ sslidentity }}/chain.pem -noout -pubkey | openssl rsa -pubin -outform DER | openssl dgst -sha256 -hex | awk '{print "le-ca TLSA 2 1 1", $NF}'
openssl x509 -in /etc/letsencrypt/live/{{ sslidentity}}/cert.pem -noout -pubkey | openssl rsa -pubin -outform DER | openssl dgst -sha256 -hex | awk '{print "cert TLSA 3 1 1", $NF}'

View File

@ -0,0 +1,6 @@
################################################################################
# AniNIX/Node0 #
# #
# This is the network virtualization platform. VMs can be found with this: #
# cd /usr/lib/systemd/system; ls -1 *vm.service | xargs -n 1 systemctl status #
################################################################################

View File

@ -0,0 +1,6 @@
################################################################################
# AniNIX/Node0 #
# #
# This is the network virtualization platform. VMs can be found with this: #
# cd /usr/lib/systemd/system; ls -1 *vm.service | xargs -n 1 systemctl status #
################################################################################

View File

@ -0,0 +1,6 @@
################################################################################
# AniNIX/Node0 #
# #
# This is the network virtualization platform. VMs can be found with this: #
# cd /usr/lib/systemd/system; ls -1 *vm.service | xargs -n 1 systemctl status #
################################################################################

View File

@ -0,0 +1,6 @@
################################################################################
# AniNIX/Node0 #
# #
# This is the network virtualization platform. VMs can be found with this: #
# cd /usr/lib/systemd/system; ls -1 *vm.service | xargs -n 1 systemctl status #
################################################################################

View File

@ -0,0 +1,6 @@
################################################################################
# AniNIX/Node0 #
# #
# This is the network virtualization platform. VMs can be found with this: #
# cd /usr/lib/systemd/system; ls -1 *vm.service | xargs -n 1 systemctl status #
################################################################################

View File

@ -0,0 +1,5 @@
################################################################################
# AniNIX/Nazara #
# #
# This is the network DNS/DHCP service, using Raspberry Pi pihole, and bastion #
################################################################################

View File

@ -1,3 +1 @@
# AniNIX/Geth Hardware Platform (Raspbian Rpi 1 B+) #

View File

@ -1,3 +1 @@
# AniNIX/Geth Hardware Platform (Raspbian Rpi 1 B+) #

View File

@ -1,3 +1 @@
# AniNIX/Geth Hardware Platform (Raspberry Pi 3 Model B Plus Rev 1.3) #

View File

@ -16,21 +16,21 @@
- name: Tap ArchLinux network config
become: yes
#when: tap is defined and not static is defined
when: tap is defined
template:
src: netctl-tap.j2
dest: "/etc/netctl/{{ ipinterface }}"
- name: Bridge ArchLinux network config
become: yes
#when: tap is defined and not static is defined
when: tap is defined
template:
src: netctl-bond.j2
dest: "/etc/netctl/br0"
- name: Tunnel ArchLinux network config
become: yes
#when: tap is defined and not static is defined
when: tap is defined
copy:
src: netctl-tun
dest: "/etc/netctl/tun0"

View File

@ -0,0 +1,57 @@
---
- name: Test root password
ignore_errors: yes
register: root_password_test
vars:
ansible_become_user: "{{ item }}"
ansible_become_method: su
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
command: id
loop:
- root
- "{{ ansible_user_id }}"
- name: Define passwords
ignore_errors: yes
vars:
ansible_become_user: "root"
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
when: root_password_test.rc is not defined or root_password_test.rc != 0
command:
cmd: /bin/bash -l -c "echo '{{item}}:{{ passwords[inventory_hostname] }}' | chpasswd {{ item }}"
loop:
- root
- "{{ ansible_user_id }}"
- name: Ensure deploy user has sudo permissions.
vars:
ansible_become_method: su
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
copy:
dest: /etc/sudoers.d/basics
content: "{{ ansible_user_id }} ALL=(ALL) NOPASSWD: ALL\n"
- name: Ensure we include /etc/sudoers.d (Current)
vars:
ansible_become_method: su
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
when: ansible_architecture != "armv6l"
lineinfile:
path: /etc/sudoers
regexp: "includedir /etc/sudoers.d"
line: "@includedir /etc/sudoers.d"
- name: Ensure we include /etc/sudoers.d (Legacy)
vars:
ansible_become_method: su
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
when: ansible_architecture == "armv6l"
lineinfile:
path: /etc/sudoers
regexp: "includedir /etc/sudoers.d"
line: "#includedir /etc/sudoers.d"

View File

@ -4,169 +4,7 @@
# This is an AniNIX convention to allow password management by Ansible.
- name: Test root password
ignore_errors: yes
register: root_password_test
vars:
ansible_become_user: "{{ item }}"
ansible_become_method: su
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
command: id
loop:
- root
- "{{ ansible_user_id }}"
- name: Define passwords
ignore_errors: yes
vars:
ansible_become_user: "root"
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
when: root_password_test.rc is not defined or root_password_test.rc != 0
command:
cmd: /bin/bash -l -c "echo '{{item}}:{{ passwords[inventory_hostname] }}' | chpasswd {{ item }}"
loop:
- root
- "{{ ansible_user_id }}"
- name: Ensure deploy user has sudo permissions.
vars:
ansible_become_method: su
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
copy:
dest: /etc/sudoers.d/basics
content: "{{ ansible_user_id }} ALL=(ALL) NOPASSWD: ALL\n"
- name: Ensure we include /etc/sudoers.d (Current)
vars:
ansible_become_method: su
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
when: ansible_architecture != "armv6l"
lineinfile:
path: /etc/sudoers
regexp: "includedir /etc/sudoers.d"
line: "@includedir /etc/sudoers.d"
- name: Ensure we include /etc/sudoers.d (Legacy)
vars:
ansible_become_method: su
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
when: ansible_architecture == "armv6l"
lineinfile:
path: /etc/sudoers
regexp: "includedir /etc/sudoers.d"
line: "#includedir /etc/sudoers.d"
- name: Set up pacman.conf
vars:
ansible_become_password: "{{ passwords[inventory_hostname] }}"
ignorepkg: "{{ holdpackages | default('') }}"
become: yes
template:
src: pacman.conf.j2
dest: /etc/pacman.conf
owner: root
group: root
mode: 0644
when: ansible_os_family == "Archlinux"
- name: Set mirror
become: yes
when: ansible_os_family == "Archlinux"
copy:
content: |
Server = {{ mirroruri }}
dest: /etc/pacman.d/mirrorlist.shadowarch
owner: root
group: root
mode: 0644
- name: Import AniNIX GPG key
vars:
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
command: /bin/bash -c 'if [ ! -f /usr/share/pacman/keyrings/aninix.gpg ]; then mkdir /tmp/aninix; curl -s https://aninix.net/AniNIX/ShadowArch/raw/branch/main/EtcFiles/aninix.gpg > /tmp/aninix/pubring.gpg; pacman-key --import /tmp/aninix; pacman-key --lsign 904DE6275579CB589D85720C1CC1E3F4ED06F296; fi'
when: ansible_os_family == "Archlinux"
- name: Set up apt sources.list
vars:
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
copy:
content: |
deb http://archive.raspberrypi.org/debian/ bullseye main
# Uncomment line below then 'apt-get update' to enable 'apt-get source'
#deb-src http://archive.raspberrypi.org/debian/ bullseye main
dest: /etc/apt/sources.list.d/raspi.list
owner: root
group: root
mode: 0644
when: ansible_os_family == "Debian"
- name: Base packages
vars:
ansible_become_method: su
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
package:
name:
- bash
- sudo
- git
- tmux
- vim
- sysstat
- iotop
- lsof
- rsync
- xfsprogs
- man-db
- man-pages
state: present
update_cache: yes
- name: Install ShadowArch (ArchLinux)
vars:
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
pacman:
name: ShadowArch
state: present
update_cache: yes
when: ansible_os_family == "Archlinux"
- name: Set up AniNIX-specific repository location (Other)
when: ansible_os_family != "Archlinux"
vars:
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
file:
path: /opt/aninix
state: directory
- name: Download ShadowArch (Other)
vars:
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
ignore_errors: yes
git:
repo: 'https://foundation.aninix.net/AniNIX/ShadowArch'
dest: '/opt/aninix/ShadowArch'
update: yes
when: ansible_os_family != "Archlinux"
- name: Install ShadowArch (Other)
vars:
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
command:
chdir: '/opt/aninix/ShadowArch'
cmd: '/bin/bash -c "make install"'
when: ansible_os_family != "Archlinux"
- include_tasks: authentication.yml
- name: Set up hostname
vars:
@ -175,14 +13,18 @@
hostname:
name: "{{ inventory_hostname }}.{{ replica_domain }}"
- include: archlinux-network.yml
- include_tasks: archlinux-network.yml
when: ansible_os_family == "Archlinux"
- include: raspbian-network.yml
- include_tasks: raspbian-network.yml
when: ansible_os_family == "Debian"
- include: dns.yml
- include_tasks: dns.yml
- include: ntp.yml
- include_tasks: ntp.yml
- include: bash.yml
- include_tasks: repositories.yml
- include_tasks: bash.yml
- include_tasks: shadowarch.yml

View File

@ -0,0 +1,67 @@
---
- name: Set up pacman.conf
vars:
ansible_become_password: "{{ passwords[inventory_hostname] }}"
ignorepkg: "{{ holdpackages | default('') }}"
become: yes
template:
src: pacman.conf.j2
dest: /etc/pacman.conf
owner: root
group: root
mode: 0644
when: ansible_os_family == "Archlinux"
- name: Set mirror
become: yes
when: ansible_os_family == "Archlinux"
copy:
content: |
Server = {{ mirroruri }}
dest: /etc/pacman.d/mirrorlist.shadowarch
owner: root
group: root
mode: 0644
- name: Import AniNIX GPG key
vars:
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
command: /bin/bash -c 'if [ ! -f /usr/share/pacman/keyrings/aninix.gpg ]; then mkdir /tmp/aninix; curl -s https://aninix.net/AniNIX/ShadowArch/raw/branch/main/EtcFiles/aninix.gpg > /tmp/aninix/pubring.gpg; pacman-key --import /tmp/aninix; pacman-key --lsign 904DE6275579CB589D85720C1CC1E3F4ED06F296; fi'
when: ansible_os_family == "Archlinux"
- name: Set up apt sources.list
vars:
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
copy:
content: |
deb http://archive.raspberrypi.org/debian/ bullseye main
# Uncomment line below then 'apt-get update' to enable 'apt-get source'
#deb-src http://archive.raspberrypi.org/debian/ bullseye main
dest: /etc/apt/sources.list.d/raspi.list
owner: root
group: root
mode: 0644
when: ansible_os_family == "Debian"
- name: Base packages
vars:
ansible_become_method: su
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
package:
name:
- bash
- sudo
- git
- tmux
- vim
- sysstat
- iotop
- lsof
- rsync
- xfsprogs
- man
state: present
update_cache: yes

View File

@ -0,0 +1,39 @@
---
- name: Install ShadowArch (ArchLinux)
vars:
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
pacman:
name: ShadowArch
state: present
update_cache: yes
when: ansible_os_family == "Archlinux"
- name: Set up AniNIX-specific repository location (Other)
when: ansible_os_family != "Archlinux"
vars:
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
file:
path: /opt/aninix
state: directory
- name: Download ShadowArch (Other)
vars:
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
ignore_errors: yes
git:
repo: 'https://foundation.aninix.net/AniNIX/ShadowArch'
dest: '/opt/aninix/ShadowArch'
update: yes
when: ansible_os_family != "Archlinux"
- name: Install ShadowArch (Other)
vars:
ansible_become_password: "{{ passwords[inventory_hostname] }}"
become: yes
command:
chdir: '/opt/aninix/ShadowArch'
cmd: '/bin/bash -c "make install"'
when: ansible_os_family != "Archlinux"

View File

@ -2,4 +2,7 @@ Description="Bridge connection"
Interface=br0
Connection=bridge
BindsToInterfaces=({{ ipinterface }} tun0)
IP=dhcp
IP=static
Address=('{{ ip }}/24')
Gateway='{{ router }}'
DNS=('{{ dns }}')

View File

@ -102,8 +102,8 @@ Include = /etc/pacman.d/mirrorlist.shadowarch
[AniNIX]
SigLevel = Required DatabaseOptional
Server = https://maat.aninix.net/
Server = http://maat.msn0.aninix.net/
[aur]
SigLevel = Required DatabaseOptional
Server = https://maat.aninix.net/aur/
Server = http://maat.msn0.aninix.net/aur/

View File

@ -10,7 +10,7 @@ auto lo
iface lo inet loopback
iface {{ ipinterface }} inet static
address {{ ansible_host }}/{{ netmask }}
address {{ ip }}/{{ netmask }}
gateway {{ router }}
auto wlan0

View File

@ -0,0 +1 @@
include "/etc/monit.d/checks/system"

View File

@ -10,6 +10,7 @@ server {
location / {
rewrite ^/martialarts(\/)*(\/index.html)*$ /assets/martialarts/index.html;
rewrite ^/hire(\/)*(\/index.html)*$ /assets/hire/index.html;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $host;
@ -34,6 +35,15 @@ server {
rewrite /martialarts/maqotw.xml /MartialArts/Wiki/raw/branch/main/rss/maqotw.xml;
}
location /25u {
include conf.d/fastcgi.config;
root /usr/share/webapps/aninix/;
location ~* 25u {
try_files $uri /25u_subnetting.php;
expires max;
}
}
location /whatismyip {
include conf.d/fastcgi.config;
root /usr/share/webapps/aninix/;
@ -52,8 +62,6 @@ server {
root /usr/share/webapps/aninix/;
try_files $uri /scratch.html;
}
}
server {

View File

@ -6,7 +6,7 @@ map $http_upgrade $connection_upgrade {
server {
#listen 443 ssl http2;
listen 443 ssl;
server_name geth.aninix.net;
server_name superintendent.aninix.net;
include conf/sec.conf;
# include conf/default.csp.conf;
@ -19,7 +19,7 @@ server {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://geth.msn0.aninix.net:8123;
proxy_pass http://superintendent.msn0.aninix.net:8123;
proxy_redirect http:// https://;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;

View File

@ -22,6 +22,7 @@
mode: 0750
loop:
- /usr/share/webapps/aninix
- /var/lib/letsencrypt
- /etc/nginx/conf
- /etc/nginx/conf.d
- /etc/modsecurity