Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time



This module implements the logic for applying a Domain Connect template to a zone.

Given a zone’s contents, a domain/host (sub-domain), a template (identified by a providerId/serviceId), variable values, and additional parameters; the library will calculate changes to the zone.

Authorization of the user, verification that the user owns the domain, and the UX to gain consent from the user are left to the DNS Provider. But all the logic for handling the application of the template, including conflict detection, parameter processing, signature verification and more are handled in this library.

The library works by taking as canonical input the current content of the zone file corresponding to the domain name being processed. And it returns the modified zone file in the same canonical format. It is up to the implementation to translate to and from this canonical format.

Some DNS Providers only apply templates to a zone at run-time. After the zone is applied the records in the zone have no indication they were applied by a template. Other DNS Providers remember the records that were applied by a template, providing advanced features in their UX.

This library can deal with both types of DNS Providers. If a DNS Provider wishes to remember template state in its zone, it simply needs to read/write this additional state with the records.


This is a Python module and corresponding class that can handle applying a template to a zone of records.

The object is initialized with a providerId, serviceId, and templateDir.

import domainconnectzone
dc = domainconnectzone.DomainConnect(<provider_id>, <service_id>, <template_dir>)

The provider id and service id map to the template name. Templates can be found in the github project at Individual template files are named <service_id>.<provider_id>.json.

The location of the templates are a parameter to the object.

If the template cannot be found, an InvalidTemplate exception is thrown.

There are several other methods on this class/object.


The first (and more common) method is to apply changes to a zone based on the template.

Input takes a list of records that exist in the zone, the domain, the host, and additional parameters for the template as a dictionary of key/value pairs. It optionally takes a query string, sig, and key to verify the signature. And an optional flag indicating if the DNS Provider is multi-template-aware.


Parameter Type Description

Zone Records


This is the list of records representing the zone. It is described below.



This is the domain name. It matches the domain of the zone, and the domain the template will be applied to.



This is the host or sub-domain. It can be None.

Group Ids


(optional) This is a list of groups to apply. If None or empty, the entire template will be applied.

Query String (qs)


(optional) This is the query string used for signature verification. It should match the entire query string, properly URL Encoded, without the sig or key values. This defaults to None.

Signature (sig)


(optional) This is the signature. This defaults to None.

Key (key)


(optional) This is the key into DNS on syncPubKeyDomain to read the public key for signature verification. This defaults to None.

*Ignore Signature (ignore_signature) *


(optional) This tells the system to ignore any signature verification. Extreme care should be taken with this parameter, as it is largely intended for internal tooling and testing. This defaults to False.

*Multi Template Aware (multi_aware) *


(optional) This tells the system that the DNS Provider wishes to engage the multi-template processing. It defaults to False.


import domainconnectzone
dc = domainconnectzone.DomainConnect("", "template1")

zone_records = [...] # List of records in the zone
domain = ''
host = None
params = {'IP': '', 'RANDOMTEXT': 'shm:1553436765:Hello'}

dc.apply_template(zone_records, domain, host, params)

Upon success this method returns a tuple containing three lists of zone records.

The first is the list new records being added.

Second is the list of records to be deleted.

The third is the list of final (complete) records that should be written to the zone.

Calling this function can throw any of a number of exceptions.


Exception Description


This is raised when the template requires a host, but no host (subdomain) is provided


This is raised when the template requires a signature and verification fails.


This is raised when the template requires a parameter that wasn’t passed in.


This is raised when invalid data is passed into the template. Usually this is a parameter that results in malformed DNS data.


This attribute returns the template in json form.


This attribute returns True if the template requires signatures, False if not.


Records passed into and returned from the Apply method represent DNS records. These are implemented using a simple list of dictionary, with each dictionary representing a DNS record.

All records have a type (A, AAAA, CNAME, NS, TXT, MX, or SRV). Depending on the type there are other attributes.

If the DNS Provider wishes to implement template state in DNS, an set of fields is required in this data structure. This will be a dictionary. It is recommended that the DNS Provider store this by serializing the dictionary into a string.

Field Type Description



This is one of A, AAAA, CNAME, NS, TXT, MX, or SRV.



This is the name/host of the record. This exists for all types. The must contain data that is relative to the root zone. For example, in the domain the name for the resolution of would contain "". A value of @ or None would indicate the apex.



This is the data for the record. This exists for all types. When the data contains a domain/host a fully qualified domain name without a trailing dot must be used.



This is the TTL for the record. This exists for all types.



This is the priority of an MX record or SRV record.



This is the protocol for an SRV record. This must be the value TCP or UDP.



This is the service of an SRV record.



This is the weight of the SRV record.



This is the port of the SRV record.



(optional) This is the json structure representing the template state for applied records. The DNS Provider should store this by serializing/deserialzing the json, allowing for future extensibility. Fields in here are interesting to the DNS Provider and are documented below.


This is the unique id representing the application of a template



This is the providerId of the applied template on this record



This is the serviceId of the applied template on this record


This was the host used to apply this template. All templates are scoped to the domain/host.



Largely internal, this indicates that the essential property on the record when applied. This is used for conflict detection when overwriting.

An example zone:

    {"type": "A","name": "@","data": "","ttl": 3000},
    {"type": "CNAME","name": "www","data": "@","ttl": 3000}


In addition to being used by the apply_template method, this independent method can be used to validate a query string against a signature and key.

import domainconnectzone
dc = domainconnectzone.DomainConnect('', 'template2')
sig = 'LyCE+7H0zr/XHaxX36pdD1eSQENRiGTFxm79m7A5NLDPiUKLe71IrsEgnDLN76ndQcLTZlr4+HhpWzKZKyFl9ieEpNzZlDHRp35H83Erhm0eDctUmI1Zct51alZ8RuTL+aa29WC+AM7+gSpnL/AHl9mxckyeEuFFqXcl/3ShwK2F9x/7r+cICefiUEzsZN3EuqOvwqQkBSqcdVy/ohjNAG/InYAYSX+0fUK9UNQfQYkuPqOAptPRjX+hUnYsXUk/eQq16aX7TzhZm+eEq+En+oiEgh7qps1yvGbJm6QXKovan/sqng40R6FBP3R3dvfZC6QrfCUtGpQ8c0D0S5oLBw=='

key = '_dck1'
qs = ''

dc.verify_sig(qs, sig, key)

If the signature fails, an InvalidSignature exception is raised


This method is useful for testing. It will prompt the user for all values for all variables in the template. These are added as key/values in a dictionary suitable for passing into the Apply function.

import domainconnectzone
dc = domainconnectzone.DomainConnect(provider_id, service_id)
params = dc.prompt()

Query String Utilities

Several helper functions are included for dealing with query strings.

qs2dict(qs, filter=[])

This will convert a query string (qs) of the form a=1&b=2&c=3&d=4 to a dictionary of the form {'a': '1', 'b': '2', 'c': '3', 'd': '4'}.

This is useful for converting a query string to a dictionary, filtering out the values not useful as parameters (e.g. domain, host, sig, key).

import domainconnectzone

qs = 'a=1&b=2&c=3&d=4'
params = domainconnectzone.QSUtil.qs2dict(qs, ['c', 'd']
# params contains {'a': '1', 'b': '2'}

qsfilter(qs, filter=[])

This is similar to the above but returns the results as a string.

import domainconnectzone

qs = 'a=1&b=2&c=3&d=4'
qs2 = domainconnectzone.QSUtil.qsfilter(qs, ['c', 'd']
# qs2 contains 'a=1&b=2'


This contains a series of simple tests. Run them by:

import Test


This module is GoDaddy specific. This will prompt the user for domain/host/providerId/serviceId and GoDaddy API Key. It will read the template, prompt for all variable values, and apply the changes to the zone. This is done by using the API Key to read the entire zone, and write the entire zone.

import GDTest


To install run:

python build
python install

Dependencies include cryptography, dnspython, and IPy


No description, website, or topics provided.







No packages published

Contributors 4