Skip to content
Snippets Groups Projects
Verified Commit 472816ab authored by Evangelos Foutras's avatar Evangelos Foutras :smiley_cat:
Browse files

acme_dns_challenge: turn into more generic dyn_dns

Extend the role (previously used for ACME DNS verifications only) to
support dynamic DNS functionality planned for sandbox.archlinux.page.
parent 5be67df4
No related branches found
No related tags found
1 merge request!754acme_dns_challenge: turn into more generic dyn_dns
Pipeline #75807 passed
......@@ -20,7 +20,7 @@ The continent mirrors america, asia and europe contain the archive mirrors as we
- Host with Arch Linux installed
- root access provided
- Enough storage to host repos / debugrepos (at least)
- Bandwidth (depends on location)
- Bandwidth (depends on location)
## Adding a new mirror box
- Add new entries in `hosts` file under `mirrors` and `geo_mirrors` sections
......@@ -38,7 +38,7 @@ The continent mirrors america, asia and europe contain the archive mirrors as we
| ----------- | ----------- | ----------- | ----------- | ----------- |
| install_arch | All | Install Arch | | Optional if you can |
| mirrors.yml | All | Setup mirror | `<fqdn>` | |
| redirect.archlinux.org.yml | acme_dns_challenge | Make TXT records | | |
| redirect.archlinux.org.yml | dyn_dns | Make TXT records | | |
| gemini.archlinux.org.yml | dbscripts | Allow debug repo syncing | | |
| mirrors.yml | geo_dns | Add new domain to DNS | All other mirrors from geo.mirror | |
| monitoring.archlinux.org.yml | wireguard,prometheus | Allow loki and prometheus to fetch data | | |
......
dyn_dns_server: "{{ hostvars['redirect.archlinux.org']['ipv4_address'] }}"
dyn_dns_zones:
_acme-challenge.geo.mirror.pkgbuild.com: &acme_challenge
key: certbot
allowed_ipv4: "{{ groups['geo_mirrors'] | map('extract', hostvars, ['ipv4_address']) }}"
allowed_ipv6: "{{ groups['geo_mirrors'] | map('extract', hostvars, ['ipv6_address']) }}"
valid_qtypes: [TXT]
_acme-challenge.riscv.mirror.pkgbuild.com: *acme_challenge
$ANSIBLE_VAULT;1.1;AES256
61373835393530366133386434373162656332363939656235646235663333633532336435353266
3364616435323230656233666633353535303436363433610a376133633938663634323932643764
36656433366566623864636462383861636538363737343861316330306561373965626366363032
6366373462303839660a653335623261306630623139643630323330633665393030333830653930
37653166613264643537383734336163313537313334363635653062653832333638356361313461
62353166393332326534356661653464333266383234396536383633323834333566633861643363
66316162356566343964623237356264633564646634653834326363386235333361656332386265
39333463343365393962663637666333376236366638306361316435306537643031346162346464
33313466353666353136386463353831353365643333613066326136343234343636343833346465
64343962303766303436613538616165623837383837303230623135623562303664333764323834
62313864653234653138336134303638666234376631663361396662653863643433313864303330
63663034353461346562
../../host_vars/redirect.archlinux.org/vault_certbot.yml
\ No newline at end of file
$ANSIBLE_VAULT;1.1;AES256
36396331303031376233613930366238363633633464636336663163363234623939623731616536
6262353930613038346636343364663532343539343661620a313262666231333164653639653531
64626638366531653865616130653235323933376235306130663034636633343764383264373632
6335643131366364620a353835353663643533396161626462343566376264633331336365373936
31393234333539656230633531626438643466656438643530363466303337356263333031396362
65656461313261303461643062353634303266316163346132656135323639363833306335343831
62353437643537333430343263626630323761356530386466633964336430373636623937326138
62336564326462366661323665663032363939353138366132636564613364386266643762326565
33386235393830336563363836333732656637363661666661656434326231323662383962643761
66303761323336383838303166313766336338656433383834663932356431613638643563353865
39346432366437303334343339383835646135326435656637646463303332343734643138653236
33643739373839656138376339626134663332613438643036656430306338393436396465616337
35336463383032346632626536383433633436653037613336313837386336306362323766356465
30336233356631643362316539326135363961393435303535376136633762373061633965353564
31393161646132323833653936346464646532353830643362366433653934326563646166303862
62666364326563353439663636383437613134333836643134646135326435646234653762333438
61306361393763356633303736333535656331636461333237633134626231633635
......@@ -14,4 +14,4 @@
- { role: promtail }
- { role: hardening }
- { role: ping }
- { role: acme_dns_challenge }
- { role: dyn_dns }
#jinja2: lstrip_blocks: True
-- Based on https://github.com/PowerDNS/pdns/wiki/Lua-Examples-(Authoritative)#updatepolicy-access-control-for-rfc2136-dynamic-updates
function updatepolicy(input)
valid_rrnames = {
{% for domain in geo_domains %}
["_acme-challenge.{{ domain }}."]=true,
{% endfor %}
}
-- only allow updates from our servers
mynetworks = newNMG()
mynetworks:addMasks({
{% for host in groups['geo_mirrors'] | sort %}
'{{ hostvars[host]['ipv4_address'] }}/32',
'{{ hostvars[host]['ipv6_address'] }}/128',
{% endfor %}
})
-- ignore non-authorized networks
if not mynetworks:match(input:getRemote())
then
pdnslog("updatepolicy: network check failed from " .. input:getRemote():toString(), pdns.loglevels.Info)
return false
end
-- ignore non-TSIG requests
if input:getTsigName():countLabels() == 0
then
pdnslog("updatepolicy: missing TSIG", pdns.loglevels.Info)
return false
end
-- only accept TXT record updates for _acme_challenge
if input:getQType() == pdns.TXT and valid_rrnames[input:getQName():toString()]
then
pdnslog("updatepolicy: query checks successful", pdns.loglevels.Info)
return true
end
pdnslog("updatepolicy: query checks failed", pdns.loglevels.Info)
return false
end
dns_rfc2136_server = {{ certbot_rfc2136_server }}
dns_rfc2136_name = {{ certbot_rfc2136_key }}
dns_rfc2136_secret = {{ certbot_rfc2136_secret }}
dns_rfc2136_algorithm = {{ certbot_rfc2136_algorithm }}
dns_rfc2136_server = {{ dyn_dns_server }}
dns_rfc2136_name = certbot
dns_rfc2136_secret = {{ dyn_dns_keys['certbot'].secret }}
dns_rfc2136_algorithm = {{ dyn_dns_keys['certbot'].algorithm | upper }}
......@@ -8,27 +8,30 @@
- {src: dnsupdate-policy.lua.j2, dest: dnsupdate-policy.lua}
notify: Restart powerdns
- name: Create directory for sqlite3 dbs
- name: Create directory for sqlite3 database
file: path=/var/lib/powerdns state=directory owner=powerdns group=powerdns mode=0755
- name: Initialize sqlite3 database for _acme-challenge zones
- name: Initialize sqlite3 database
command: sqlite3 -init /usr/share/doc/powerdns/schema.sqlite3.sql /var/lib/powerdns/pdns.sqlite3 ""
become: true
become_user: powerdns
args:
creates: /var/lib/powerdns/pdns.sqlite3
- name: Create _acme-challenge zones
- name: Create zones
shell: |
pdnsutil create-zone _acme-challenge.{{ item }} {{ inventory_hostname }}
pdnsutil replace-rrset _acme-challenge.{{ item }} @ SOA "{{ inventory_hostname }}. root.archlinux.org. 0 10800 3600 604800 3600"
loop: "{{ geo_domains }}"
become: true
become_user: powerdns
pdnsutil create-zone {{ item.zone }} {{ inventory_hostname }}
pdnsutil replace-rrset {{ item.zone }} @ SOA "{{ inventory_hostname }}. root.archlinux.org. 0 10800 3600 604800 3600"
loop: "{{ dyn_dns_zones | dict2items(key_name='zone') }}"
loop_control:
label: "{{ item.zone }}"
changed_when: false
- name: Import TSIG key (for certbot)
command: pdnsutil import-tsig-key {{ certbot_rfc2136_key }} {{ certbot_rfc2136_algorithm }} {{ certbot_rfc2136_secret }}
- name: Import TSIG keys
command: pdnsutil import-tsig-key {{ item.key }} {{ item.value.algorithm }} {{ item.value.secret }}
loop: "{{ dyn_dns_keys | dict2items }}"
loop_control:
label: "{{ item.key }}"
changed_when: false
- name: Open powerdns ipv4 port for monitoring.archlinux.org
......
#jinja2: lstrip_blocks: True
-- Based on https://github.com/PowerDNS/pdns/wiki/Lua-Examples-(Authoritative)#updatepolicy-access-control-for-rfc2136-dynamic-updates
function updatepolicy(input)
local zones = {
{% for zone, prop in dyn_dns_zones.items() %}
["{{ zone }}."] = {
["key"] = "{{ prop.key }}.",
["allowed_networks"] = {
{% for ipv4 in prop.allowed_ipv4 %}
'{{ ipv4 }}{{ '' if '/' in ipv4 else '/32' }}',
{% endfor %}
{% for ipv6 in prop.allowed_ipv6 %}
'{{ ipv6 }}{{ '' if '/' in ipv6 else '/128' }}',
{% endfor %}
},
["valid_qtypes"] = {
{% for qtype in prop.valid_qtypes %}
[pdns.{{ qtype }}] = true,
{% endfor %}
},
["subdomains"] = "{{ prop.subdomains | default('no') }}",
},
{% endfor %}
}
local zone_name = input:getZoneName():toString()
local zone = zones[zone_name]
-- reject unknown zones
if not zone
then
pdnslog("updatepolicy: unknown zone " .. zone_name, pdns.loglevels.Info)
return false
end
local allowed_networks = newNMG(zone["allowed_networks"])
-- reject unauthorized networks
if not allowed_networks:match(input:getRemote())
then
pdnslog("updatepolicy: network check failed from " .. input:getRemote():toString(), pdns.loglevels.Info)
return false
end
input_qname = input:getQName():toString()
-- reject subdomain records when subdomains == "no"
if zone["subdomains"] == "no" and input_qname ~= zone_name
then
pdnslog("updatepolicy: subdomain records not allowed in zone " .. zone_name, pdns.loglevels.Info)
return false
end
-- reject apex records when subdomains == "only"
if zone["subdomains"] == "only" and input_qname == zone_name
then
pdnslog("updatepolicy: apex records not allowed in zone " .. zone_name, pdns.loglevels.Info)
return false
end
-- reject non-TSIG requests
if input:getTsigName():countLabels() == 0
then
pdnslog("updatepolicy: missing TSIG", pdns.loglevels.Info)
return false
end
input_tsig_name = input:getTsigName():toString()
-- reject unauthorized TSIG key names
if zone["key"] ~= input_tsig_name
then
pdnslog("updatepolicy: wrong TSIG " .. input_tsig_name .. " for zone " .. zone_name, pdns.loglevels.Info)
return false
end
-- reject disallowed record types
if not zone["valid_qtypes"][input:getQType()]
then
pdnslog("updatepolicy: disallowed record type " .. input:getQType(), pdns.loglevels.Info)
return false
end
pdnslog("updatepolicy: query checks successful", pdns.loglevels.Info)
return true
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment