summaryrefslogtreecommitdiff
path: root/roles
diff options
context:
space:
mode:
Diffstat (limited to 'roles')
-rw-r--r--roles/jail/meta/main.yml2
-rw-r--r--roles/jail/tasks/main.yml34
-rw-r--r--roles/jail/templates/jail.conf.j218
-rw-r--r--roles/jailhost/handlers/main.yml9
-rw-r--r--roles/jailhost/tasks/main.yml64
-rw-r--r--roles/pf/handlers/main.yml15
-rw-r--r--roles/pf/tasks/main.yml19
-rw-r--r--roles/pf/templates/pf.conf.j256
8 files changed, 217 insertions, 0 deletions
diff --git a/roles/jail/meta/main.yml b/roles/jail/meta/main.yml
new file mode 100644
index 0000000..574a987
--- /dev/null
+++ b/roles/jail/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+# - role: jailhost
diff --git a/roles/jail/tasks/main.yml b/roles/jail/tasks/main.yml
new file mode 100644
index 0000000..670a886
--- /dev/null
+++ b/roles/jail/tasks/main.yml
@@ -0,0 +1,34 @@
+- name: create dataset for jail
+ community.general.zfs:
+ name: "{{ jailset }}/{{ jail.name }}"
+ state: present
+ origin: "{{ jailset }}/base@{{ base_jail_patch_level }}"
+
+- name: make sure jail conf dir exists
+ file:
+ path: "{{ jailbase }}/conf"
+ state: directory
+ mode: '0755'
+
+- name: create jail conf {{ jail.name }}
+ ansible.builtin.template:
+ src: jail.conf.j2
+ dest: "{{ jailbase }}/conf/{{ jail.name }}.conf"
+
+- name: create additional datasets
+ community.general.zfs:
+ name: "{{ jailset }}/tank/{{ item }}"
+ state: present
+ extra_zfs_properties:
+ jailed: on
+ loop: "{{ jail.additional_data_sets | default([]) }}"
+
+- name: start jail
+ shell:
+ cmd: jls -j {{ jail.name }} || jail -f {{ jailbase }}/conf/{{ jail.name }}.conf -c {{ jail.name }}
+
+- name: Make sure packages are up to date in {{ jail.name }}
+ community.general.pkgng:
+ name: "*"
+ state: latest
+ jail: "{{ jail.name }}"
diff --git a/roles/jail/templates/jail.conf.j2 b/roles/jail/templates/jail.conf.j2
new file mode 100644
index 0000000..0b55078
--- /dev/null
+++ b/roles/jail/templates/jail.conf.j2
@@ -0,0 +1,18 @@
+{{ jail.name }} {
+ exec.start = '/bin/sh /etc/rc';
+ exec.stop = '/bin/sh /etc/rc.shutdown jail';
+ mount.devfs;
+ host.hostname={{ jail.name }}.in.prison;
+ allow.raw_sockets;
+ allow.mount;
+ allow.mount.devfs;
+ allow.mount.zfs;
+ devfs_ruleset = 4;
+ enforce_statfs = 1;
+ ip6.addr='em0|{{ jail.ip }}';
+ path=/usr/local/jails/{{ jail.name }};
+
+ {% for dataset in jail.additional_data_sets | default([]) -%}
+ exec.poststart+="zfs jail ${name} poolen/jails/tank/{{ dataset }}";
+ {% endfor -%}
+}
diff --git a/roles/jailhost/handlers/main.yml b/roles/jailhost/handlers/main.yml
new file mode 100644
index 0000000..4177d4c
--- /dev/null
+++ b/roles/jailhost/handlers/main.yml
@@ -0,0 +1,9 @@
+- name: restart netif
+ service:
+ name: netif
+ state: restarted
+
+- name: restart routing
+ service:
+ name: routing
+ state: restarted
diff --git a/roles/jailhost/tasks/main.yml b/roles/jailhost/tasks/main.yml
new file mode 100644
index 0000000..a26351b
--- /dev/null
+++ b/roles/jailhost/tasks/main.yml
@@ -0,0 +1,64 @@
+- name: create jails dataset
+ community.general.zfs:
+ name: poolen/jails
+ state: present
+ extra_zfs_properties:
+ mountpoint: /usr/local/jails
+
+- name: create jails tank dataset
+ community.general.zfs:
+ name: poolen/jails/tank
+ state: present
+
+- name: create base jail dataset
+ community.general.zfs:
+ name: poolen/jails/base
+ state: present
+
+- name: install base jail
+ shell: |
+ set -e
+ bsdinstall checksum || echo 'checksums failed'
+ bsdinstall distextract || echo 'distextract failed'
+ bsdinstall config || error 'failed to save config'
+
+ bsdinstall entropy
+ environment:
+ BSDINSTALL_CHROOT: "/usr/local/jails/base"
+ DISTRIBUTIONS: "base.txz"
+ nonInteractive: "YES"
+ args:
+ creates: "/usr/local/jails/base/bin"
+
+- name: configure base jail
+ shell: |
+ cp /etc/resolv.conf /usr/local/jails/base/etc/
+ cp /etc/localtime /usr/local/jails/base/etc/
+ cp /var/db/zoneinfo /usr/local/jails/base/var/db/
+ args:
+ creates: "/usr/local/jails/base/etc/resolv.conf"
+
+- name: apply updates for base jail
+ ansible.builtin.shell: |
+ freebsd-update -b /usr/local/jails/base fetch
+ freebsd-update -b /usr/local/jails/base install
+ register: result_update
+ failed_when: result_update.rc != 0 and result_update.rc != 2
+ changed_when: result_update.rc != 2
+
+- name: determine patch level of base jail
+ shell: /usr/local/jails/base/bin/freebsd-version -u
+ register: patch_level
+ environment:
+ ROOT: /usr/local/jails/base
+
+- name: snapshot the base jail
+ community.general.zfs:
+ name: "poolen/jails/base@{{ patch_level.stdout }}"
+ state: present
+
+- name: set patch level as fact
+ ansible.builtin.set_fact:
+ base_jail_patch_level: "{{ patch_level.stdout }}"
+ cacheable: yes
+
diff --git a/roles/pf/handlers/main.yml b/roles/pf/handlers/main.yml
new file mode 100644
index 0000000..4baf234
--- /dev/null
+++ b/roles/pf/handlers/main.yml
@@ -0,0 +1,15 @@
+---
+- name: start pflog
+ service:
+ name: pflog
+ state: started
+
+- name: start pf
+ service:
+ name: pf
+ state: started
+ async: 45
+ poll: 5
+
+- name: reload pf
+ shell: pfctl -nf /etc/pf.conf && pfctl -f /etc/pf.conf
diff --git a/roles/pf/tasks/main.yml b/roles/pf/tasks/main.yml
new file mode 100644
index 0000000..b7c405a
--- /dev/null
+++ b/roles/pf/tasks/main.yml
@@ -0,0 +1,19 @@
+- name: enable pf
+ community.general.sysrc:
+ name: pf_enable
+ value: "YES"
+ notify: start pf
+
+- name: enable pflog
+ community.general.sysrc:
+ name: pflog_enable
+ value: "YES"
+ notify: start pflog
+
+- name: template pf.conf
+ template:
+ src: pf.conf.j2
+ dest: /etc/pf.conf
+ notify: reload pf
+
+- meta: flush_handlers
diff --git a/roles/pf/templates/pf.conf.j2 b/roles/pf/templates/pf.conf.j2
new file mode 100644
index 0000000..8819ee0
--- /dev/null
+++ b/roles/pf/templates/pf.conf.j2
@@ -0,0 +1,56 @@
+# our interface
+ext_if = "em0"
+
+# IPv6 link local prefix.
+PFX_LNKLOC = "fe80::/10"
+
+# IPv6 Solicited Node Multicast Prefix.
+MC_SOLNOD = "ff02::1:ff00:0/104"
+
+# IPv6 All Nodes Link Local Multicast Address.
+MC_NODLNK = "ff02::1"
+
+# skip loopback
+set skip on lo0
+set loginterface $ext_if
+set block-policy drop
+
+scrub in on $ext_if
+
+## RULES ##
+
+# block and log all traffic not matching below rules
+block in
+
+# allow ssh traffic to the host on the custom port
+pass in quick proto tcp to port 2223
+
+# allow http/https
+pass in quick proto {tcp, udp} to port { http, https }
+
+# allow ssh for gubbhub
+pass in quick proto tcp to port 2224
+
+# ping
+pass in quick inet6 proto icmp6 icmp6-type echoreq
+pass in quick inet proto icmp icmp-type echoreq
+
+# ipv6 stuff
+
+# Allow NS from unspecified to solicited node multicast address (DAD).
+pass quick inet6 proto icmp6 from :: to $MC_SOLNOD icmp6-type neighbrsol no state
+
+# Allow IPv6 Router Discovery.
+pass in quick inet6 proto icmp6 from $PFX_LNKLOC to $MC_NODLNK icmp6-type routeradv no state
+
+# Allow IPv6 Neighbor Discovery (ND/NUD/DAD).
+pass in quick inet6 proto icmp6 to { ($ext_if), $MC_SOLNOD } icmp6-type { neighbrsol, neighbradv } no state
+
+# Allow any outgoing traffic
+pass out
+
+# TODO: We seem to not only get neighbor advertisements from the local subnet? How does
+# this work?
+#pass in quick inet6 proto icmp6 from { $PFX_LNKLOC, ($ext_if:network) } to { ($ext_if), $MC_SOLNOD } icmp6-type neighbrsol no state
+#pass in quick inet6 proto icmp6 from { $PFX_LNKLOC, ($ext_if:network) } to { ($ext_if), $MC_NODLNK } icmp6-type neighbradv no state
+