Difference between revisions of "Designate/Blueprints/IPABackend"
(→Configuration) |
(→backend.create_domain(self, context, domain)) |
||
Line 129: | Line 129: | ||
} | } | ||
The 'force': True parameter is used because, by default, IPA will not allow the use of an SOA mname if there is no corresponding A/AAAA record that can be resolved. Also note that, in the dnszone_add method, only one name server can be specified with the idnssoamname parameter. This is the first one returned by the central_service.find_servers method. The other servers are added as NS records by the create_domain method. | The 'force': True parameter is used because, by default, IPA will not allow the use of an SOA mname if there is no corresponding A/AAAA record that can be resolved. Also note that, in the dnszone_add method, only one name server can be specified with the idnssoamname parameter. This is the first one returned by the central_service.find_servers method. The other servers are added as NS records by the create_domain method. | ||
+ | ==== backend.update_domain(self, context, domain) ==== | ||
+ | Same as above, but with method name dnszone_mod. | ||
+ | ==== backend.delete_domain(self, context, domain) ==== | ||
+ | The method name is dnszone_del, and the only parameter is the domain name. | ||
== API Changes == | == API Changes == |
Revision as of 23:02, 2 April 2014
Contents
Overview
Gerrit Patch | [] |
---|---|
Launchpad Blueprint | [1] |
Summary
This implements support for using FreeIPA as a backend. FreeIPA has full support for DNS, using the JSON RPC interface for dnszone (domain) and dnsrecord commands.
Requirements
- python-kerberos 1.1 or later
- MIT kerberos5 version 1.11.3 or later
- A FreeIPA deployment, with an account that has access to manage the DNS portion. The admin@DOMAIN account can be used for testing, but is not recommended for production. You must generate a keytab file for this account, and Designate Central must have read access to the keytab file.
- The CA cert file from FreeIPA (default /etc/ipa/ca.crt).
Configuration
To use the IPA backend, in /etc/designate/designate.conf set
[service:central] backend_driver = ipa
Then set the [backend:ipa] configuration parameters:
Name | Required | Default | Description |
---|---|---|---|
ipa_host | Yes | None | Name (FQDN) of IPA host |
ipa_port | No | 80 | Port number for IPA HTTPS service |
ipa_client_keytab | Yes | None | Absolute path to IPA client kerberos keytab file |
ipa_ca_cert | Yes | None | Absolute path to IPA CA cert file |
ipa_base_url | No | https://$ipa_host/ipa | Base URL for IPA HTTPS RPC interfaces |
ipa_json_url | No | https://$ipa_host/ipa/json | Base URL for IPA JSON RPC interface |
ipa_version | Yes | 2.65 | IPA JSON RPC version |
HTTPS
IPA requires the use of HTTPS for security. By default, IPA generates a CA cert and stores it in /etc/ipa/ca.crt. For HTTPS communication with IPA, the requests module is used, and the request verify member is set to the IPA CA cert.
Kerberos
IPA requires the use of Kerberos for authentication. The IPA backend uses the KRB5_CLIENT_KEYTAB feature of MIT Kerberos 1.11. For the HTTP communication with IPA, the backend uses the requests module, and sets the header Authorization: negotiate $token where $token is the Kerberos token generated by the python-kerberos module from the keytab file. This is done automatically with the requests object via the auth member. There is a subclass of requests.auth.AuthBase called IPAAuth which handles the Kerberos authentication upon demand.
The Kerberos auth token will expire periodically. An IPA request will return with a status_code of 401 when the token expires, and the code in the backend will refresh the auth token.
One current limitation is that only one identity can be used at a time. This is because KRB5_CLIENT_KEYTAB is global.
IPA JSON RPC
This interface is not currently documented in the official documentation, but is officially supported. A JSON call to IPA looks like this:
{ 'method': $methodname, 'params': [ [ $positionalparam, $positionalparam2 ], { $param1: $value1, ... 'version': $ipa_version }], 'id': 0 }
Where $methodname is one of 'dnszone_add', 'dnszone_mod', 'dnszone_del', 'dnsrecord_add', 'dnsrecord_mod', 'dnsrecord_del'.
All of the methods take $positionalparam, which is usually the name of the zone (domain). The dnsrecord methods use $positionalparam2 as the record name.
Depending on the method and record type, there will be keyword params $param1, etc. For example, a dnszone_add looks like this:
{ 'method': 'dnszone_add', 'params': [ [[ 'example.org.' ]], { 'idnssoamname': 'ns.example.org.', 'force': True, 'idnssoarname': 'hostmaster@example.org.', 'dnsttl': 3600, 'idnssoaserial': 13789910123, 'idnssoaexpire': 12345, 'idnssoaminimum': 1200, 'idnssoarefresh': 54321, 'idnssoaretry': 11111, 'version': '2.65' }], 'id': 0 }
Adding an A record looks like this:
{ 'method': 'dnsrecord_add', 'params': [ [ 'example.org.', 'a'], { 'arecord': '192.168.122.100.', 'version': '2.65' }], 'id': 0 }
The ipa backend code has mappings from the domain/recordset/record object properties to the IPA JSON parameters.
Create, Update, Delete Domain
backend.create_domain(self, context, domain)
The code first does
servers = self.central_service.find_servers(self.admin_context)
to get the list of name servers for the domain. Then it sends the following IPA JSON RPC:
{ 'method': 'dnszone_add', 'params': [ [[ domain['name'] ]], { 'idnssoamname': servers[0]['name'], 'force': True, 'idnssoarname': domain['email'], 'dnsttl': domain['ttl'], 'idnssoaserial': domain['serial'], 'idnssoaexpire': domain['expire'], 'idnssoaminimum': domain['minimum'], 'idnssoarefresh': domain['refresh'], 'idnssoaretry': domain['retry'], 'version': '2.65' }], 'id': 0 }
The 'force': True parameter is used because, by default, IPA will not allow the use of an SOA mname if there is no corresponding A/AAAA record that can be resolved. Also note that, in the dnszone_add method, only one name server can be specified with the idnssoamname parameter. This is the first one returned by the central_service.find_servers method. The other servers are added as NS records by the create_domain method.
backend.update_domain(self, context, domain)
Same as above, but with method name dnszone_mod.
backend.delete_domain(self, context, domain)
The method name is dnszone_del, and the only parameter is the domain name.
API Changes
None
One Per Change
Verb | Resource | Description |
---|---|---|
GET | /resource | Description of call |
GET | /resource/{id} | Description of call |
Database Changes
Description of Changes to DB schemas
eg -
Name | Data Type | Length | Nullable | Details |
---|---|---|---|---|
id | VARCHAR | 36 | False | Primary Key, Generated UUID |
name | VARCHAR | 255 | False | Domain name to be blacklisted |
version | INTEGER | - | False | Designate API version |
created_at | DATETIME | - | False | UTC time of creation |
updated_at | DATETIME | - | True | UTC time of creation |
description | VARCHAR | 160 | True | UTF-8 text field |