BIND9/Design/DNSSEC describes very basic functionality where DNS zone is signed with provided signing keys. Those keys need to be generated and periodically rotated.
This document describes short-term solution for automatic key generation/rotation feature. See also DNSSEC Longterm Key Rotation. We decided to go this way because we think that short-term solution is much easier to achieve so we will be able to test our solution before we decide to invest in long-term effort.
References:
PKCS#11
provider for OpenDNSSEC and BIND.The basic idea is that DNSSEC private keys will never be sent or stored to LDAP DB unencrypted. All cryptographic operations will be done inside SoftHSM.
There are three levels of keys, see related discussion in mailing list thread: https://www.redhat.com/archives/freeipa-devel/2014-April/msg00565.html
If mailing list contradicts statements in this document contradicts then this design document is authoritative “source of truth” and takes precedence.
This design page summarizes workflows related to key management. Results of key generation and unwrapping (raw keys) are always stored in SoftHSM. Wrapped keys can be stored in LDAP or somewhere else.
This operation needs to be detected and guarded so only one replica will
become DNSSEC master. It can be done by writing who is DNSSEC master to
cn=masters
.
cn=DNS,cn=<replica FQDN>,cn=masters,cn=ipa,cn=etc,dc=example
sub-tree in LDAP.cn=master, cn=keys, cn=sec, cn=dns, dc=example
sub-tree in
LDAP.This is done by ipa-replica-install
:
cn=DNS,cn=<replica FQDN>,cn=masters,cn=ipa,cn=etc,dc=example
sub-tree in LDAP.This is done by little daemon running on replica 1
:
SyncRepl
) a new public key in
cn=masters
sub-tree and will use own private key (replica1
‘s)
to re-encrypt master key using public key of the new replica
(replica2
)cn=master, cn=keys, cn=sec, cn=dns, dc=example
sub-tree in
LDAP.`This is done by little daemon running on replica 2
:
replica2
‘s private key.NOTE: replica1
cannot be uninstalled at the moment. Support for
this scenario requires more work.
NOTE: Old master keys remain in LDAP and old DNSSEC keys are not
touched at all. After all, all keys used before replica removal are on
replica2
‘s disk anyway.
This step is done by ipa-replica-manage:
cn=masters
.All operations with keys are done by little daemon running on
replica1
:
replica2
‘s public key was deleted and initiate master
key rotation.cn=masters
) and store it to LDAPKey wrapping is done only by replica1
which is running OpenDNSSEC
Enforcer daemon.
cn=keys, cn=sec, cn=dns
.cn=keys, idnsname=example.net, cn=dns
This is done by little daemons running on all replicas with DNS.
SyncRepl
).ipaWrappingKey
attribute.Prerequisites:
cn=keys, idnsname=example.net, cn=dns
).DNSSEC data are logically separated and stored in different parts of LDAP DIT:
dc=example
├── cn=dns
│ ├── cn=sec
│ │ └── cn=keys
│ │ ├── ipk11UniqueId=00555c3d4e5f
│ │ │ ^ DNS zone public + private key + PKCS#11 metadata
│ │ ├── ipk11UniqueId=00abcdef1234
│ │ │ ^ DNS zone public + private key + PKCS#11 metadata
│ │ ├── ipk11UniqueId=111b2c3d4e90
│ │ │ ^ replica1 public key + PKCS#11 metadata
│ │ ├── ipk11UniqueId=1234567890ab
│ │ │ ^ replica2 public key + PKCS#11 metadata
│ │ ├── ipk11UniqueId=9876543210fe
│ │ │ ^ master secret key - PKCS#11 metadata + pointers to key data
│ │ ├── ipk11UniqueId=abcdef012345
│ │ │ ^ master secret key data for replica1
│ │ └── ipk11UniqueId=fedcba987654
│ │ ^ master secret key data for replica2
│ │
│ ├── idnsname=example.net
│ │ └── cn=keys
│ │ └── cn=ksk-20140716010203
│ │ ^ DNSSEC metadata only + PKCS#11 URI of the key
│ └── idnsname=example.org
│ └── cn=keys
│ └── cn=ksk-20141009010203
│ ^ DNSSEC metadata only + PKCS#11 URI of the key
└── cn=etc
└── cn=ipa
└── cn=masters
├── cn=replica1.example
│ ├── cn=DNS
│ ├── cn=DNSKeyExporter
│ ├── cn=DNSKeySync
│ └── cn=OpenDNSSEC
└── cn=replica2.example
├── cn=DNS
└── cn=DNSKeySync
This page is authoritative source of truth. Some details of the schema were changed many times and mailing list threads become incomprehensible.
Key is stored in objects desribed by LDAP schema for PKCS#11.
Discussion: https://www.redhat.com/archives/freeipa-devel/2014-April/msg00565.html
Metadata are stored in separate LDAP objects. The object contains PKCS#11 URI which points to the key material.
We have to have enough metadata to generate files which are usually produced by dnssec-keyfromlabel utility. The metadata have to contain timestamps which are necessary for key management according to RFC 6781.
Discussion: https://www.redhat.com/archives/freeipa-devel/2014-June/msg00305.html
Arbitrary name. It will be used as part of object DN.
<DNSSEC key type>-<timestamp of key creation>-<PKCS#11 ID in hex>
KSK-20140619125038Z-bba18ce06079720a33940ec5dee077ef
( 2.16.840.1.113730.3.8.5.27
NAME 'idnsSecAlgorithm'
DESC 'DNSKEY algorithm: string used as mnemonic'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
SINGLE-VALUE
X-ORIGIN 'IPA v4' )
( 2.16.840.1.113730.3.8.5.19
NAME 'idnsSecKeyCreated'
DESC 'DNSSEC key creation timestamp'
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
SINGLE-VALUE
X-ORIGIN 'IPA v4' )
( 2.16.840.1.113730.3.8.5.28
NAME 'idnsSecKeyRef'
DESC 'PKCS#11 URI of the key'
EQUALITY caseExactMatch
SINGLE-VALUE
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
( 2.16.840.1.113730.3.8.5.21
NAME 'idnsSecKeyActivate'
DESC 'DNSSEC key (planned) activation time'
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
SINGLE-VALUE
X-ORIGIN 'IPA v4' )
( 2.16.840.1.113730.3.8.5.23
NAME 'idnsSecKeyDelete'
DESC 'DNSSEC key (planned) deletion timestamp'
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
SINGLE-VALUE
X-ORIGIN 'IPA v4' )
( 2.16.840.1.113730.3.8.5.22
NAME 'idnsSecKeyInactive'
DESC 'DNSSEC key (planned) inactivation time'
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
SINGLE-VALUE
X-ORIGIN 'IPA v4' )
( 2.16.840.1.113730.3.8.5.20
NAME 'idnsSecKeyPublish'
DESC 'DNSSEC key (planned) publication time'
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
SINGLE-VALUE
X-ORIGIN 'IPA v4' )
( 2.16.840.1.113730.3.8.5.25
NAME 'idnsSecKeyRevoke'
DESC 'DNSKEY REVOKE flag (equivalent to bit 8): RFC 5011'
EQUALITY booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
SINGLE-VALUE
X-ORIGIN 'IPA v4' )
( 2.16.840.1.113730.3.8.5.26
NAME 'idnsSecKeySep'
DESC 'DNSKEY SEP flag (equivalent to bit 15): RFC 4035'
EQUALITY booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
SINGLE-VALUE
X-ORIGIN 'IPA v4' )
( 2.16.840.1.113730.3.8.5.24
NAME 'idnsSecKeyZone'
DESC 'DNSKEY ZONE flag (equivalent to bit 7): RFC 4035'
EQUALITY booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
SINGLE-VALUE
X-ORIGIN 'IPA v4' )
Represents metadata for single DNSSEC key pair.
( 2.16.840.1.113730.3.8.6.4
NAME 'idnsSecKey'
DESC 'DNSSEC key metadata' STRUCTURAL
MUST ( idnsSecKeyRef $ idnsSecKeyCreated $ idnsSecAlgorithm )
MAY ( idnsSecKeyPublish $ idnsSecKeyActivate $ idnsSecKeyInactive $ idnsSecKeyDelete $ idnsSecKeyZone $ idnsSecKeyRevoke $ idnsSecKeySep $ cn )
X-ORIGIN 'IPA v4' )
Any additional requirements or changes discovered during the implementation phase:
We have to use version 2 because SoftHSM v1 depends on Botan which we don’t like.
SoftHSM v2 itself needs some enhancements:
CKA_SENSITIVE
flag handling is somehow broken:SoftHSM’s support for key wrapping with symmetric keys is present in the code base but it depends on support in OpenSSL. This support was not available in upstream without patch.
It is not that easy to export raw keys from SoftHSM v2 so we should use
PKCS#11
interface to interconnect BIND and SoftHSM directly.
This interface have to be backported from BIND 9.10 to BIND 9.9 which is a non-trivial task.
CKA_EXTRACTABLE
flag for private keys is not configurable:SyncRepl
hook is necessary for correct implementation of
ipa-dnskeysyncd
daemon.python-ldap
version
which will hopefully include our patches.
For simplicity, this short-term solution will not provide any explicit user interface for key management. In emergency cases user can use OpenDNSSEC command line tools to enforce key rotation.
FreeIPA will provide only minimal user interface for installation/upgrade and DNSSEC enablement for particular DNS zone.
Commands to enable/disable key generation and zone signing:
$ ipa dnszone-mod example.com. --dnssec=TRUE
$ ipa dnszone-mod example.com. --dnssec=FALSE
New command ipa-dnssec-install
will “elect” one replica to be
DNSSEC-key-master.
No expected impact. Key data will be replicated from one node to others, no replication conflicts are expected. New data will be written approximatelly once per month per DNS zone.
Upgrade has to install and configure all new depedencies. One replica has to be manually selected as DNSSEC key master after upgrade/installation: See https://www.redhat.com/archives/freeipa-devel/2014-July/msg00182.html for discussion.
New depedencies:
PKCS#11
operations from command
line (only used internally by FreeIPA)No impact was expected at the beginning but chain of consequences starting with SoftHSM v1->SoftHSM v2 transition led to depedencies.
Test scenarios that will be transformed to test cases for FreeIPA Continuous Integration during implementation or review phase.
General idea: Muck with system clock on OpenDNSSEC node and check if new keys are generated as necessary.
I have got suggestion from Siôn Lloyd:
We have a feature here that may help you... When you configure/build the enforcer you can include a flag “–enable-timeshift” which allows you to overwrite the time that the enforcer uses... With this flag set the enforcerd process looks for an environment variable set via, e.g.:
export ENFORCER_TIMESHIFT=‘01-01-2010 12:00:00’
If this exists it will run once as if it is that time then exit. We use this feature in some of our tests as it means we can have deterministic results. Maybe this would be useful for you too?
—Siôn Lloyd
Petr Spacek <pspacek@…>