We have to transform OpenDNSSEC version 1.x key states into key states understood by BIND. Versions used:
Currently we do not have support for:
For this reason some options are ignored. This should be fixed in future.
BIND is using set of timestamps to determine use of a particular key. Information about timing options from manual page dnssec-settime(8) follow:
-P date/offset
Sets the date on which a key is to be published to the zone. After that date, the key will be included in the zone but will not be used to sign it.
-P sync date/offset
Sets the date on which CDS and CDNSKEY records that match this key are to be published to the zone.
-A date/offset
Sets the date on which the key is to be activated. After that date, the key will be included in the zone and used to sign it.
-R date/offset
Sets the date on which the key is to be revoked. After that date, the key will be flagged as revoked. It will be included in the zone and will be used to sign it.
-I date/offset
:
Sets the date on which the key is to be retired. After that date, the key will still be included in the zone, but it will not be used to sign it.
-D date/offset
Sets the date on which the key is to be deleted. After that date, the key will no longer be included in the zone. (It may remain in the key repository, however.)
-D sync date/offset
Sets the date on which the CDS and CDNSKEY records that match this key are to be deleted.
Private key file format generated by dnssec-* utilities looks like this:
Created: 20151220115444
Publish: 20151220135927
Activate: 20151220145927
Revoke: 20151221083330
Inactive: 20151220155927
Delete: 20151220175927
SyncPublish: 20151220125927
SyncDelete: 20151220165927
Created
timestamp is set to current time when dnssec-* utility
is called.SyncPublish
(-P sync
) and SyncDelete
(-D sync
) options.Revoke
(-R
) because RFC 5011 is not
supported.According to wiki page Key States, OpenDNSSEC is internally using following key states:
Enforcer is using database table dnsseckeys
to store key state and
timestamps for particular key. These timestamps often refer to future,
to a planned state transitions. Beware: dnsseckeys
table contains
timestamps in local time zone!
Internally a key is represented as KsmKey
structure filled by
opendnssec//enforcer/ksm/ksm_key.c:KsmKey()
function.
Enforcer normally generates configuration files for signerd
and
signerd
then signs the zone using specifed keys. Relevant parts of
signerd
configuration format are described in
opendnssec/conf/signconf.rnc:
element Key {
# sign all the DNSKEY RRsets with this key?
element KSK { empty }?,
# sign all non-DNSKEY RRsets with this key?
element ZSK { empty }?,
# include this key in the zonefile?
element Publish { empty }?,
# deactivate this key (i.e. do not recycle any signatures)
element Deactivate { empty }?,
# Ignore DS and use RFC5011 to maintain chain of trust.
element RFC5011 { empty }?
}
Element Deactivate
is completely unused so we can ignore it.
Currently we do not have server-side support for RFC 5011 so we will
ignore RFC5011
, too.
Configuration for signerd
is generated by
opendnssec/enforcer/enforcerd/enforcer.c:commGenSignConf()
function.
Most importantly, it iterates over all keys returned by enforcer/ksm/ksm_request.c:KsmRequestIssueKeys():
/*+
* KsmRequestIssueKeys - Issue Keys
*
* Description:
* Done as the last step in the "REQUEST KEYS" operation, this actually
* issues the keys that should be in the current zone file. All keys in
* the "publish", "ready", "active" and "retire" states are included.
*
* Arguments:
* int keytype
* Type of keys required.
*
* KSM_REQUEST_CALLBACK callback
* Callback function called for every key that will be issued.
* ...
*/
The code actually selects all keys in states (KSM_STATE_PUBLISH, KSM_STATE_READY, KSM_STATE_ACTIVE, KSM_STATE_RETIRE, KSM_STATE_KEYPUBLISH).
Keys returned by KsmRequestIssueKeys()
are further processed by
callback function
opendnssec/enforcer/enforcerd/enforcer.c:commKeyConfig()
which transforms key state into signerd
configuration:
if (key_data->keytype == KSM_TYPE_KSK) {
if (!(key_data->rfc5011 && key_data->state == KSM_STATE_PUBLISH))
fprintf(file, "\t\t\t\t<KSK />\n");
}
if (key_data->keytype == KSM_TYPE_ZSK && key_data->state == KSM_STATE_ACTIVE)
{
fprintf(file, "\t\t\t\t<ZSK />\n");
}
if ((key_data->state > KSM_STATE_GENERATE && key_data->state < KSM_STATE_DEAD) || key_data->state == KSM_STATE_KEYPUBLISH)
{
fprintf(file, "\t\t\t\t<Publish />\n");
}
OpenDNSSEC’s key state constants are defined in opendnssec/enforcer/ksm/include/ksm/ksm.h:
#define KSM_STATE_GENERATE 1
#define KSM_STATE_PUBLISH 2
#define KSM_STATE_READY 3
#define KSM_STATE_ACTIVE 4
#define KSM_STATE_RETIRE 5
#define KSM_STATE_DEAD 6
#define KSM_STATE_DSSUB 7
#define KSM_STATE_DSPUBLISH 8
#define KSM_STATE_DSREADY 9
#define KSM_STATE_KEYPUBLISH 10
We need to make sure that current state in OpenDNSSEC matches key state in LDAP and in BIND.
We cannot unconditionaly copy timestamps of planned state changes from
dnsseckeys
table to LDAP and to BIND private key files.
The reason is that planned key state transition may not happen for some reason. These reasons include not running OpenDNSSEC key daemon, or a bug in export/import scripts which will prevent upload of new keys and metadata to LDAP. In these situations BIND would actually do the transition as planned which may leave the DNS zone with only inactive keys, which would break chain of trust because parent zone would still contain DS record. Example of what would happen because of unconditional copying of timestamp:
enforcerd
or break replication from DNSSEC key master.Solution is to closely map meaning of key states in enforcerd
and
signerd
to meaning of key states expressed by BIND timestamps. Added
restriction is that BIND should not see timestamps for planned key state
transitions because these may not happen as planned.
Please note that this is not 1:1 mapping because OpenDNSSEC has more states than BIND. E.g. READY key state does not have its direct equivalent in BIND. Also, the logic is different for ZSK and KSK (see commKeyConfig()).
For current and all preceding key states, timestamps in dnsseckeys
SQL table used by enforcerd
always refer to the past. E.g. if key
state is PUBLISH
key then publish
timestamp is <= current time.
KsmRequestIssueKeys()
limits set of key states which can be visible in DNS zones to
(KSM_STATE_PUBLISH, KSM_STATE_READY, KSM_STATE_ACTIVE,
KSM_STATE_RETIRE, KSM_STATE_KEYPUBLISH). Keys in all other states
are not included in the zone, which means that current time has to be
before Publish
or past Dead
timestamps in BIND key file, or that
no timestamp except Created
can be present in the BIND key file.
Created
: BIND timestamp does nothing functionaly-wise so we may
always copy it.Publish
: According to
commKeyConfig()
all keys in states (KSM_STATE_PUBLISH, KSM_STATE_READY,
KSM_STATE_ACTIVE, KSM_STATE_RETIRE, KSM_STATE_KEYPUBLISH)
should be always published. Given the
assumption
above, we may simply copy
publish
timestamp to LDAP for all keys in states.Delete
: This state directly maps to
dead state.Transformation of other states depends on key type conditions in commKeyConfig():
Activate
: Considering that we do not support RFC 5011 yet,
commKeyConfig()
will always use all KSK keys in states (KSM_STATE_PUBLISH,
KSM_STATE_READY, KSM_STATE_ACTIVE, KSM_STATE_RETIRE,
KSM_STATE_KEYPUBLISH) for signing. Using our
assumption,
we can always put
publish
timestamp from SQL database into Activate
field in LDAP and key
file.Inactive
: State
retired is
effectively ignored for KSK so this field will be always empty.Activate
: Equal to
active state.Inactive
: Equal to
retired state.