Initial commit, squashed
This commit is contained in:
commit
158e8740b8
83 changed files with 2718 additions and 0 deletions
16
roles/firewall_master/files/accept-fri.nft
Normal file
16
roles/firewall_master/files/accept-fri.nft
Normal file
|
@ -0,0 +1,16 @@
|
|||
table inet filter {
|
||||
set fri {
|
||||
typeof ip saddr; flags interval
|
||||
elements = { 10.32.0.0/14, 192.168.0.0/16, 141.255.211.0/24, 193.2.76.0/24 }
|
||||
}
|
||||
|
||||
set fri/6 {
|
||||
typeof ip6 saddr; flags interval
|
||||
elements = { 2001:1470:fffd::/48 }
|
||||
}
|
||||
|
||||
chain input {
|
||||
ip saddr @fri tcp dport { ssh, http, https } accept
|
||||
ip6 saddr @fri/6 tcp dport { ssh, http, https } accept
|
||||
}
|
||||
}
|
16
roles/firewall_master/files/friwall.ini
Normal file
16
roles/firewall_master/files/friwall.ini
Normal file
|
@ -0,0 +1,16 @@
|
|||
[uwsgi]
|
||||
uid = friwall
|
||||
gid = friwall
|
||||
|
||||
socket = /run/friwall.socket
|
||||
chown-socket = friwall:nginx
|
||||
chmod-socket = 660
|
||||
|
||||
plugin = python3
|
||||
chdir = /srv/friwall/app
|
||||
mount = /=wsgi:app
|
||||
env = PYTHONUSERBASE=/srv/friwall/.local
|
||||
env = HOME=/srv/friwall
|
||||
|
||||
# Microsoft OIDC endpoint sends some fat‐ass headers.
|
||||
buffer-size = 16384
|
18
roles/firewall_master/files/pusher.initd
Executable file
18
roles/firewall_master/files/pusher.initd
Executable file
|
@ -0,0 +1,18 @@
|
|||
#!/sbin/openrc-run
|
||||
|
||||
command="/srv/friwall/app/$RC_SVCNAME"
|
||||
command_background="yes"
|
||||
command_user="friwall"
|
||||
command_group="nogroup"
|
||||
directory="/srv/friwall"
|
||||
pidfile="/run/$RC_SVCNAME.pid"
|
||||
|
||||
depend() {
|
||||
need net
|
||||
}
|
||||
|
||||
stop() {
|
||||
ebegin "Stopping $RC_SVCNAME"
|
||||
pkill -INT -g $(cat "$pidfile") && rm -f "$pidfile"
|
||||
eend $?
|
||||
}
|
2
roles/firewall_master/files/uwsgi.ini
Normal file
2
roles/firewall_master/files/uwsgi.ini
Normal file
|
@ -0,0 +1,2 @@
|
|||
[uwsgi]
|
||||
emperor = /etc/uwsgi/conf.d
|
39
roles/firewall_master/handlers/main.yml
Normal file
39
roles/firewall_master/handlers/main.yml
Normal file
|
@ -0,0 +1,39 @@
|
|||
- name: restart interfaces
|
||||
shell: ifdown --force --auto && ifup --auto
|
||||
when: "'handler' not in ansible_skip_tags"
|
||||
|
||||
- name: reload nftables
|
||||
service:
|
||||
name: nftables
|
||||
state: reloaded
|
||||
when: "'handler' not in ansible_skip_tags"
|
||||
|
||||
- name: reload nginx
|
||||
service:
|
||||
name: nginx
|
||||
state: reloaded
|
||||
when: "'handler' not in ansible_skip_tags"
|
||||
|
||||
- name: restart nginx
|
||||
service:
|
||||
name: nginx
|
||||
state: restarted
|
||||
when: "'handler' not in ansible_skip_tags"
|
||||
|
||||
- name: restart pusher
|
||||
service:
|
||||
name: pusher
|
||||
state: restarted
|
||||
when: "'handler' not in ansible_skip_tags"
|
||||
|
||||
- name: reload uwsgi
|
||||
service:
|
||||
name: uwsgi
|
||||
state: reloaded
|
||||
when: "'handler' not in ansible_skip_tags"
|
||||
|
||||
- name: restart uwsgi
|
||||
service:
|
||||
name: uwsgi
|
||||
state: restarted
|
||||
when: "'handler' not in ansible_skip_tags"
|
9
roles/firewall_master/tasks/mail.yml
Normal file
9
roles/firewall_master/tasks/mail.yml
Normal file
|
@ -0,0 +1,9 @@
|
|||
- name: Install mail server
|
||||
package:
|
||||
name: opensmtpd
|
||||
|
||||
- name: Enable mail server
|
||||
service:
|
||||
name: smtpd
|
||||
enabled: yes
|
||||
state: started
|
42
roles/firewall_master/tasks/main.yml
Normal file
42
roles/firewall_master/tasks/main.yml
Normal file
|
@ -0,0 +1,42 @@
|
|||
- name: Set up network interfaces
|
||||
template:
|
||||
dest: /etc/network/interfaces
|
||||
src: interfaces.j2
|
||||
mode: 0644
|
||||
notify: restart interfaces
|
||||
|
||||
- name: Install nftables
|
||||
package:
|
||||
name: nftables
|
||||
|
||||
- name: Accept connections from FRI addresses
|
||||
copy:
|
||||
dest: /etc/nftables.d/
|
||||
src: accept-fri.nft
|
||||
notify: reload nftables
|
||||
|
||||
- name: Enable nftables
|
||||
service:
|
||||
name: nftables
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
- name: Install qemu guest agent
|
||||
package:
|
||||
name: qemu-guest-agent
|
||||
|
||||
- name: Enable qemu guest agent
|
||||
service:
|
||||
name: qemu-guest-agent
|
||||
enabled: yes
|
||||
runlevel: boot
|
||||
state: started
|
||||
|
||||
- name: Set up mail server
|
||||
import_tasks: mail.yml
|
||||
|
||||
- name: Set up friwall user
|
||||
import_tasks: user.yml
|
||||
|
||||
- name: Set up web UI
|
||||
import_tasks: web.yml
|
14
roles/firewall_master/tasks/user.yml
Normal file
14
roles/firewall_master/tasks/user.yml
Normal file
|
@ -0,0 +1,14 @@
|
|||
- name: Create friwall group
|
||||
group:
|
||||
name: friwall
|
||||
system: yes
|
||||
|
||||
- name: Create friwall user
|
||||
user:
|
||||
name: friwall
|
||||
system: yes
|
||||
home: /srv/friwall
|
||||
shell: /sbin/nologin
|
||||
generate_ssh_key: yes
|
||||
ssh_key_comment: "{{ inventory_hostname }}"
|
||||
ssh_key_type: ed25519
|
110
roles/firewall_master/tasks/web.yml
Normal file
110
roles/firewall_master/tasks/web.yml
Normal file
|
@ -0,0 +1,110 @@
|
|||
---
|
||||
- name: Install packages
|
||||
package:
|
||||
name: git,inotify-tools,nginx,py3-pip,procps-ng,rsync,uwsgi,uwsgi-python3,wireguard-tools
|
||||
|
||||
- name: Clone web files
|
||||
become: yes
|
||||
become_user: friwall
|
||||
become_method: su
|
||||
become_flags: "-s /bin/sh"
|
||||
git:
|
||||
repo: "{{ friwall_repo }}"
|
||||
dest: /srv/friwall/app
|
||||
force: yes
|
||||
notify: reload uwsgi
|
||||
|
||||
- name: Install requirements
|
||||
become: yes
|
||||
become_user: friwall
|
||||
become_method: su
|
||||
become_flags: '-s /bin/sh'
|
||||
pip:
|
||||
requirements: /srv/friwall/app/requirements.txt
|
||||
extra_args: --user
|
||||
|
||||
- name: Configure base settings
|
||||
template:
|
||||
dest: "/srv/friwall/{{ item }}"
|
||||
src: "{{ item }}.j2"
|
||||
owner: friwall
|
||||
group: friwall
|
||||
mode: 0600
|
||||
force: no
|
||||
loop:
|
||||
- nodes.json
|
||||
- settings.json
|
||||
notify: restart uwsgi
|
||||
|
||||
- name: Configure list of networks
|
||||
template:
|
||||
dest: "/srv/friwall/networks.json"
|
||||
src: "networks.json.j2"
|
||||
owner: friwall
|
||||
group: friwall
|
||||
mode: 0600
|
||||
|
||||
- name: Configure uwsgi
|
||||
copy:
|
||||
dest: /etc/uwsgi/
|
||||
src: uwsgi.ini
|
||||
notify: restart uwsgi
|
||||
|
||||
- name: Configure uwsgi instance
|
||||
copy:
|
||||
dest: /etc/uwsgi/conf.d/
|
||||
src: friwall.ini
|
||||
owner: friwall
|
||||
group: friwall
|
||||
|
||||
- name: Enable uwsgi
|
||||
service:
|
||||
name: uwsgi
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
- name: Configure nginx instance
|
||||
template:
|
||||
dest: /etc/nginx/http.d/friwall.conf
|
||||
src: nginx.conf.j2
|
||||
notify: reload nginx
|
||||
|
||||
- name: Run nginx in default VRF
|
||||
lineinfile:
|
||||
path: /etc/conf.d/nginx
|
||||
line: "vrf=\"default\""
|
||||
notify: restart nginx
|
||||
|
||||
- name: Enable nginx
|
||||
service:
|
||||
name: nginx
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
- name: Install config pusher initscript
|
||||
copy:
|
||||
dest: /etc/init.d/pusher
|
||||
src: pusher.initd
|
||||
mode: 0755
|
||||
notify: restart pusher
|
||||
|
||||
- name: Enable config pusher service
|
||||
service:
|
||||
name: pusher
|
||||
enabled: true
|
||||
state: started
|
||||
|
||||
- name: Regenerate config daily
|
||||
cron:
|
||||
name: "regenerate config"
|
||||
job: "cd ~/app ; FLASK_APP=web python3 -m flask generate"
|
||||
user: friwall
|
||||
hour: "3"
|
||||
minute: "33"
|
||||
|
||||
- name: Try (re-)pushing config periodically
|
||||
cron:
|
||||
name: "push config"
|
||||
job: "cd ~/app ; FLASK_APP=web python3 -m flask push"
|
||||
user: friwall
|
||||
minute: "*/15"
|
14
roles/firewall_master/templates/interfaces.j2
Normal file
14
roles/firewall_master/templates/interfaces.j2
Normal file
|
@ -0,0 +1,14 @@
|
|||
auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
{% for iface in interfaces %}
|
||||
auto {{ iface.name }}
|
||||
iface {{ iface.name }} inet static
|
||||
{% for address in iface.ip_addresses %}
|
||||
address {{ address.address }}
|
||||
{% endfor %}
|
||||
{% if iface.custom_fields.gateway %}
|
||||
gateway {{ iface.custom_fields.gateway.address | ipaddr('address') }}
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
21
roles/firewall_master/templates/networks.json.j2
Normal file
21
roles/firewall_master/templates/networks.json.j2
Normal file
|
@ -0,0 +1,21 @@
|
|||
{% set groups = vlans | map(attribute='name') | select('match', '.+-.+')
|
||||
| map('split', '-') | map('first') | unique -%}
|
||||
{% set prefixes = query('netbox.netbox.nb_lookup', 'prefixes', raw_data=true) %}
|
||||
|
||||
{
|
||||
{% for vlan in vlans %}
|
||||
{% set vlan_prefixes = prefixes | selectattr('vlan') | selectattr('vlan.id', '==', vlan.id) | map(attribute='prefix') %}
|
||||
"{{ vlan.name }}": {
|
||||
"ip": {{ vlan_prefixes | ipv4 | to_json }},
|
||||
"ip6": {{ vlan_prefixes | ipv6 | to_json }}
|
||||
}{% if not loop.last or groups %},{% endif +%}
|
||||
{% endfor %}
|
||||
|
||||
{% for group in groups %}
|
||||
{% set group_prefixes = prefixes | selectattr('vlan') | selectattr('vlan.name', 'match', '^'~group) | map(attribute='prefix') %}
|
||||
"{{ group }}": {
|
||||
"ip": {{ group_prefixes | ipv4 | to_json }},
|
||||
"ip6": {{ group_prefixes | ipv6 | to_json }}
|
||||
}{% if not loop.last %},{% endif +%}
|
||||
{% endfor %}
|
||||
}
|
21
roles/firewall_master/templates/nginx.conf.j2
Normal file
21
roles/firewall_master/templates/nginx.conf.j2
Normal file
|
@ -0,0 +1,21 @@
|
|||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name {{ fqdn }};
|
||||
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
server_name {{ fqdn }};
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/{{ fqdn }}/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/{{ fqdn }}/privkey.pem;
|
||||
|
||||
location / {
|
||||
uwsgi_pass unix:/run/friwall.socket;
|
||||
include uwsgi_params;
|
||||
}
|
||||
}
|
10
roles/firewall_master/templates/nodes.json.j2
Normal file
10
roles/firewall_master/templates/nodes.json.j2
Normal file
|
@ -0,0 +1,10 @@
|
|||
{% set nodes = query('netbox.netbox.nb_lookup', 'devices', raw_data=true)
|
||||
| selectattr('config_context') | selectattr('config_context', 'contains', 'master')
|
||||
| selectattr('config_context.master', '==', inventory_hostname)
|
||||
| map(attribute='name') -%}
|
||||
|
||||
{
|
||||
{% for node in nodes %}
|
||||
"{{ hostvars[node].interfaces | selectattr('name', '==', 'lo') | map(attribute='ip_addresses') | first | selectattr('role') | selectattr('role.value', '==', 'loopback') | map(attribute='address') | ipv4 | first | ipaddr('address') }}": -1{{ '' if loop.last else ',' }} {# TODO help my eyes the goggles do nothing +#}
|
||||
{% endfor %}
|
||||
}
|
10
roles/firewall_master/templates/settings.json.j2
Normal file
10
roles/firewall_master/templates/settings.json.j2
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"ldap_host": "{{ domain }}",
|
||||
"ldap_user": "{{ ldap_user }}",
|
||||
"ldap_pass": "{{ ldap_pass }}",
|
||||
"ldap_base_dn": "{{ ldap_base_dn }}",
|
||||
"oidc_server": "{{ oidc_server }}",
|
||||
"oidc_client_id": "{{ oidc_client_id }}",
|
||||
"oidc_client_secret": "{{ oidc_client_secret }}",
|
||||
"wg_net": "{{ wg_net }}",
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue