* Closes #147

* Fixing tests

* Ensuring we can validate max dates.
This commit is contained in:
kevgliss
2016-05-23 11:28:25 -07:00
parent bd727b825d
commit 656269ff17
22 changed files with 334 additions and 200 deletions

View File

@ -6,49 +6,35 @@
:license: Apache, see LICENSE for more details.
.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
"""
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from sqlalchemy.orm import relationship
from sqlalchemy import Column, Integer, String, Text, func, ForeignKey, DateTime, PassiveDefault, Boolean
from sqlalchemy.dialects.postgresql import JSON
from lemur.database import db
from lemur.models import roles_authorities
from lemur.common import defaults
class Authority(db.Model):
__tablename__ = 'authorities'
id = Column(Integer, primary_key=True)
owner = Column(String(128))
owner = Column(String(128), nullable=False)
name = Column(String(128), unique=True)
body = Column(Text())
chain = Column(Text())
bits = Column(Integer())
cn = Column(String(128))
not_before = Column(DateTime)
not_after = Column(DateTime)
active = Column(Boolean, default=True)
date_created = Column(DateTime, PassiveDefault(func.now()), nullable=False)
plugin_name = Column(String(64))
description = Column(Text)
options = Column(JSON)
date_created = Column(DateTime, PassiveDefault(func.now()), nullable=False)
roles = relationship('Role', secondary=roles_authorities, passive_deletes=True, backref=db.backref('authority'), lazy='dynamic')
user_id = Column(Integer, ForeignKey('users.id'))
certificates = relationship("Certificate", backref='authority')
authority_certificate = relationship("Certificate", backref='root_authority', uselist=False, foreign_keys='Certificate.root_authority_id')
certificates = relationship("Certificate", backref='authority', foreign_keys='Certificate.authority_id')
def __init__(self, name, owner, plugin_name, body, roles=None, chain=None, description=None):
cert = x509.load_pem_x509_certificate(bytes(body), default_backend())
self.name = name
self.body = body
self.chain = chain
self.owner = owner
self.description = description
self.plugin_name = plugin_name
self.cn = defaults.common_name(cert)
self.not_before = defaults.not_before(cert)
self.not_after = defaults.not_after(cert)
if roles:
self.roles = roles
def __init__(self, **kwargs):
self.owner = kwargs['owner']
self.roles = kwargs.get('roles', [])
self.name = kwargs.get('name')
self.description = kwargs.get('description')
self.authority_certificate = kwargs['authority_certificate']
self.plugin_name = kwargs['plugin']['slug']

View File

@ -12,6 +12,7 @@ from marshmallow import validate
from marshmallow.exceptions import ValidationError
from lemur.schemas import PluginInputSchema, PluginOutputSchema, ExtensionSchema, AssociatedAuthoritySchema, AssociatedRoleSchema
from lemur.users.schemas import UserNestedOutputSchema
from lemur.common.schema import LemurInputSchema, LemurOutputSchema
from lemur.common import validators
@ -61,25 +62,39 @@ class AuthorityInputSchema(LemurInputSchema):
class AuthorityUpdateSchema(LemurInputSchema):
owner = fields.Email()
owner = fields.Email(required=True)
description = fields.String()
active = fields.Boolean()
roles = fields.Nested(AssociatedRoleSchema(many=True))
class RootAuthorityCertificateOutputSchema(LemurOutputSchema):
__envelope__ = False
id = fields.Integer()
active = fields.Boolean()
bits = fields.Integer()
body = fields.String()
chain = fields.String()
description = fields.String()
name = fields.String()
cn = fields.String()
not_after = fields.DateTime()
not_before = fields.DateTime()
owner = fields.Email()
status = fields.Boolean()
user = fields.Nested(UserNestedOutputSchema)
class AuthorityOutputSchema(LemurOutputSchema):
id = fields.Integer()
description = fields.String()
name = fields.String()
owner = fields.Email()
not_before = fields.DateTime()
not_after = fields.DateTime()
plugin = fields.Nested(PluginOutputSchema)
body = fields.String()
chain = fields.String()
active = fields.Boolean()
options = fields.Dict()
roles = fields.List(fields.Nested(AssociatedRoleSchema))
authority_certificate = fields.Nested(RootAuthorityCertificateOutputSchema)
class AuthorityNestedOutputSchema(LemurOutputSchema):
@ -87,13 +102,8 @@ class AuthorityNestedOutputSchema(LemurOutputSchema):
description = fields.String()
name = fields.String()
owner = fields.Email()
not_before = fields.DateTime()
not_after = fields.DateTime()
plugin = fields.Nested(PluginOutputSchema)
body = fields.String()
chain = fields.String()
active = fields.Boolean()
options = fields.Dict()
authority_update_schema = AuthorityUpdateSchema()

View File

@ -9,14 +9,13 @@
"""
from flask import g
from flask import current_app
from lemur import database
from lemur.extensions import metrics
from lemur.authorities.models import Authority
from lemur.roles import service as role_service
from lemur.notifications import service as notification_service
from lemur.certificates.models import Certificate
from lemur.certificates.service import upload
def update(authority_id, description=None, owner=None, active=None, roles=None):
@ -40,42 +39,28 @@ def update(authority_id, description=None, owner=None, active=None, roles=None):
return database.update(authority)
def create(kwargs):
def mint(**kwargs):
"""
Create a new authority.
Creates the authority based on the plugin provided.
"""
issuer = kwargs['plugin']['plugin_object']
body, chain, roles = issuer.create_authority(kwargs)
return body, chain, roles
def create_authority_roles(roles, **kwargs):
"""
Creates all of the necessary authority roles.
:param roles:
:param kwargs:
:return:
"""
issuer = kwargs['plugin']['plugin_object']
kwargs['creator'] = g.current_user.email
cert_body, intermediate, issuer_roles = issuer.create_authority(kwargs)
cert = Certificate(body=cert_body, chain=intermediate, **kwargs)
if kwargs['type'] == 'subca':
cert.description = "This is the ROOT certificate for the {0} sub certificate authority the parent \
authority is {1}.".format(kwargs.get('name'), kwargs.get('parent'))
else:
cert.description = "This is the ROOT certificate for the {0} certificate authority.".format(
kwargs.get('name')
)
cert.user = g.current_user
cert.notifications = notification_service.create_default_expiration_notifications(
'DEFAULT_SECURITY',
current_app.config.get('LEMUR_SECURITY_TEAM_EMAIL')
)
# we create and attach any roles that the issuer gives us
role_objs = []
for r in issuer_roles:
for r in roles:
role = role_service.create(
r['name'],
password=r['password'],
description="{0} auto generated role".format(issuer.title),
description="Auto generated role for {0}".format(kwargs['plugin']['plugin_object'].title),
username=r['username'])
# the user creating the authority should be able to administer it
@ -93,22 +78,39 @@ def create(kwargs):
)
role_objs.append(owner_role)
return role_objs
authority = Authority(
kwargs.get('name'),
kwargs['owner'],
issuer.slug,
cert_body,
description=kwargs['description'],
chain=intermediate,
roles=role_objs
)
database.update(cert)
def create(**kwargs):
"""
Creates a new authority.
"""
kwargs['creator'] = g.user.email
body, chain, roles = mint(**kwargs)
kwargs['body'] = body
kwargs['chain'] = chain
kwargs['roles'] = create_authority_roles(roles, **kwargs)
if kwargs['type'] == 'subca':
description = "This is the ROOT certificate for the {0} sub certificate authority the parent \
authority is {1}.".format(kwargs.get('name'), kwargs.get('parent'))
else:
description = "This is the ROOT certificate for the {0} certificate authority.".format(
kwargs.get('name')
)
kwargs['description'] = description
cert = upload(**kwargs)
kwargs['authority_certificate'] = cert
authority = Authority(**kwargs)
authority = database.create(authority)
g.user.authorities.append(authority)
g.current_user.authorities.append(authority)
metrics.send('authority_created', 'counter', 1, metric_tags=dict(owner=authority.owner))
return authority

View File

@ -167,7 +167,7 @@ class AuthoritiesList(AuthenticatedResource):
:statuscode 403: unauthenticated
:statuscode 200: no error
"""
return service.create(data)
return service.create(**data)
class Authorities(AuthenticatedResource):