From 708b93bdea4b623a6b1fe3d2ca7e472fd60c4cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?A=2E=20T=C3=A4ffner?= Date: Sat, 23 Jan 2016 01:14:04 +0100 Subject: [PATCH] PHP-Variants are working. Need to create a cronjob then basic implementation is ready. Next step is to implement some DNSSEC-Requiring Record Types uon request of some others (will be within this branch before removing the WIP state) --- install/lib/installer_base.lib.php | 7 -- install/tpl/dnssec-autocreate.sh.master | 15 ---- install/tpl/dnssec-autopickup.sh.master | 49 ----------- install/tpl/dnssec-autoupdate.sh.master | 22 ----- install/tpl/dnssec-config.sh.master | 19 ----- install/tpl/dnssec-create.sh.master | 82 ------------------ install/tpl/dnssec-delete.sh.master | 26 ------ install/tpl/dnssec-update.sh.master | 41 --------- server/plugins-available/bind_plugin.inc.php | 89 +++++++++++++++----- 9 files changed, 68 insertions(+), 282 deletions(-) delete mode 100644 install/tpl/dnssec-autocreate.sh.master delete mode 100644 install/tpl/dnssec-autopickup.sh.master delete mode 100644 install/tpl/dnssec-autoupdate.sh.master delete mode 100644 install/tpl/dnssec-config.sh.master delete mode 100644 install/tpl/dnssec-create.sh.master delete mode 100644 install/tpl/dnssec-delete.sh.master delete mode 100644 install/tpl/dnssec-update.sh.master diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php index 013001d8b9..c3c59fcd6c 100644 --- a/install/lib/installer_base.lib.php +++ b/install/lib/installer_base.lib.php @@ -1510,13 +1510,6 @@ class installer_base { chmod($content, 2770); //* Install scripts for dnssec implementation - $this->process_bind_file('dnssec-update.sh', '/server/scripts/'); - $this->process_bind_file('dnssec-create.sh', '/server/scripts/'); - $this->process_bind_file('dnssec-delete.sh', '/server/scripts/'); - $this->process_bind_file('dnssec-autoupdate.sh', '/server/scripts/'); - $this->process_bind_file('dnssec-autopickup.sh', '/server/scripts/'); - $this->process_bind_file('dnssec-autocreate.sh', '/server/scripts/'); - $this->process_bind_file('dnssec-config.sh', '/server/scripts/'); $this->process_bind_file('named.conf.options', '/etc/bind/', true); //TODO replace hardcoded path } diff --git a/install/tpl/dnssec-autocreate.sh.master b/install/tpl/dnssec-autocreate.sh.master deleted file mode 100644 index 75c56f1ab0..0000000000 --- a/install/tpl/dnssec-autocreate.sh.master +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -source {dnssec_conffile} - -mysqlcheck=`mysql -u $dbuser --password=$dbpass -h $dbhost -Bse "use $dbase; show tables;" | wc -c` -if [ "$mysqlcheck" = 0 ];then - echo "could not connect to database" - exit 0 -fi - -mysqlcheck=`mysql -u $dbuser --password=$dbpass -h $dbhost -Bse "use $dbase; select origin from dns_soa where active='Y' and dnssec_initialized='N';" | awk {' print $1 '}` -for ACTIVE in $mysqlcheck; do - /usr/local/ispconfig/server/scripts/dnssec/dnssec-create.sh ${ACTIVE::-1} -done - -cd $curpath diff --git a/install/tpl/dnssec-autopickup.sh.master b/install/tpl/dnssec-autopickup.sh.master deleted file mode 100644 index a578c77055..0000000000 --- a/install/tpl/dnssec-autopickup.sh.master +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash -source {dnssec_conffile} - -mysqlcheck=`mysql -u $dbuser --password=$dbpass -h $dbhost -Bse "use $dbase; show tables;" | wc -c` -if [ "$mysqlcheck" = 0 ];then - echo "could not connect to database" - exit 0 -fi - -mysqlcheck=`mysql -u $dbuser --password=$dbpass -h $dbhost -Bse "use $dbase; select origin from dns_soa where active='Y' and dnssec_initialized='Y';"` -for origindomain in $mysqlcheck; do - domain=${origindomain::-1} - dnssechelp=`head -1 $bindpath/dsset-$domain.` - dnssecid=`echo $dnssechelp | awk {' print $4 '}` - dnssecalg=`echo $dnssechelp | awk {' print $5 '}` - dnssecdt=`echo $dnssechelp | awk {' print $6 '}` - dnssecd=`echo $dnssechelp | awk {' print $7 '}` - echo "DS Record 1:">/tmp/.dnssec-autopick - echo "Key Tag/ID: $dnssecid">>/tmp/.dnssec-autopick - echo "Algorithm: $dnssecalg">>/tmp/.dnssec-autopick - echo "Digest/HASH Type: $dnssecdt">>/tmp/.dnssec-autopick - echo "Digest/HASH: $dnssecd">>/tmp/.dnssec-autopick - - dns2sechelp=`tail -n 1 $bindpath/dsset-$domain.` - dns2secid=`echo $dns2sechelp | awk {' print $4 '}` - dns2secalg=`echo $dns2sechelp | awk {' print $5 '}` - dns2secdt=`echo $dns2sechelp | awk {' print $6 '}` - dns2secd=`echo $dns2sechelp | awk {' print $7""$8 '}` - echo "">>/tmp/.dnssec-autopick - echo "DS Record 2:">>/tmp/.dnssec-autopick - echo "Key Tag/ID: $dns2secid">>/tmp/.dnssec-autopick - echo "Algorithm: $dns2secalg">>/tmp/.dnssec-autopick - echo "Digest/HASH Type: $dns2secdt">>/tmp/.dnssec-autopick - echo "Digest/HASH: $dns2secd">>/tmp/.dnssec-autopick - - echo "">>/tmp/.dnssec-autopick - echo "In DS-Record format:">>/tmp/.dnssec-autopick - cat $bindpath/dsset-$domain.>>/tmp/.dnssec-autopick - - echo "">>/tmp/.dnssec-autopick - echo "DNSKEY-Records:">>/tmp/.dnssec-autopick - cat $bindpath/K$domain.+*.key>>/tmp/.dnssec-autopick - - mysql -u $dbuser --password=$dbpass -h $dbhost -Bse "use $dbase; UPDATE dns_soa SET dnssec_info='`cat /tmp/.dnssec-autopick`', dnssec_initialized='Y' WHERE origin='$domain.'" - rm /tmp/.dnssec-autopick -done - -echo "I'm done!" -exit 0 \ No newline at end of file diff --git a/install/tpl/dnssec-autoupdate.sh.master b/install/tpl/dnssec-autoupdate.sh.master deleted file mode 100644 index 526582513b..0000000000 --- a/install/tpl/dnssec-autoupdate.sh.master +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -source {dnssec_conffile} - -if [ ! -d $backuppath ]; then mkdir -p $backuppath; fi -#connect to database -mysqlcheck=`mysql -u $dbuser --password=$dbpass -h $dbhost -Bse "use $dbase; show tables;" | wc -c` -if [ "$mysqlcheck" = 0 ];then - echo "could not connect to database" - exit 0 -fi - - -mysqlcheck=`mysql -u $dbuser --password=$dbpass -h $dbhost -Bse "use $dbase; select origin from dns_soa where active='Y' and dnssec_initialized='Y';" | awk {' print $1 '}` -for ACTIVE in $mysqlcheck; do - /usr/local/ispconfig/server/scripts/dnssec/dnssec-update.sh ${ACTIVE::-1} -done - -done - -echo "I'm done - You might want to reload bind now" - -exit diff --git a/install/tpl/dnssec-config.sh.master b/install/tpl/dnssec-config.sh.master deleted file mode 100644 index cdb5c29593..0000000000 --- a/install/tpl/dnssec-config.sh.master +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -#mysql -dbase={mysql_server_ispconfig_database} -dbhost={mysql_server_ip} -dbuser={mysql_server_ispconfig_user} -dbpass={mysql_server_ispconfig_password} - -bindpath=/etc/bind -backuppath=$bindpath/backup -curpath=`pwd` -if [ -f /etc/gentoo-release ] ; then -filespre="pri/" -else -filespre="pri." -fi -timenow=`/bin/date +"%Y%m%d-%H%M%S"` - -namedconf="$bindpath/named.conf.local" -md5namedconf="$bindpath/named.conf.local.md5" diff --git a/install/tpl/dnssec-create.sh.master b/install/tpl/dnssec-create.sh.master deleted file mode 100644 index 521c62042a..0000000000 --- a/install/tpl/dnssec-create.sh.master +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/bash -source {dnssec_conffile} -domain="${1::-1}" - -mysqlcheck=`mysql -u $dbuser --password=$dbpass -h $dbhost -Bse "use $dbase; show tables;" | wc -c` -if [ "$mysqlcheck" = 0 ];then - echo "$0 could not connect to database" - exit 0 -fi - -if [ `cat /proc/sys/kernel/random/entropy_avail` -lt 400 ] ; then - echo "ERROR: DNSSEC is not working as available entropy is below 400. Please consider installing package haveged. Skipping generation of keys as well as signing..." - cp $filespre$domain $filespre$domain.signed - mysql -u $dbuser --password=$dbpass -h $dbhost -Bse "use $dbase; UPDATE dns_soa SET dnssec_info='Error during generation of keys. Please contact our support. Reason: Too less entropy available.', dnssec_initialized='N' WHERE origin='$domain.'" - exit 20 -fi - -mysqlcheck=`mysql -u $dbuser --password=$dbpass -h $dbhost -Bse "use $dbase; select * from dns_soa where dnssec_initialized='Y' and origin='$domain.';" | wc -c` -if [ "$mysqlcheck" -gt 1 ];then - echo "DNSSEC: $domain seems to be initialized. If that is wrong correct dnssec_initialized in dns_soa table" - exit 0 -fi -cd $bindpath - -if [ ! $domain = "" ];then - if [ ! -f $filespre$domain ]; then - echo "$domain zone file ($filespre$domain) does not exist" - exit 0 - else - if [ -f dsset-$domain. ];then - echo "dnssec keys for $domain already exists!" - exit 0 - else - echo "Creating keys for $domain" - dnssec-keygen -a NSEC3RSASHA1 -b 2048 -n ZONE $domain - dnssec-keygen -f KSK -a NSEC3RSASHA1 -b 4096 -n ZONE $domain - for key in `ls K$domain*.key`; do - echo "\$INCLUDE $bindpath/$key">> $filespre$domain - done - dnssec-signzone -A -3 $(head -c 1000 /dev/random | sha1sum | cut -b 1-16) -N INCREMENT -o $domain -t $filespre$domain - fi -fi -serial=`cat $bindpath/$filespre$domain |grep "serial," |awk {' print $domain '}` -echo "" -dnssechelp=`head -1 $bindpath/dsset-$domain.` -dnssecid=`echo $dnssechelp | awk {' print $4 '}` -dnssecalg=`echo $dnssechelp | awk {' print $5 '}` -dnssecdt=`echo $dnssechelp | awk {' print $6 '}` -dnssecd=`echo $dnssechelp | awk {' print $7 '}` -echo "DS Record 1:">/tmp/.dnssec-$domain -echo "Key Tag/ID: $dnssecid">>/tmp/.dnssec-$domain -echo "Algorithm: $dnssecalg">>/tmp/.dnssec-$domain -echo "Digest/HASH Type: $dnssecdt">>/tmp/.dnssec-$domain -echo "Digest/HASH: $dnssecd">>/tmp/.dnssec-$domain - -dns2sechelp=`tail -n 1 $bindpath/dsset-$domain.` -dns2secid=`echo $dns2sechelp | awk {' print $4 '}` -dns2secalg=`echo $dns2sechelp | awk {' print $5 '}` -dns2secdt=`echo $dns2sechelp | awk {' print $6 '}` -dns2secd=`echo $dns2sechelp | awk {' print $7""$8 '}` -echo "">>/tmp/.dnssec-$domain -echo "DS Record 2:">>/tmp/.dnssec-$domain -echo "Key Tag/ID: $dns2secid">>/tmp/.dnssec-$domain -echo "Algorithm: $dns2secalg">>/tmp/.dnssec-$domain -echo "Digest/HASH Type: $dns2secdt">>/tmp/.dnssec-$domain -echo "Digest/HASH: $dns2secd">>/tmp/.dnssec-$domain - -echo "">>/tmp/.dnssec-$domain -echo "In DS-Record format:">>/tmp/.dnssec-$domain -cat $bindpath/dsset-$domain.>>/tmp/.dnssec-$domain - -echo "">>/tmp/.dnssec-$domain -echo "DNSKEY-Records:">>/tmp/.dnssec-$domain -cat $bindpath/K$domain.+*.key>>/tmp/.dnssec-$domain - -mysql -u $dbuser --password=$dbpass -h $dbhost -Bse "use $dbase; UPDATE dns_soa SET dnssec_info='`cat /tmp/.dnssec-$domain`', dnssec_initialized='Y' WHERE origin='$domain.'" -rm /tmp/.dnssec-$domain - -else - echo "usage: dnssec-create.sh " -fi -cd $curpath diff --git a/install/tpl/dnssec-delete.sh.master b/install/tpl/dnssec-delete.sh.master deleted file mode 100644 index 03d54b17c5..0000000000 --- a/install/tpl/dnssec-delete.sh.master +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -source {dnssec_conffile} -pardomain="${1::-1}" - -echo "$1 $2 $3 $4 domain: $domain" > /tmp/.last-call-to-dnssec-update - -if [ -z "$1" ];then - echo "No domain given" - exit 1 -fi - -#connect to database -mysqlcheck=`mysql -u $dbuser --password=$dbpass -h $dbhost -Bse "use $dbase; show tables;" | wc -c` -if [ "$mysqlcheck" = 0 ];then - echo "could not connect to database" - exit 0 -fi - -rm $bindpath/K$pardomain.+*.key -rm $bindpath/K$pardomain.+*.private -rm "$bindpath/$filespre$pardomain.signed" -rm "$bindpath/dsset-$pardomain." - -echo "DNSSEC Keys and zonefile for $pardomain deleted" - -exit 0 diff --git a/install/tpl/dnssec-update.sh.master b/install/tpl/dnssec-update.sh.master deleted file mode 100644 index 1aeff9058a..0000000000 --- a/install/tpl/dnssec-update.sh.master +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -source {dnssec_conffile} -pardomain="${1::-1}" -cd $bindpath - -if [ ! -d $backuppath ]; then mkdir -p $backuppath; fi -#connect to database for testing -mysqlcheck=`mysql -u $dbuser --password=$dbpass -h $dbhost -Bse "use $dbase; show tables;" | wc -c` -if [ "$mysqlcheck" = 0 ];then - echo "$0 could not connect to database" - cd $curpath - exit 0 -fi - -if [ ! -f .dsset-$pardomain ] ; then - {ispconfig_install_dir}/server/scripts/dnssec-create.sh $pardomain. -fi - -mysqlcheck=`mysql -u $dbuser --password=$dbpass -h $dbhost -Bse "use $dbase; select id,serial from dns_soa where active='Y' and origin='$pardomain.';" | awk {' print $1":"$2 '}` - echo $mysqlcheck - zoneid=`echo $mysqlcheck | sed 's/:/ /g' | awk {' print $1 '}` - domain=$pardomain - serial=`echo $mysqlcheck | sed 's/:/ /g' | awk {' print $2 '}` - fserial=`/usr/sbin/named-checkzone $domain $bindpath/$filespre$domain | egrep -ho '[0-9]{10}'` - includecheck=`cat $bindpath/$filespre$domain |grep "INCLUDE" |wc -l` - if [ ! $includecheck = 2 ] ;then - echo "">> $bindpath/pri.$domain - for key in `ls $bindpath/K$pardomain.+*.key`; do - echo "Including $key..." - echo "\$INCLUDE $key">> $bindpath/pri.$domain - done - else - echo "Includes are there. Why ever..." - fi - - /usr/sbin/dnssec-signzone -A -3 $(head -c 1000 /dev/random | sha1sum | cut -b 1-16) -N increment -o $domain -t $filespre$domain - mysql -u $dbuser --password=$dbpass -h $dbhost -Bse "use $dbase; update dns_soa set serial='$fserial', dnssec_info='`cat /tmp/.dnssec-$domain`' where origin='$domain.'; update dns_rr set serial='$fserial' WHERE zone=$zoneid" - -echo "DNSSEC for $pardomain has been configured" -cd $curpath -exit 0 diff --git a/server/plugins-available/bind_plugin.inc.php b/server/plugins-available/bind_plugin.inc.php index 64fb1de637..e647928005 100644 --- a/server/plugins-available/bind_plugin.inc.php +++ b/server/plugins-available/bind_plugin.inc.php @@ -77,7 +77,7 @@ class bind_plugin { } //* This creates DNSSEC-Keys and calls soa_dnssec_update. - function soa_dnssec_create($data) { + function soa_dnssec_create(&$data) { global $app, $conf; //* Load libraries @@ -99,9 +99,17 @@ class bind_plugin { } //* Verify that we do not already have keys (overwriting-protection) - //TODO : change this when distribution information has been integrated into server record if (file_exists($dns_config['bind_zonefiles_dir'].'/dsset-'.$domain.'.')) { return $this->soa_dnssec_update($data); + } else if ($data['new']['dnssec_initialized'] == 'Y') { //In case that we generated keys but the dsset-file was not generated + $keycount=0; + foreach (glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'*.key') as $keyfile) { + $keycount++; + } + if ($keycount > 0) { + $this->soa_dnssec_sign($data); + return true; + } } //Do some magic... @@ -109,19 +117,50 @@ class bind_plugin { '/usr/sbin/dnssec-keygen -a NSEC3RSASHA1 -b 2048 -n ZONE '.escapeshellcmd($domain).';'. '/usr/sbin/dnssec-keygen -f KSK -a NSEC3RSASHA1 -b 4096 -n ZONE '.escapeshellcmd($domain)); - $this->soa_dnssec_update($data, true); //Now sign the zone + $this->soa_dnssec_sign($data); //Now sign the zone for the first time + $data['new']['dnssec_initialized']='Y'; + } + + function soa_dnssec_sign(&$data) { + global $app, $conf; + + //* Load libraries + $app->uses("getconf,tpl"); + + //* load the server configuration options + $dns_config = $app->getconf->get_server_config($conf["server_id"], 'dns'); + //TODO : change this when distribution information has been integrated into server record + $filespre = (file_exists('/etc/gentoo-release')) ? 'pri/' : 'pri.'; + + $domain = substr($data['new']['origin'], 0, strlen($data['new']['origin'])-1); + if (!file_exists($dns_config['bind_zonefiles_dir'].'/'.$filespre.$domain)) return false; + + $zonefile = file_get_contents($dns_config['bind_zonefiles_dir'].'/'.$filespre.$domain); + $keycount=0; + foreach (glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'*.key') as $keyfile) { + $includeline = '$INCLUDE '.basename($keyfile); + if (!preg_match('@'.preg_quote($includeline).'@', $zonefile)) $zonefile .= "\n".$includeline."\n"; + $keycount++; + } + if ($keycount != 2) $app->log('DNSSEC Warning: There are more or less than 2 keyfiles for zone '.$domain, LOGLEVEL_WARN); + file_put_contents($dns_config['bind_zonefiles_dir'].'/'.$filespre.$domain, $zonefile); + + //Sign the zone and set it valid for max. 16 days + exec('cd '.escapeshellcmd($dns_config['bind_zonefiles_dir']).';'. + '/usr/sbin/dnssec-signzone -A -e +1382400 -3 $(head -c 1000 /dev/random | sha1sum | cut -b 1-16) -N increment -o '.escapeshellcmd($domain).' -t '.$filespre.escapeshellcmd($domain)); + + //Write Data back ino DB $dnssecdata = "DS-Records:\n".file_get_contents($dns_config['bind_zonefiles_dir'].'/dsset-'.$domain.'.'); - opendir($dns_config['bind_zonefiles_dir']); $dnssecdata .= "\n------------------------------------\n\nDNSKEY-Records:\n"; - foreach (glob('K'.$domain.'*.key') as $keyfile) { + foreach (glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'*.key') as $keyfile) { $dnssecdata .= file_get_contents($keyfile)."\n\n"; } $app->db->query('UPDATE dns_soa SET dnssec_info=\''.$dnssecdata.'\', dnssec_initialized=\'Y\' WHERE id='.$data['new']['id']); } - function soa_dnssec_update($data, $new=false) { + function soa_dnssec_update(&$data, $new=false) { global $app, $conf; //* Load libraries @@ -142,7 +181,7 @@ class bind_plugin { return false; } - if (!$new && !file_exists($dns_config['bind_zonefiles_dir'].'/dsset-'.$domain.'.')) return $this->soa_dnssec_create($data); + if (!$new && !file_exists($dns_config['bind_zonefiles_dir'].'/dsset-'.$domain.'.')) $this->soa_dnssec_create($data); $dbdata = $app->db->queryOneRecord('SELECT id,serial FROM dns_soa WHERE id='.$data['new']['id']); exec('cd '.escapeshellcmd($dns_config['bind_zonefiles_dir']).';'. @@ -152,20 +191,28 @@ class bind_plugin { return false; } - opendir($dns_config['bind_zonefiles_dir']); - $zonefile = file_get_contents(escapeshellcmd($dns_config['bind_zonefiles_dir']).'/'.$filespre.escapeshellcmd($domain)); - $keycount=0; - foreach (glob('K'.$domain.'*.key') as $keyfile) { - $includeline = '$INCLUDE '.$keyfile; - if (!preg_match('/'.$line.'/', $zonefile)) $zonefile .= "\n".$includeline."\n"; - $keycount++; - } - if ($keycount > 2) $app->log('DNSSEC Warning: There are more than 2 keyfiles for zone '.$domain, LOGLEVEL_WARN); - file_put_contents($dns_config['bind_zonefiles_dir'].'/'.$filespre.$domain, $zonefile); + $this->soa_dnssec_sign($data); + } + + function soa_dnssec_delete(&$data) { + global $app, $conf; + + //* Load libraries + $app->uses("getconf,tpl"); + + //* load the server configuration options + $dns_config = $app->getconf->get_server_config($conf["server_id"], 'dns'); - //Sign the zone and set it valid for max. 16 days - exec('cd '.escapeshellcmd($dns_config['bind_zonefiles_dir']).';'. - '/usr/sbin/dnssec-signzone -A -e +1382400 -3 $(head -c 1000 /dev/random | sha1sum | cut -b 1-16) -N increment -o '.escapeshellcmd($domain).' -t '.$filespre.escapeshellcmd($domain)); + //TODO : change this when distribution information has been integrated into server record + $filespre = (file_exists('/etc/gentoo-release')) ? 'pri/' : 'pri.'; + + $domain = substr($data['new']['origin'], 0, strlen($data['new']['origin'])-1); + + unlink($dns_config['bind_zonefiles_dir'].'/K'.$domain.'.+*'); + unlink($dns_config['bind_zonefiles_dir'].'/'.$filespre.$domain.'.signed'); + unlink($dns_config['bind_zonefiles_dir'].'/dsset-'.$domain.'.'); + + $app->db->query('UPDATE dns_soa SET dnssec_info=\'\', dnssec_initialized=\'N\' WHERE id='.$data['new']['id']); } function soa_insert($event_name, $data) { @@ -239,7 +286,7 @@ class bind_plugin { //* DNSSEC-Implementation if($data['old']['origin'] != $data['new']['origin']) { - if (@$data['old']['dnssec_initialized'] == 'Y' && strlen(@$data['old']['origin']) > 3) exec('/usr/local/ispconfig/server/scripts/dnssec-delete.sh '.escapeshellcmd($data['old']['origin'])); //delete old keys + if (@$data['old']['dnssec_initialized'] == 'Y' && strlen(@$data['old']['origin']) > 3) $this->soa_dnssec_delete($data); //delete old keys if ($data['new']['dnssec_wanted'] == 'Y') $this->soa_dnssec_create($data); } else if ($data['new']['dnssec_wanted'] == 'Y' && $data['old']['dnssec_initialized'] == 'N') $this->soa_dnssec_create($data); -- GitLab