On 22.10.2013 16:44, Martin Kosek wrote:
On 10/21/2013 10:57 PM, Simo Sorce wrote:
Comments inline.

On Mon, 2013-10-21 at 18:48 +0200, Petr Spacek wrote:
On 1.10.2013 17:11, Petr Spacek wrote:

[trim]

I should make one thing clear:
We already do two-way synchronization between LDAP and DNS server (run-time).

Persistent search (and now syncrepl) dumps content of LDAP database to a internal database in DNS server and the bind-dyndb-ldap plugin operates on this internal database. I.e. changes done in LDAP are asynchronously applied to internal database and vice versa, changes done via DNS protocol are written back to LDAP.

This is why we are able to apply any change in LDAP almost immediatelly to DNS data. It is true that there are nasty corner cases, but up to now we didn't receive many complains about data inconsistency. (This will change after the major refactoring in bind-dyndb-ldap 4.0 :-))

Proposal - variant A ("classical" views)
====================
- keep it simple :-)
- single level inheritance, all views inherit from 'base' (Base is our current
cn=dns subtree, so old and new plugins can co-exist. The base can be empty.)
- the data in views can be modified via DNS updates, a change done to
inherited data creates an override (BIND9 does the same): e.g. name 'r1.z.' is
shared between View1 and View2. Value change in View1 doesn't affect View2.
- particular record from the 'base' can be overriden (deleted/replaced) in any
view
- changes done to the base are propagated to all views

LDAP schema
-----------
My goal is to maintain 1:1 mapping between "name+view" pair and LDAP DN. This
is crucial for DNS updates. The other option is to maintain some 'record->LDAP
DN database' or do a LDAP search before each DNS update - I would like to
avoid that.

Each view is stored as separate object under cn=dns.
DN: idnsView=view1, cn=dns
- this object stores settings specific to particular view (allowed clients,
recursion ...)

Zone in particular view is stored inside view container:
DN: idnsName=zone1, idnsView=view1, dn=dns
- this object can be empty container
- attributes without explicit configuration are inherited from the base
- a zone doesn't appear in the DNS view if the container is not present (i.e.
it is possible to hide the zone from particular view)
'Override' records for particular name in zone and view are stored as:
DN: idnsName=name1, idnsName=zone1, idnsView=view1, cn=dns

Doesn't this scheme means you always have to do 2 searches ? One to find
if the object is in the view and one to the base ?

We could use multivalued RDNs to achieve something similar but that will
require you only one search (assuming it matters).

Reading = 0 searches :-D Psearch/SyncRepl delivers the data from LDAP asynchronously to the plugin, almost immediatelly after each change in LDAP.

- values added on top of inherited set are represented as normal DNS
attributes: e.g. aRecord: 192.0.2.1
- values deleted from inherited set - *are open question*: It would be great
if we could store it under the same object as additions, it would make
implementation a bit simpler.
- Would it be acceptable to store override 'delete TXT record "hello"' as
attribute 'tXTRecord;x-deleted: test'?

I think this would be acceptable, however what happens if then someone
deletes the base object and later on again recreates it ?

Will the view still 'mask' it ?
My original idea was: "Yes, it will." The main reason is that user can have some tools which do LDAP delete/add instead of replace/modify, so some data from the base could be accidentally exposed if we delete 'override' automatically with base object.

Is this the actual desired outcome maybe ?
This is a good question :-) This is most generic/powerful mechanism but it could create some nasty surprises. One drawback is that you have to go and add 'mask'/'delete' record to affected views (if necessary) when you add a record to the base.

Another variants:
aa) Do overrides on name-level instead of record level. I.e. records for particular name will not be inherited if the override is present.

Example:
Base definition:
- gateway.example.com. A   203.0.113.66
- gateway.example.com. TXT "this record came from base"
- example.com          MX  10 gateway.example.com.

View definition:
- gateway.example.com. A 10.1.1.1

Result - view:
- gateway.example.com. A  10.1.1.1
- example.com          MX 10 gateway.example.com.

=> A and TXT records from base were not inherited because override for the name 'gateway' was present in the view. => MX record for name 'example.com' was inherited because there is no override with this name in the view. => Modification done in 'base' will not affect view in any way if the override is present, so there can't be information leak.
=> This approach doesn't require ;x-deleted or cn=deleted trick.

ab) No inheritance at all.
This is what BIND9 does if dynamic updates are enabled. After first update the inheritance relationship is broken and views operate independently.

Obviously, this is simplest and clearest solution. Maybe that it is enough for most users, look at the support in open source software ...

Maybe that some UI support for copying from one view to the other would be 
enough?

Should we allow Dynamic Updates in Views at all ?
It would be too simple without dynamic updates :-)

I think that we should allow updates, otherwise we can drop all the code for DNS updates from SSSD, ipa-client-install etc.

Of course, we can implement first version without support for updates and add it later, if there is a demand. We just need to keep it in mind during design.

- The other option is to store deleted attributes in separate object:
DN: cn=deleted, idnsName=record1, idnsName=zone1, idnsView=view1, cn=dns

This sound cumbersome and require a 3rd search for every query, nack :)
Again, 0 searches because of syncrepl :-)

I like variant A, I think it is the most sensible and the only one
really needed. People have an internal view and want to 'filter' it some
for the external world or similar.


Proposal - variant B (shared record groups)
====================
- not so simple to implement, especially update-performance could be an issue
- multiple zones can share the same record group
- each view can contain arbitrary zones anf those zones can inherit arbitrary
record groups - inheritance is fully configurable
- the data in views can be modified via DNS updates, a change done to
inherited data creates an override (BIND9 does the same): e.g. name 'r1.z.' is
shared between View1 and View2. Value change in View1 doesn't affect View2.
- particular record from any shared record group can be overriden
(deleted/replaced) in any zone in any view
- changes done to the shared record group are propagated to all views (this is
the hard part!)

Sound very complex not only to build, but to explain to admins as well,
is anyone actually going to need this level of complexity, what scenario
would really benefit from this that can't be done with A ?
I can see one use case:

Domains 'flower-eshop.com' and 'parfums-eshop.com' are hosted in 'data centre 1', while domains 'car-eshop.com' and 'software-eshop.com' are hosted in 'data centre 2'.

Typically it means that sites in one DC/group share the same set of NS records, MX records etc.

So the admin will define record group "DC1":
NS ns1.dc1.examplewebhoster.com.
NS ns2.backup.examplewebhoster.com.
MX 10 mx1.dc1.examplewebhoster.com.
MX 20 mx1.dc2.examplewebhoster.com.

Record group "DC2":
NS ns1.dc2.examplewebhoster.com.
NS ns1.backup.examplewebhoster.com.
MX 20 mx1.dc1.examplewebhoster.com.
MX 10 mx1.dc2.examplewebhoster.com.

Now record group DC1 is assigned to servers hosted at DC1 and so on.
Result = new mail server for DC1 has to be added to single place (the record group DC1) and all domains hosted at DC1 will automagically pick up the new server.

So you don't need to construct cycles over all servers in DC1, modify each record by hand etc.

This sounds nice 'on the paper', but I don't know how big the real demand is ...

LDAP schema
-----------
Group of shared records - container:
DN: idnsRecordGroup=group1, cn=dns

One shared name:
DN: idnsName=record1, idnsRecordGroup=group1, cn=dns
- contains DNS records for that name as usual

Each view is stored as separate object under cn=dns.
DN: idnsView=view1, cn=dns

Zone in particular view is stored inside view container:
DN: idnsName=zone1, idnsView=view1, dn=dns
- zone has a attribute with DNs of inherited record groups

'Override' records for particular name in zone and view are stored as:
DN: idnsName=name1, idnsName=zone1, idnsView=view1, cn=dns


After each change to any data we have to compute new resulting value. It means
to combine the data for particular name from all record groups and then apply
overrides for particular instance.

It means a lot of bookkeeping after each change ...


Proposal - variant 0
====================
Do not implement it in bind-dyndb-ldap and wait if Martin Basti succeeds with
his thesis. He is trying to design and implement some generic/pluggable
LDAP<->DNS synchronization mechanism.

Personally, I think that variant "0" is the best one! :-D One of side effects
is that our depedency on BIND 9 will be lowered and most of the work will be
deferred to the real DNS server.


Synchronization is always very, very hard, especially when you throw in
the word 'generic'. Especially problematic are races. I would proceed
with A unless there is solid evidence this can work with all corner
cases and in a short period of time.

Simo.


I read all the proposals, I would personally stick with variant A as this is
something that is doable in near future. Variant 0 seems a bit utopic to me,
One year, may be. Views are pretty complex thing - don't forget to integration with DNSSEC ...

especially when speaking about synchronization corner cases. Martin's thesis

Please see the note at the beginning of my e-mail. We already do two-way synchronization in bind-dyndb-ldap.

may prove me wrong, we will see.

Sure. Stand-alone daemon usually has some specific problems which are not so problematic for plug-ins, we will see.

--
Petr^2 Spacek

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

Reply via email to