Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor AXFR code #92

Open
wants to merge 15 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions bind_sync/lib/Atomia/DNS/Syncer.pm
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,28 @@ sub reload_updated_slavezones {

my $config_zones = $self->parse_slavezone_config();

my $zones = $self->soap->GetChangedSlaveZones($self->config->{"servername"} || die("you have to specify servername in config"));
my $zones;

die("error fetching updated slave zones, got no or bad result from soap-server") unless defined($zones) && $zones->result && ref($zones->result) eq "ARRAY";
$zones = $self->soap->GetChangedSlaveZones($self->config->{"servername"} || die("you have to specify servername in config"));
die("error fetching updated slave zones, got no or bad result from soap-server") unless defined($zones) &&

$zones->result && ref($zones->result) eq "ARRAY";
$zones = $zones->result;

my $tsigkeys_result;

if (!defined($self->config->{"disable_tsig_keys"}) || $self->config->{"disable_tsig_keys"} eq "0") {
$tsigkeys_result = $self->soap->GetSlavezonesTSIGKeys($self->config->{"servername"} || die("you have to specify servername in config"));
$tsigkeys_result = $tsigkeys_result->result;
}

my %tsigkeys;
foreach my $tsigkey (@$tsigkeys_result) {
my $zone_name = $tsigkey->{"zone_name"};
my $tsigkey_name = $tsigkey->{"tsigkey_name"};

$tsigkeys{$zone_name} = $tsigkey_name;
}

return if scalar(@$zones) == 0;

Expand All @@ -220,6 +238,15 @@ sub reload_updated_slavezones {
die("bad response from GetSlaveZone") unless scalar(@$zone) == 1;
$zone = $zone->[0];

if (!defined($self->config->{"disable_tsig_keys"}) || $self->config->{"disable_tsig_keys"} eq "0") {
if (exists $tsigkeys{$zonename}) {
# dereference zone hash, append tsigkeyname, then reference it again and put it back into $zone in order to have tsigkeyname available later
my %zone_hash = %$zone;
$zone_hash{tsigkeyname} = $tsigkeys{$zonename};
$zone = \%zone_hash;
}
}

push @$changes, $zonerec->{"id"};
};

Expand All @@ -236,6 +263,10 @@ sub reload_updated_slavezones {
if (defined($zone)) {
die("error fetching zone for $zonename") unless ref($zone) eq "HASH" && defined($zone->{"master"});
$config_zones->{$zonename} = $zone->{"master"};

if (!defined($self->config->{"disable_tsig_keys"}) || $self->config->{"disable_tsig_keys"} eq "0") {
$config_zones->{$zonename."-key"} = $zone->{"tsigkeyname"};
}
} else {
delete $config_zones->{$zonename};
}
Expand Down
64 changes: 61 additions & 3 deletions powerdns_sync/lib/Atomia/DNS/PowerDNSDatabase.pm
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,15 @@ sub add_zone {
$self->dbi->do($query) || die "error updating record disabled property, query=$query: $DBI::errstr";
}

if (!defined($self->config->{"disable_tsig_keys"}) || $self->config->{"disable_tsig_keys"} eq "0") {
if(defined($zone->{"tsigkeyname"}) && length($zone->{"tsigkeyname"}) > 0) {
$self->assign_tsig_key($domain_id, $zone->{"tsigkeyname"}, 'TSIG-ALLOW-AXFR');
}
else {
$self->unassign_tsig_key($domain_id);
}
}

$self->dbi->commit();
};

Expand Down Expand Up @@ -410,12 +419,25 @@ sub add_slave_zone {

$self->dbi->do($query) || die "error inserting domain row: $DBI::errstr";

my $domain_id;
if (defined($tsig) || (!defined($self->config->{"disable_tsig_keys"}) || $self->config->{"disable_tsig_keys"} eq "0")) {
$domain_id = $self->dbi(1)->last_insert_id(undef, undef, "domains", undef) || die "error retrieving last_insert_id";
}

if (defined($tsig)) {
my $domain_id = $self->dbi(1)->last_insert_id(undef, undef, "domains", undef) || die "error retrieving last_insert_id";
$query = "INSERT INTO outbound_tsig_keys (domain_id, secret, name) VALUES ($domain_id, $tsig, $tsig_name)";
$self->dbi->do($query) || die "error inserting tsig row using $query: $DBI::errstr";
}

if (!defined($self->config->{"disable_tsig_keys"}) || $self->config->{"disable_tsig_keys"} eq "0") {
if(defined($options->{"tsigkeyname"}) && length($options->{"tsigkeyname"}) > 0) {
$self->assign_tsig_key($domain_id, $options->{"tsigkeyname"}, 'AXFR-MASTER-TSIG');
}
else {
$self->unassign_tsig_key($domain_id);
}
}

$self->dbi->commit();
};

Expand Down Expand Up @@ -494,7 +516,7 @@ sub remove_tsig_key {
}
}

sub assign_tsig_key {
sub assign_tsig_key_deprecated {
my $self = shift;
my $domain_name = shift;
my $domainmetadata = shift;
Expand Down Expand Up @@ -530,7 +552,7 @@ sub assign_tsig_key {
}
}

sub unassign_tsig_key {
sub unassign_tsig_key_deprecated {
my $self = shift;
my $domain_name = shift;

Expand All @@ -553,4 +575,40 @@ sub unassign_tsig_key {
}
}

sub assign_tsig_key{
my $self = shift;
my $domain_id = shift;
my $tsigkey_name = shift;
my $tsigkey_kind = shift;

die "bad or missing domain_id during assign tsig key" unless defined($domain_id) && ref($domain_id) eq "";
die "bad or missing tsigkey_name during assign tsig key" unless defined($tsigkey_name) && ref($tsigkey_name) eq "";
die "bad or missing tsigkey_kind during assign tsig key" unless defined($tsigkey_kind) && ref($tsigkey_kind) eq "";

$domain_id = $self->dbi->quote($domain_id);
$tsigkey_name = $self->dbi->quote($tsigkey_name);
$tsigkey_kind = $self->dbi->quote($tsigkey_kind);

my $query;
my $domain_id_check = $self->dbi->selectrow_arrayref("SELECT id FROM domainmetadata WHERE domain_id = $domain_id AND kind = $tsigkey_kind");
if (defined($domain_id_check) && ref($domain_id_check) eq "ARRAY") {
# row already exists, update it
$query = "UPDATE domainmetadata SET content = $tsigkey_name WHERE domain_id = $domain_id AND kind = $tsigkey_kind";
}
else {
# row doesn't exist, add it
$query = "INSERT INTO domainmetadata (domain_id, kind, content) VALUES ($domain_id, $tsigkey_kind, $tsigkey_name)";
}

$self->dbi->do($query) || die "error inserting row: $DBI::errstr";
}

sub unassign_tsig_key {
my $self = shift;
my $domain_id = shift;

$domain_id = $self->dbi->quote($domain_id);
$self->dbi->do("DELETE FROM domainmetadata WHERE domain_id = $domain_id AND kind IN ('TSIG-ALLOW-AXFR', 'AXFR-MASTER-TSIG')") || die "error unassigning tsigkey: $DBI::errstr";
}

1;
58 changes: 54 additions & 4 deletions powerdns_sync/lib/Atomia/DNS/PowerDNSSyncer.pm
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,27 @@ sub sync_dnssec_keys {
sub reload_updated_zones {
my $self = shift;

my $zones = $self->soap->GetChangedZonesBatch($self->config->{"servername"} || die("you have to specify servername in config"), 10000);
my $zones;

$zones = $self->soap->GetChangedZonesBatch($self->config->{"servername"} || die("you have to specify servername in config"), 10000);
die("error fetching updated zones, got no or bad result from soap-server") unless defined($zones) &&
$zones->result && ref($zones->result) eq "ARRAY";

my $tsigkeys_result;

if (!defined($self->config->{"disable_tsig_keys"}) || $self->config->{"disable_tsig_keys"} eq "0") {
$tsigkeys_result = $self->soap->GetZonesTSIGKeys($self->config->{"servername"} || die("you have to specify servername in config"));
$tsigkeys_result = $tsigkeys_result->result;
}

my %tsigkeys;
foreach my $tsigkey (@$tsigkeys_result) {
my $zone_name = $tsigkey->{"zone_name"};
my $tsigkey_name = $tsigkey->{"tsigkey_name"};

$tsigkeys{$zone_name} = $tsigkey_name;
}

$zones = $zones->result;

my $changes_to_keep = [];
Expand Down Expand Up @@ -150,6 +168,12 @@ sub reload_updated_zones {
my $transaction = undef;
my $change_id = undef;

if (exists $tsigkeys{$zone->{"name"}}) {
my $tsigkey_name = $tsigkeys{$zone->{"name"}};

$zone->{"tsigkeyname"} = $tsigkey_name;
}

eval {
$change_id = $zone->{"id"} || die("bad data from GetUpdatedZones, id not specified");

Expand Down Expand Up @@ -315,11 +339,28 @@ sub full_reload_slavezones {
sub reload_updated_slavezones {
my $self = shift;

my $zones = $self->soap->GetChangedSlaveZones($self->config->{"servername"} || die("you have to specify servername in config"));
my $zones;

$zones = $self->soap->GetChangedSlaveZones($self->config->{"servername"} || die("you have to specify servername in config"));
die("error fetching updated slave zones, got no or bad result from soap-server") unless defined($zones) &&
$zones->result && ref($zones->result) eq "ARRAY";
$zones = $zones->result;

my $tsigkeys_result;

if (!defined($self->config->{"disable_tsig_keys"}) || $self->config->{"disable_tsig_keys"} eq "0") {
$tsigkeys_result = $self->soap->GetSlavezonesTSIGKeys($self->config->{"servername"} || die("you have to specify servername in config"));
$tsigkeys_result = $tsigkeys_result->result;
}

my %tsigkeys;
foreach my $tsigkey (@$tsigkeys_result) {
my $zone_name = $tsigkey->{"zone_name"};
my $tsigkey_name = $tsigkey->{"tsigkey_name"};

$tsigkeys{$zone_name} = $tsigkey_name;
}

return if scalar(@$zones) == 0;

my $changes = [];
Expand All @@ -337,6 +378,15 @@ sub reload_updated_slavezones {

die("error fetching zone for $zonename") unless !defined($zone) || (ref($zone) eq "HASH" && defined($zone->{"master"}));

if (!defined($self->config->{"disable_tsig_keys"}) || $self->config->{"disable_tsig_keys"} eq "0") {
# dereference zone hash, append tsigkeyname, then reference it again and put it back into $zone in order to have tsigkeyname available later
if (exists $tsigkeys{$zonename}) {
my %zone_hash = %$zone;
$zone_hash{tsigkeyname} = $tsigkeys{$zonename};
$zone = \%zone_hash;
}
}

$self->sync_slave_zone($zonename, $zone);
$self->soap->MarkSlaveZoneUpdated($zonerec->{"id"}, "OK", "");
};
Expand Down Expand Up @@ -578,9 +628,9 @@ sub sync_domainmetadata {
my $domainmetadata = shift;

if (defined($domainmetadata)) {
$self->database->assign_tsig_key($domain_name, $domainmetadata);
$self->database->assign_tsig_key_deprecated($domain_name, $domainmetadata);
} else {
$self->database->unassign_tsig_key($domain_name);
$self->database->unassign_tsig_key_deprecated($domain_name);
}
}

Expand Down
2 changes: 1 addition & 1 deletion server/conf/atomiadns.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
db_name = zonedata
db_hostname = localhost
db_username = atomiadns
db_password = %password
db_password = %password
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

[tsigkeyassignmentitem|tsigkeyassignmentitem Datatype - Atomia DNS API] is a struct with the following members:
|| Member || Type || Description ||
| zone_id | int | the id of the zone |
| zone_name | int | the name of the zone |
| tsigkey_name | string | the name of the TSIG key for this zone |
{excerpt:hidden=true}{excerpt}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[tsigkeyassignmentlist|tsigkeyassignmentlist Datatype - Atomia DNS API] is an array of [tsigkeyassignmentitem|tsigkeyassignmentitem Datatype - Atomia DNS API]-structs.
19 changes: 18 additions & 1 deletion server/debian/atomiadns-database.postinst
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ if [ $retval != 0 ]; then
echo "database zonedata already exist, but doesn't contain the atomiadns schema. You will have to make sure that the schema matches $basedir/schema manually"
exit 1
else
latest_version="94"
latest_version="95"

if [ "$schema_version" = "$latest_version" ]; then
echo "The installed schema is the latest version, keeping the database as it is."
Expand Down Expand Up @@ -670,6 +670,23 @@ if [ $retval != 0 ]; then
recreate_procedure "setzonestatus"
fi

if [ "$schema_version" -lt 95 ]; then
execute_query "ALTER TABLE domainmetadata ADD UNIQUE(domain_id, kind);"
execute_query "ALTER TABLE tsigkey DROP CONSTRAINT tsigkey_name_key;"
execute_query "ALTER TABLE tsigkey ADD UNIQUE(nameserver_group_id, name);"
execute_query "ALTER TABLE domainmetadata DROP CONSTRAINT kind_format;"
execute_query "ALTER TABLE domainmetadata ADD CONSTRAINT kind_format CHECK (kind IN ('master','slave','TSIG-ALLOW-AXFR','AXFR-MASTER-TSIG'));"
execute_query "DROP TRIGGER IF EXISTS domainmetadata_trigger ON domainmetadata;"
execute_query "DROP FUNCTION IF EXISTS domainmetadata_update();"
execute_query "DROP FUNCTION IF EXISTS assigntsigkey(varchar,varchar,varchar,varchar);"
recreate_procedure "assigntsigkey"
recreate_procedure "unassigntsigkey"
recreate_ddl_procedure "domainmetadata_change_update"
create_trigger "domainmetadata_change_trigger"
recreate_procedure "getzonestsigkeys"
recreate_procedure "getslavezonestsigkeys"
fi

set_schema_version "$latest_version"
else
echo "database zonedata already exist, but contains a bad schema version ($schema_version), this should never happen and indicates a bug."
Expand Down
2 changes: 2 additions & 0 deletions server/docbook_api_documentation/typeincludes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="types/ds_set.xml" />
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="types/external_keyset.xml" />
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="types/zskinfo.xml" />
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="types/tsigkeyassignmentitem.xml" />
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="types/tsigkeyassignmentlist.xml" />
</section>
2 changes: 2 additions & 0 deletions server/docbook_api_documentation/typeindex.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@
<listitem><para><link linkend="datatype-ds_set">ds_set Datatype - Atomia DNS API</link></para></listitem>
<listitem><para><link linkend="datatype-external_keyset">external_keyset Datatype - Atomia DNS API</link></para></listitem>
<listitem><para><link linkend="datatype-zskinfo">zskinfo Datatype - Atomia DNS API</link></para></listitem>
<listitem><para><link linkend="datatype-tsigkeyassignmentitem">tsigkeyassignmentitem Datatype - Atomia DNS API</link></para></listitem>
<listitem><para><link linkend="datatype-tsigkeyassignmentlist">tsigkeyassignmentlist Datatype - Atomia DNS API</link></para></listitem>
</itemizedlist>
12 changes: 12 additions & 0 deletions server/docbook_api_documentation/types/changedzonewithtsig.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<section xml:id="datatype-tsigkeyassignmentitem">
<title>tsigkeyassignmentitem Datatype - Atomia DNS API</title>
<para>
<link linkend="datatype-tsigkeyassignmentitem">tsigkeyassignmentitem</link> is a struct with the following members:
<informaltable><colgroup /><thead><tr><td><para>Parameter</para></td><td><para>Type</para></td><td><para>Description</para></td></tr></thead><tbody>
<tr><td>id</td><td>int</td><td>the id of the change-row</td></tr>
<tr><td>name</td><td>string</td><td>the name of the zone this change-row applies to</td></tr>
<tr><td>changetime</td><td>int</td><td>he unix timestamp of this change (will be used as serial in SOA)</td></tr>
<tr><td>tsigkeyname</td><td>string</td><td>the name of the TSIG key for this zone</td></tr>
</tbody></informaltable>

</para></section>
3 changes: 3 additions & 0 deletions server/docbook_api_documentation/types/changeswithtsig.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<section xml:id="datatype-tsigkeyassignmentlist">
<title>tsigkeyassignmentlist Datatype - Atomia DNS API</title>
<para><link linkend="datatype-tsigkeyassignmentlist">tsigkeyassignmentlist</link> is an array of <link linkend="datatype-tsigkeyassignmentitem">tsigkeyassignmentitem</link>-structs.</para></section>
4 changes: 3 additions & 1 deletion server/generate_wsdl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ methodawk='BEGIN {
methods["GetChangedDomainIDs"] = "Gets domains with newly assigned TSIG keys.";
methods["GetDomainMetaData"] = "Gets data for assigning a TSIG key.";
methods["MarkDomainMetaDataUpdated"] = "Marks a domain meta data as updated after asigning a TSIG key.";
methods["UnassignTSIGKey"] = "Unassigns a TSIG key to a domain.";
methods["UnassignTSIGKey"] = "Unassigns a TSIG key from a domain.";
methods["GetZonesTSIGKeys"] = "Fetches a list of all changed zones for a nameserver, but limit response to a number of changes and include a TSIG key name for the selected zone.";
methods["GetSlavezonesTSIGKeys"] = "Fetches a list of all changed slave-zones for a nameserver and includes a TSIG key name for the selected slave-zone.";
methods["GetZoneStatusBulk"] = "Gets zones status.";
methods["SetZoneStatus"] = "Sets zone status.";
methods["Noop"] = "Do nothing. Meant for generating token without doing anything when authenticating.";
Expand Down
20 changes: 20 additions & 0 deletions server/lib/Atomia/DNS/ServerHandler.pm
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,24 @@ sub handleChanges {
return SOAP::Data->new(name => "changes", value => \@rowarray);
}

sub handleTSIGKeyAssignmentList {
my $self = shift;
my $method = shift;
my $signature = shift;

my $rows;

my $sth = $self->handleAll($method, $signature, 0, undef, @_);
$rows = $sth->fetchall_arrayref({});
die("error polling database for changes: $DBI::errstr") unless defined($rows) && ref($rows) eq "ARRAY" && !$DBI::err;

my @rowarray = map {
SOAP::Data->new(name => "tsigkeyassignmentitem", value => $_)
} @$rows;

return SOAP::Data->new(name => "tsigkeyassignmentlist", value => \@rowarray);
}

sub handleAllowedTransfer {
my $self = shift;
my $method = shift;
Expand Down Expand Up @@ -1245,6 +1263,8 @@ sub handleOperation {
$retval = $self->handleSlaveZone($method, $signature, @_);
} elsif ($return_type eq "changes") {
$retval = $self->handleChanges($method, $signature, @_);
} elsif ($return_type eq "tsigkeyassignmentlist") {
$retval = $self->handleTSIGKeyAssignmentList($method, $signature, @_);
} elsif ($return_type eq "zonestruct") {
$retval = $self->handleZoneStruct($method, $signature, @_);
} elsif ($return_type eq "int") {
Expand Down
2 changes: 2 additions & 0 deletions server/lib/Atomia/DNS/Signatures.pm
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ our $signatures = {
"GetDomainMetaData" => "domainmetadata string",
"MarkDomainMetaDataUpdated" => "void bigint string string",
"UnassignTSIGKey" => "void string",
"GetZonesTSIGKeys" => "tsigkeyassignmentlist string",
"GetSlavezonesTSIGKeys" => "tsigkeyassignmentlist string",
"TestOp" => "void string string string string",
"Noop" => "string",
"SetZoneStatus" => "void string string",
Expand Down
Loading