Allow to pass CA parameters from section.
[slapos.git] / slapos / recipe / certificate_authority / __init__.py
1 ##############################################################################
2 #
3 # Copyright (c) 2010 Vifib SARL and Contributors. All Rights Reserved.
4 #
5 # WARNING: This program as such is intended to be used by professional
6 # programmers who take the whole responsibility of assessing all potential
7 # consequences resulting from its eventual inadequacies and bugs
8 # End users who are looking for a ready-to-use solution with commercial
9 # guarantees and support are strongly adviced to contract a Free Software
10 # Service Company
11 #
12 # This program is Free Software; you can redistribute it and/or
13 # modify it under the terms of the GNU General Public License
14 # as published by the Free Software Foundation; either version 3
15 # of the License, or (at your option) any later version.
16 #
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU General Public License for more details.
21 #
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #
26 ##############################################################################
27 import os
28 import hashlib
29 import ConfigParser
30
31 from slapos.recipe.librecipe import GenericBaseRecipe
32
33 class Recipe(GenericBaseRecipe):
34
35 def setPath(self):
36 self.ca_dir = self.options['ca-dir']
37 self.request_directory = self.options['requests-directory']
38 self.ca_private = self.options['ca-private']
39 self.ca_certs = self.options['ca-certs']
40 self.ca_newcerts = self.options['ca-newcerts']
41 self.ca_crl = self.options['ca-crl']
42 self.ca_key_ext = '.key'
43 self.ca_crt_ext = '.crt'
44
45 def install(self):
46 path_list = []
47
48 ca_country_code = self.options.get('country-code', 'XX')
49 ca_email = self.options.get('email', 'xx@example.com')
50 # XXX-BBB: State by mistake has been configured as string "('State',)"
51 # string, so keep this for backward compatibility of existing
52 # automatically setup CAs
53 ca_state = self.options.get('state', "('State',)")
54 ca_city = self.options.get('city', 'City')
55 ca_company = self.options.get('company', 'Company')
56
57 self.setPath()
58
59 config = dict(ca_dir=self.ca_dir, request_dir=self.request_directory)
60
61 for f in ['crlnumber', 'serial']:
62 if not os.path.exists(os.path.join(self.ca_dir, f)):
63 open(os.path.join(self.ca_dir, f), 'w').write('01')
64 if not os.path.exists(os.path.join(self.ca_dir, 'index.txt')):
65 open(os.path.join(self.ca_dir, 'index.txt'), 'w').write('')
66 openssl_configuration = os.path.join(self.ca_dir, 'openssl.cnf')
67 config.update(
68 working_directory=self.ca_dir,
69 country_code=ca_country_code,
70 state=ca_state,
71 city=ca_city,
72 company=ca_company,
73 email_address=ca_email,
74 )
75 self.createFile(openssl_configuration, self.substituteTemplate(
76 self.getTemplateFilename('openssl.cnf.ca.in'), config))
77
78 ca_wrapper = self.createPythonScript(
79 self.options['wrapper'],
80 '%s.certificate_authority.runCertificateAuthority' % __name__,
81 dict(
82 openssl_configuration=openssl_configuration,
83 openssl_binary=self.options['openssl-binary'],
84 certificate=os.path.join(self.ca_dir, 'cacert.pem'),
85 key=os.path.join(self.ca_private, 'cakey.pem'),
86 crl=self.ca_crl,
87 request_dir=self.request_directory
88 )
89 )
90 path_list.append(ca_wrapper)
91
92 return path_list
93
94 class Request(Recipe):
95
96 def _options(self, options):
97 if 'name' not in options:
98 options['name'] = self.name
99
100 def install(self):
101 self.setPath()
102
103 key_file = self.options['key-file']
104 cert_file = self.options['cert-file']
105
106 name = self.options['name']
107 hash_ = hashlib.sha512(name).hexdigest()
108 key = os.path.join(self.ca_private, hash_ + self.ca_key_ext)
109 certificate = os.path.join(self.ca_certs, hash_ + self.ca_crt_ext)
110 parser = ConfigParser.RawConfigParser()
111 parser.add_section('certificate')
112 parser.set('certificate', 'name', name)
113 parser.set('certificate', 'key_file', key)
114 parser.set('certificate', 'certificate_file', certificate)
115 parser.write(open(os.path.join(self.request_directory, hash_), 'w'))
116
117 for link in [key_file, cert_file]:
118 if os.path.islink(link):
119 os.unlink(link)
120 elif os.path.exists(link):
121 raise OSError("%r file should be a symbolic link.")
122
123 os.symlink(key, key_file)
124 os.symlink(certificate, cert_file)
125
126 wrapper = self.createPythonScript(
127 self.options['wrapper'],
128 'slapos.recipe.librecipe.execute.execute_wait',
129 [ [self.options['executable']],
130 [certificate, key] ],
131 )
132
133 return [key_file, cert_file, wrapper]