class pfSenseCERT(object): def __init__(self, module): self.module = module self.pfsense = PFSenseModule(module) self.certs = self.pfsense.get_elements('cert') def _find_cert(self, name): found = None i = 0 for cert in self.certs: i = self.pfsense.get_index(cert) if cert.find('descr').text == name: found = cert break return (found, i) def validate_cert(self, cert): lines = cert.splitlines() if lines[0] == '-----BEGIN CERTIFICATE-----' and lines[ -1] == '-----END CERTIFICATE-----': return base64.b64encode(cert) elif re.match('LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t', cert): return cert else: self.module.fail_json( msg='Could not recognize certificate format: %s' % (cert)) def validate_prv(self, prv): lines = prv.splitlines() if lines[0] == '-----BEGIN PRIVATE KEY-----' and lines[ -1] == '-----END PRIVATE KEY-----': return base64.b64encode(prv) elif lines[0] == '-----BEGIN RSA PRIVATE KEY----' and lines[ -1] == '-----END RSA PRIVATE KEY-----': return base64.b64encode(prv) elif re.match('LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0t', prv): return prv elif re.match('LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0t', prv): return prv else: self.module.fail_json( msg='Could not recognize private key format: %s' % (prv)) def add(self, cert): cert_elt, cert_idx = self._find_cert(cert['descr']) changed = False diff = {} stdout = None stderr = None if cert_elt is None: diff['before'] = '' changed = True cert_elt = self.pfsense.new_element('cert') cert['refid'] = self.pfsense.uniqid() self.pfsense.copy_dict_to_element(cert, cert_elt) self.pfsense.root.append(cert_elt) descr = 'ansible pfsensible.core.cert added %s' % (cert['descr']) else: diff['before'] = self.pfsense.element_to_dict(cert_elt) if self.pfsense.copy_dict_to_element(cert, cert_elt): changed = True descr = 'ansible pfsensible.core.cert updated "%s"' % ( cert['descr']) if changed and not self.module.check_mode: self.pfsense.write_config(descr=descr) # cert_import will base64 encode the cert + key and will fix 'certref' for CERTs that reference each other # $cert needs to be an existing reference (particularly 'refid' must be set) before calling cert_import # key and serial are optional arguments. TODO - handle key and serial (dummy, stdout, stderr) = self.pfsense.phpshell(""" init_config_arr(array('cert')); $cert =& lookup_cert('{refid}'); cert_import($cert, '{cert}','{priv}'); print_r($cert); print_r($config['cert']); write_config();""".format( refid=cert_elt.find('refid').text, cert=base64.b64decode(cert_elt.find('crt').text), priv=base64.b64decode(cert_elt.find('prv').text))) diff['after'] = self.pfsense.element_to_dict(cert_elt) self.module.exit_json(changed=changed, diff=diff, stdout=stdout, stderr=stderr) def remove(self, cert): cert_elt, dummy = self._find_cert(cert['descr']) changed = False diff = {} diff['after'] = {} if cert_elt is not None: changed = True diff['before'] = self.pfsense.element_to_dict(cert_elt) self.certs.remove(cert_elt) else: diff['before'] = {} if changed and not self.module.check_mode: self.pfsense.write_config( descr='ansible pfsensible.core.cert removed "%s"' % (cert['descr'])) self.module.exit_json(changed=changed, diff=diff)
class pfSenseCA(object): def __init__(self, module): self.module = module self.pfsense = PFSenseModule(module) self.cas = self.pfsense.get_elements('ca') self.crls = self.pfsense.get_elements('crl') def _find_ca(self, name): found = None i = 0 for ca in self.cas: i = self.pfsense.get_index(ca) if ca.find('descr').text == name: found = ca break return (found, i) def _find_crl(self, caref): found = None i = 0 for crl in self.crls: i = self.pfsense.get_index(crl) if crl.find('caref').text == caref: found = crl break return (found, i) def validate_cert(self, cert): # TODO - Make sure certificate purpose includes CA lines = cert.splitlines() if lines[0] == '-----BEGIN CERTIFICATE-----' and lines[ -1] == '-----END CERTIFICATE-----': return base64.b64encode(cert) elif re.match('LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t', cert): return cert else: self.module.fail_json( msg='Could not recognize certificate format: %s' % (cert)) def validate_crl(self, crl): lines = crl.splitlines() if lines[0] == '-----BEGIN X509 CRL-----' and lines[ -1] == '-----END X509 CRL-----': return base64.b64encode(crl) elif re.match('LS0tLS1CRUdJTiBYNTA5IENSTC0tLS0t', crl): return crl else: self.module.fail_json(msg='Could not recognize CRL format: %s' % (crl)) def add(self, ca): ca_elt, ca_idx = self._find_ca(ca['descr']) changed = False crl = {} diff = {} stdout = None stderr = None if 'crl' in ca: crl['method'] = 'existing' crl['text'] = ca.pop('crl') if ca_elt is None: diff['before'] = '' changed = True ca_elt = self.pfsense.new_element('ca') ca['refid'] = self.pfsense.uniqid() self.pfsense.copy_dict_to_element(ca, ca_elt) self.pfsense.root.append(ca_elt) if 'text' in crl: crl_elt = self.pfsense.new_element('crl') crl['refid'] = self.pfsense.uniqid() crl['descr'] = ca['descr'] + ' CRL' crl['caref'] = ca['refid'] self.pfsense.copy_dict_to_element(crl, crl_elt) self.pfsense.root.append(crl_elt) descr = 'ansible pfsensible.core.ca added %s' % (ca['descr']) else: diff['before'] = self.pfsense.element_to_dict(ca_elt) if 'text' in crl: crl_elt, crl_index = self._find_crl(ca_elt.find('refid').text) if crl_elt is None: changed = True crl_elt = self.pfsense.new_element('crl') crl['refid'] = self.pfsense.uniqid() crl['descr'] = ca['descr'] + ' CRL' crl['caref'] = ca_elt.find('refid').text self.pfsense.copy_dict_to_element(crl, crl_elt) # Add after the existing ca entry self.pfsense.root.insert(ca_idx + 1, crl_elt) else: diff['before']['crl'] = crl_elt.find('text').text changed = self.pfsense.copy_dict_to_element(crl, crl_elt) if self.pfsense.copy_dict_to_element(ca, ca_elt): changed = True descr = 'ansible pfsensible.core.ca updated "%s"' % (ca['descr']) if changed and not self.module.check_mode: self.pfsense.write_config(descr=descr) # ca_import will base64 encode the cert + key and will fix 'caref' for CAs that reference each other # $ca needs to be an existing reference (particularly 'refid' must be set) before calling ca_import # key and serial are optional arguments. TODO - handle key and serial (dummy, stdout, stderr) = self.pfsense.phpshell(""" init_config_arr(array('ca')); $ca =& lookup_ca('{refid}'); ca_import($ca, '{cert}'); print_r($ca); print_r($config['ca']); write_config();""".format(refid=ca_elt.find('refid').text, cert=base64.b64decode( ca_elt.find('crt').text))) if 'text' in crl: self.pfsense.phpshell(""" require_once("openvpn.inc"); openvpn_refresh_crls(); require_once("vpn.inc"); vpn_ipsec_configure();""") diff['after'] = self.pfsense.element_to_dict(ca_elt) if 'text' in crl: diff['after']['crl'] = crl['text'] self.module.exit_json(changed=changed, diff=diff, stdout=stdout, stderr=stderr) def remove(self, ca): ca_elt, dummy = self._find_ca(ca['descr']) changed = False diff = {} diff['after'] = {} if ca_elt is not None: changed = True diff['before'] = self.pfsense.element_to_dict(ca_elt) crl_elt, dummy = self._find_crl(ca_elt.find('refid').text) self.cas.remove(ca_elt) if crl_elt is not None: diff['before']['crl'] = crl_elt.find('text').text self.crls.remove(crl_elt) else: diff['before'] = {} if changed and not self.module.check_mode: self.pfsense.write_config( descr='ansible pfsensible.core.ca removed "%s"' % (ca['descr'])) self.module.exit_json(changed=changed, diff=diff)