Add NS1 backend
Introduce an NS1 backend. Signed-off-by: Michael Hood <mhood@ns1.com> Change-Id: I80fe08238005a94161e2dbcc89e77c90cde0a715
This commit is contained in:
parent
75668d084c
commit
5aac48f08b
|
@ -0,0 +1,136 @@
|
||||||
|
# Copyright 2021 NS1 Inc. https://www.ns1.com
|
||||||
|
#
|
||||||
|
# Author: Dragan Blagojevic <dblagojevic@daitan.com>
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
import requests
|
||||||
|
from oslo_config import cfg
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from designate import exceptions
|
||||||
|
from designate.backend import base
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
class NS1Backend(base.Backend):
|
||||||
|
__plugin_name__ = 'ns1'
|
||||||
|
|
||||||
|
__backend_status__ = 'untested'
|
||||||
|
|
||||||
|
def __init__(self, target):
|
||||||
|
super(NS1Backend, self).__init__(target)
|
||||||
|
|
||||||
|
self.api_endpoint = "https://" + self.options.get('api_endpoint')
|
||||||
|
self.api_token = self.options.get('api_token')
|
||||||
|
self.tsigkey_name = self.options.get('tsigkey_name', None)
|
||||||
|
self.tsigkey_hash = self.options.get('tsigkey_hash', None)
|
||||||
|
self.tsigkey_value = self.options.get('tsigkey_value', None)
|
||||||
|
|
||||||
|
self.headers = {
|
||||||
|
"X-NSONE-Key": self.api_token
|
||||||
|
}
|
||||||
|
|
||||||
|
def _build_url(self, zone):
|
||||||
|
return "%s/v1/zones/%s" % (self.api_endpoint, zone.name.rstrip('.'))
|
||||||
|
|
||||||
|
def _get_master(self):
|
||||||
|
try:
|
||||||
|
return self.masters[0]
|
||||||
|
except IndexError as e:
|
||||||
|
LOG.error('No masters host set in pools.yaml')
|
||||||
|
raise exceptions.Backend(e)
|
||||||
|
|
||||||
|
def _check_zone_exists(self, zone):
|
||||||
|
|
||||||
|
try:
|
||||||
|
requests.get(
|
||||||
|
self._build_url(zone),
|
||||||
|
headers=self.headers
|
||||||
|
).raise_for_status()
|
||||||
|
except requests.HTTPError as e:
|
||||||
|
if e.response.status_code == 404:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
LOG.error('HTTP error in check zone exists. Zone %s', zone)
|
||||||
|
raise exceptions.Backend(e)
|
||||||
|
except requests.ConnectionError as e:
|
||||||
|
LOG.error('Connection error in check zone exists. Zone %s', zone)
|
||||||
|
raise exceptions.Backend(e)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def create_zone(self, context, zone):
|
||||||
|
|
||||||
|
master = self._get_master()
|
||||||
|
# designate requires "." at end of zone name, NS1 requires omitting
|
||||||
|
data = {
|
||||||
|
"zone": zone.name.rstrip('.'),
|
||||||
|
"secondary": {
|
||||||
|
"enabled": True,
|
||||||
|
"primary_ip": master.host,
|
||||||
|
"primary_port": master.port
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.tsigkey_name:
|
||||||
|
tsig = {
|
||||||
|
"enabled": True,
|
||||||
|
"hash": self.tsigkey_hash,
|
||||||
|
"name": self.tsigkey_name,
|
||||||
|
"key": self.tsigkey_value
|
||||||
|
}
|
||||||
|
data['secondary']['tsig'] = tsig
|
||||||
|
|
||||||
|
if not self._check_zone_exists(zone):
|
||||||
|
try:
|
||||||
|
requests.put(
|
||||||
|
self._build_url(zone),
|
||||||
|
json=data,
|
||||||
|
headers=self.headers
|
||||||
|
).raise_for_status()
|
||||||
|
except requests.HTTPError as e:
|
||||||
|
# check if the zone was actually created
|
||||||
|
if self._check_zone_exists(zone):
|
||||||
|
LOG.info("%s was created with an error. Deleting zone",
|
||||||
|
zone.name)
|
||||||
|
try:
|
||||||
|
self.delete_zone(context, zone)
|
||||||
|
except exceptions.Backend:
|
||||||
|
LOG.error('Could not delete errored zone %s',
|
||||||
|
zone.name)
|
||||||
|
raise exceptions.Backend(e)
|
||||||
|
else:
|
||||||
|
LOG.info("Can't create zone %s because it already exists",
|
||||||
|
zone.name)
|
||||||
|
|
||||||
|
self.mdns_api.notify_zone_changed(
|
||||||
|
context, zone, self.host, self.port, self.timeout,
|
||||||
|
self.retry_interval, self.max_retries, self.delay)
|
||||||
|
|
||||||
|
def delete_zone(self, context, zone):
|
||||||
|
"""Delete a DNS zone"""
|
||||||
|
|
||||||
|
# First verify that the zone exists
|
||||||
|
if self._check_zone_exists(zone):
|
||||||
|
try:
|
||||||
|
requests.delete(
|
||||||
|
self._build_url(zone),
|
||||||
|
headers=self.headers
|
||||||
|
).raise_for_status()
|
||||||
|
except requests.HTTPError as e:
|
||||||
|
raise exceptions.Backend(e)
|
||||||
|
else:
|
||||||
|
LOG.warning("Trying to delete zone %s but that zone is not "
|
||||||
|
"present in the ns1 backend. Assuming success.",
|
||||||
|
zone)
|
|
@ -0,0 +1,217 @@
|
||||||
|
# Copyright 2021 NS1 Inc. https://www.ns1.com
|
||||||
|
#
|
||||||
|
# Author: Dragan Blagojevic <dblagojevic@daitan.com>
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
import requests_mock
|
||||||
|
from designate import exceptions
|
||||||
|
from designate import objects
|
||||||
|
from designate.backend import impl_ns1
|
||||||
|
import designate.tests
|
||||||
|
from designate.tests import fixtures
|
||||||
|
|
||||||
|
|
||||||
|
class NS1BackendTestCase(designate.tests.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(NS1BackendTestCase, self).setUp()
|
||||||
|
self.stdlog = fixtures.StandardLogging()
|
||||||
|
self.useFixture(self.stdlog)
|
||||||
|
|
||||||
|
self.api_address = 'https://192.0.2.3/v1/zones/example.com'
|
||||||
|
self.context = self.get_context()
|
||||||
|
self.zone = objects.Zone(
|
||||||
|
id='e2bed4dc-9d01-11e4-89d3-123b93f75cba',
|
||||||
|
name='example.com.',
|
||||||
|
email='example@example.com',
|
||||||
|
)
|
||||||
|
|
||||||
|
self.target = {
|
||||||
|
'id': '4588652b-50e7-46b9-b688-a9bad40a873e',
|
||||||
|
'type': 'ns1',
|
||||||
|
'masters': [
|
||||||
|
{'host': '192.0.2.1', 'port': 53},
|
||||||
|
{'host': '192.0.2.2', 'port': 35},
|
||||||
|
],
|
||||||
|
'options': [
|
||||||
|
{'key': 'api_endpoint', 'value': '192.0.2.3'},
|
||||||
|
{'key': 'api_token', 'value': 'test_key'},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
self.target_tsig = {
|
||||||
|
'id': '4588652b-50e7-46b9-b688-a9bad40a873e',
|
||||||
|
'type': 'ns1',
|
||||||
|
'masters': [
|
||||||
|
{'host': '192.0.2.1', 'port': 53},
|
||||||
|
{'host': '192.0.2.2', 'port': 35},
|
||||||
|
],
|
||||||
|
'options': [
|
||||||
|
{'key': 'api_endpoint', 'value': '192.0.2.3'},
|
||||||
|
{'key': 'api_token', 'value': 'test_key'},
|
||||||
|
{'key': 'tsigkey_name', 'value': 'test_key'},
|
||||||
|
{'key': 'tsigkey_hash', 'value': 'hmac-sha512'},
|
||||||
|
{'key': 'tsigkey_value', 'value': 'aaaabbbbccc'},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
self.put_request_json = {
|
||||||
|
'zone': u'example.com',
|
||||||
|
'secondary': {
|
||||||
|
'enabled': True,
|
||||||
|
'primary_ip': '192.0.2.1',
|
||||||
|
'primary_port': 53
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.put_request_tsig_json = {
|
||||||
|
'zone': u'example.com',
|
||||||
|
'secondary': {
|
||||||
|
'enabled': True,
|
||||||
|
'primary_ip': '192.0.2.1',
|
||||||
|
'primary_port': 53,
|
||||||
|
'tsig': {
|
||||||
|
'enabled': True,
|
||||||
|
'hash': 'hmac-sha512',
|
||||||
|
'name': 'test_key',
|
||||||
|
'key': 'aaaabbbbccc'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.backend = impl_ns1.NS1Backend(
|
||||||
|
objects.PoolTarget.from_dict(self.target)
|
||||||
|
)
|
||||||
|
self.backend_tsig = impl_ns1.NS1Backend(
|
||||||
|
objects.PoolTarget.from_dict(self.target_tsig)
|
||||||
|
)
|
||||||
|
|
||||||
|
@requests_mock.mock()
|
||||||
|
def test_create_zone_success(self, req_mock):
|
||||||
|
req_mock.put(self.api_address)
|
||||||
|
req_mock.get(
|
||||||
|
self.api_address,
|
||||||
|
status_code=404
|
||||||
|
)
|
||||||
|
|
||||||
|
self.backend.create_zone(self.context, self.zone)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
req_mock.last_request.json(),
|
||||||
|
self.put_request_json
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
req_mock.last_request.headers.get('X-NSONE-Key'), 'test_key'
|
||||||
|
)
|
||||||
|
|
||||||
|
@requests_mock.mock()
|
||||||
|
def test_create_zone_with_tsig_success(self, req_mock):
|
||||||
|
req_mock.put(self.api_address)
|
||||||
|
req_mock.get(
|
||||||
|
self.api_address,
|
||||||
|
status_code=404
|
||||||
|
)
|
||||||
|
|
||||||
|
self.backend_tsig.create_zone(self.context, self.zone)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
req_mock.last_request.json(),
|
||||||
|
self.put_request_tsig_json
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
req_mock.last_request.headers.get('X-NSONE-Key'), 'test_key'
|
||||||
|
)
|
||||||
|
|
||||||
|
@requests_mock.mock()
|
||||||
|
def test_create_zone_already_exists(self, req_mock):
|
||||||
|
|
||||||
|
req_mock.get(self.api_address, status_code=200)
|
||||||
|
req_mock.put(self.api_address)
|
||||||
|
|
||||||
|
self.backend.create_zone(self.context, self.zone)
|
||||||
|
|
||||||
|
self.assertIn(
|
||||||
|
"Can't create zone example.com. because it already exists",
|
||||||
|
self.stdlog.logger.output
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
req_mock.last_request.headers.get('X-NSONE-Key'), 'test_key'
|
||||||
|
)
|
||||||
|
|
||||||
|
@requests_mock.mock()
|
||||||
|
def test_create_zone_fail(self, req_mock):
|
||||||
|
req_mock.put(
|
||||||
|
self.api_address,
|
||||||
|
status_code=500,
|
||||||
|
)
|
||||||
|
req_mock.get(
|
||||||
|
self.api_address,
|
||||||
|
status_code=404,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertRaisesRegexp(
|
||||||
|
exceptions.Backend,
|
||||||
|
'500 Server Error: None for url: '
|
||||||
|
'%s' % self.api_address,
|
||||||
|
self.backend.create_zone, self.context, self.zone
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
req_mock.last_request.headers.get('X-NSONE-Key'), 'test_key'
|
||||||
|
)
|
||||||
|
|
||||||
|
@requests_mock.mock()
|
||||||
|
def test_delete_zone_success(self, req_mock):
|
||||||
|
req_mock.delete(self.api_address, status_code=200)
|
||||||
|
req_mock.get(self.api_address, status_code=200)
|
||||||
|
|
||||||
|
self.backend.delete_zone(self.context, self.zone)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
req_mock.last_request.headers.get('X-NSONE-Key'), 'test_key'
|
||||||
|
)
|
||||||
|
|
||||||
|
@requests_mock.mock()
|
||||||
|
def test_delete_zone_missing(self, req_mock):
|
||||||
|
req_mock.delete(self.api_address, status_code=200)
|
||||||
|
req_mock.get(self.api_address, status_code=404)
|
||||||
|
|
||||||
|
self.backend.delete_zone(self.context, self.zone)
|
||||||
|
|
||||||
|
self.assertIn(
|
||||||
|
"Trying to delete zone "
|
||||||
|
"<Zone id:'e2bed4dc-9d01-11e4-89d3-123b93f75cba' type:'None' "
|
||||||
|
"name:'example.com.' pool_id:'None' serial:'None' action:'None' "
|
||||||
|
"status:'None'> "
|
||||||
|
"but that zone is not "
|
||||||
|
"present in the ns1 backend. Assuming success.",
|
||||||
|
self.stdlog.logger.output
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
req_mock.last_request.headers.get('X-NSONE-Key'), 'test_key'
|
||||||
|
)
|
||||||
|
|
||||||
|
@requests_mock.mock()
|
||||||
|
def test_delete_zone_fail(self, req_mock):
|
||||||
|
req_mock.delete(self.api_address, status_code=500)
|
||||||
|
req_mock.get(self.api_address, status_code=200)
|
||||||
|
|
||||||
|
self.assertRaisesRegexp(
|
||||||
|
exceptions.Backend,
|
||||||
|
'500 Server Error: None for url: '
|
||||||
|
'%s' % self.api_address,
|
||||||
|
self.backend.delete_zone, self.context, self.zone
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
req_mock.last_request.headers.get('X-NSONE-Key'), 'test_key'
|
||||||
|
)
|
|
@ -0,0 +1,107 @@
|
||||||
|
# Configure the NS1 backend
|
||||||
|
|
||||||
|
# Requirements:
|
||||||
|
# A working NS1 managed DNS / DDI environment is needed to use this DevStack plugin.
|
||||||
|
|
||||||
|
# Enable with:
|
||||||
|
# DESIGNATE_BACKEND_DRIVER=ns1
|
||||||
|
|
||||||
|
# Dependencies:
|
||||||
|
# ``functions`` file
|
||||||
|
# ``designate`` configuration
|
||||||
|
|
||||||
|
# install_designate_backend - install any external requirements
|
||||||
|
# configure_designate_backend - make configuration changes, including those to other services
|
||||||
|
# init_designate_backend - initialize databases, etc.
|
||||||
|
# start_designate_backend - start any external services
|
||||||
|
# stop_designate_backend - stop any external services
|
||||||
|
# cleanup_designate_backend - remove transient data and cache
|
||||||
|
|
||||||
|
# Save trace setting
|
||||||
|
DP_NS1_XTRACE=$(set +o | grep xtrace)
|
||||||
|
set +o xtrace
|
||||||
|
|
||||||
|
# Defaults
|
||||||
|
# --------
|
||||||
|
|
||||||
|
DESIGNATE_NS1_DNS_IP=${DESIGNATE_NS1_DNS_IP:-172.31.45.104}
|
||||||
|
DESIGNATE_NS1_DNS_PORT=${DESIGNATE_NS1_DNS_PORT:-5333}
|
||||||
|
DESIGNATE_NS1_XFR_IP=${DESIGNATE_NS1_XFR_IP:-172.31.45.104}
|
||||||
|
DESIGNATE_NS1_XFR_PORT=${DESIGNATE_NS1_XFR_PORT:-5400}
|
||||||
|
DESIGNATE_NS1_API_IP=${DESIGNATE_NS1_API_IP:-172.31.45.104}
|
||||||
|
DESIGNATE_NS1_API_TOKEN=${DESIGNATE_NS1_API_TOKEN:-default}
|
||||||
|
|
||||||
|
|
||||||
|
# Entry Points
|
||||||
|
# ------------
|
||||||
|
|
||||||
|
|
||||||
|
# install_designate_backend - install any external requirements
|
||||||
|
function install_designate_backend {
|
||||||
|
if is_ubuntu; then
|
||||||
|
install_package python-dev libxslt1-dev libxslt1.1 libxml2-dev libxml2 libssl-dev
|
||||||
|
elif is_fedora; then
|
||||||
|
install_package python-devel libxslt1-devel libxslt1.1 libxml2-devel libxml2 libssl-devel
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# configure_designate_backend - make configuration changes, including those to other services
|
||||||
|
function configure_designate_backend {
|
||||||
|
|
||||||
|
# Generate Designate pool.yaml file
|
||||||
|
sudo tee $DESIGNATE_CONF_DIR/pools.yaml > /dev/null <<EOF
|
||||||
|
---
|
||||||
|
- name: default
|
||||||
|
description: DevStack NS1 Pool
|
||||||
|
attributes: {}
|
||||||
|
|
||||||
|
ns_records:
|
||||||
|
- hostname: $DESIGNATE_DEFAULT_NS_RECORD
|
||||||
|
priority: 1
|
||||||
|
|
||||||
|
nameservers:
|
||||||
|
- host: $DESIGNATE_NS1_DNS_IP
|
||||||
|
port: $DESIGNATE_NS1_DNS_PORT
|
||||||
|
|
||||||
|
targets:
|
||||||
|
- type: ns1
|
||||||
|
description: NS1 Managed DNS
|
||||||
|
|
||||||
|
masters:
|
||||||
|
- host: $(ipv6_unquote $DESIGNATE_SERVICE_HOST)
|
||||||
|
port: $DESIGNATE_SERVICE_PORT_MDNS
|
||||||
|
|
||||||
|
options:
|
||||||
|
host: $DESIGNATE_NS1_XFR_IP
|
||||||
|
port: $DESIGNATE_NS1_XFR_PORT
|
||||||
|
api_endpoint: $DESIGNATE_NS1_API_IP
|
||||||
|
api_token: $DESIGNATE_NS1_API_TOKEN
|
||||||
|
# NOTE: TSIG key has to be set manually if it's necessary
|
||||||
|
#tsigkey_name: testkey
|
||||||
|
#tsigkey_hash: hmac-sha512
|
||||||
|
#tsigkey_value: 4EJz00m4ZWe005HjLiXRedJbSnCUx5Dt+4wVYsBweG5HKAV6cqSVJ/oem/6mLgDNFAlLP3Jg0npbg1SkP7RMDg==
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# init_designate_backend - initialize databases, etc.
|
||||||
|
function init_designate_backend {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
# start_designate_backend - start any external services
|
||||||
|
function start_designate_backend {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
# stop_designate_backend - stop any external services
|
||||||
|
function stop_designate_backend {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
# cleanup_designate_backend - remove transient data and cache
|
||||||
|
function cleanup_designate_backend {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
# Restore xtrace
|
||||||
|
$DP_NS1_XTRACE
|
|
@ -0,0 +1,66 @@
|
||||||
|
..
|
||||||
|
Copyright 2021 NS1 inc. https://www.ns1.com
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
not use this file except in compliance with the License. You may obtain
|
||||||
|
a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
License for the specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
|
||||||
|
.. _backend-ns1:
|
||||||
|
|
||||||
|
NS1 Backend
|
||||||
|
===========
|
||||||
|
|
||||||
|
NS1 Configuration
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
|
||||||
|
1. Configure the NS1 Backend using this sample target snippet
|
||||||
|
|
||||||
|
.. literalinclude:: sample_yaml_snippets/ns1.yaml
|
||||||
|
:language: yaml
|
||||||
|
|
||||||
|
2. Then update the pools in designate
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ designate-manage pool update
|
||||||
|
|
||||||
|
See :ref:`designate_manage_pool` for further details on
|
||||||
|
the ``designate-manage pool`` command, and :ref:`pools`
|
||||||
|
for information about the yaml file syntax
|
||||||
|
|
||||||
|
|
||||||
|
TSIG Key Configuration
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
In some cases a deployer may need to use tsig keys to sign AXFR (zone transfer)
|
||||||
|
requests. As NS1 does not support a per host key setup, this needs to be set
|
||||||
|
on a per zone basis, on creation.
|
||||||
|
|
||||||
|
To do this, generate a tsigkey using any of available utilities
|
||||||
|
(e.g. tsig-keygen):
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ tsig-keygen -a hmac-sha512 testkey
|
||||||
|
key "testkey" {
|
||||||
|
algorithm hmac-sha512;
|
||||||
|
secret "vQbMI3u5QGUyRu6FWRm16eL0F0dfOOmVJjWKCTg4mIMNnba0g2PLrV+0G92WcTfJrgqZ20a4hv3RWDICKCcJhw==";
|
||||||
|
};
|
||||||
|
|
||||||
|
Then insert it into Designate. Make sure the pool id is correct
|
||||||
|
(the ``--resource-id`` below.)
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
openstack tsigkey create --name testkey --algorithm hmac-sha512 --secret 4EJz00m4ZWe005HjLiXRedJbSnCUx5Dt+4wVYsBweG5HKAV6cqSVJ/oem/6mLgDNFAlLP3Jg0npbg1SkP7RMDg== --scope POOL --resource-id 794ccc2c-d751-44fe-b57f-8894c9f5c842
|
||||||
|
|
||||||
|
Then add it to the ``pools.yaml`` file as shown in the example.
|
|
@ -0,0 +1,25 @@
|
||||||
|
targets:
|
||||||
|
- type: ns1
|
||||||
|
description: NS1 DNS Server
|
||||||
|
|
||||||
|
# List out the designate-mdns servers from which NS1 servers should
|
||||||
|
# request zone transfers (AXFRs) from.
|
||||||
|
masters:
|
||||||
|
- host: 192.0.2.1
|
||||||
|
port: 5354
|
||||||
|
|
||||||
|
# NS1 Configuration options
|
||||||
|
options:
|
||||||
|
#NS1 XFR container ip and port
|
||||||
|
host: 192.0.2.2
|
||||||
|
port: 5302
|
||||||
|
#NS1 API enpoint IP address or name (Core container). Enter only base address or name.
|
||||||
|
#Plugin will generate full api address, e.g. https://192.0.2.2/v1/zones/<zone name>
|
||||||
|
api_endpoint: 192.0.2.2
|
||||||
|
#NS1 API key
|
||||||
|
api_token: changeme
|
||||||
|
# If a tsigkey is needed, uncomment the line below and insert the key name, algorithm and value
|
||||||
|
# NOTE: TSIG key has to be set manually
|
||||||
|
#tsigkey_name: testkey
|
||||||
|
#tsigkey_hash: hmac-sha512
|
||||||
|
#tsigkey_value: 4EJz00m4ZWe005HjLiXRedJbSnCUx5Dt+4wVYsBweG5HKAV6cqSVJ/oem/6mLgDNFAlLP3Jg0npbg1SkP7RMDg==
|
|
@ -52,6 +52,7 @@ backend-impl-akamai=Akamai eDNS
|
||||||
backend-impl-akamai_v2=Akamai DNS v2
|
backend-impl-akamai_v2=Akamai DNS v2
|
||||||
backend-impl-infoblox-xfr=Infoblox (XFR)
|
backend-impl-infoblox-xfr=Infoblox (XFR)
|
||||||
backend-impl-nsd4=NSD4
|
backend-impl-nsd4=NSD4
|
||||||
|
backend-impl-ns1=NS1 DNS
|
||||||
backend-impl-agent=Agent
|
backend-impl-agent=Agent
|
||||||
backend-impl-bind9-agent=Bind9 (Agent)
|
backend-impl-bind9-agent=Bind9 (Agent)
|
||||||
backend-impl-denominator=Denominator
|
backend-impl-denominator=Denominator
|
||||||
|
@ -80,6 +81,11 @@ notes=Akamai has turned off the eDNS API - see https://community.akamai.com/cust
|
||||||
[backends.backend-impl-akamai_v2]
|
[backends.backend-impl-akamai_v2]
|
||||||
docs=akamai_v2_backend_docs
|
docs=akamai_v2_backend_docs
|
||||||
|
|
||||||
|
[backends.backend-impl-ns1]
|
||||||
|
docs=ns1_backend_docs
|
||||||
|
status=untested
|
||||||
|
config=backends/sample_yaml_snippets/ns1.yaml
|
||||||
|
|
||||||
[backends.backend-impl-agent]
|
[backends.backend-impl-agent]
|
||||||
|
|
||||||
[backends.backend-impl-bind9-agent]
|
[backends.backend-impl-bind9-agent]
|
||||||
|
|
|
@ -80,6 +80,7 @@ designate.backend =
|
||||||
infoblox = designate.backend.impl_infoblox:InfobloxBackend
|
infoblox = designate.backend.impl_infoblox:InfobloxBackend
|
||||||
fake = designate.backend.impl_fake:FakeBackend
|
fake = designate.backend.impl_fake:FakeBackend
|
||||||
agent = designate.backend.agent:AgentPoolBackend
|
agent = designate.backend.agent:AgentPoolBackend
|
||||||
|
ns1 = designate.backend.impl_ns1:NS1Backend
|
||||||
|
|
||||||
designate.backend.agent_backend =
|
designate.backend.agent_backend =
|
||||||
bind9 = designate.backend.agent_backend.impl_bind9:Bind9Backend
|
bind9 = designate.backend.agent_backend.impl_bind9:Bind9Backend
|
||||||
|
|
Loading…
Reference in New Issue