Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

just some ideas for fixes / conveniences #79

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
40 changes: 40 additions & 0 deletions get_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import gi
gi.require_version('Gtk','3.0')
from gi.repository import Gtk, GLib
b = Gtk.Builder()
b.add_from_file("info.glade.xml")
info = {}
class UI:
def __getattr__(self,name):
val = b.get_object(name)
setattr(self,name,val)
return val
def commit(self, button):
prefixes = set()
for prefix, in self.prefixes:
prefixes.add(prefix)
self.info['prefixes'] = tuple(prefixes)
self.info['email'] = self.email.get_text()
Gtk.main_quit()
def get_info(self,domain, info):
self.info = info
self.domain.set_text(domain)
if 'prefixes' in info:
for prefix in info['prefixes']:
self.prefixes.append([prefix])
if 'email' in info:
self.email.set_text(info['email'])
self.top.show_all()
Gtk.main()
return self.info
def hide(self,*a):
ui.top.hide()
Gtk.main_quit()

ui = UI()
# email, domain, prefixes, done
ui.top.connect('delete-event',ui.hide)
ui.done.connect('clicked',ui.commit)

import sys
sys.modules[__name__] = ui.get_info
134 changes: 134 additions & 0 deletions info.glade.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-apply</property>
</object>
<object class="GtkListStore" id="prefixes">
<columns>
<!-- column-name prefix -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkWindow" id="top">
<property name="can_focus">False</property>
<property name="default_height">400</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Email</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="email">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">@</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="domain">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">(domain)</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkTreeView">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="model">prefixes</property>
<property name="headers_clickable">False</property>
<property name="enable_search">False</property>
<property name="show_expanders">False</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="sizing">fixed</property>
<property name="title" translatable="yes">Prefixes</property>
<child>
<object class="GtkCellRendererText">
<property name="editable">True</property>
</object>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="done">
<property name="label" translatable="yes">OK</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">image1</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
109 changes: 109 additions & 0 deletions make.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/usr/bin/env python3
import os,sys

if not 'domain' in os.environ:
raise SystemExit("domain=foo.bar.com python make.py")

domain = os.environ['domain']
out = os.environ.get("out","/etc/letsencrypt/")

mkdir = os.mkdir
exists = os.path.exists
J = os.path.join

import subprocess
call = subprocess.check_call

def need_update(target,*deps):
def deco(handle):
if exists(target):
test = os.stat(target).st_mtime
for dep in deps:
# this is eager, not lazy like make
assert exists(dep),"Dependencies should be built first"
if test < os.stat(dep).st_mtime:
break
else:
return
else:
test = None
# need rebuild
try:
temp = target+".temp"
ret = handle(temp)
os.rename(temp,target)
except:
# don't leave targets around if they've been touched
# and we errored out!
if (exists(target) and
(test is None or
os.stat(target).st_mtime != test)):
os.unlink(target)
raise
return deco
U = need_update

def check_location(loc):
if not exists(loc):
os.makedirs(loc)
key = J(loc,"key")
pub = J(loc,"pub")

if not exists(key):
call(["openssl","genrsa","-out",key,"4096"])
@U(pub,key)
def _(pub):
call(["openssl","rsa", "-in", key,"-pubout","-out",pub])
return key,pub

def user(name):
return J("user",name)

def check_cert(loc):
key,pub = check_location(loc)
csr = J(loc,"csr")
cert = J(loc,"cert")
import json
info = J(loc,"info.json")
try:
with open(info) as inp:
info = json.load(inp)
if 'edit' in os.environ:
info = get_info(domain, info)
except (FileNotFoundError,TypeError,ValueError):
# Ask user for info
import get_info
derp = get_info(domain,{'email': 'webmaster'})
with open(info,"wt") as out:
info = derp
json.dump(info,out)

@U(csr,key)
def _(csr):
print('make CSR')
from make_csr import make_csr
make_csr(csr, domain, key, *info['prefixes'])
@U(cert,csr)
def _(cert):
with open(cert,'wt') as out:
import sign_csr
out.write(sign_csr(pubkey=user("pub"),
csr=csr,
privkey=user("key"),
email=info['email']+'@'+domain,
file_based="run_server" not in os.environ,
debug='debug' in os.environ))

check_location("user")

if out:
if not exists(out):
os.makedirs(out)
out = J(out,domain)
else:
out = domain

if not exists(out):
os.mkdir(out)

check_cert(out)
37 changes: 37 additions & 0 deletions make_csr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import os,sys
import subprocess as s
call = s.check_call
import shutil
import tempfile

def make_csr(csr,domain,key,*prefixes):
if len(prefixes) == 0:
return call(["openssl",
"req","-new", "-sha256", "-key", key,
"-subj", "/CN="+domain,"-out",csr])
domains = [domain]
for prefix in prefixes:
domains.append(prefix+"."+domain)
domains = ("DNS:"+domain for domain in domains)
domains = ",".join(domains)
with tempfile.NamedTemporaryFile() as out:
with open("/etc/ssl/openssl.cnf","rb") as inp:
shutil.copyfileobj(inp,out)
out.write(("""
[SAN]
subjectAltName="""+domains).encode('utf-8'))
out.flush()
call(["openssl",
"req", "-new", "-sha256","-key", key, "-subj", "/",
"-reqexts", "SAN", "-config", out.name,"-out",csr])

if __name__ == '__main__':
key,domain = sys.argv[1:3]
if len(sys.argv) > 4:
status = make_csr(domain+"/csr",domain,key,*sys.argv[4:])
else:
status = make_csr(domain+"/csr",domain,key)
if status != 0:
raise SystemExit(status)


Loading