Compare commits
3 commits
6a9a4142ce
...
29598ef4bb
Author | SHA1 | Date | |
---|---|---|---|
Timotej Lazar | 29598ef4bb | ||
Timotej Lazar | 38c3464279 | ||
Timotej Lazar | 393614aa79 |
|
@ -7,6 +7,7 @@ class FilterModule(object):
|
||||||
'''Various utilities for manipulating NetBox data'''
|
'''Various utilities for manipulating NetBox data'''
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
if 'NETBOX_API' in os.environ and 'NETBOX_TOKEN' in os.environ:
|
||||||
self.nb = pynetbox.api(os.getenv('NETBOX_API'), os.getenv('NETBOX_TOKEN'))
|
self.nb = pynetbox.api(os.getenv('NETBOX_API'), os.getenv('NETBOX_TOKEN'))
|
||||||
|
|
||||||
def filters(self):
|
def filters(self):
|
||||||
|
@ -37,11 +38,12 @@ class FilterModule(object):
|
||||||
|
|
||||||
def allowed_prefixes(self, service):
|
def allowed_prefixes(self, service):
|
||||||
'''Return a list of allowed IP prefixes for the given service'''
|
'''Return a list of allowed IP prefixes for the given service'''
|
||||||
service_data = self.nb.ipam.services.get(service['id']).custom_fields
|
if 'custom_fields' in service:
|
||||||
if service_data['allowed_prefixes']:
|
service = service['custom_fields']
|
||||||
yield from self.nb.ipam.prefixes.filter(id=[prefix['id'] for prefix in service_data['allowed_prefixes']])
|
if prefixes := service.get('allowed_prefixes'):
|
||||||
if service_data['allowed_vlans']:
|
yield from self.nb.ipam.prefixes.filter(id=[prefix['id'] for prefix in prefixes])
|
||||||
yield from self.nb.ipam.prefixes.filter(vlan_id=[vlan['id'] for vlan in service_data['allowed_vlans']])
|
if vlans := service.get('allowed_vlans'):
|
||||||
if service_data['allowed_clusters']:
|
yield from self.nb.ipam.prefixes.filter(vlan_id=[vlan['id'] for vlan in vlans])
|
||||||
for device in self.nb.dcim.devices.filter(cluster_id=[cluster['id'] for cluster in service_data['allowed_clusters']]):
|
if clusters := service.get('allowed_clusters'):
|
||||||
|
for device in self.nb.dcim.devices.filter(cluster_id=[cluster['id'] for cluster in clusters]):
|
||||||
yield from self.nb.ipam.ip_addresses.filter(role='loopback', device_id=device.id)
|
yield from self.nb.ipam.ip_addresses.filter(role='loopback', device_id=device.id)
|
||||||
|
|
8
roles/alpine/files/unattended-upgrade
Normal file
8
roles/alpine/files/unattended-upgrade
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
upgrade() {
|
||||||
|
echo "Starting upgrade on $(date)"
|
||||||
|
apk upgrade --update
|
||||||
|
}
|
||||||
|
|
||||||
|
upgrade >> /var/log/unattended-upgrade.log
|
3
roles/alpine/files/unattended-upgrade.logrotate
Normal file
3
roles/alpine/files/unattended-upgrade.logrotate
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
/var/log/unattended-upgrade.log {
|
||||||
|
missingok
|
||||||
|
}
|
|
@ -22,6 +22,7 @@
|
||||||
name:
|
name:
|
||||||
- git
|
- git
|
||||||
- iproute2
|
- iproute2
|
||||||
|
- logrotate
|
||||||
- nftables
|
- nftables
|
||||||
- procps
|
- procps
|
||||||
- rsync
|
- rsync
|
||||||
|
@ -64,3 +65,15 @@
|
||||||
name: qemu-guest-agent
|
name: qemu-guest-agent
|
||||||
enabled: yes
|
enabled: yes
|
||||||
state: started
|
state: started
|
||||||
|
|
||||||
|
- name: Install automatic upgrade script
|
||||||
|
copy:
|
||||||
|
dest: /etc/periodic/weekly/
|
||||||
|
src: unattended-upgrade
|
||||||
|
mode: 0755
|
||||||
|
|
||||||
|
- name: Configure log rotation for automatic upgrades
|
||||||
|
copy:
|
||||||
|
dest: /etc/logrotate.d/unattended-upgrade
|
||||||
|
src: unattended-upgrade.logrotate
|
||||||
|
mode: 0644
|
||||||
|
|
|
@ -7,7 +7,9 @@ table inet filter {
|
||||||
{% set prefixes4 = prefixes | selectattr('family.value', '==', 4) | map('string') %}
|
{% set prefixes4 = prefixes | selectattr('family.value', '==', 4) | map('string') %}
|
||||||
{% set prefixes6 = prefixes | selectattr('family.value', '==', 6) | map('string') %}
|
{% set prefixes6 = prefixes | selectattr('family.value', '==', 6) | map('string') %}
|
||||||
{% set ports = service.ports | compact_numlist %}
|
{% set ports = service.ports | compact_numlist %}
|
||||||
|
{% if 'name' in service %}
|
||||||
# service {{ service.name }}
|
# service {{ service.name }}
|
||||||
|
{% endif %}
|
||||||
{% if prefixes4 or prefixes6 %}
|
{% if prefixes4 or prefixes6 %}
|
||||||
{% if prefixes4 %}
|
{% if prefixes4 %}
|
||||||
ip saddr { {{ prefixes4 | join(', ') }} } tcp dport { {{ ports }} } accept
|
ip saddr { {{ prefixes4 | join(', ') }} } tcp dport { {{ ports }} } accept
|
||||||
|
|
|
@ -54,7 +54,7 @@ table inet filter {
|
||||||
ip saddr @allowed accept # TODO remove exceptions
|
ip saddr @allowed accept # TODO remove exceptions
|
||||||
ip6 saddr @allowed/6 accept # TODO remove exceptions
|
ip6 saddr @allowed/6 accept # TODO remove exceptions
|
||||||
|
|
||||||
{% for service in cluster.custom_fields.services %}
|
{% for service in cluster_services %}
|
||||||
{% set prefixes = service | allowed_prefixes %}
|
{% set prefixes = service | allowed_prefixes %}
|
||||||
{% set prefixes4 = prefixes | selectattr('family.value', '==', 4) | map('string') %}
|
{% set prefixes4 = prefixes | selectattr('family.value', '==', 4) | map('string') %}
|
||||||
{% set prefixes6 = prefixes | selectattr('family.value', '==', 6) | map('string') %}
|
{% set prefixes6 = prefixes | selectattr('family.value', '==', 6) | map('string') %}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
{% for fqdn in fqdns %}
|
|
||||||
server {
|
server {
|
||||||
listen 443 ssl http2;
|
listen 443 ssl http2;
|
||||||
listen [::]:443 ssl http2;
|
listen [::]:443 ssl http2;
|
||||||
server_name {{ fqdn }};
|
server_name {{ dns_name }};
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/{{ fqdn }}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/{{ dns_name }}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/{{ fqdn }}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/{{ dns_name }}/privkey.pem;
|
||||||
|
|
||||||
client_max_body_size 100M;
|
client_max_body_size 100M;
|
||||||
|
|
||||||
|
@ -35,5 +34,3 @@ server {
|
||||||
fastcgi_pass unix:/run/php-fpm.socket;
|
fastcgi_pass unix:/run/php-fpm.socket;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{% endfor %}
|
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
# Make expensive lookups to NetBox once for later reference by any host.
|
# Make expensive lookups to NetBox once for later reference by any host.
|
||||||
- name: Lookup networks and prefixes
|
- when: lookup("env", "NETBOX_API") != ""
|
||||||
|
block:
|
||||||
|
- name: Lookup networks and prefixes
|
||||||
set_fact:
|
set_fact:
|
||||||
vlans: '{{ query("netbox.netbox.nb_lookup", "vlans", api_filter="group=new-net", raw_data=true)
|
vlans: '{{ query("netbox.netbox.nb_lookup", "vlans", api_filter="group=new-net", raw_data=true)
|
||||||
| sort(attribute="vid") }}'
|
| sort(attribute="vid") }}'
|
||||||
prefixes: '{{ query("netbox.netbox.nb_lookup", "prefixes", raw_data=true)
|
prefixes: '{{ query("netbox.netbox.nb_lookup", "prefixes", raw_data=true)
|
||||||
| sort(attribute="prefix") | sort(attribute="family.value") }}'
|
| sort(attribute="prefix") | sort(attribute="family.value") }}'
|
||||||
|
|
||||||
- name: Get my cluster and all nodes in it
|
- when: 'cluster is defined'
|
||||||
|
block:
|
||||||
|
- name: Get my cluster and all nodes in it
|
||||||
set_fact:
|
set_fact:
|
||||||
cluster: '{{ query("netbox.netbox.nb_lookup", "clusters", raw_data=true, api_filter="name="+cluster) | first }}'
|
cluster: '{{ query("netbox.netbox.nb_lookup", "clusters", raw_data=true, api_filter="name="+cluster) | first }}'
|
||||||
nodes: '{{ groups["cluster_"+cluster] | map("extract", hostvars) | rejectattr("is_virtual") }}'
|
nodes: '{{ groups["cluster_"+cluster] | map("extract", hostvars) | rejectattr("is_virtual") }}'
|
||||||
when: cluster
|
|
||||||
|
|
||||||
- name: Get my domain names if any
|
- name: Get cluster services
|
||||||
set_fact:
|
set_fact:
|
||||||
fqdns: '{{ interfaces | map(attribute="ip_addresses") | flatten
|
cluster_services: '{{ (cluster_services|default([])) + query("netbox.netbox.nb_lookup", "services", raw_data=true, api_filter="id="+item) }}'
|
||||||
| map(attribute="dns_name") | reject("==", "") | sort | unique }}'
|
loop: '{{ cluster.custom_fields.services | map(attribute="id") | map("string") }}'
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
{% for fqdn in fqdns %}
|
|
||||||
server {
|
server {
|
||||||
server_name {{ fqdn }};
|
server_name {{ dns_name }};
|
||||||
|
|
||||||
listen [::]:443 ssl ipv6only=off;
|
listen [::]:443 ssl ipv6only=off;
|
||||||
ssl_certificate /etc/letsencrypt/live/{{ fqdn }}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/{{ dns_name }}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/{{ fqdn }}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/{{ dns_name }}/privkey.pem;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
proxy_pass http://unix:/var/lib/forgejo/socket;
|
proxy_pass http://unix:/var/lib/forgejo/socket;
|
||||||
|
@ -19,5 +18,3 @@ server {
|
||||||
client_max_body_size 512M;
|
client_max_body_size 512M;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{% endfor %}
|
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
line: '{{ item.line }}'
|
line: '{{ item.line }}'
|
||||||
loop:
|
loop:
|
||||||
- key: '^ALLOWED_HOSTS = '
|
- key: '^ALLOWED_HOSTS = '
|
||||||
line: "ALLOWED_HOSTS = [{{ fqdns | map('regex_replace', '^(.*)$', '\"\\1\"') | join(', ') }}]"
|
line: "ALLOWED_HOSTS = ['{{ dns_name }}']"
|
||||||
- key: 'USER.*PostgreSQL username'
|
- key: 'USER.*PostgreSQL username'
|
||||||
line: " 'USER': '{{ user }}', # PostgreSQL username"
|
line: " 'USER': '{{ user }}', # PostgreSQL username"
|
||||||
# XXX unnecessary?
|
# XXX unnecessary?
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
{% for fqdn in fqdns %}
|
|
||||||
server {
|
server {
|
||||||
server_name {{ fqdn }};
|
server_name {{ dns_name }};
|
||||||
|
|
||||||
listen [::]:443 ssl ipv6only=off;
|
listen [::]:443 ssl ipv6only=off;
|
||||||
ssl_certificate /etc/letsencrypt/live/{{ fqdn }}/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/{{ dns_name }}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/{{ fqdn }}/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/{{ dns_name }}/privkey.pem;
|
||||||
|
|
||||||
client_max_body_size 100m;
|
client_max_body_size 100m;
|
||||||
|
|
||||||
|
@ -19,5 +18,3 @@ server {
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{% endfor %}
|
|
||||||
|
|
|
@ -26,9 +26,8 @@
|
||||||
|
|
||||||
- name: Get LE certificate
|
- name: Get LE certificate
|
||||||
command:
|
command:
|
||||||
cmd: certbot certonly --non-interactive --agree-tos --register-unsafely-without-email --webroot --webroot-path /srv/http -d {{ item }}
|
cmd: certbot certonly --non-interactive --agree-tos --register-unsafely-without-email --webroot --webroot-path /srv/http -d {{ dns_name }}
|
||||||
creates: '/etc/letsencrypt/renewal/{{ item }}.conf'
|
creates: '/etc/letsencrypt/renewal/{{ dns_name }}.conf'
|
||||||
loop: '{{ fqdns }}'
|
|
||||||
|
|
||||||
- name: Enable certbot renewal
|
- name: Enable certbot renewal
|
||||||
cron:
|
cron:
|
||||||
|
|
|
@ -8,16 +8,16 @@ IN Ping(ACCEPT) -log nolog # don’t be rude
|
||||||
IN SSH(ACCEPT) -i mgmt # for ansible etc.
|
IN SSH(ACCEPT) -i mgmt # for ansible etc.
|
||||||
IN ACCEPT -source {{ nodes | map('device_address') | flatten | selectattr('family.value', '==', 4) | map(attribute='address') | join(',') }} # my cluster
|
IN ACCEPT -source {{ nodes | map('device_address') | flatten | selectattr('family.value', '==', 4) | map(attribute='address') | join(',') }} # my cluster
|
||||||
IN ACCEPT -source {{ nodes | map('device_address') | flatten | selectattr('family.value', '==', 6) | map(attribute='address') | join(',') }} # my cluster
|
IN ACCEPT -source {{ nodes | map('device_address') | flatten | selectattr('family.value', '==', 6) | map(attribute='address') | join(',') }} # my cluster
|
||||||
{% for service in cluster.custom_fields.services %}
|
{% for service in cluster_services %}
|
||||||
{% set prefixes = service | allowed_prefixes %}
|
{% set prefixes = service | allowed_prefixes %}
|
||||||
{% set prefixes4 = prefixes | selectattr('family.value', '==', 4) | map('string') %}
|
{% set prefixes4 = prefixes | selectattr('family.value', '==', 4) | map('string') %}
|
||||||
{% set prefixes6 = prefixes | selectattr('family.value', '==', 6) | map('string') %}
|
{% set prefixes6 = prefixes | selectattr('family.value', '==', 6) | map('string') %}
|
||||||
{% set ports = service.ports | compact_numlist(range_delimiter=':') %}
|
{% set ports = service.ports | compact_numlist(range_delimiter=':') %}
|
||||||
{% if prefixes4 %}
|
{% if prefixes4 %}
|
||||||
IN ACCEPT -source {{ prefixes4 | join(',') }} -p {{ service.protocol }} -dport {{ ports }} # {{ service.name }}
|
IN ACCEPT -source {{ prefixes4 | join(',') }} -p {{ service.protocol.value }} -dport {{ ports }} # {{ service.name }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if prefixes6 %}
|
{% if prefixes6 %}
|
||||||
IN ACCEPT -source {{ prefixes6 | join(',') }} -p {{ service.protocol }} -dport {{ ports }} # {{ service.name }}
|
IN ACCEPT -source {{ prefixes6 | join(',') }} -p {{ service.protocol.value }} -dport {{ ports }} # {{ service.name }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue