On 04/12/2013 01:26 PM, Ana Krivokapic wrote:
On 04/12/2013 12:44 PM, Martin Kosek wrote:
On 04/12/2013 12:20 PM, Ana Krivokapic wrote:
On 04/11/2013 03:03 PM, Alexander Bokovoy wrote:
On Thu, 11 Apr 2013, Ana Krivokapic wrote:
On 04/11/2013 01:43 PM, Alexander Bokovoy wrote:
On Thu, 11 Apr 2013, Petr Spacek wrote:
On 11.4.2013 13:24, Alexander Bokovoy wrote:
On Thu, 11 Apr 2013, Petr Spacek wrote:
On 11.4.2013 13:09, Ana Krivokapic wrote:
Integrate realmdomains with IPA DNS

Add an entry to realmdomains when a DNS zone is added to IPA.
Delete the
related entry from realmdomains when the DNS zone is deleted from
IPA.

https://fedorahosted.org/freeipa/ticket/3544
I would add a TXT record as I described in
https://fedorahosted.org/freeipa/ticket/3544#comment:8

This integration probably should go to both commands, realmdomains-*
dnszone-*.

Any objections? AB?
Adding TXT record is probably harmless.

I would actually add the TXT record creation only to realmdomains-* and
trigger it only in case we manage our DNS and DNS zone is there.
This way a hook from dnszone-add will trigger adding TXT record back
(via call to
realmdomains-mod --add and then TXT record addition from there). Also the fact that admin added manually some domain to realmdomains mapping means that it is implied to be used in obtaining TGTs, so TXT record is
helpful there as well.
Okay, it makes sense. We will see how it will work in reality.
One more thing to check is that we don't do this for our own domain.

Our own domain is already in realmdomains by default, and it cannot be removed from there. So I don't think any check related to our domain is
necessary.
We shouldn't start creating TXT records for our own domain, that's what
I'm asking for here.

Think about server install stage -- we start creating our own domain and
the hook then causes to create realmdomains entry for the domain,
causing realmdomains-mod code to raise ValidationError which is not
handled in dnszone-add code with this patch.

Same for TXT record creation starting from realmdomains-mod side -- it
simply should avoid calling dnsrecord-add for the case we know wouldn't
work.

I just realized that this ticket was not marked as RFE although it obviously is one. I fixed the ticket summary and wrote the design page for this enhancement:

http://www.freeipa.org/page/V3/DNS_realmdomains_integration

Right, that was a good thing to do. I just have comment for the UPN enumeration image which you linked in the RFE - can you please process it, upload to the wiki and include in the overview? This will make the RFE page more appealing and it will also prevent us from having a broken link when Alexander removes
the file from his temporary directory.

Thanks,
Martin

Sure, done.


I added the functionality to create TXT record to realmdomains-mod, and also made sure that the case of our own domain is handled properly. Unit tests have been added to cover the new functionality. One unit test of the dns plugin needed adjusting, but it still fails due to the bug in the testing framework[1]. It should pass after the bug is fixed.

Updated patch is attached.

[1] https://fedorahosted.org/freeipa/ticket/3562

--
Regards,

Ana Krivokapic
Associate Software Engineer
FreeIPA team
Red Hat Inc.

From 0ec8401acdd71ecd1cfbb1b0e6e39ce3556a2075 Mon Sep 17 00:00:00 2001
From: Ana Krivokapic <akriv...@redhat.com>
Date: Fri, 12 Apr 2013 15:20:07 +0200
Subject: [PATCH] Integrate realmdomains with IPA DNS

Add an entry to realmdomains when a DNS zone is added to IPA.
Delete the related entry from realmdomains when the DNS zone is deleted
from IPA.

Add _kerberos TXT record to DNS zone when a new realmdomain is added.
Delete _kerberos TXT record from DNS zone when realmdomain is deleted.

Add unit tests to cover new functionality.

https://fedorahosted.org/freeipa/ticket/3544
---
 ipalib/plugins/dns.py                              |  21 +++
 ipalib/plugins/realmdomains.py                     |  53 +++++++
 tests/test_xmlrpc/test_dns_plugin.py               |   8 +-
 .../test_dns_realmdomains_integration.py           | 168 +++++++++++++++++++++
 4 files changed, 249 insertions(+), 1 deletion(-)
 create mode 100644 tests/test_xmlrpc/test_dns_realmdomains_integration.py

diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
index becec14232e283e1f76cf4dd5d43de5cbba62d6e..f8ba158f56a5acb00d0ef6f6af00fda50bbb866a 100644
--- a/ipalib/plugins/dns.py
+++ b/ipalib/plugins/dns.py
@@ -1841,6 +1841,16 @@ class dnszone_add(LDAPCreate):
                                dns_record,
                                nameserver_ip_address)
 
+        # Add entry to realmdomains
+        # except for our own domain and for forwarded zones
+        zone = keys[0]
+
+        if zone != api.env.domain and not options.get('idnsforwarders'):
+            try:
+                api.Command['realmdomains_mod'](add_domain=zone, force=True)
+            except errors.EmptyModlist:
+                pass
+
         return dn
 
 api.register(dnszone_add)
@@ -1857,6 +1867,17 @@ class dnszone_del(LDAPDelete):
                     force=True)
         except errors.NotFound:
             pass
+
+        # Delete entry from realmdomains
+        # except for our own domain
+        zone = keys[0]
+
+        if zone != api.env.domain:
+            try:
+                api.Command['realmdomains_mod'](del_domain=zone, force=True)
+            except errors.AttrValueNotFound:
+                pass
+
         return True
 
 api.register(dnszone_del)
diff --git a/ipalib/plugins/realmdomains.py b/ipalib/plugins/realmdomains.py
index f3dbf8dae21c94be12b432ef8d4de28cd83ab64e..2965bf355b1353e64b2c65fd1b484c5ee9a2d721 100644
--- a/ipalib/plugins/realmdomains.py
+++ b/ipalib/plugins/realmdomains.py
@@ -133,6 +133,59 @@ class realmdomains_mod(LDAPUpdate):
         entry_attrs['associateddomain'] = domains
         return dn
 
+    def execute(self, *keys, **options):
+        dn = self.obj.get_dn(*keys, **options)
+        ldap = self.obj.backend
+
+        domains_old = set(ldap.get_entry(dn)[1]['associateddomain'])
+        result = super(realmdomains_mod, self).execute(*keys, **options)
+        domains_new = set(ldap.get_entry(dn)[1]['associateddomain'])
+
+        domains_added = domains_new - domains_old
+        domains_deleted = domains_old - domains_new
+
+        # Add a _kerberos TXT record for zones that correspond with
+        # domains which were added
+        for d in domains_added:
+            # Skip our own domain
+            if d == api.env.domain:
+                continue
+            try:
+                api.Command['dnszone_show'](unicode(d))
+            except errors.NotFound:
+                pass
+            else:
+                try:
+                    api.Command['dnsrecord_add'](
+                        unicode(d),
+                        u'_kerberos',
+                        txtrecord=api.env.realm
+                    )
+                except errors.EmptyModlist:
+                    pass
+
+        # Delete _kerberos TXT record from zones that correspond with
+        # domains which were deleted
+        for d in domains_deleted:
+            # Skip our own domain
+            if d == api.env.domain:
+                continue
+            try:
+                api.Command['dnszone_show'](unicode(d))
+            except errors.NotFound:
+                pass
+            else:
+                try:
+                    api.Command['dnsrecord_del'](
+                        unicode(d),
+                        u'_kerberos',
+                        txtrecord=api.env.realm
+                    )
+                except errors.AttrValueNotFound:
+                    pass
+
+        return result
+
 api.register(realmdomains_mod)
 
 
diff --git a/tests/test_xmlrpc/test_dns_plugin.py b/tests/test_xmlrpc/test_dns_plugin.py
index 7b14fc6709dceb18bfd3a920f1829dcc1871061b..24fc7ecc4e50ecfc115da0ece3555b58d08ca326 100644
--- a/tests/test_xmlrpc/test_dns_plugin.py
+++ b/tests/test_xmlrpc/test_dns_plugin.py
@@ -34,6 +34,7 @@ dnszone1_rname = u'root.%s.' % dnszone1
 dnszone1_permission = u'Manage DNS zone %s' % dnszone1
 dnszone1_permission_dn = DN(('cn',dnszone1_permission),
                             api.env.container_permission,api.env.basedn)
+dnszone1_txtrec_dn = DN(('idnsname', '_kerberos'), dnszone1_dn)
 dnszone2 = u'dnszone2.test'
 dnszone2_dn = DN(('idnsname', dnszone2), api.env.container_dns, api.env.basedn)
 dnszone2_mname = u'ns1.%s.' % dnszone2
@@ -526,7 +527,7 @@ class test_dns(Declarative):
             command=('dnsrecord_find', [dnszone1], {}),
             expected={
                 'summary': None,
-                'count': 3,
+                'count': 4,
                 'truncated': False,
                 'result': [
                     {
@@ -535,6 +536,11 @@ class test_dns(Declarative):
                         'idnsname': [u'@'],
                     },
                     {
+                        'dn': dnszone1_txtrec_dn,
+                        'txtrecord': [api.env.realm],
+                        'idnsname': [u'_kerberos'],
+                    },
+                    {
                         'dn': dnszone1_mname_dn,
                         'idnsname': [u'ns1'],
                         'arecord': [u'1.2.3.4'],
diff --git a/tests/test_xmlrpc/test_dns_realmdomains_integration.py b/tests/test_xmlrpc/test_dns_realmdomains_integration.py
new file mode 100644
index 0000000000000000000000000000000000000000..223596f45579d17ec2cafcd1fa1bec0f84a7c8dd
--- /dev/null
+++ b/tests/test_xmlrpc/test_dns_realmdomains_integration.py
@@ -0,0 +1,168 @@
+# Authors:
+#   Ana Krivokapic <akriv...@redhat.com>
+#
+# Copyright (C) 2013  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+Test integration of DNS and realmdomains.
+1. dnszone_{add,del} should create/delete appropriate entry in realmdomains.
+2. realmdomains_mod should add a _kerberos TXT record in the DNS zone.
+"""
+
+from ipalib import api, errors
+from ipapython.dn import DN
+from tests.test_xmlrpc import objectclasses
+from xmlrpc_test import Declarative, fuzzy_digits
+
+
+cn = u'Realm Domains'
+dn = DN(('cn', cn), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
+our_domain = api.env.domain
+dnszone_1 = u'example1.com'
+dnszone_1_dn = DN(('idnsname', dnszone_1), api.env.container_dns,
+                  api.env.basedn)
+idnssoamname = u'ns1.%s.' % dnszone_1
+idnssoarname = u'root.%s.' % dnszone_1
+dnszone_2 = u'example2.com'
+dnszone_2_dn = DN(('idnsname', dnszone_2), api.env.container_dns,
+                  api.env.basedn)
+
+
+def assert_realmdomain_and_txt_record_present(response):
+    zone = response['value']
+
+    r = api.Command['realmdomains_show']()
+    assert zone in r['result']['associateddomain']
+
+    r = api.Command['dnsrecord_show'](zone, u'_kerberos')
+    assert api.env.realm in r['result']['txtrecord']
+
+    return True
+
+
+def assert_realmdomain_and_txt_record_not_present(response):
+    zone = response['value']
+
+    r = api.Command['realmdomains_show']()
+    assert zone not in r['result']['associateddomain']
+
+    try:
+        api.Command['dnsrecord_show'](zone, u'_kerberos')
+    except errors.NotFound:
+        return True
+
+
+class test_dns_realmdomains_integration(Declarative):
+    cleanup_commands = [
+        ('realmdomains_mod', [], {'associateddomain': [our_domain]}),
+        ('dnszone_del', [dnszone_1, dnszone_2], {'continue': True}),
+    ]
+
+    tests = [
+        dict(
+            desc='Check realmdomain and TXT record get created '
+                 'during dnszone_add',
+            command=(
+                'dnszone_add', [dnszone_1], {
+                    'idnssoamname': idnssoamname,
+                    'idnssoarname': idnssoarname,
+                    'ip_address': u'1.2.3.4',
+                }
+            ),
+            expected={
+                'value': dnszone_1,
+                'summary': None,
+                'result': {
+                    'dn': dnszone_1_dn,
+                    'idnsname': [dnszone_1],
+                    'idnszoneactive': [u'TRUE'],
+                    'idnssoamname': [idnssoamname],
+                    'nsrecord': [idnssoamname],
+                    'idnssoarname': [idnssoarname],
+                    'idnssoaserial': [fuzzy_digits],
+                    'idnssoarefresh': [fuzzy_digits],
+                    'idnssoaretry': [fuzzy_digits],
+                    'idnssoaexpire': [fuzzy_digits],
+                    'idnssoaminimum': [fuzzy_digits],
+                    'idnsallowdynupdate': [u'FALSE'],
+                    'idnsupdatepolicy': [u'grant %(realm)s krb5-self * A; '
+                                         u'grant %(realm)s krb5-self * AAAA; '
+                                         u'grant %(realm)s krb5-self * SSHFP;'
+                                         % dict(realm=api.env.realm)],
+                    'idnsallowtransfer': [u'none;'],
+                    'idnsallowquery': [u'any;'],
+                    'objectclass': objectclasses.dnszone,
+
+                },
+            },
+            extra_check=assert_realmdomain_and_txt_record_present,
+        ),
+
+        dict(
+            desc='Check realmdomain and TXT record do not get created '
+                 'during dnszone_add for forwarded zone',
+            command=(
+                'dnszone_add', [dnszone_2], {
+                    'idnssoamname': idnssoamname,
+                    'idnssoarname': idnssoarname,
+                    'idnsforwarders': u'1.2.3.4',
+                    'idnsforwardpolicy': u'only',
+                    'force': True,
+                }
+            ),
+            expected={
+                'value': dnszone_2,
+                'summary': None,
+                'result': {
+                    'dn': dnszone_2_dn,
+                    'idnsname': [dnszone_2],
+                    'idnszoneactive': [u'TRUE'],
+                    'idnssoamname': [idnssoamname],
+                    'idnsforwarders': [u'1.2.3.4'],
+                    'idnsforwardpolicy': [u'only'],
+                    'nsrecord': [idnssoamname],
+                    'idnssoarname': [idnssoarname],
+                    'idnssoaserial': [fuzzy_digits],
+                    'idnssoarefresh': [fuzzy_digits],
+                    'idnssoaretry': [fuzzy_digits],
+                    'idnssoaexpire': [fuzzy_digits],
+                    'idnssoaminimum': [fuzzy_digits],
+                    'idnsallowdynupdate': [u'FALSE'],
+                    'idnsupdatepolicy': [u'grant %(realm)s krb5-self * A; '
+                                         u'grant %(realm)s krb5-self * AAAA; '
+                                         u'grant %(realm)s krb5-self * SSHFP;'
+                                         % dict(realm=api.env.realm)],
+                    'idnsallowtransfer': [u'none;'],
+                    'idnsallowquery': [u'any;'],
+                    'objectclass': objectclasses.dnszone,
+
+                },
+            },
+            extra_check=assert_realmdomain_and_txt_record_not_present,
+        ),
+
+        dict(
+            desc='Check realmdomain and TXT record get deleted '
+                 'during dnszone_del',
+            command=('dnszone_del', [dnszone_1], {}),
+            expected={
+                'value': dnszone_1,
+                'summary': u'Deleted DNS zone "%s"' % dnszone_1,
+                'result': {'failed': u''},
+            },
+            extra_check=assert_realmdomain_and_txt_record_not_present,
+        ),
+    ]
-- 
1.8.1.4

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to