[Date Prev][Date Next] [Thread Prev][Thread Next]
Re: [Freeipa-devel] DNSSEC support design considerations: key material handling
- From: Petr Spacek <pspacek redhat com>
- To: Simo Sorce <simo redhat com>
- Cc: freeipa-devel redhat com
- Subject: Re: [Freeipa-devel] DNSSEC support design considerations: key material handling
- Date: Mon, 15 Jul 2013 16:58:00 +0200
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:
Yes. Client receives delete notification with entryUUID, so we can
unambiguously identify the deleted entry.
> > * 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
Syncrepl includes notice of deletions too, right ?
I wrote example LDAP client and it works (against OpenLDAP :-).
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.
> (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.
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 ?)
Is this just the search? or is it search + zone load ?
Just the search.
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.
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 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
I think that we sorted out necessary changes in storage/database part of the
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
- 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  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  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
22.214.171.124.4.1.14126.96.36.199.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
- 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
188.8.131.52.4.1.14184.108.40.206.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
- 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?
- 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
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.
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!
[Date Prev][Date Next] [Thread Prev][Thread Next]