[Freeipa-devel] DNSSEC support design considerations: key material handling

Petr Spacek pspacek at redhat.com
Mon Jul 15 14:58:00 UTC 2013


Hello,

first pair of this message quickly concludes discussion about database part of 
the DNSSEC support and then key material handling is discussed.

I'm sorry for the wall of text.

On 27.6.2013 18:43, Simo Sorce wrote:
>>> > >                * How to get sorted list of entries from LDAP? Use LDAP
>>> > >                  server-side sorting? Do we have necessary indices?
>>> > >
>>> > >We can do client side sorting as well I guess, I do not have a strong
>>> > >opinion here. The main reason why you need ordering is to detect delete
>>> > >records right ?
>> >Exactly. I realized that server-side sorting doesn't make sense because we
>> >plan to use syncrepl, so there is nothing to sort - only the flow of
>> >incremental updates.
> Syncrepl includes notice of deletions too, right ?
Yes. Client receives delete notification with entryUUID, so we can 
unambiguously identify the deleted entry.

I wrote example LDAP client and it works (against OpenLDAP :-).

>>>          > (Filesystem) cache maintenance
>>>
>>>          > Questions: How often should we save the cache from operating
>>>          memory to disk?
>>>
>>> Prerequisite to be able to evaluate this question. How expensive is it
>>> to save the cache ?
>> My test zone contains 65535 AAAA records, 255 A records, 1 SOA + 1 NS record.
>>
>> Benchmark results:
>> zone dump   < 0.5 s (to text file)
>> zone load   < 1 s (from text file)
>> zone delete < 9 s (LOL. This is caused by implementation details of RBTDB.)
>>
>> LDAP search on the whole sub-tree: < 15 s
>
> Ouch, this looks very slow, missing indexes ?)
I don't see any 'notes=U' in access log. Also, my OpenLDAP instance with the 
same DNS data can do the same search < 2 seconds.

> Is this just the search? or is it search + zone load ?
Just the search.

>> Load time for bind-dyndb-ldap 3.x: < 120 s
>
> So, a reload from scratch can take many 10s of seconds on big zones, did
> this test include DNSSEC signing ? Or would we need to add that on top ?
The time is for plain load. Current code is horribly ineffective and generates 
one extra LDAP search for each update. This madness will be eliminated by 
syncrepl, so the plain load time should be cut to much smaller value. We will see.

The other problem is that current code serializes a lot of work. This also 
will be mitigated to certain level (not completely, for now).

>> Originally, I planed to write a script which would compare data in LDAP with
>> zone file on disk. This script could be used for debugging & automated
>> testing, so we can assess if the code behaves correctly and decide if we want
>> to implement automatic re-synchronization when necessary.
>
> Wouldn't this script be subject to races depending at what time it is
> accessing either LDAP or the file ?
Yes, it would. The script was intended for 'lab use':
1. Run DNS server.
2. Do big amount of dynamic updates in short time.
3. Shutdown DNS and LDAP servers.
4. Compare data in DNS database with data in LDAP.

This could tell us how often and how many inconsistencies occur. After that we 
can make up some re-synchronization intervals etc.

> The main issue here is that it is hard to know when doing a full re-sync
> is necessary. And because it is expensive I am wary of doing it
> automatically too often.
>
> However perhaps a timed event so it is done once a day it is not a bad
> idea.
I agree.


I think that we sorted out necessary changes in storage/database part of the 
DNSSEC integration.


The remaining part is mostly about key management.

Following text mentions 'DNSSEC keys' many times, so I tried to summarize how 
keys are used in DNSSEC. Feel free to skip it.

== DNSSEC theory ==

Each zone has *at least* two key pairs. They are called Key Signing Key (KSK, 
the first key pair) and Zone Signing Key (ZSK, the second key pair).

- *Parent* zone contains a copy of public part of the KSK.
- Zone itself contains public part of ZSK (and KSK).
- Client uses public part of KSK (obtained from secure parent zone) for ZSK 
verification.
- ZSK is used for signing of the real data in the zone (i.e. generating RRSIG 
records) and verification on client side.

Each key and signature contains key-id, so one zone can be signed by multiple 
KSKs and ZSKs at the same time. This solves the key roll over problem.

Each key contains this set of timestamps:
Created, Revoke - self descriptive :-)
Publish - public part of the key will be visible in zone after this time
Active - new signatures with this key can be generated after this time
Inactive - new signatures with this key cannot be generated after this time
Delete - public part of the key will deleted from the zone after this time

NIST says [1] that KSK should be changed ~ each 1-3 years (it requires change 
in parent zone) and ZSK should be changed ~ each 1-3 months.

The recommendation says [1] that zone should have two ZSKs: One Active (used 
for signature generation) and second only Published (ready for roll over in 
case of emergency/when the first key pair expires). This mitigates problems 
with caches and stale key material during roll-over.

