def remove_cert(self, cn): """Removes certificates and index entries for a specified client Args: cn (str): The common name of the client (defaults to None) """ cn = zencode.encode(cn) for entry in self.list_certs(cn): self._try_remove( path.join(self.easyrsa_pki, 'certs_by_serial', entry.serial + '.pem')) self._try_remove(path.join(self.easyrsa_pki, 'issued', cn + '.crt')) self._try_remove(path.join(self.easyrsa_pki, 'private', cn + '.key')) self._try_remove(path.join(self.easyrsa_pki, 'reqs', cn + '.req')) new_index_lines = [] with open(path.join(self.easyrsa_pki, 'index.txt')) as index_file: for line in index_file: entry = CertificateListing.parse(line) if entry is not None and entry.cn != cn: new_index_lines.append(line) with open(path.join(self.easyrsa_pki, 'index.txt'), 'w') as index_file: index_file.write(''.join(new_index_lines))
def list_certs(self, cn=None): """Returns all certificates information, or for a particular client Args: cn (str): The common name of the client (defaults to None) Returns: list[CertificateListing]: The certificate information for all certificates on the challenge, or for a specific client if specified """ if cn: cn = zencode.encode(cn) listing = list() with open(path.join(self.easyrsa_pki, 'index.txt')) as index_file: for line in index_file: entry = CertificateListing.parse(line) if entry is not None and (cn is None or entry.cn == cn): try: entry.cn = zencode.decode(entry.cn) except ValueError: pass # This is not an encoded name listing.append(entry) return listing
def revoke_cert(self, cn): """Revokes the certificates for a client Args: cn (str): The common name of the client """ cn = zencode.encode(cn) def revoke_error_handler(e): if e.returncode == 1: if EASYRSA_ALREADY_REVOKED_MSG in e.stderr: return True if EASYRSA_NONEXIST_REVOKE_MSG in e.stderr: raise EntryNotFoundError(cn) return False proc = self._run( [self.easyrsa, 'revoke', cn], revoke_error_handler, input=b'yes', ) if proc: logging.info("Revoked certificate for '{}'".format(cn)) else: logging.info("Already revoked certificate for '{}'".format(cn)) self._run([self.easyrsa, 'gen-crl'], )
def add_cert(self, cn): """Creates certificates for a client Args: cn (str): The common name of the client """ cn = zencode.encode(cn) proc = self._run( [self.easyrsa, 'build-client-full', cn, 'nopass'], lambda e: e.returncode == 1 and EASYRSA_ALREADY_EXISTS_MSG in e. stderr, ) if proc: logging.info("Using existing certs for {0}".format(cn)) else: logging.info("Built new certs for {0}".format(cn))
def get_config(self, cn): """Returns the confgiuration file text for an OpenvVPN client Args: cn (str): The common name of the client Returns: str: The file text for the client's OpenVPN client """ cn = zencode.encode(cn) def get_error_handler(e): if e.returncode == 1: if EASYRSA_NONEXIST_GET_MSG in e.stderr: raise EntryNotFoundError(cn) return False config = self._run([getclient, cn], get_error_handler).stdout.decode('utf-8') logging.info("Compiled configuration file for '{}'".format(cn)) return config