Browse Source

added logger

tags/v2.0.0
Robin Thoni 8 years ago
parent
commit
61e6edde2f
2 changed files with 145 additions and 23 deletions
  1. 18
    0
      fake-letsencrypt.sh
  2. 127
    23
      sitegen.py

+ 18
- 0
fake-letsencrypt.sh View File

@@ -0,0 +1,18 @@
1
+#! /usr/bin/env sh
2
+
3
+dir="$(dirname $(readlink -f "${0}"))"
4
+host="${1}"
5
+
6
+if [ "${host}" = "error.com" ]
7
+then
8
+    echo "Failed to get certificate" >&2
9
+    exit 1
10
+fi
11
+
12
+leDir="${dir}/tests/etc/letsencypt/live/${host}"
13
+
14
+sleep 1
15
+
16
+mkdir -p "${leDir}"
17
+touch "${leDir}/cert.pem" "${leDir}/privkey.pem" "${leDir}/chain.pem"
18
+echo "Generation successful"

+ 127
- 23
sitegen.py View File

@@ -3,6 +3,7 @@
3 3
 import json
4 4
 import argparse
5 5
 import os
6
+import subprocess
6 7
 
7 8
 from os import path
8 9
 
@@ -25,6 +26,7 @@ class SiteGen:
25 26
     templatesDir = ""
26 27
     certRenewTime = ""
27 28
     letsencryptCommand = ""
29
+    letsencryptDir = ""
28 30
     certDir = ""
29 31
 
30 32
     def __init__(self, config):
@@ -36,8 +38,13 @@ class SiteGen:
36 38
         self.templatesDir = path.join(self.confDir, "templates")
37 39
         self.certRenewTime = config["certRenewTime"]
38 40
         self.letsencryptCommand = config["letsencryptCommand"]
41
+        self.letsencryptDir = config["letsencryptDir"]
39 42
         self.certDir = config["certDir"]
40 43
 
44
+    def make_dirs(self):
45
+        if not path.isdir(self.certDir):
46
+            os.makedirs(self.certDir)
47
+
41 48
     def get_hook_dir(self, hook_type, is_enabled):
42 49
         return path.join(self.hooksEnabledDir if is_enabled else self.hooksAvailableDir, hook_type)
43 50
 
@@ -56,26 +63,110 @@ class SiteGen:
56 63
     def is_hook_enabled(self, hook_type, hook_name):
57 64
         return self.is_hook_present(hook_type, hook_name, True)
58 65
 
59
-    def cert_request(self, domain):
60
-        pass
61
-
62
-    def cert_check(self, domain):
63
-        pass
64
-
65
-    def cert_renew(self, domain):
66
-        pass
67
-
68
-    def site_create(self, domain):
66
+    def get_letsencrypt_dir(self, domain):
67
+        return path.join(self.letsencryptDir, domain)
68
+
69
+    def symlink_letsencrypt_file(self, domain, file, outfile):
70
+        letsencrypt_cert_file = path.abspath(self.get_letsencrypt_dir(domain))
71
+        my_cert_file = path.join(self.certDir, outfile)
72
+        if path.lexists(my_cert_file):
73
+            os.remove(my_cert_file)
74
+        os.symlink(path.join(letsencrypt_cert_file, file), my_cert_file)
75
+
76
+    def get_cert_files(self, domain):
77
+        return [path.abspath(path.join(self.certDir, domain + ".crt")),
78
+                path.abspath(path.join(self.certDir, domain + ".key")),
79
+                path.abspath(path.join(self.certDir, domain + "-chain.crt"))]
80
+
81
+    def execute(self, exe, args, get_output):
82
+        args.insert(0, exe)
83
+        proc = subprocess.Popen(args, stdout=(subprocess.PIPE if get_output else None))
84
+        out = proc.communicate()
85
+        return proc.returncode, out[0]
86
+
87
+    def execute_hooks(self, hook_type, args):
88
+        for hook_name in self.get_hook_files(hook_type, True):
89
+            self.execute(self.get_hook_file(hook_type, hook_name, True), args, False)
90
+
91
+    def is_cert_present(self, domain):
92
+        cert_files = self.get_cert_files(domain)
93
+        for cert_file in cert_files:
94
+            if not path.isfile(cert_file):
95
+                return False
96
+        return True
97
+
98
+    def get_cert_end_date(self, domain):
99
+        cert_files = self.get_cert_files(domain)
100
+        res, out = self.execute("openssl", ["x509", "-noout", "-in", cert_files[0], "-enddate"], True)
101
+        if res == 0:
102
+            return out.decode("UTF-8").split("=")[1][:-1]
103
+        return None
104
+
105
+    def is_cert_gonna_expire(self, domain, checkend):
106
+        cert_files = self.get_cert_files(domain)
107
+        res, out = self.execute("openssl", ["x509", "-noout", "-in", cert_files[0], "-checkend", str(checkend)], True)
108
+        return res == 1
109
+
110
+    def get_all_domains(self):
111
+        files = os.listdir(self.certDir)
112
+        files.sort()
113
+        domains = []
114
+        for file in files:
115
+            if file.endswith(".crt") and self.is_cert_present(file[:-4]):
116
+                domains.append(file[:-4])
117
+        return domains
118
+
119
+    def cert_request(self, domain, logger):
120
+        logger("Requesting: %s" % domain)
121
+
122
+        res, out = self.execute(self.letsencryptCommand, [domain], False)
123
+        if res != 0:
124
+            raise SiteGenException("Certificate request failed with code %i" % res, res)
125
+
126
+        self.symlink_letsencrypt_file(domain, "cert.pem", domain + ".crt")
127
+        self.symlink_letsencrypt_file(domain, "privkey.pem", domain + ".key")
128
+        self.symlink_letsencrypt_file(domain, "chain.pem", domain + "-chain.crt")
129
+
130
+        cert_files = self.get_cert_files(domain)
131
+        cert_files.insert(0, domain)
132
+        self.execute_hooks("cert", cert_files)
133
+
134
+    def certs_request(self, domains, logger):
135
+        for domain in domains:
136
+            self.cert_request(domain, logger)
137
+
138
+    def cert_check(self, domain, logger):
139
+        if not self.is_cert_present(domain):
140
+            raise SiteGenException("Certificate not present: %s" % domain, 1)
141
+        if self.is_cert_gonna_expire(domain, self.certRenewTime):
142
+            logger("%s: %s" % (domain, self.get_cert_end_date(domain)))
143
+            return True
144
+        return False
145
+
146
+    def certs_check(self, domains, logger):
147
+        for domain in domains:
148
+            self.cert_check(domain, logger)
149
+
150
+    def cert_renew(self, domain, logger):
151
+        if self.cert_check(domain, logger):
152
+            self.cert_request(domain, logger)
153
+
154
+    def certs_renew(self, domains, logger):
155
+        for domain in domains:
156
+            self.cert_renew(domain, logger)
157
+
158
+    def site_create(self, domain, logger):
69 159
         pass
