Merge branch 'master' into hackday
This commit is contained in:
commit
3ef550f738
8
Makefile
8
Makefile
|
@ -110,10 +110,10 @@ ifndef VIRTUAL_ENV
|
||||||
endif
|
endif
|
||||||
@echo "--> Updating Python requirements"
|
@echo "--> Updating Python requirements"
|
||||||
pip install --upgrade pip-tools
|
pip install --upgrade pip-tools
|
||||||
pip-compile --output-file requirements-docs.txt requirements-docs.in -U
|
pip-compile --output-file requirements-docs.txt requirements-docs.in -U --no-index
|
||||||
pip-compile --output-file requirements-dev.txt requirements-dev.in -U
|
pip-compile --output-file requirements-dev.txt requirements-dev.in -U --no-index
|
||||||
pip-compile --output-file requirements-tests.txt requirements-tests.in -U
|
pip-compile --output-file requirements-tests.txt requirements-tests.in -U --no-index
|
||||||
pip-compile --output-file requirements.txt requirements.in -U
|
pip-compile --output-file requirements.txt requirements.in -U --no-index
|
||||||
@echo "--> Done updating Python requirements"
|
@echo "--> Done updating Python requirements"
|
||||||
@echo "--> Installing new dependencies"
|
@echo "--> Installing new dependencies"
|
||||||
pip install -e .
|
pip install -e .
|
||||||
|
|
|
@ -65,6 +65,36 @@ Basic Configuration
|
||||||
SQLALCHEMY_DATABASE_URI = 'postgresql://<user>:<password>@<hostname>:5432/lemur'
|
SQLALCHEMY_DATABASE_URI = 'postgresql://<user>:<password>@<hostname>:5432/lemur'
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: SQLALCHEMY_POOL_SIZE
|
||||||
|
:noindex:
|
||||||
|
|
||||||
|
The default connection pool size is 5 for sqlalchemy managed connections. Depending on the number of Lemur instances,
|
||||||
|
please specify per instance connection pool size. Below is an example to set connection pool size to 10.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
SQLALCHEMY_POOL_SIZE = 10
|
||||||
|
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
This is an optional setting but important to review and set for optimal database connection usage and for overall database performance.
|
||||||
|
|
||||||
|
.. data:: SQLALCHEMY_MAX_OVERFLOW
|
||||||
|
:noindex:
|
||||||
|
|
||||||
|
This setting allows to create connections in addition to specified number of connections in pool size. By default, sqlalchemy
|
||||||
|
allows 10 connections to create in addition to the pool size. This is also an optional setting. If `SQLALCHEMY_POOL_SIZE` and
|
||||||
|
`SQLALCHEMY_MAX_OVERFLOW` are not speficied then each Lemur instance may create maximum of 15 connections.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
SQLALCHECK_MAX_OVERFLOW = 0
|
||||||
|
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Specifying the `SQLALCHEMY_MAX_OVERFLOW` to 0 will enforce limit to not create connections above specified pool size.
|
||||||
|
|
||||||
|
|
||||||
.. data:: LEMUR_ALLOW_WEEKEND_EXPIRATION
|
.. data:: LEMUR_ALLOW_WEEKEND_EXPIRATION
|
||||||
:noindex:
|
:noindex:
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ of Lemur. You'll want to make sure you have a few things on your local system fi
|
||||||
* pip
|
* pip
|
||||||
* virtualenv (ideally virtualenvwrapper)
|
* virtualenv (ideally virtualenvwrapper)
|
||||||
* node.js (for npm and building css/javascript)
|
* node.js (for npm and building css/javascript)
|
||||||
* (Optional) PostgreSQL
|
+* `PostgreSQL <https://lemur.readthedocs.io/en/latest/quickstart/index.html#setup-postgres>`_
|
||||||
|
|
||||||
Once you've got all that, the rest is simple:
|
Once you've got all that, the rest is simple:
|
||||||
|
|
||||||
|
@ -77,6 +77,7 @@ Create a default Lemur configuration just as if this were a production instance:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
lemur create_config
|
||||||
lemur init
|
lemur init
|
||||||
|
|
||||||
You'll likely want to make some changes to the default configuration (we recommend developing against Postgres, for example). Once done, migrate your database using the following command:
|
You'll likely want to make some changes to the default configuration (we recommend developing against Postgres, for example). Once done, migrate your database using the following command:
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, print_function
|
import time
|
||||||
|
from flask import g, request
|
||||||
|
|
||||||
from lemur import factory
|
from lemur import factory
|
||||||
from lemur.extensions import metrics
|
from lemur.extensions import metrics
|
||||||
|
@ -75,17 +76,6 @@ def configure_hook(app):
|
||||||
"""
|
"""
|
||||||
from flask import jsonify
|
from flask import jsonify
|
||||||
from werkzeug.exceptions import HTTPException
|
from werkzeug.exceptions import HTTPException
|
||||||
from lemur.decorators import crossdomain
|
|
||||||
if app.config.get('CORS'):
|
|
||||||
@app.after_request
|
|
||||||
@crossdomain(origin=u"http://localhost:3000", methods=['PUT', 'HEAD', 'GET', 'POST', 'OPTIONS', 'DELETE'])
|
|
||||||
def after(response):
|
|
||||||
return response
|
|
||||||
|
|
||||||
@app.after_request
|
|
||||||
def log_status(response):
|
|
||||||
metrics.send('status_code_{}'.format(response.status_code), 'counter', 1)
|
|
||||||
return response
|
|
||||||
|
|
||||||
@app.errorhandler(Exception)
|
@app.errorhandler(Exception)
|
||||||
def handle_error(e):
|
def handle_error(e):
|
||||||
|
@ -95,3 +85,29 @@ def configure_hook(app):
|
||||||
|
|
||||||
app.logger.exception(e)
|
app.logger.exception(e)
|
||||||
return jsonify(error=str(e)), code
|
return jsonify(error=str(e)), code
|
||||||
|
|
||||||
|
@app.before_request
|
||||||
|
def before_request():
|
||||||
|
g.request_start_time = time.time()
|
||||||
|
|
||||||
|
@app.after_request
|
||||||
|
def after_request(response):
|
||||||
|
# Return early if we don't have the start time
|
||||||
|
if not hasattr(g, 'request_start_time'):
|
||||||
|
return response
|
||||||
|
|
||||||
|
# Get elapsed time in milliseconds
|
||||||
|
elapsed = time.time() - g.request_start_time
|
||||||
|
elapsed = int(round(1000 * elapsed))
|
||||||
|
|
||||||
|
# Collect request/response tags
|
||||||
|
tags = {
|
||||||
|
'endpoint': request.endpoint,
|
||||||
|
'request_method': request.method.lower(),
|
||||||
|
'status_code': response.status_code
|
||||||
|
}
|
||||||
|
|
||||||
|
# Record our response time metric
|
||||||
|
metrics.send('response_time', 'TIMER', elapsed, metric_tags=tags)
|
||||||
|
metrics.send('status_code_{}'.format(response.status_code), 'counter', 1)
|
||||||
|
return response
|
||||||
|
|
|
@ -14,10 +14,11 @@ from sqlalchemy import and_, func
|
||||||
|
|
||||||
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 cryptography.hazmat.primitives.asymmetric import rsa, ec
|
||||||
|
|
||||||
from flask_restful.reqparse import RequestParser
|
from flask_restful.reqparse import RequestParser
|
||||||
|
|
||||||
|
from lemur.constants import CERTIFICATE_KEY_TYPES
|
||||||
from lemur.exceptions import InvalidConfiguration
|
from lemur.exceptions import InvalidConfiguration
|
||||||
|
|
||||||
paginated_parser = RequestParser()
|
paginated_parser = RequestParser()
|
||||||
|
@ -78,17 +79,43 @@ def generate_private_key(key_type):
|
||||||
"""
|
"""
|
||||||
Generates a new private key based on key_type.
|
Generates a new private key based on key_type.
|
||||||
|
|
||||||
Valid key types: RSA2048, RSA4096
|
Valid key types: RSA2048, RSA4096', 'ECCPRIME192V1', 'ECCPRIME256V1', 'ECCSECP192R1',
|
||||||
|
'ECCSECP224R1', 'ECCSECP256R1', 'ECCSECP384R1', 'ECCSECP521R1', 'ECCSECP256K1',
|
||||||
|
'ECCSECT163K1', 'ECCSECT233K1', 'ECCSECT283K1', 'ECCSECT409K1', 'ECCSECT571K1',
|
||||||
|
'ECCSECT163R2', 'ECCSECT233R1', 'ECCSECT283R1', 'ECCSECT409R1', 'ECCSECT571R2'
|
||||||
|
|
||||||
:param key_type:
|
:param key_type:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
valid_key_types = ['RSA2048', 'RSA4096']
|
|
||||||
|
|
||||||
if key_type not in valid_key_types:
|
_CURVE_TYPES = {
|
||||||
|
"ECCPRIME192V1": ec.SECP192R1(),
|
||||||
|
"ECCPRIME256V1": ec.SECP256R1(),
|
||||||
|
|
||||||
|
"ECCSECP192R1": ec.SECP192R1(),
|
||||||
|
"ECCSECP224R1": ec.SECP224R1(),
|
||||||
|
"ECCSECP256R1": ec.SECP256R1(),
|
||||||
|
"ECCSECP384R1": ec.SECP384R1(),
|
||||||
|
"ECCSECP521R1": ec.SECP521R1(),
|
||||||
|
"ECCSECP256K1": ec.SECP256K1(),
|
||||||
|
|
||||||
|
"ECCSECT163K1": ec.SECT163K1(),
|
||||||
|
"ECCSECT233K1": ec.SECT233K1(),
|
||||||
|
"ECCSECT283K1": ec.SECT283K1(),
|
||||||
|
"ECCSECT409K1": ec.SECT409K1(),
|
||||||
|
"ECCSECT571K1": ec.SECT571K1(),
|
||||||
|
|
||||||
|
"ECCSECT163R2": ec.SECT163R2(),
|
||||||
|
"ECCSECT233R1": ec.SECT233R1(),
|
||||||
|
"ECCSECT283R1": ec.SECT283R1(),
|
||||||
|
"ECCSECT409R1": ec.SECT409R1(),
|
||||||
|
"ECCSECT571R2": ec.SECT571R1(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if key_type not in CERTIFICATE_KEY_TYPES:
|
||||||
raise Exception("Invalid key type: {key_type}. Supported key types: {choices}".format(
|
raise Exception("Invalid key type: {key_type}. Supported key types: {choices}".format(
|
||||||
key_type=key_type,
|
key_type=key_type,
|
||||||
choices=",".join(valid_key_types)
|
choices=",".join(CERTIFICATE_KEY_TYPES)
|
||||||
))
|
))
|
||||||
|
|
||||||
if 'RSA' in key_type:
|
if 'RSA' in key_type:
|
||||||
|
@ -98,6 +125,11 @@ def generate_private_key(key_type):
|
||||||
key_size=key_size,
|
key_size=key_size,
|
||||||
backend=default_backend()
|
backend=default_backend()
|
||||||
)
|
)
|
||||||
|
elif 'ECC' in key_type:
|
||||||
|
return ec.generate_private_key(
|
||||||
|
curve=_CURVE_TYPES[key_type],
|
||||||
|
backend=default_backend()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def is_weekend(date):
|
def is_weekend(date):
|
||||||
|
|
|
@ -9,3 +9,26 @@ NONSTANDARD_NAMING_TEMPLATE = "{issuer}-{not_before}-{not_after}"
|
||||||
|
|
||||||
SUCCESS_METRIC_STATUS = 'success'
|
SUCCESS_METRIC_STATUS = 'success'
|
||||||
FAILURE_METRIC_STATUS = 'failure'
|
FAILURE_METRIC_STATUS = 'failure'
|
||||||
|
|
||||||
|
CERTIFICATE_KEY_TYPES = [
|
||||||
|
'RSA2048',
|
||||||
|
'RSA4096',
|
||||||
|
'ECCPRIME192V1',
|
||||||
|
'ECCPRIME256V1',
|
||||||
|
'ECCSECP192R1',
|
||||||
|
'ECCSECP224R1',
|
||||||
|
'ECCSECP256R1',
|
||||||
|
'ECCSECP384R1',
|
||||||
|
'ECCSECP521R1',
|
||||||
|
'ECCSECP256K1',
|
||||||
|
'ECCSECT163K1',
|
||||||
|
'ECCSECT233K1',
|
||||||
|
'ECCSECT283K1',
|
||||||
|
'ECCSECT409K1',
|
||||||
|
'ECCSECT571K1',
|
||||||
|
'ECCSECT163R2',
|
||||||
|
'ECCSECT233R1',
|
||||||
|
'ECCSECT283R1',
|
||||||
|
'ECCSECT409R1',
|
||||||
|
'ECCSECT571R2'
|
||||||
|
]
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
"""
|
|
||||||
.. module: lemur.decorators
|
|
||||||
:copyright: (c) 2015 by Netflix Inc., see AUTHORS for more
|
|
||||||
:license: Apache, see LICENSE for more details.
|
|
||||||
"""
|
|
||||||
from builtins import str
|
|
||||||
|
|
||||||
from datetime import timedelta
|
|
||||||
from flask import make_response, request, current_app
|
|
||||||
|
|
||||||
from functools import update_wrapper
|
|
||||||
|
|
||||||
|
|
||||||
# this is only used for dev
|
|
||||||
def crossdomain(origin=None, methods=None, headers=None,
|
|
||||||
max_age=21600, attach_to_all=True,
|
|
||||||
automatic_options=True): # pragma: no cover
|
|
||||||
if methods is not None:
|
|
||||||
methods = ', '.join(sorted(x.upper() for x in methods))
|
|
||||||
|
|
||||||
if headers is not None and not isinstance(headers, str):
|
|
||||||
headers = ', '.join(x.upper() for x in headers)
|
|
||||||
|
|
||||||
if not isinstance(origin, str):
|
|
||||||
origin = ', '.join(origin)
|
|
||||||
|
|
||||||
if isinstance(max_age, timedelta):
|
|
||||||
max_age = max_age.total_seconds()
|
|
||||||
|
|
||||||
def get_methods():
|
|
||||||
if methods is not None:
|
|
||||||
return methods
|
|
||||||
|
|
||||||
options_resp = current_app.make_default_options_response()
|
|
||||||
return options_resp.headers['allow']
|
|
||||||
|
|
||||||
def decorator(f):
|
|
||||||
def wrapped_function(*args, **kwargs):
|
|
||||||
if automatic_options and request.method == 'OPTIONS':
|
|
||||||
resp = current_app.make_default_options_response()
|
|
||||||
else:
|
|
||||||
resp = make_response(f(*args, **kwargs))
|
|
||||||
if not attach_to_all and request.method != 'OPTIONS':
|
|
||||||
return resp
|
|
||||||
|
|
||||||
h = resp.headers
|
|
||||||
h['Access-Control-Allow-Origin'] = origin
|
|
||||||
h['Access-Control-Allow-Methods'] = get_methods()
|
|
||||||
h['Access-Control-Max-Age'] = str(max_age)
|
|
||||||
h['Access-Control-Allow-Headers'] = "Origin, X-Requested-With, Content-Type, Accept, Authorization "
|
|
||||||
h['Access-Control-Allow-Credentials'] = 'true'
|
|
||||||
return resp
|
|
||||||
|
|
||||||
f.provide_automatic_options = False
|
|
||||||
return update_wrapper(wrapped_function, f)
|
|
||||||
return decorator
|
|
|
@ -26,3 +26,6 @@ sentry = Sentry()
|
||||||
|
|
||||||
from blinker import Namespace
|
from blinker import Namespace
|
||||||
signals = Namespace()
|
signals = Namespace()
|
||||||
|
|
||||||
|
from flask_cors import CORS
|
||||||
|
cors = CORS()
|
||||||
|
|
|
@ -21,7 +21,7 @@ from flask import Flask
|
||||||
|
|
||||||
from lemur.certificates.hooks import activate_debug_dump
|
from lemur.certificates.hooks import activate_debug_dump
|
||||||
from lemur.common.health import mod as health
|
from lemur.common.health import mod as health
|
||||||
from lemur.extensions import db, migrate, principal, smtp_mail, metrics, sentry
|
from lemur.extensions import db, migrate, principal, smtp_mail, metrics, sentry, cors
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_BLUEPRINTS = (
|
DEFAULT_BLUEPRINTS = (
|
||||||
|
@ -124,6 +124,8 @@ def configure_extensions(app):
|
||||||
smtp_mail.init_app(app)
|
smtp_mail.init_app(app)
|
||||||
metrics.init_app(app)
|
metrics.init_app(app)
|
||||||
sentry.init_app(app)
|
sentry.init_app(app)
|
||||||
|
app.config['CORS_HEADERS'] = 'Content-Type'
|
||||||
|
cors.init_app(app, resources=r'/api/*', headers='Content-Type', origin='*', supports_credentials=True)
|
||||||
|
|
||||||
|
|
||||||
def configure_blueprints(app, blueprints):
|
def configure_blueprints(app, blueprints):
|
||||||
|
|
|
@ -157,7 +157,7 @@ def map_cis_fields(options, csr):
|
||||||
"csr": csr,
|
"csr": csr,
|
||||||
"signature_hash": signature_hash(options.get('signing_algorithm')),
|
"signature_hash": signature_hash(options.get('signing_algorithm')),
|
||||||
"validity": {
|
"validity": {
|
||||||
"valid_to": options['validity_end'].format('YYYY-MM-DD')
|
"valid_to": options['validity_end'].format('YYYY-MM-DDTHH:MM:SSZ')
|
||||||
},
|
},
|
||||||
"organization": {
|
"organization": {
|
||||||
"name": options['organization'],
|
"name": options['organization'],
|
||||||
|
@ -491,6 +491,11 @@ class DigiCertCISIssuerPlugin(IssuerPlugin):
|
||||||
|
|
||||||
self.session.headers.pop('Accept')
|
self.session.headers.pop('Accept')
|
||||||
end_entity = pem.parse(certificate_pem)[0]
|
end_entity = pem.parse(certificate_pem)[0]
|
||||||
|
|
||||||
|
if 'ECC' in issuer_options['key_type']:
|
||||||
|
return "\n".join(str(end_entity).splitlines()), current_app.config.get('DIGICERT_ECC_CIS_INTERMEDIATE'), data['id']
|
||||||
|
|
||||||
|
# By default return RSA
|
||||||
return "\n".join(str(end_entity).splitlines()), current_app.config.get('DIGICERT_CIS_INTERMEDIATE'), data['id']
|
return "\n".join(str(end_entity).splitlines()), current_app.config.get('DIGICERT_CIS_INTERMEDIATE'), data['id']
|
||||||
|
|
||||||
def revoke_certificate(self, certificate, comments):
|
def revoke_certificate(self, certificate, comments):
|
||||||
|
|
|
@ -103,7 +103,7 @@ def test_map_cis_fields(app):
|
||||||
'signature_hash': 'sha256',
|
'signature_hash': 'sha256',
|
||||||
'organization': {'name': 'Example, Inc.', 'units': ['Example Org']},
|
'organization': {'name': 'Example, Inc.', 'units': ['Example Org']},
|
||||||
'validity': {
|
'validity': {
|
||||||
'valid_to': arrow.get(2017, 5, 7).format('YYYY-MM-DD')
|
'valid_to': arrow.get(2017, 5, 7).format('YYYY-MM-DDTHH:MM:SSZ')
|
||||||
},
|
},
|
||||||
'profile_name': None
|
'profile_name': None
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ def test_map_cis_fields(app):
|
||||||
'signature_hash': 'sha256',
|
'signature_hash': 'sha256',
|
||||||
'organization': {'name': 'Example, Inc.', 'units': ['Example Org']},
|
'organization': {'name': 'Example, Inc.', 'units': ['Example Org']},
|
||||||
'validity': {
|
'validity': {
|
||||||
'valid_to': arrow.get(2018, 11, 3).format('YYYY-MM-DD')
|
'valid_to': arrow.get(2018, 11, 3).format('YYYY-MM-DDTHH:MM:SSZ')
|
||||||
},
|
},
|
||||||
'profile_name': None
|
'profile_name': None
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
datadog==0.14.0
|
|
@ -0,0 +1,4 @@
|
||||||
|
try:
|
||||||
|
VERSION = __import__('pkg_resources').get_distribution(__name__).version
|
||||||
|
except Exception as e:
|
||||||
|
VERSION = 'Unknown'
|
|
@ -0,0 +1,45 @@
|
||||||
|
import lemur_statsd as plug
|
||||||
|
|
||||||
|
from flask import current_app
|
||||||
|
from lemur.plugins.bases.metric import MetricPlugin
|
||||||
|
from datadog import DogStatsd
|
||||||
|
|
||||||
|
|
||||||
|
class StatsdMetricPlugin(MetricPlugin):
|
||||||
|
title = 'Statsd'
|
||||||
|
slug = 'statsd-metrics'
|
||||||
|
description = 'Adds support for sending metrics to Statsd'
|
||||||
|
version = plug.VERSION
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
host = current_app.config.get('STATSD_HOST')
|
||||||
|
port = current_app.config.get('STATSD_PORT')
|
||||||
|
prefix = current_app.config.get('STATSD_PREFIX')
|
||||||
|
|
||||||
|
self.statsd = DogStatsd(host=host, port=port, namespace=prefix)
|
||||||
|
|
||||||
|
def submit(self, metric_name, metric_type, metric_value, metric_tags=None, options=None):
|
||||||
|
valid_types = ['COUNTER', 'GAUGE', 'TIMER']
|
||||||
|
tags = []
|
||||||
|
|
||||||
|
if metric_type.upper() not in valid_types:
|
||||||
|
raise Exception(
|
||||||
|
"Invalid Metric Type for Statsd, '{metric}' choose from: {options}".format(
|
||||||
|
metric=metric_type, options=','.join(valid_types)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if metric_tags:
|
||||||
|
if not isinstance(metric_tags, dict):
|
||||||
|
raise Exception("Invalid Metric Tags for Statsd: Tags must be in dict format")
|
||||||
|
else:
|
||||||
|
tags = map(lambda e: "{0}:{1}".format(*e), metric_tags.items())
|
||||||
|
|
||||||
|
if metric_type.upper() == 'COUNTER':
|
||||||
|
self.statsd.increment(metric_name, metric_value, tags)
|
||||||
|
elif metric_type.upper() == 'GAUGE':
|
||||||
|
self.statsd.gauge(metric_name, metric_value, tags)
|
||||||
|
elif metric_type.upper() == 'TIMER':
|
||||||
|
self.statsd.timing(metric_name, metric_value, tags)
|
||||||
|
|
||||||
|
return
|
|
@ -0,0 +1,24 @@
|
||||||
|
"""Basic package information"""
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
install_requires = [
|
||||||
|
'lemur',
|
||||||
|
'datadog'
|
||||||
|
]
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='lemur_statsd',
|
||||||
|
version='1.0.0',
|
||||||
|
author='Cloudflare Security Engineering',
|
||||||
|
author_email='',
|
||||||
|
include_package_data=True,
|
||||||
|
packages=find_packages(),
|
||||||
|
zip_safe=False,
|
||||||
|
install_requires=install_requires,
|
||||||
|
entry_points={
|
||||||
|
'lemur.plugins': [
|
||||||
|
'statsd = lemur_statsd.plugin:StatsdMetricPlugin',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
|
@ -20,7 +20,8 @@
|
||||||
Key Type
|
Key Type
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<select class="form-control" ng-model="authority.keyType" ng-options="option for option in ['RSA2048', 'RSA4096']" ng-init="authority.keyType = 'RSA2048'"></select>
|
<select class="form-control" ng-model="authority.keyType" ng-options="option for option in ['RSA2048', 'RSA4096', 'ECCPRIME192V1', 'ECCPRIME256V1', 'ECCSECP192R1', 'ECCSECP224R1', 'ECCSECP256R1', 'ECCSECP384R1', 'ECCSECP521R1', 'ECCSECP256K1',
|
||||||
|
'ECCSECT163K1', 'ECCSECT233K1', 'ECCSECT283K1', 'ECCSECT409K1', 'ECCSECT571K1', 'ECCSECT163R2', 'ECCSECT233R1', 'ECCSECT283R1', 'ECCSECT409R1', 'ECCSECT571R2']" ng-init="authority.keyType = 'RSA2048'"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div ng-show="authority.sensitivity == 'high'" class="form-group">
|
<div ng-show="authority.sensitivity == 'high'" class="form-group">
|
||||||
|
|
|
@ -32,7 +32,10 @@
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<select class="form-control" ng-model="certificate.keyType"
|
<select class="form-control" ng-model="certificate.keyType"
|
||||||
ng-options="option for option in ['RSA2048', 'RSA4096']"
|
ng-options="option for option in ['RSA2048', 'RSA4096', 'ECCPRIME192V1', 'ECCPRIME256V1', 'ECCSECP192R1',
|
||||||
|
'ECCSECP224R1', 'ECCSECP256R1', 'ECCSECP384R1', 'ECCSECP521R1', 'ECCSECP256K1',
|
||||||
|
'ECCSECT163K1', 'ECCSECT233K1', 'ECCSECT283K1', 'ECCSECT409K1', 'ECCSECT571K1',
|
||||||
|
'ECCSECT163R2', 'ECCSECT233R1', 'ECCSECT283R1', 'ECCSECT409R1', 'ECCSECT571R2']"
|
||||||
ng-init="certificate.keyType = 'RSA2048'"></select>
|
ng-init="certificate.keyType = 'RSA2048'"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,9 +6,27 @@ def test_generate_private_key():
|
||||||
|
|
||||||
assert generate_private_key('RSA2048')
|
assert generate_private_key('RSA2048')
|
||||||
assert generate_private_key('RSA4096')
|
assert generate_private_key('RSA4096')
|
||||||
|
assert generate_private_key('ECCPRIME192V1')
|
||||||
|
assert generate_private_key('ECCPRIME256V1')
|
||||||
|
assert generate_private_key('ECCSECP192R1')
|
||||||
|
assert generate_private_key('ECCSECP224R1')
|
||||||
|
assert generate_private_key('ECCSECP256R1')
|
||||||
|
assert generate_private_key('ECCSECP384R1')
|
||||||
|
assert generate_private_key('ECCSECP521R1')
|
||||||
|
assert generate_private_key('ECCSECP256K1')
|
||||||
|
assert generate_private_key('ECCSECT163K1')
|
||||||
|
assert generate_private_key('ECCSECT233K1')
|
||||||
|
assert generate_private_key('ECCSECT283K1')
|
||||||
|
assert generate_private_key('ECCSECT409K1')
|
||||||
|
assert generate_private_key('ECCSECT571K1')
|
||||||
|
assert generate_private_key('ECCSECT163R2')
|
||||||
|
assert generate_private_key('ECCSECT233R1')
|
||||||
|
assert generate_private_key('ECCSECT283R1')
|
||||||
|
assert generate_private_key('ECCSECT409R1')
|
||||||
|
assert generate_private_key('ECCSECT571R2')
|
||||||
|
|
||||||
with pytest.raises(Exception):
|
with pytest.raises(Exception):
|
||||||
generate_private_key('ECC')
|
generate_private_key('LEMUR')
|
||||||
|
|
||||||
|
|
||||||
def test_get_authority_key():
|
def test_get_authority_key():
|
||||||
|
|
|
@ -2,15 +2,15 @@
|
||||||
# This file is autogenerated by pip-compile
|
# This file is autogenerated by pip-compile
|
||||||
# To update, run:
|
# To update, run:
|
||||||
#
|
#
|
||||||
# pip-compile --output-file requirements-dev.txt requirements-dev.in
|
# pip-compile --no-index --output-file requirements-dev.txt requirements-dev.in
|
||||||
#
|
#
|
||||||
aspy.yaml==1.0.0 # via pre-commit
|
aspy.yaml==1.1.0 # via pre-commit
|
||||||
cached-property==1.4.2 # via pre-commit
|
cached-property==1.4.2 # via pre-commit
|
||||||
certifi==2018.1.18 # via requests
|
certifi==2018.1.18 # via requests
|
||||||
cfgv==1.0.0 # via pre-commit
|
cfgv==1.0.0 # via pre-commit
|
||||||
chardet==3.0.4 # via requests
|
chardet==3.0.4 # via requests
|
||||||
flake8==3.5.0
|
flake8==3.5.0
|
||||||
identify==1.0.9 # via pre-commit
|
identify==1.0.11 # via pre-commit
|
||||||
idna==2.6 # via requests
|
idna==2.6 # via requests
|
||||||
invoke==0.22.1
|
invoke==0.22.1
|
||||||
mccabe==0.6.1 # via flake8
|
mccabe==0.6.1 # via flake8
|
||||||
|
@ -23,7 +23,7 @@ pyyaml==3.12 # via aspy.yaml, pre-commit
|
||||||
requests-toolbelt==0.8.0 # via twine
|
requests-toolbelt==0.8.0 # via twine
|
||||||
requests==2.18.4 # via requests-toolbelt, twine
|
requests==2.18.4 # via requests-toolbelt, twine
|
||||||
six==1.11.0 # via cfgv, pre-commit
|
six==1.11.0 # via cfgv, pre-commit
|
||||||
tqdm==4.21.0 # via twine
|
tqdm==4.22.0 # via twine
|
||||||
twine==1.11.0
|
twine==1.11.0
|
||||||
urllib3==1.22 # via requests
|
urllib3==1.22 # via requests
|
||||||
virtualenv==15.2.0 # via pre-commit
|
virtualenv==15.2.0 # via pre-commit
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# This file is autogenerated by pip-compile
|
# This file is autogenerated by pip-compile
|
||||||
# To update, run:
|
# To update, run:
|
||||||
#
|
#
|
||||||
# pip-compile --output-file requirements-docs.txt requirements-docs.in
|
# pip-compile --no-index --output-file requirements-docs.txt requirements-docs.in
|
||||||
#
|
#
|
||||||
alabaster==0.7.10 # via sphinx
|
alabaster==0.7.10 # via sphinx
|
||||||
babel==2.5.3 # via sphinx
|
babel==2.5.3 # via sphinx
|
||||||
|
@ -16,7 +16,7 @@ markupsafe==1.0 # via jinja2
|
||||||
packaging==17.1 # via sphinx
|
packaging==17.1 # via sphinx
|
||||||
pygments==2.2.0 # via sphinx
|
pygments==2.2.0 # via sphinx
|
||||||
pyparsing==2.2.0 # via packaging
|
pyparsing==2.2.0 # via packaging
|
||||||
pytz==2018.3 # via babel
|
pytz==2018.4 # via babel
|
||||||
requests==2.18.4 # via sphinx
|
requests==2.18.4 # via sphinx
|
||||||
six==1.11.0 # via packaging, sphinx, sphinxcontrib-httpdomain
|
six==1.11.0 # via packaging, sphinx, sphinxcontrib-httpdomain
|
||||||
snowballstemmer==1.2.1 # via sphinx
|
snowballstemmer==1.2.1 # via sphinx
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
# This file is autogenerated by pip-compile
|
# This file is autogenerated by pip-compile
|
||||||
# To update, run:
|
# To update, run:
|
||||||
#
|
#
|
||||||
# pip-compile --output-file requirements-tests.txt requirements-tests.in
|
# pip-compile --no-index --output-file requirements-tests.txt requirements-tests.in
|
||||||
#
|
#
|
||||||
asn1crypto==0.24.0 # via cryptography
|
asn1crypto==0.24.0 # via cryptography
|
||||||
attrs==17.4.0 # via pytest
|
attrs==17.4.0 # via pytest
|
||||||
aws-xray-sdk==0.95 # via moto
|
aws-xray-sdk==0.95 # via moto
|
||||||
boto3==1.7.2 # via moto
|
boto3==1.7.4 # via moto
|
||||||
boto==2.48.0 # via moto
|
boto==2.48.0 # via moto
|
||||||
botocore==1.10.2 # via boto3, moto, s3transfer
|
botocore==1.10.4 # via boto3, moto, s3transfer
|
||||||
certifi==2018.1.18 # via requests
|
certifi==2018.1.18 # via requests
|
||||||
cffi==1.11.5 # via cryptography
|
cffi==1.11.5 # via cryptography
|
||||||
chardet==3.0.4 # via requests
|
chardet==3.0.4 # via requests
|
||||||
|
@ -21,7 +21,7 @@ docker-pycreds==0.2.2 # via docker
|
||||||
docker==3.2.1 # via moto
|
docker==3.2.1 # via moto
|
||||||
docutils==0.14 # via botocore
|
docutils==0.14 # via botocore
|
||||||
factory-boy==2.10.0
|
factory-boy==2.10.0
|
||||||
faker==0.8.12
|
faker==0.8.13
|
||||||
flask==0.12.2 # via pytest-flask
|
flask==0.12.2 # via pytest-flask
|
||||||
freezegun==0.3.10
|
freezegun==0.3.10
|
||||||
idna==2.6 # via cryptography, requests
|
idna==2.6 # via cryptography, requests
|
||||||
|
@ -35,17 +35,17 @@ mock==2.0.0 # via moto
|
||||||
more-itertools==4.1.0 # via pytest
|
more-itertools==4.1.0 # via pytest
|
||||||
moto==1.3.1
|
moto==1.3.1
|
||||||
nose==1.3.7
|
nose==1.3.7
|
||||||
pbr==4.0.1 # via mock
|
pbr==4.0.2 # via mock
|
||||||
pluggy==0.6.0 # via pytest
|
pluggy==0.6.0 # via pytest
|
||||||
py==1.5.3 # via pytest
|
py==1.5.3 # via pytest
|
||||||
pyaml==17.12.1 # via moto
|
pyaml==17.12.1 # via moto
|
||||||
pycparser==2.18 # via cffi
|
pycparser==2.18 # via cffi
|
||||||
pyflakes==1.6.0
|
pyflakes==1.6.0
|
||||||
pytest-flask==0.10.0
|
pytest-flask==0.10.0
|
||||||
pytest-mock==1.8.0
|
pytest-mock==1.9.0
|
||||||
pytest==3.5.0
|
pytest==3.5.0
|
||||||
python-dateutil==2.6.1 # via botocore, faker, freezegun, moto
|
python-dateutil==2.6.1 # via botocore, faker, freezegun, moto
|
||||||
pytz==2018.3 # via moto
|
pytz==2018.4 # via moto
|
||||||
pyyaml==3.12 # via pyaml
|
pyyaml==3.12 # via pyaml
|
||||||
requests-mock==1.4.0
|
requests-mock==1.4.0
|
||||||
requests==2.18.4 # via aws-xray-sdk, docker, moto, requests-mock
|
requests==2.18.4 # via aws-xray-sdk, docker, moto, requests-mock
|
||||||
|
|
|
@ -11,6 +11,7 @@ Flask-RESTful==0.3.6
|
||||||
Flask-Script==2.0.6
|
Flask-Script==2.0.6
|
||||||
Flask-SQLAlchemy
|
Flask-SQLAlchemy
|
||||||
Flask==0.12
|
Flask==0.12
|
||||||
|
Flask-Cors
|
||||||
future
|
future
|
||||||
gunicorn
|
gunicorn
|
||||||
inflection
|
inflection
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# This file is autogenerated by pip-compile
|
# This file is autogenerated by pip-compile
|
||||||
# To update, run:
|
# To update, run:
|
||||||
#
|
#
|
||||||
# pip-compile --output-file requirements.txt requirements.in
|
# pip-compile --no-index --output-file requirements.txt requirements.in
|
||||||
#
|
#
|
||||||
acme==0.23.0
|
acme==0.23.0
|
||||||
alembic-autogenerate-enums==0.0.2
|
alembic-autogenerate-enums==0.0.2
|
||||||
|
@ -12,13 +12,14 @@ arrow==0.12.1
|
||||||
asn1crypto==0.24.0 # via cryptography
|
asn1crypto==0.24.0 # via cryptography
|
||||||
bcrypt==3.1.4 # via flask-bcrypt, paramiko
|
bcrypt==3.1.4 # via flask-bcrypt, paramiko
|
||||||
blinker==1.4 # via flask-mail, flask-principal, raven
|
blinker==1.4 # via flask-mail, flask-principal, raven
|
||||||
boto3==1.7.2
|
boto3==1.7.4
|
||||||
botocore==1.10.2 # via boto3, s3transfer
|
botocore==1.10.4 # via boto3, s3transfer
|
||||||
cffi==1.11.5 # via bcrypt, cryptography, pynacl
|
cffi==1.11.5 # via bcrypt, cryptography, pynacl
|
||||||
click==6.7 # via flask
|
click==6.7 # via flask
|
||||||
cryptography==2.2.2
|
cryptography==2.2.2
|
||||||
docutils==0.14 # via botocore
|
docutils==0.14 # via botocore
|
||||||
flask-bcrypt==0.7.1
|
flask-bcrypt==0.7.1
|
||||||
|
flask-cors==3.0.3
|
||||||
flask-mail==0.9.1
|
flask-mail==0.9.1
|
||||||
flask-migrate==2.1.1
|
flask-migrate==2.1.1
|
||||||
flask-principal==0.4.0
|
flask-principal==0.4.0
|
||||||
|
@ -42,7 +43,7 @@ marshmallow==2.15.0
|
||||||
mock==2.0.0 # via acme
|
mock==2.0.0 # via acme
|
||||||
ndg-httpsclient==0.4.4
|
ndg-httpsclient==0.4.4
|
||||||
paramiko==2.4.1
|
paramiko==2.4.1
|
||||||
pbr==4.0.1 # via mock
|
pbr==4.0.2 # via mock
|
||||||
pem==17.1.0
|
pem==17.1.0
|
||||||
psycopg2==2.7.4
|
psycopg2==2.7.4
|
||||||
pyasn1-modules==0.2.1 # via python-ldap
|
pyasn1-modules==0.2.1 # via python-ldap
|
||||||
|
@ -55,7 +56,7 @@ pyrfc3339==1.0 # via acme
|
||||||
python-dateutil==2.6.1 # via alembic, arrow, botocore
|
python-dateutil==2.6.1 # via alembic, arrow, botocore
|
||||||
python-editor==1.0.3 # via alembic
|
python-editor==1.0.3 # via alembic
|
||||||
python-ldap==3.0.0
|
python-ldap==3.0.0
|
||||||
pytz==2018.3 # via acme, flask-restful, pyrfc3339
|
pytz==2018.4 # via acme, flask-restful, pyrfc3339
|
||||||
raven[flask]==6.6.0
|
raven[flask]==6.6.0
|
||||||
requests[security]==2.11.1
|
requests[security]==2.11.1
|
||||||
retrying==1.3.3
|
retrying==1.3.3
|
||||||
|
|
Loading…
Reference in New Issue