Ensuring that acme and cryptography respect different key types (#554)
This commit is contained in:
parent
0f5e925a1a
commit
7f823a04cd
|
@ -13,12 +13,12 @@ from flask import current_app
|
||||||
from cryptography import x509
|
from cryptography import x509
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
from cryptography.hazmat.primitives import hashes, serialization
|
from cryptography.hazmat.primitives import hashes, serialization
|
||||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
|
||||||
|
|
||||||
from lemur import database
|
from lemur import database
|
||||||
from lemur.extensions import metrics
|
from lemur.extensions import metrics
|
||||||
from lemur.plugins.base import plugins
|
from lemur.plugins.base import plugins
|
||||||
from lemur.certificates.models import Certificate
|
from lemur.certificates.models import Certificate
|
||||||
|
from lemur.common.utils import generate_private_key
|
||||||
|
|
||||||
from lemur.destinations.models import Destination
|
from lemur.destinations.models import Destination
|
||||||
from lemur.notifications.models import Notification
|
from lemur.notifications.models import Notification
|
||||||
|
@ -317,13 +317,7 @@ def create_csr(**csr_config):
|
||||||
:param csr_config:
|
:param csr_config:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if 'RSA' in csr_config.get('key_type'):
|
private_key = generate_private_key(csr_config.get('key_type'))
|
||||||
key_size = int(csr_config.get('key_type')[3:])
|
|
||||||
private_key = rsa.generate_private_key(
|
|
||||||
public_exponent=65537,
|
|
||||||
key_size=key_size,
|
|
||||||
backend=default_backend()
|
|
||||||
)
|
|
||||||
|
|
||||||
# TODO When we figure out a better way to validate these options they should be parsed as str
|
# TODO When we figure out a better way to validate these options they should be parsed as str
|
||||||
builder = x509.CertificateSigningRequestBuilder()
|
builder = x509.CertificateSigningRequestBuilder()
|
||||||
|
|
|
@ -11,6 +11,7 @@ import random
|
||||||
|
|
||||||
from cryptography import x509
|
from cryptography import x509
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||||
|
|
||||||
from flask_restful.reqparse import RequestParser
|
from flask_restful.reqparse import RequestParser
|
||||||
|
|
||||||
|
@ -37,12 +38,44 @@ def get_psuedo_random_string():
|
||||||
|
|
||||||
|
|
||||||
def parse_certificate(body):
|
def parse_certificate(body):
|
||||||
|
"""
|
||||||
|
Helper function that parses a PEM certificate.
|
||||||
|
|
||||||
|
:param body:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
if isinstance(body, str):
|
if isinstance(body, str):
|
||||||
body = body.encode('utf-8')
|
body = body.encode('utf-8')
|
||||||
|
|
||||||
return x509.load_pem_x509_certificate(body, default_backend())
|
return x509.load_pem_x509_certificate(body, default_backend())
|
||||||
|
|
||||||
|
|
||||||
|
def generate_private_key(key_type):
|
||||||
|
"""
|
||||||
|
Generates a new private key based on key_type.
|
||||||
|
|
||||||
|
Valid key types: RSA2048, RSA4096
|
||||||
|
|
||||||
|
:param key_type:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
valid_key_types = ['RSA2048', 'RSA4096']
|
||||||
|
|
||||||
|
if key_type not in valid_key_types:
|
||||||
|
raise Exception("Invalid key type: {key_type}. Supported key types: {choices}".format(
|
||||||
|
key_type=key_type,
|
||||||
|
choices=",".join(valid_key_types)
|
||||||
|
))
|
||||||
|
|
||||||
|
if 'RSA' in key_type:
|
||||||
|
key_size = int(key_type[3:])
|
||||||
|
return rsa.generate_private_key(
|
||||||
|
public_exponent=65537,
|
||||||
|
key_size=key_size,
|
||||||
|
backend=default_backend()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def is_weekend(date):
|
def is_weekend(date):
|
||||||
"""
|
"""
|
||||||
Determines if a given date is on a weekend.
|
Determines if a given date is on a weekend.
|
||||||
|
|
|
@ -16,9 +16,10 @@ from acme.client import Client
|
||||||
from acme import jose
|
from acme import jose
|
||||||
from acme import messages
|
from acme import messages
|
||||||
|
|
||||||
|
from lemur.common.utils import generate_private_key
|
||||||
|
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
from cryptography.hazmat.primitives import serialization
|
from cryptography.hazmat.primitives import serialization
|
||||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
|
||||||
|
|
||||||
import OpenSSL.crypto
|
import OpenSSL.crypto
|
||||||
|
|
||||||
|
@ -101,12 +102,6 @@ def request_certificate(acme_client, authorizations, csr):
|
||||||
return pem_certificate, pem_certificate_chain
|
return pem_certificate, pem_certificate_chain
|
||||||
|
|
||||||
|
|
||||||
def generate_rsa_private_key():
|
|
||||||
return rsa.generate_private_key(
|
|
||||||
public_exponent=65537, key_size=2048, backend=default_backend()
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def setup_acme_client():
|
def setup_acme_client():
|
||||||
key = current_app.config.get('ACME_PRIVATE_KEY').strip()
|
key = current_app.config.get('ACME_PRIVATE_KEY').strip()
|
||||||
acme_email = current_app.config.get('ACME_EMAIL')
|
acme_email = current_app.config.get('ACME_EMAIL')
|
||||||
|
@ -127,7 +122,7 @@ def acme_client_for_private_key(acme_directory_url, private_key):
|
||||||
|
|
||||||
|
|
||||||
def register(email):
|
def register(email):
|
||||||
private_key = generate_rsa_private_key()
|
private_key = generate_private_key('RSA2048')
|
||||||
acme_client = acme_client_for_private_key(current_app.config('ACME_DIRECTORY_URL'), private_key)
|
acme_client = acme_client_for_private_key(current_app.config('ACME_DIRECTORY_URL'), private_key)
|
||||||
|
|
||||||
registration = acme_client.register(
|
registration = acme_client.register(
|
||||||
|
|
|
@ -13,19 +13,15 @@ from flask import current_app
|
||||||
from cryptography import x509
|
from cryptography import x509
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
from cryptography.hazmat.primitives import hashes, serialization
|
from cryptography.hazmat.primitives import hashes, serialization
|
||||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
|
||||||
|
|
||||||
|
|
||||||
from lemur.plugins.bases import IssuerPlugin
|
from lemur.plugins.bases import IssuerPlugin
|
||||||
from lemur.plugins import lemur_cryptography as cryptography_issuer
|
from lemur.plugins import lemur_cryptography as cryptography_issuer
|
||||||
|
|
||||||
|
from lemur.common.utils import generate_private_key
|
||||||
|
|
||||||
|
|
||||||
def build_root_certificate(options):
|
def build_root_certificate(options):
|
||||||
private_key = rsa.generate_private_key(
|
private_key = generate_private_key(options.get('key_type'))
|
||||||
public_exponent=65537,
|
|
||||||
key_size=2048,
|
|
||||||
backend=default_backend()
|
|
||||||
)
|
|
||||||
|
|
||||||
subject = issuer = x509.Name([
|
subject = issuer = x509.Name([
|
||||||
x509.NameAttribute(x509.OID_COUNTRY_NAME, options['country']),
|
x509.NameAttribute(x509.OID_COUNTRY_NAME, options['country']),
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
import arrow
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_root_certificate():
|
||||||
|
from lemur.plugins.lemur_cryptography.plugin import build_root_certificate
|
||||||
|
|
||||||
|
options = {
|
||||||
|
'key_type': 'RSA2048',
|
||||||
|
'country': 'US',
|
||||||
|
'state': 'CA',
|
||||||
|
'location': 'Example place',
|
||||||
|
'organization': 'Example, Inc.',
|
||||||
|
'organizational_unit': 'Example Unit',
|
||||||
|
'common_name': 'Example ROOT',
|
||||||
|
'validity_start': arrow.get('2016-12-01').datetime,
|
||||||
|
'validity_end': arrow.get('2016-12-02').datetime,
|
||||||
|
'first_serial': 1
|
||||||
|
|
||||||
|
}
|
||||||
|
cert_pem, private_key_pem = build_root_certificate(options)
|
||||||
|
|
||||||
|
assert cert_pem
|
||||||
|
assert private_key_pem
|
||||||
|
|
||||||
|
|
||||||
|
def test_issue_certificate(authority):
|
||||||
|
from lemur.tests.vectors import CSR_STR
|
||||||
|
from lemur.plugins.lemur_cryptography.plugin import issue_certificate
|
||||||
|
|
||||||
|
options = {
|
||||||
|
'authority': authority,
|
||||||
|
'validity_start': arrow.get('2016-12-01').datetime,
|
||||||
|
'validity_end': arrow.get('2016-12-02').datetime
|
||||||
|
}
|
||||||
|
cert = issue_certificate(CSR_STR, options)
|
||||||
|
assert cert
|
|
@ -0,0 +1,11 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
def test_generate_private_key():
|
||||||
|
from lemur.common.utils import generate_private_key
|
||||||
|
|
||||||
|
assert generate_private_key('RSA2048')
|
||||||
|
assert generate_private_key('RSA4096')
|
||||||
|
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
generate_private_key('ECC')
|
|
@ -269,34 +269,3 @@ zm3Cn4Ul8DO26w9QS4fmZjmnPOZFXYMWoOR6osHzb62PWQ8FBMqXcdToBV2Q9Iw4
|
||||||
PiFAxlc0tVjlLqQ=
|
PiFAxlc0tVjlLqQ=
|
||||||
-----END CERTIFICATE REQUEST-----
|
-----END CERTIFICATE REQUEST-----
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
CSR_PEM_STR = """
|
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEpgIBAAKCAQEAzZ2PgKflffhIPzwLXe26tuw+7Q72y9dAMrDVEms8u4Cch3yc
|
|
||||||
hN6Il5tvM4xTc0UN+aobAhaVoPDN+haXT/XyBRvbFV1f8nvmDQZGdmkyYkZ2xK2X
|
|
||||||
MvKnPtjEXdiShPYNKSEqfYQBHhDy08EqBqn+VajmgXoQai+TijVK+yQMVUyB9aFV
|
|
||||||
PO8P+sYP1rFIsj6OPVl8Rf9w2TT9VDk2In38SIgEYU2/RLZV6beYjpYnN8P7wV+q
|
|
||||||
rB/vlySLrNlhPgAZQFVEEwr3Om4KbuM43PJ5ZtwpapACnMZ9rmxHXq/hYYWoDGBr
|
|
||||||
G2BvvyFqymDektAYxNurTTIjpZiHm4poxHRaZwIDAQABAoIBAQCm5MwVBrKtI/ko
|
|
||||||
colbbVoPngSZkHrcC9SNEKFyON7r5sGm64t0AdjnDgAd3DnkJ1nnm54efMxo/OyD
|
|
||||||
oRCik6QlZ23VkpwNi2m4iq5o8Iw33rAKhkhizzjXN0V0UxTinYEjMEt348ywZdtj
|
|
||||||
67c7/4F0cArhb32hYwqjtQwuex0Tofb37Aj5rNPv1n8ytbhz1vriAVZHZEcjdjdn
|
|
||||||
CSVeblufORQKRzK3wW5nRN721b9gSvEJHfHeNpXQO9X8Yl5tn7UxjoQWXLZK+khv
|
|
||||||
pawN8BFt7lVLkQR14Nq7bKwuJ6KR1ig698a1Ii8Luyh2BgfIc25ryuzs8fFCioKi
|
|
||||||
TK/nzMQ5AoGBAPxtbTrkTTNQ03hnfefRVKGwNHPqLhIQpI99FC4yLYYHsUwFmMVR
|
|
||||||
ccg4aqNUtI0zn1snKC58NICxIPP9c0NuHqBuNuwhuRPINfQfjg/aOpE2QycZcew1
|
|
||||||
BQxXH5d3zXWKLpN15kIS2s18/MpNgTFx2Z0EGqLezDXs6JaPJkqg04glAoGBANCG
|
|
||||||
h106B9hbuTPYCAlTwvaoWnbaxLmtlWzRpqYBuiiBPGvLc545faXkJKb5/zd002kK
|
|
||||||
wblGrPtCnhTvCtHbTg/KuR/R8EsAriPhpWK+N4hCADJ8SLOxMU5S9O24FEK50ltN
|
|
||||||
Q84LS2Wo9fWXQhojiBrctn/ws5ngRCfUbhQeA3ybAoGBAOW7vWaUswIZ9GwnXDon
|
|
||||||
lGuXDxXTslw0k2AXyM8GUdIinCSBD3m9Vt2PItZFWBEOQ2DVMUelOK9LBZ+pMkbT
|
|
||||||
KMJ/rDKZunQbiacFNOiOhzDzfohOKxV7Z33EqPbUTMRFn4ALFCVcPZA4yWRgx0y1
|
|
||||||
vgSd4JQMSzRkyYWFAKd42SuVAoGBAIG84aWQQGdNkin+Y+mhsrCSSE6giDtaE5jz
|
|
||||||
y7KHapJe7f/HQnUUIee/zUoSSsbvKcW2CpfCsEdXyFEP9PRidOwAXjO9A7s2fiIW
|
|
||||||
9zY7UQO2xLakevtJ6HppxLfOitSFFqr1pJUik9N5TyZw6JCowLqtzeJGGQhI7z60
|
|
||||||
vZRIpDS3AoGBAPYJgNB7EcWj5U39ol+8cofG1kPauoEaildTur5ftzyzjy4DXrOW
|
|
||||||
sfU/xhUp6EKLGSXEPqeXAWR6ARf1F4U9Ozp6KA93lGSrSY561jKoqhxxOXAf5il2
|
|
||||||
p7Fzh2CckUeiGd5el+h2WUCOcgtlPlfRyV/Mlvx1H0gFieGucXTP23Ox
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
||||||
"""
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[pytest]
|
[tool:pytest]
|
||||||
python_files=test*.py
|
python_files=test*.py
|
||||||
addopts=--tb=native -p no:doctest
|
addopts=--tb=native -p no:doctest
|
||||||
norecursedirs=bin dist docs htmlcov script hooks node_modules .* {args}
|
norecursedirs=bin dist docs htmlcov script hooks node_modules .* {args}
|
||||||
|
|
Loading…
Reference in New Issue