· 8 years ago · Jan 20, 2018, 04:16 AM
1#!/usr/bin/env python3
2
3import os
4import sys
5import sqlite3
6import time
7
8DATABASE = '/etc/puppetlabs/puppet/autosign.db'
9
10def get_psks_from_csr(csr_pem):
11 supplied_psks = []
12 try:
13 from asn1crypto import csr, pem
14 _, _, csr_der = pem.unarmor(csr_pem.encode('ascii'))
15 loaded = csr.CertificationRequest.load(csr_der)
16 for item in loaded['certification_request_info']['attributes'].native:
17 if item['type'] == 'challenge_password':
18 supplied_psks.extend(item['values'])
19 except Exception:
20 # Just fail. No autosigning if no PSKs supplied
21 sys.exit(1)
22
23 return supplied_psks
24
25
26def init_db():
27 db = sqlite3.connect(DATABASE)
28 c = db.cursor()
29
30 c.execute('''
31CREATE TABLE IF NOT EXISTS autosign_tokens (token TEXT PRIMARY KEY, valid_until TEXT NOT NULL);
32''')
33 c.close()
34 return 0
35
36def create_token(valid_for_seconds):
37 import string
38 import random
39 db = sqlite3.connect(DATABASE)
40 c = db.cursor()
41 token = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(32))
42
43 valid_until = str(int(time.time()+valid_for_seconds))
44 c.execute('INSERT INTO autosign_tokens values (?, ?);', (token, valid_until))
45 print(token)
46 db.commit();
47 db.close();
48 return 0
49
50
51def process_request():
52 req = sys.stdin.read()
53 psks = get_psks_from_csr(req)
54 # We will use only the first one in case there are multiple somehow
55 psk = psks[0]
56 autosign = False
57 if psk:
58 c = sqlite3.connect(DATABASE).cursor()
59 c.execute('SELECT valid_until from autosign_tokens where token = ?;', [psk]);
60 res = c.fetchone()
61
62 if res:
63 if int(res[0]) > int(time.time()):
64 print("Autosigner found match for PSK, allowing certificate")
65 autosign = True
66 else:
67 print("Autosigned found match for PSK, but it is expired:", res[0])
68 return 0 if autosign else 1
69
70def invalidate_all_tokens():
71 db = sqlite3.connect(DATABASE)
72 c = db.cursor()
73
74 c.execute('''DELETE FROM autosign_tokens;''')
75 db.commit();
76 c.close()
77 return 0
78
79def main():
80 command = sys.argv[1]
81 r = 1
82 if command == "init_db":
83 print("initializing database")
84 r = init_db()
85 elif command == "create_token":
86 lifetime = 6800
87 if len(sys.argv) == 3:
88 lifetime = int(sys.argv[2])
89 r = create_token(lifetime)
90 elif command == "process_request":
91 r = process_request()
92 elif command == "invalidate_all_tokens":
93 print("Invalidating all tokens")
94 r = invalidate_all_tokens()
95 else:
96 print("Invalid command:", command)
97
98 sys.exit(r)
99
100main()