跳转到: 导航, 搜索

Designate/蓝图/IPABackend

概述

Gerrit补丁 [1]
Launchpad蓝图 [2]

总结

这实现了使用 FreeIPA 作为后端的功能。FreeIPA 对 DNS 具有完全支持,使用 JSON RPC 接口进行 dnszone(域)和 dnsrecord 命令。

需求

这些需求_不_在 requirements.txt 中,因此默认情况下不会安装它们。Designate 提供了一个文件 ipa-requirements.txt,可以使用 pip install -r ipa-requirements.txt 来使用。具体要求是

  • python-kerberos 1.1 或更高版本
  • MIT kerberos5 版本 1.11.3 或更高版本
  • 一个 FreeIPA 部署,以及一个具有管理 DNS 部分权限的帐户。admin@DOMAIN 帐户可用于测试,但不建议用于生产环境。您必须为此帐户生成 keytab 文件,并且 Designate Central 必须具有对 keytab 文件的读取权限。
  • 来自 FreeIPA 的 CA 证书文件(默认 /etc/ipa/ca.crt)。

配置

要使用 IPA 后端,在 /etc/designate/designate.conf 中设置

[service:central]
backend_driver = ipa

然后设置 [backend:ipa] 配置参数

姓名 必需 默认 描述
ipa_host Yes IPA 主机的名称(FQDN)
ipa_port 443 IPA HTTPS 服务的端口号
ipa_client_keytab Yes IPA 客户端 kerberos keytab 文件的绝对路径
ipa_ca_cert Yes IPA CA 证书文件的绝对路径
ipa_base_url https://$ipa_host[:$ipa_port]/ipa IPA HTTPS RPC 接口的基本 URL
ipa_json_url $ipa_base_url/json IPA JSON RPC 接口的基本 URL
ipa_connect_retries 1 Designate 在放弃之前尝试连接到 IPA 的次数
ipa_force_ns_use IPA 要求指定的名称服务器或 SOA MNAME 可解析 - 如果设置此选项,Designate 将强制 IPA 使用给定的名称服务器,即使它不可解析
ipa_version Yes 2.65 IPA JSON RPC 版本
ipa_auth_driver_class designate.backend.impl_ipa.auth.IPAAuth 实现 IPA 身份验证驱动程序的类

HTTPS

IPA 要求出于安全原因使用 HTTPS。默认情况下,IPA 会生成一个 CA 证书并将其存储在 /etc/ipa/ca.crt 中。为了与 IPA 进行 HTTPS 通信,使用 requests 模块,并且请求的 verify 成员设置为 IPA CA 证书。

Kerberos

IPA 要求使用 Kerberos 进行身份验证。IPA 后端使用 MIT Kerberos 1.11 的 KRB5_CLIENT_KEYTAB 功能。对于与 IPA 的 HTTP 通信,后端使用 requests 模块,并设置标头 Authorization: negotiate $token,其中 $token 是由 python-kerberos 模块从 keytab 文件生成的 Kerberos 令牌。这通过 requests 对象的 auth 成员自动完成。有一个 requests.auth.AuthBase 的子类称为 IPAAuth,它按需处理 Kerberos 身份验证。

Kerberos 身份验证令牌会定期过期。当令牌过期时,IPA 请求将返回状态码 401,后端代码将刷新身份验证令牌。

当前的一个限制是,一次只能使用一个身份。这是因为 KRB5_CLIENT_KEYTAB 是全局的。

IPA JSON RPC

此接口当前未在官方文档中记录,但官方支持。对 IPA 的 JSON 调用如下所示

{
  'method': $methodname,
  'params': [
    [ $positionalparam, $positionalparam2 ],
    {
      $param1: $value1,
      ...
      'version': $ipa_version
    }],
  'id': 0
}

其中 $methodname 是 'dnszone_add'、'dnszone_mod'、'dnszone_del'、'dnsrecord_add'、'dnsrecord_mod'、'dnsrecord_del' 中的一个。

所有方法都采用 $positionalparam,通常是区域(域)的名称。dnsrecord 方法使用 $positionalparam2 作为记录名称。

根据方法和记录类型,将会有关键字参数 $param1 等。例如,dnszone_add 如下所示

{
  'method': 'dnszone_add',
  'params': [
    [[ 'example.org.' ]],
    {
      'idnssoamname': 'ns.example.org.',
      'idnssoarname': 'hostmaster@example.org.',
      'dnsttl': 3600,
      'idnssoaserial': 13789910123,
      'idnssoaexpire': 12345,
      'idnssoaminimum': 1200,
      'idnssoarefresh': 54321,
      'idnssoaretry': 11111,
      'version': '2.65'
    }],
  'id': 0
}

添加 A 记录如下所示

{
  'method': 'dnsrecord_add',
  'params': [
    [ 'example.org.', 'a' ],
    {
      'arecord': '192.168.122.100',
      'version': '2.65'
    }],
  'id': 0
}

ipa 后端代码具有从域/记录集/记录对象属性到 IPA JSON 参数的映射。

创建、更新、删除域

backend.create_domain(self, context, domain)

代码首先执行

servers = self.central_service.find_servers(self.admin_context)

以获取域的名称服务器列表。然后它发送以下 IPA JSON RPC

{
  'method': 'dnszone_add',
  'params': [
    [[ domain['name'] ]],
    {
      'idnssoamname': servers[0]['name'],
      '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
}

请注意,在 dnszone_add 方法中,只能使用 idnssoamname 参数指定一个名称服务器。这是 central_service.find_servers 方法返回的第一个服务器。其他服务器作为 NS 记录由 create_domain 方法添加。另请注意,IPA 要求 idnssoamname 和添加的任何 NS 记录必须可解析。如果您想强制使用不可解析的 NS 记录,请使用 ipa-force-ns-use 配置选项。

backend.update_domain(self, context, domain)

与上面相同,但方法名称为 dnszone_mod。

backend.delete_domain(self, context, domain)

方法名称为 dnszone_del,唯一的参数是域名。

创建、更新、删除记录集

IPA 将在添加第一个记录时“创建”相应的记录集。同样,IPA 将在删除最后一个记录时删除相应的记录集。唯一支持的记录集操作是更新。

backend.update_recordset(self, context, domain, recordset)

IPA 允许更改记录集中的唯一内容是 ttl。但是,IPA 不允许在没有至少一个记录的情况下创建记录集。如果用户尝试在记录集中存在记录之前更新记录集,IPA 后端将无法更新记录集,并且会静默成功(即不会引发异常)。这不应该成为问题,因为 IPA 后端将在 create_record() 方法中创建第一个记录时设置 ttl。

创建、更新、删除记录

backend.create_record(self, context, domain, recordset, record)

IPA 想要记录名称的相对主机/域名,而不是 FQDN。因此,与其添加 a.example.org. 的 A 记录,IPA 想要向 example.org. 域添加一个名为 'a' 的记录。同样对于 PTR 记录 - IPA 想要在 122.168.192.in-addr.arpa. 域中添加 '100'。当前 IPA 中存在一个错误 - 如果要向域本身添加记录,则必须使用 '@' 作为域名。后端代码中存在逻辑来处理这些情况。下面的 recname 参数是通过此逻辑从 recordset['name'] 派生的。

记录的类型是从 recordset['type'] 到 IPA 关键字的映射派生的。因此,recordset['type'] = 'A' 映射到 'arecord' 等。

JSON 如下所示

{
  'method': 'dnsrecord_add',
  'params': [
    [ domain['name'], recname ],
    {
      'arecord': record['data'],
      'version': '2.65'
    }],
  'id': 0
}

对于 SRV 和 MX 记录,record['priority'] 添加到 record['data'] 的开头。

backend.update_record(self, context, domain, recordset, record)

IPA 没有与 Designate 相同的记录的唯一标识符概念。没有简单的方法来仅修改特定记录的数据。例如,没有简单的方法来仅修改特定 MX 记录的优先级。对于更新,ipa 后端将获取给定 record['recordset_id'] 的所有记录,并替换该类型的所有记录。例如,如果在 IPA 中存在如下 MX 记录

10 mx1.example.org.
20 mx2.example.org.
30 mx3.example.org.

并且有一个 update_record 以更新第二个记录的优先级为 5,ipa 后端将执行如下 dnsrecord_mod

{
  'method': 'dnsrecord_mod',
  'params': [
    [ domain['name'], recname ],
    {
      'mxrecord': ['10 mx1.example.org.', '5 mx2.example.org.', '30 mx3.example.org.'],
      'version': '2.65'
    }],
  'id': 0
}

这预计不会导致性能问题,除非有数百条记录(可能吗?可能)。

backend.delete_domain(self, context, domain)

方法名称为 dnsrecord_del。与 create_record 相同的类型和数据映射完成。IPA 能够删除特定的记录数据,例如,您可以删除上述 '10 mx1.example.org.' MX 记录。

使用 IPA 进行测试

有一个默认情况下未运行的测试,称为 _test_service_ipa.py。要运行此测试,您需要一个名为 designate-ipa-test.conf 的配置文件,其中 IPA 配置如上所述。此文件应与您的常规 designate.conf 位于同一目录中。您还需要一个正在运行的 IPA 服务器。您可以像这样运行它(假设您已经设置了您的 venv)

cd ~/designate
tools/with_venv.sh python -m testtools.run designate.tests.test_central._test_service_ipa

将 IPA 数据导入 Designate

Designate 有一个新的命令行工具 - ipaextractor.py。这允许您使用 IPA 的 DNS 域和记录信息填充 Designate 内部数据库。它使用 IPA 的 dnszone_find 和 dnsrecord_find JSON 接口来获取 IPA 中的所有域和记录,然后使用 Designate API JSON 接口来擦除和填充 Designate Central 数据库。

ipaextractor.py

警告:首先编辑 designate.conf 并将 service:central backend_driver 设置为 fake!这将允许您仅更改 Designate Central 数据库。ipaextractor 将尝试阻止您将其与实时 IPA 后端一起使用 - 它将检查 designate.conf,并且它将进行实时检查以查看 IPA 后端是否正在被 Designate 使用。如果脚本检测到正在使用 IPA 后端,它将退出并显示错误。

用法

contrib/ipaextractor.py [--debug|--nodebug] [--verbose|--noverbose] ... other args ...

这将使用默认 designate.conf 进行配置

contrib/ipaextractor.py --config-file file.conf

这将使用给定的配置文件

ipaextractor.py [--config-file file.conf] \
           --backend:ipa-ipa-host hostname \
           ... other ipa options specified as --backend:ipa-optionname ... \
           --service:ipa-api-base-uri=http://designateapihost:port

这可用于手动传入参数。在命令行中传入的参数将覆盖配置文件中的参数。ipa 参数如上所述,Designate URL 是 designate API URL (https://:9001/v1)。

这将完全擦除 Designate 中的所有内容,并将其替换为 IPA 的内容。

运行成功后,编辑 designate.conf 以将 service:central backend_driver 切换到 ipa。

API 变更

数据库更改