Created
February 8, 2016 18:38
-
-
Save nitmir/b81307b0be12031a5b71 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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