Added revoke support to cfssl plugin (#1007)

* Added revoke support to cfssl plugin
This commit is contained in:
Johannes Langer 2017-11-29 23:33:22 +01:00 committed by kevgliss
parent dfb9e3a0c8
commit 5ac3ecb85e
3 changed files with 79 additions and 3 deletions

View File

@ -53,6 +53,14 @@ def parse_certificate(body):
return x509.load_pem_x509_certificate(body, default_backend())
def get_authority_key(body):
"""Returns the authority key for a given certificate in hex format"""
parsed_cert = parse_certificate(body)
authority_key = parsed_cert.extensions.get_extension_for_class(
x509.AuthorityKeyIdentifier).value.key_identifier
return authority_key.hex()
def generate_private_key(key_type):
"""
Generates a new private key based on key_type.

View File

@ -13,8 +13,11 @@ import requests
from flask import current_app
from lemur.common.utils import parse_certificate
from lemur.common.utils import get_authority_key
from lemur.plugins.bases import IssuerPlugin
from lemur.plugins import lemur_cfssl as cfssl
from lemur.extensions import metrics
class CfsslIssuerPlugin(IssuerPlugin):
@ -46,11 +49,15 @@ class CfsslIssuerPlugin(IssuerPlugin):
data = json.dumps(data)
response = self.session.post(url, data=data.encode(encoding='utf_8', errors='strict'))
if response.status_code > 399:
metrics.send('cfssl_create_certificate_failure', 'counter', 1)
raise Exception(
"Error revoking cert. Please check your CFSSL API server")
response_json = json.loads(response.content.decode('utf_8'))
cert = response_json['result']['certificate']
# TODO add external ID
return cert, current_app.config.get('CFSSL_INTERMEDIATE'), None
parsed_cert = parse_certificate(cert)
metrics.send('cfssl_create_certificate_success', 'counter', 1)
return cert, current_app.config.get('CFSSL_INTERMEDIATE'), parsed_cert.serial_number
@staticmethod
def create_authority(options):
@ -63,3 +70,20 @@ class CfsslIssuerPlugin(IssuerPlugin):
"""
role = {'username': '', 'password': '', 'name': 'cfssl'}
return current_app.config.get('CFSSL_ROOT'), "", [role]
def revoke_certificate(self, certificate, comments):
"""Revoke a CFSSL certificate."""
base_url = current_app.config.get('CFSSL_URL')
create_url = '{0}/api/v1/cfssl/revoke'.format(base_url)
data = '{"serial": "' + certificate.external_id + '","authority_key_id": "' + \
get_authority_key(certificate.body) + \
'", "reason": "superseded"}'
current_app.logger.debug("Revoking cert: {0}".format(data))
response = self.session.post(
create_url, data=data.encode(encoding='utf_8', errors='strict'))
if response.status_code > 399:
metrics.send('cfssl_revoke_certificate_failure', 'counter', 1)
raise Exception(
"Error revoking cert. Please check your CFSSL API server")
metrics.send('cfssl_revoke_certificate_success', 'counter', 1)
return response.json()

View File

@ -9,3 +9,47 @@ def test_generate_private_key():
with pytest.raises(Exception):
generate_private_key('ECC')
def test_get_authority_key():
'''test get authority key function'''
from lemur.common.utils import get_authority_key
test_cert = '''-----BEGIN CERTIFICATE-----
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
KFfxwrO1
-----END CERTIFICATE-----'''
authority_key = get_authority_key(test_cert)
assert authority_key == 'feacb541be81771293affa412d8dc9f66a3ebb80'