Skip to content

Instantly share code, notes, and snippets.

@nitmir
Created February 8, 2016 18:38
Show Gist options
  • Save nitmir/b81307b0be12031a5b71 to your computer and use it in GitHub Desktop.
Save nitmir/b81307b0be12031a5b71 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
import os
import shutil
import shelltoolbox
BASE_PATH = "/etc/opendkim"
BASE_KEY_PATH = os.path.join(BASE_PATH, "keys")
BASE_SELECTOR = "mail"
OPENDKIM_UID = 148
OPENDKIM_GID = 163
_generate_key = shelltoolbox.command("/usr/bin/opendkim-genkey")
update_serial = shelltoolbox.command("/etc/bind/update_serial")
reload_opendkim = shelltoolbox.command("/usr/sbin/service", "opendkim", "reload")
def incr():
file = os.path.join(BASE_KEY_PATH, 'incr')
if os.path.isfile(file):
with open(file) as f:
i = int(f.read().strip())
else:
i = 5
i+=1
with open(file, 'w') as f:
f.write("%d" % i)
return i
def get_domains():
domains = []
for file in os.listdir(BASE_KEY_PATH):
if os.path.isdir(os.path.join(BASE_KEY_PATH, file)) and not file.startswith('.'):
domains.append(file)
return domains
def KeyTable(domains, selector):
data = []
for domain in domains:
data.append(
"%(selector)s._domainkey.%(domain)s %(domain)s:%(selector)s:%(key_path)s/%(domain)s/%(selector)s.private" % {
'selector': selector,
'domain': domain,
'key_path': BASE_KEY_PATH,
}
)
data.append("")
KeyTable_path = os.path.join(BASE_PATH, "KeyTable")
with open(KeyTable_path + ".new", 'w') as f:
f.write("\n".join(data))
os.rename(KeyTable_path + ".new", KeyTable_path)
def SigningTable(domains, selector):
data = []
for domain in domains:
data.append("*@%(domain)s %(selector)s._domainkey.%(domain)s" % {'domain': domain, 'selector': selector})
data.append("")
SigningTable_path = os.path.join(BASE_PATH, "SigningTable")
with open(SigningTable_path + ".new", 'w') as f:
f.write("\n".join(data))
os.rename(SigningTable_path + ".new", SigningTable_path)
def TrustedHosts(domains):
data = [ "127.0.0.1", "localhost", "10.0.0.0/8", "192.168.0.0/16", ""]
data.extend(domains)
data.append("")
for domain in domains:
data.append("*.%s" % domain)
data.append("")
TrustedHosts_path = os.path.join(BASE_PATH, "TrustedHosts")
with open(TrustedHosts_path + ".new", 'w') as f:
f.write("\n".join(data))
os.rename(TrustedHosts_path + ".new", TrustedHosts_path)
def generate_key(domain, selector):
ret = _generate_key('-s', selector, '-d', domain, '-b', "2048")
os.chmod("%s.txt" % selector, 0644)
os.chown("%s.private" % selector, OPENDKIM_UID, OPENDKIM_GID)
return ret
def rotate(domain, i):
dir = os.path.join(BASE_KEY_PATH, domain)
if os.path.isdir(dir):
os.chdir(dir)
try:
os.remove("%s%s.txt" % (BASE_SELECTOR, (i-2)))
os.remove("%s%s.private" % (BASE_SELECTOR, (i-2)))
except OSError:
pass
try:
current_pubkey = os.readlink("current.txt")
except OSError:
generate_key(domain, "%s%s" % (BASE_SELECTOR, (i-1)))
current_pubkey = "%s%s.txt" % (BASE_SELECTOR, (i-1))
try:
next_pubkey = os.readlink("next.txt")
except OSError:
generate_key(domain, "%s%s" % (BASE_SELECTOR, i))
next_pubkey = "%s%s.txt" % (BASE_SELECTOR, i)
try:
os.remove("retired.txt")
except OSError:
pass
os.symlink(current_pubkey, "retired.txt")
try:
os.remove("current.txt")
except OSError:
pass
os.symlink(next_pubkey, "current.txt")
try:
os.remove("next.txt")
except OSError:
pass
selector = "%s%s" % (BASE_SELECTOR, (i+1))
generate_key(domain, selector)
os.symlink("%s.txt" % selector, "next.txt")
print "%s: %s" % (domain, update_serial(domain))
if __name__ == "__main__":
domains = get_domains()
print "Domains found: %s" % ', '.join(domains)
i = incr()
selector = "%s%s" % (BASE_SELECTOR, i)
for domain in domains:
rotate(domain, i)
KeyTable(domains, selector)
SigningTable(domains, selector)
TrustedHosts(domains)
reload_opendkim()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment