Closes 262 (#324)
Moves the authority -> role relationship from a 1 -> many to a many -> many. This will allow one role to control and have access to many authorities.
This commit is contained in:
@ -14,7 +14,8 @@ from sqlalchemy import Column, Integer, String, Text, func, ForeignKey, DateTime
|
||||
from sqlalchemy.dialects.postgresql import JSON
|
||||
|
||||
from lemur.database import db
|
||||
from lemur.certificates.models import get_cn, get_not_after, get_not_before
|
||||
from lemur.models import roles_authorities
|
||||
from lemur.common import defaults
|
||||
|
||||
|
||||
class Authority(db.Model):
|
||||
@ -33,28 +34,21 @@ class Authority(db.Model):
|
||||
plugin_name = Column(String(64))
|
||||
description = Column(Text)
|
||||
options = Column(JSON)
|
||||
roles = relationship('Role', backref=db.backref('authority'), lazy='dynamic')
|
||||
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')
|
||||
|
||||
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
|
||||
cert = x509.load_pem_x509_certificate(bytes(body), default_backend())
|
||||
self.cn = get_cn(cert)
|
||||
self.not_before = get_not_before(cert)
|
||||
self.not_after = get_not_after(cert)
|
||||
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 as_dict(self):
|
||||
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
|
||||
|
||||
def serialize(self):
|
||||
blob = self.as_dict()
|
||||
return blob
|
||||
|
@ -63,6 +63,7 @@ class AuthorityInputSchema(LemurInputSchema):
|
||||
class AuthorityUpdateSchema(LemurInputSchema):
|
||||
owner = fields.Email()
|
||||
description = fields.String()
|
||||
active = fields.Boolean()
|
||||
roles = fields.Nested(AssociatedRoleSchema(many=True))
|
||||
|
||||
|
||||
|
@ -16,7 +16,6 @@ from lemur.authorities.models import Authority
|
||||
from lemur.roles import service as role_service
|
||||
from lemur.notifications import service as notification_service
|
||||
|
||||
from lemur.roles.models import Role
|
||||
from lemur.certificates.models import Certificate
|
||||
|
||||
|
||||
@ -29,8 +28,9 @@ def update(authority_id, description=None, owner=None, active=None, roles=None):
|
||||
:return:
|
||||
"""
|
||||
authority = get(authority_id)
|
||||
|
||||
if roles:
|
||||
authority = database.update_list(authority, 'roles', Role, roles)
|
||||
authority.roles = roles
|
||||
|
||||
if active:
|
||||
authority.active = active
|
||||
@ -52,8 +52,7 @@ def create(kwargs):
|
||||
kwargs['creator'] = g.current_user.email
|
||||
cert_body, intermediate, issuer_roles = issuer.create_authority(kwargs)
|
||||
|
||||
cert = Certificate(cert_body, chain=intermediate)
|
||||
cert.owner = kwargs['owner']
|
||||
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 \
|
||||
@ -73,7 +72,6 @@ def create(kwargs):
|
||||
# we create and attach any roles that the issuer gives us
|
||||
role_objs = []
|
||||
for r in issuer_roles:
|
||||
|
||||
role = role_service.create(
|
||||
r['name'],
|
||||
password=r['password'],
|
||||
@ -86,6 +84,16 @@ def create(kwargs):
|
||||
|
||||
role_objs.append(role)
|
||||
|
||||
# create an role for the owner and assign it
|
||||
owner_role = role_service.get_by_name(kwargs['owner'])
|
||||
if not owner_role:
|
||||
owner_role = role_service.create(
|
||||
kwargs['owner'],
|
||||
description="Auto generated role based on owner: {0}".format(kwargs['owner'])
|
||||
)
|
||||
|
||||
role_objs.append(owner_role)
|
||||
|
||||
authority = Authority(
|
||||
kwargs.get('name'),
|
||||
kwargs['owner'],
|
||||
@ -99,14 +107,6 @@ def create(kwargs):
|
||||
database.update(cert)
|
||||
authority = database.create(authority)
|
||||
|
||||
# the owning dl or role should have this authority associated with it
|
||||
owner_role = role_service.get_by_name(kwargs['owner'])
|
||||
|
||||
if not owner_role:
|
||||
owner_role = role_service.create(kwargs['owner'])
|
||||
|
||||
owner_role.authority = authority
|
||||
|
||||
g.current_user.authorities.append(authority)
|
||||
|
||||
return authority
|
||||
@ -181,8 +181,8 @@ def render(args):
|
||||
if not g.current_user.is_admin:
|
||||
authority_ids = []
|
||||
for role in g.current_user.roles:
|
||||
if role.authority:
|
||||
authority_ids.append(role.authority.id)
|
||||
for authority in role.authorities:
|
||||
authority_ids.append(authority.id)
|
||||
query = query.filter(Authority.id.in_(authority_ids))
|
||||
|
||||
return database.sort_and_page(query, Authority, args)
|
||||
|
@ -279,15 +279,15 @@ class Authorities(AuthenticatedResource):
|
||||
roles.append(role)
|
||||
permission = AuthorityPermission(authority_id, roles)
|
||||
|
||||
# we want to make sure that we cannot add roles that we are not members of
|
||||
if not g.current_user.is_admin:
|
||||
role_ids = set([r.id for r in data['roles']])
|
||||
user_role_ids = set([r.id for r in g.current_user.roles])
|
||||
|
||||
if not role_ids.issubset(user_role_ids):
|
||||
return dict(message="You are not allowed to associate a role which you are not a member of"), 400
|
||||
|
||||
if permission.can():
|
||||
# we want to make sure that we cannot add roles that we are not members of
|
||||
if not g.current_user.is_admin:
|
||||
role_ids = set([r.id for r in data['roles']])
|
||||
user_role_ids = set([r.id for r in g.current_user.roles])
|
||||
|
||||
if not role_ids.issubset(user_role_ids):
|
||||
return dict(message="You are not allowed to associate a role which you are not a member of."), 403
|
||||
|
||||
return service.update(
|
||||
authority_id,
|
||||
owner=data['owner'],
|
||||
@ -296,7 +296,7 @@ class Authorities(AuthenticatedResource):
|
||||
roles=data['roles']
|
||||
)
|
||||
|
||||
return dict(message="You are not authorized to update this authority"), 403
|
||||
return dict(message="You are not authorized to update this authority."), 403
|
||||
|
||||
|
||||
class CertificateAuthority(AuthenticatedResource):
|
||||
@ -345,7 +345,7 @@ class CertificateAuthority(AuthenticatedResource):
|
||||
"""
|
||||
cert = certificate_service.get(certificate_id)
|
||||
if not cert:
|
||||
return dict(message="Certificate not found"), 404
|
||||
return dict(message="Certificate not found."), 404
|
||||
|
||||
return cert.authority
|
||||
|
||||
|
Reference in New Issue
Block a user