70 160
 
71
-    def site_remove(self, domain):
161
+    def site_remove(self, domain, logger):
72 162
         pass
73 163
 
74
-    def hook_enable(self, hook_type, hook_name):
164
+    def hook_enable(self, hook_type, hook_name, logger):
75 165
         if not self.is_hook_present(hook_type, hook_name, False):
76 166
             raise SiteGenException("Hook is not present", 1)
77 167
         if self.is_hook_enabled(hook_type, hook_name):
78 168
             raise SiteGenException("Hook is already enabled", 0)
169
+        logger("Enabling %s %s" % (hook_type, hook_name))
79 170
         hook_dir = self.get_hook_dir(hook_type, hook_name)
80 171
         if not path.isdir(hook_dir):
81 172
             os.makedirs(hook_dir)
@@ -85,11 +176,12 @@ class SiteGen:
85 176
 
86 177
         os.symlink(hook_relative_file, hook_file_enabled)
87 178
 
88
-    def hook_disable(self, hook_type, hook_name):
179
+    def hook_disable(self, hook_type, hook_name, logger):
89 180
         if not self.is_hook_present(hook_type, hook_name, False):
90 181
             raise SiteGenException("Hook is not present", 1)
91 182
         if not self.is_hook_enabled(hook_type, hook_name):
92 183
             raise SiteGenException("Hook is not enabled", 0)
184
+        logger("Disabling %s %s" % (hook_type, hook_name))
93 185
         os.remove(self.get_hook_file(hook_type, hook_name, True))
94 186
 
95 187
 
@@ -119,35 +211,47 @@ def main():
119 211
         config = json.load(f)
120 212
 
121 213
     site_gen = SiteGen(config)
122
-    print(site_gen.get_hook_files("site", True))
214
+
215
+    site_gen.make_dirs()
216
+
217
+    logger = print
123 218
 
124 219
     try:
125 220
         if args.cert_request is not None:
126
-            site_gen.cert_request(args.cert_request)
221
+            if args.cert_request == "":
222
+                site_gen.certs_request(site_gen.get_all_domains(), logger)
223
+            else:
224
+                site_gen.cert_request(args.cert_request, logger)
127 225
 
128 226
         elif args.cert_check is not None:
129
-            site_gen.cert_check(args.cert_check)
227
+            if args.cert_check == "":
228
+                site_gen.certs_check(site_gen.get_all_domains(), logger)
229
+            else:
230
+                site_gen.cert_check(args.cert_check, logger)
130 231
 
131 232
         elif args.cert_renew is not None:
132
-            site_gen.cert_renew(args.cert_renew)
233
+            if args.cert_renew == "":
234
+                site_gen.certs_renew(site_gen.get_all_domains(), logger)
235
+            else:
236
+                site_gen.cert_renew(args.cert_renew, logger)
133 237
 
134 238
         elif args.site_create is not None:
135
-            site_gen.site_create(args.site_create)
239
+            site_gen.site_create(args.site_create, logger)
136 240
 
137 241
         elif args.site_remove is not None:
138
-            site_gen.site_remove(args.site_remove)
242
+            site_gen.site_remove(args.site_remove, logger)
139 243
 
140 244
         elif args.site_hook_enable is not None:
141
-            site_gen.hook_enable("site", args.site_hook_enable)
245
+            site_gen.hook_enable("site", args.site_hook_enable, logger)
142 246
 
143 247
         elif args.site_hook_disable is not None:
144
-            site_gen.hook_disable("site", args.site_hook_disable)
248
+            site_gen.hook_disable("site", args.site_hook_disable, logger)
145 249
 
146 250
         elif args.hook_cert_enable is not None:
147
-            site_gen.hook_enable("cert", args.hook_cert_enable)
251
+            site_gen.hook_enable("cert", args.hook_cert_enable, logger)
148 252
 
149 253
         elif args.hook_cert_disable is not None:
150
-            site_gen.hook_disable("cert", args.hook_cert_disable)
254
+            site_gen.hook_disable("cert", args.hook_cert_disable, logger)
151 255
 
152 256
         else:
153 257
             parser.print_help()

Loading…
Cancel
Save