1#!/usr/local/bin/perl 2# Called by the let's encrypt client to remove a DNS record for validation 3 4$no_acl_check++; 5$ENV{'WEBMIN_CONFIG'} ||= "/etc/webmin"; 6$ENV{'WEBMIN_VAR'} ||= "/var/webmin"; 7if ($0 =~ /^(.*)\/[^\/]+$/) { 8 chdir($pwd = $1); 9 } 10else { 11 chop($pwd = `pwd`); 12 } 13$0 = "$pwd/letsencrypt-cleanup.pl"; 14require './webmin-lib.pl'; 15&foreign_require("bind8"); 16 17# Validate params 18my $dname = $ENV{'CERTBOT_DOMAIN'}; 19$dname || die "Missing CERTBOT_DOMAIN environment variable"; 20 21# Find the DNS domain and records 22my $d = &get_virtualmin_for_domain($dname); 23my ($zone, $zname) = &get_bind_zone_for_domain($dname); 24my ($recs, $file); 25if ($zone) { 26 # Use BIND module API calls 27 $zone->{'file'} || die "Zone $dname does not have a records file"; 28 &lock_file(&bind8::make_chroot(&bind8::absolute_path($zone->{'file'}))); 29 $recs = [ &bind8::read_zone_file($zone->{'file'}, $zname) ]; 30 $file = $zone->{'file'}; 31 } 32elsif ($d) { 33 # Use Virtualmin API calls 34 &virtual_server::obtain_lock_dns($d); 35 ($recs, $file) = &virtual_server::get_domain_dns_records_and_file($d); 36 } 37else { 38 die "No DNS zone named $dname found"; 39 } 40 41# Find and remove the record. Does nothing if it doesn't exist so as not to 42# fail a repeated cleanup. 43my ($r) = grep { $_->{'name'} eq "_acme-challenge.".$dname."." } @$recs; 44if ($r) { 45 &bind8::delete_record($file, $r); 46 } 47 48if ($zone) { 49 # Apply using BIND API calls 50 &bind8::sign_dnssec_zone_if_key($zone, $recs); 51 &bind8::bump_soa_record($file, $recs); 52 &unlock_file(&bind8::make_chroot(&bind8::absolute_path($file))); 53 &bind8::restart_zone($zone->{'name'}, $zone->{'view'}); 54 } 55else { 56 # Apply using Virtualmin API 57 &virtual_server::post_records_change($d, $recs, $file); 58 &virtual_server::release_lock_dns($d); 59 &virtual_server::reload_bind_records($d); 60 } 61 62&webmin_log("letsencryptcleanup", undef, $dname); 63