[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

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


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
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 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 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

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]