dnssec #13
4 changed files with 65 additions and 32 deletions
2
bundles/bind/files/dnssec.key
Normal file
2
bundles/bind/files/dnssec.key
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
; ${type} ${key_id}
|
||||||
|
${record}
|
13
bundles/bind/files/dnssec.private
Normal file
13
bundles/bind/files/dnssec.private
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
Private-key-format: ${data['Private-key-format']}
|
||||||
|
Algorithm: ${data['Algorithm']}
|
||||||
|
Modulus: ${data['Modulus']}
|
||||||
|
PublicExponent: ${data['PublicExponent']}
|
||||||
|
PrivateExponent: ${data['PrivateExponent']}
|
||||||
|
Prime1: ${data['Prime1']}
|
||||||
|
Prime2: ${data['Prime2']}
|
||||||
|
Exponent1: ${data['Exponent1']}
|
||||||
|
Exponent2: ${data['Exponent2']}
|
||||||
|
Coefficient: ${data['Coefficient']}
|
||||||
|
Created: ${data['Created']}
|
||||||
|
Publish: ${data['Publish']}
|
||||||
|
Activate: ${data['Activate']}
|
|
@ -23,6 +23,20 @@ directories[f'/var/lib/bind'] = {
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
directories[f'/var/cache/bind/keys'] = {
|
||||||
|
'group': 'bind',
|
||||||
|
'purge': True,
|
||||||
|
'needs': [
|
||||||
|
'pkg_apt:bind9',
|
||||||
|
],
|
||||||
|
'needed_by': [
|
||||||
|
'svc_systemd:bind9',
|
||||||
|
],
|
||||||
|
'triggers': [
|
||||||
|
'svc_systemd:bind9:restart',
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
files['/etc/default/bind9'] = {
|
files['/etc/default/bind9'] = {
|
||||||
'source': 'defaults',
|
'source': 'defaults',
|
||||||
'needed_by': [
|
'needed_by': [
|
||||||
|
@ -132,32 +146,20 @@ for view_name, view_conf in master_node.metadata.get('bind/views').items():
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for zone, conf in master_node.metadata.get('bind/zones').items():
|
for zone_name, zone_conf in master_node.metadata.get('bind/zones').items():
|
||||||
directories[f"/var/lib/bind/{view_name}"] = {
|
for sk in ('zsk_data', 'ksk_data'):
|
||||||
'owner': 'bind',
|
data = zone_conf['dnssec'][sk]
|
||||||
'group': 'bind',
|
|
||||||
'purge': True,
|
|
||||||
'needed_by': [
|
|
||||||
'svc_systemd:bind9',
|
|
||||||
],
|
|
||||||
'triggers': [
|
|
||||||
'svc_systemd:bind9:restart',
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
for zone_name, zone_conf in view_conf['zones'].items():
|
files[f"/var/cache/bind/keys/K{zone_name}.+008+{data['key_id']}.private"] = {
|
||||||
files[f"/var/lib/bind/{view_name}/{zone_name}"] = {
|
|
||||||
'source': 'db',
|
|
||||||
'content_type': 'mako',
|
'content_type': 'mako',
|
||||||
'unless': f"test -f /var/lib/bind/{view_name}/{zone_name}" if zone_conf.get('allow_update', False) else 'false',
|
'source': 'dnssec.private',
|
||||||
'context': {
|
'context': {
|
||||||
'serial': datetime.now().strftime('%Y%m%d%H'),
|
'data': data['privkey_file'],
|
||||||
'records': zone_conf['records'],
|
|
||||||
'hostname': node.metadata.get('bind/hostname'),
|
|
||||||
'type': node.metadata.get('bind/type'),
|
|
||||||
},
|
},
|
||||||
'owner': 'bind',
|
|
||||||
'group': 'bind',
|
'group': 'bind',
|
||||||
|
'needs': [
|
||||||
|
'pkg_apt:bind9',
|
||||||
|
],
|
||||||
'needed_by': [
|
'needed_by': [
|
||||||
'svc_systemd:bind9',
|
'svc_systemd:bind9',
|
||||||
],
|
],
|
||||||
|
@ -166,6 +168,27 @@ for zone, conf in master_node.metadata.get('bind/zones').items():
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
files[f"/var/cache/bind/keys/K{zone_name}.+008+{data['key_id']}.key"] = {
|
||||||
|
'content_type': 'mako',
|
||||||
|
'source': 'dnssec.key',
|
||||||
|
'context': {
|
||||||
|
'type': sk,
|
||||||
|
'key_id': data['key_id'],
|
||||||
|
'record': data['dnskey_record'],
|
||||||
|
},
|
||||||
|
'group': 'bind',
|
||||||
|
'needs': [
|
||||||
|
'pkg_apt:bind9',
|
||||||
|
],
|
||||||
|
'needed_by': [
|
||||||
|
'svc_systemd:bind9',
|
||||||
|
],
|
||||||
|
'triggers': [
|
||||||
|
'svc_systemd:bind9:restart',
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
svc_systemd['bind9'] = {}
|
svc_systemd['bind9'] = {}
|
||||||
|
|
||||||
actions['named-checkconf'] = {
|
actions['named-checkconf'] = {
|
||||||
|
|
|
@ -30,11 +30,6 @@ def generate_signing_key_pair(zone, salt, repo):
|
||||||
privkey = repo.libs.rsa.generate_deterministic_rsa_private_key(
|
privkey = repo.libs.rsa.generate_deterministic_rsa_private_key(
|
||||||
b64decode(str(repo.vault.random_bytes_as_base64_for(f'dnssec {salt} ' + zone)))
|
b64decode(str(repo.vault.random_bytes_as_base64_for(f'dnssec {salt} ' + zone)))
|
||||||
)
|
)
|
||||||
privkey_pem = privkey.private_bytes(
|
|
||||||
crypto_serialization.Encoding.PEM,
|
|
||||||
crypto_serialization.PrivateFormat.PKCS8,
|
|
||||||
crypto_serialization.NoEncryption()
|
|
||||||
).decode()
|
|
||||||
|
|
||||||
public_exponent = privkey.private_numbers().public_numbers.e
|
public_exponent = privkey.private_numbers().public_numbers.e
|
||||||
modulo = privkey.private_numbers().public_numbers.n
|
modulo = privkey.private_numbers().public_numbers.n
|
||||||
|
@ -44,6 +39,7 @@ def generate_signing_key_pair(zone, salt, repo):
|
||||||
exponent1 = privkey.private_numbers().dmp1
|
exponent1 = privkey.private_numbers().dmp1
|
||||||
exponent2 = privkey.private_numbers().dmq1
|
exponent2 = privkey.private_numbers().dmq1
|
||||||
coefficient = privkey.private_numbers().iqmp
|
coefficient = privkey.private_numbers().iqmp
|
||||||
|
flags = 256 if salt == 'zsk' else 257
|
||||||
|
|
||||||
dnskey = ''.join(privkey.public_key().public_bytes(
|
dnskey = ''.join(privkey.public_key().public_bytes(
|
||||||
crypto_serialization.Encoding.PEM,
|
crypto_serialization.Encoding.PEM,
|
||||||
|
@ -53,7 +49,7 @@ def generate_signing_key_pair(zone, salt, repo):
|
||||||
return {
|
return {
|
||||||
'dnskey': dnskey,
|
'dnskey': dnskey,
|
||||||
'dnskey_record': f'{zone}. IN DNSKEY {flags} {protocol} {algorithm} {dnskey}',
|
'dnskey_record': f'{zone}. IN DNSKEY {flags} {protocol} {algorithm} {dnskey}',
|
||||||
'privkey': privkey_pem,
|
'key_id': _calc_keyid(flags, protocol, algorithm, dnskey),
|
||||||
'privkey_file': {
|
'privkey_file': {
|
||||||
'Private-key-format': 'v1.3',
|
'Private-key-format': 'v1.3',
|
||||||
'Algorithm': f'{algorithm} ({algorithm_name})',
|
'Algorithm': f'{algorithm} ({algorithm_name})',
|
||||||
|
@ -106,13 +102,12 @@ def _calc_keyid(flags, protocol, algorithm, dnskey):
|
||||||
|
|
||||||
return ((cnt & 0xFFFF) + (cnt >> 16)) & 0xFFFF
|
return ((cnt & 0xFFFF) + (cnt >> 16)) & 0xFFFF
|
||||||
|
|
||||||
def dnskey_to_ds(zone, flags, protocol, algorithm, dnskey):
|
def dnskey_to_ds(zone, flags, protocol, algorithm, dnskey, key_id):
|
||||||
keyid = _calc_keyid(flags, protocol, algorithm, dnskey)
|
|
||||||
ds = _calc_ds(zone, flags, protocol, algorithm, dnskey)
|
ds = _calc_ds(zone, flags, protocol, algorithm, dnskey)
|
||||||
|
|
||||||
return[
|
return[
|
||||||
f"{zone}. IN DS {str(keyid)} {str(algorithm)} 1 {ds['sha1'].lower()}",
|
f"{zone}. IN DS {str(key_id)} {str(algorithm)} 1 {ds['sha1'].lower()}",
|
||||||
f"{zone}. IN DS {str(keyid)} {str(algorithm)} 2 {ds['sha256'].lower()}",
|
f"{zone}. IN DS {str(key_id)} {str(algorithm)} 2 {ds['sha256'].lower()}",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Result
|
# Result
|
||||||
|
@ -120,7 +115,7 @@ def dnskey_to_ds(zone, flags, protocol, algorithm, dnskey):
|
||||||
def generate_dnssec_for_zone(zone, node):
|
def generate_dnssec_for_zone(zone, node):
|
||||||
zsk_data = generate_signing_key_pair(zone, salt='zsk', repo=node.repo)
|
zsk_data = generate_signing_key_pair(zone, salt='zsk', repo=node.repo)
|
||||||
ksk_data = generate_signing_key_pair(zone, salt='ksk', repo=node.repo)
|
ksk_data = generate_signing_key_pair(zone, salt='ksk', repo=node.repo)
|
||||||
ds_records = dnskey_to_ds(zone, flags, protocol, algorithm, ksk_data['dnskey'])
|
ds_records = dnskey_to_ds(zone, flags, protocol, algorithm, ksk_data['dnskey'], ksk_data['key_id'])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'zsk_data': zsk_data,
|
'zsk_data': zsk_data,
|
||||||
|
|
Loading…
Reference in a new issue