BIND 9 can do signature maintenance/ZSK key roll over automatically. It needs 
only keys stored in files (with proper timestamps) and all signatures will be 
generated & removed when the right time passes.

KSK has to be rolled over manually because it requires changes in parent zone. 
(It could be automated for sub-zones if their parent zone is also managed by 
the same IPA server.)

== End of DNSSEC theory ==



1) How will we handle generation of key pairs? How will externally generated 
keys be imported?

Personally, I would start with 'classical' command line utilities like 
dnssec-keygen etc. and extend 'ipa' tool to import generated keys. (Import = 
read keys from text files and create appropriate attributes to LDAP.)

Initial key generation is closely related to the question how should we handle 
(periodic) key regeneration? (e.g. "Generate new ZSK each month.")

Is it okay to use normal cron job to handle the key generation? I.e. to call 
dnssec-keygen with proper parameters each month and store the result in LDAP?

Or should we teach certmonger to take care of DNSSEC keys? Certmonger would 
have to call dnssec-keygen and to do some IPA calls. (I assume that key 
parsing and import will be handled by IPA framework.)

We can postpone the key management for the first version and just provide 
interface for key removal and import from file.



2) Second question is how and where keys should be stored. AFAIK BIND 9 
expects that keys will be stored in file system: One key pair as two files in 
specified directory. We probably want to store keys in LDAP, as usual.

My proposal is to represent each key pair by object with new class 
idnsDNSSECKey. This 'key pair object' will be stored inside zone container. E.g.
DNS zone = idnsname=ipa.test,cn=dns,dc=ipa,dc=test
Key pair = cn=005+01908,idnsname=ipa.test,cn=dns,dc=ipa,dc=test

Private key is represented by opaque blob (size ~ 1-2 kiB), so octetString 
could be the right syntax:
attributetypes: ( x.x.x.x.x NAME 'idnsSecPrivateKey' SYNTAX 
1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE )

Public key can be represented with normal DNSKEY record (size ~ 200-500 B), so 
it would be possible to use normal DNSKEY attribute. I see two problems with 
this approach:
- DNSKEY record (= attribute) is multi-valued by definition, but only one 
public key can be present in a key pair.
- DNSKEY records will be managed automatically by BIND so we don't want to let 
users to mess with them directly. DNSKEYRecord attribute is not defined at the 
moment and I'm not willing to define it now.

For these reasons I think that we can define new public key attribute in the 
same way as private key attribute:
attributetypes: ( x.x.x.x.x NAME 'idnsSecPublicKey' SYNTAX 
1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE )

The resulting object class could be:
objectClasses: ( x.x.x.x.x NAME 'idnsSecKeyPair' DESC 'DNSSEC key pair' SUP 
top STRUCTURAL MUST ( cn $ idnsSecPrivateKey $ idnsSecPublicKey ) )

CN attribute is user readable key name. It could be anything. BIND's syntax 
follows (text copied from dnssec-keyfromlabel):
This is an identification string for the key files: String of the form 
"Knnnn.+aaa+iiiii":
- nnnn is the key name (zone name)
- aaa is the numeric representation of the algorithm
- iiiii is the key identifier (or footprint)

Naturally, we can omit leading "K" and zone name, because we know the name 
from parent object in the LDAP/DIT. Also, it could be nice to indicate the 
type of the key - KSK or ZSK.

Attribute idnsSecPrivateKey should be readable only by DNS admins (and DNS 
servers :-). I'm not sure if we should make restrict read access even more. Is 
there a valid reason for admin to read the blob? I don't know, but admin can 
read the file on disk anyway ...

 From user interface point of view, key pairs are bit hard to deal with. 
Private key format is algorithm-dependent, so the only universal way to get 
standardized fields like valid-from/active-from/valid-to/revoked timestamps 
etc. is to call parser from bind-libs.



3) How will the configuration be stored?
Parameters are:
- DNSSEC enabled/disabled for one zone or globally - proposal: add a new 
boolean attribute idnsSecInlineSigning to zone and global config object
- NSEC3 parameters - proposal: use standard NSEC3PARAM record in the zone

The rest of the configuration options are related to the key management 
problem. We need to know:
- how many key pairs (e.g. 2 KSKs, 2 ZSKs)
- when (e.g. generate new key pair 30 days before active key expires)
- of which key types (KSK or ZSK)
- with which algorithms
- with which key lengths
should be generated. Note that we need to store configuration about X KSKs and 
Y ZSKs.

Again, we can postpone the key management for the first version.


4) For future versions - do we plan to add support for PKCS#11 HSMs? BIND 9 
can use OpenSSL for this stuff (somehow), but I didn't look into details.


[1] http://csrc.nist.gov/publications/nistpubs/800-81r1/sp-800-81r1.pdf 
section 9.3 Generation of Public Key-Private Key Pair (DNSSEC-OP1) page 9-5


Congratulations, you reached end of the text :-)

Have a nice day!

-- 
Petr^2 Spacek




More information about the Freeipa-devel mailing list