diff --git a/lemur/auth/permissions.py b/lemur/auth/permissions.py
index 8b64b558..5b6d7902 100644
--- a/lemur/auth/permissions.py
+++ b/lemur/auth/permissions.py
@@ -18,6 +18,9 @@ admin_permission = Permission(RoleNeed('admin'))
CertificateCreator = namedtuple('certificate', ['method', 'value'])
CertificateCreatorNeed = partial(CertificateCreator, 'key')
+CertificateOwner = namedtuple('certificate', ['method', 'value'])
+CertificateOwnerNeed = partial(CertificateOwner, 'role')
+
class SensitiveDomainPermission(Permission):
def __init__(self):
@@ -36,6 +39,15 @@ class UpdateCertificatePermission(Permission):
super(UpdateCertificatePermission, self).__init__(c_need, RoleNeed(owner), RoleNeed('admin'))
+class CertificatePermission(Permission):
+ def __init__(self, certificate_id, roles):
+ needs = [RoleNeed('admin'), CertificateCreatorNeed(certificate_id)]
+ for r in roles:
+ needs.append(CertificateOwnerNeed(str(r)))
+
+ super(CertificatePermission, self).__init__(*needs)
+
+
RoleUser = namedtuple('role', ['method', 'value'])
ViewRoleCredentialsNeed = partial(RoleUser, 'roleView')
diff --git a/lemur/auth/service.py b/lemur/auth/service.py
index 352b905d..ad1cf4f6 100644
--- a/lemur/auth/service.py
+++ b/lemur/auth/service.py
@@ -165,7 +165,7 @@ def on_identity_loaded(sender, identity):
# identity with the roles that the user provides
if hasattr(user, 'roles'):
for role in user.roles:
- identity.provides.add(ViewRoleCredentialsNeed(role.id))
+ identity.provides.add(ViewRoleCredentialsNeed(role.name))
identity.provides.add(RoleNeed(role.name))
# apply ownership for authorities
diff --git a/lemur/authorities/views.py b/lemur/authorities/views.py
index 500a1187..cd204d8d 100644
--- a/lemur/authorities/views.py
+++ b/lemur/authorities/views.py
@@ -5,7 +5,7 @@
:license: Apache, see LICENSE for more details.
.. moduleauthor:: Kevin Glisson
"""
-from flask import Blueprint, g
+from flask import Blueprint
from flask.ext.restful import reqparse, Api
from lemur.common.utils import paginated_parser
@@ -13,7 +13,6 @@ from lemur.common.schema import validate_schema
from lemur.auth.service import AuthenticatedResource
from lemur.auth.permissions import AuthorityPermission
-from lemur.roles import service as role_service
from lemur.certificates import service as certificate_service
from lemur.authorities import service
@@ -270,24 +269,11 @@ class Authorities(AuthenticatedResource):
if not authority:
return dict(message='Not Found'), 404
- role = role_service.get_by_name(authority.owner)
-
# all the authority role members should be allowed
roles = [x.name for x in authority.roles]
-
- # allow "owner" roles by team DL
- roles.append(role)
permission = AuthorityPermission(authority_id, roles)
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'],
diff --git a/lemur/certificates/schemas.py b/lemur/certificates/schemas.py
index d34c2fb1..a31a1c51 100644
--- a/lemur/certificates/schemas.py
+++ b/lemur/certificates/schemas.py
@@ -11,11 +11,12 @@ from marshmallow import fields, validates_schema, post_load
from marshmallow.exceptions import ValidationError
from lemur.schemas import AssociatedAuthoritySchema, AssociatedDestinationSchema, AssociatedCertificateSchema, \
- AssociatedNotificationSchema, PluginInputSchema, ExtensionSchema
+ AssociatedNotificationSchema, PluginInputSchema, ExtensionSchema, AssociatedRoleSchema
from lemur.authorities.schemas import AuthorityNestedOutputSchema
from lemur.destinations.schemas import DestinationNestedOutputSchema
from lemur.notifications.schemas import NotificationNestedOutputSchema
+from lemur.roles.schemas import RoleNestedOutputSchema
# from lemur.domains.schemas import DomainNestedOutputSchema
from lemur.users.schemas import UserNestedOutputSchema
@@ -51,6 +52,7 @@ class CertificateInputSchema(CertificateSchema):
destinations = fields.Nested(AssociatedDestinationSchema, missing=[], many=True)
notifications = fields.Nested(AssociatedNotificationSchema, missing=[], many=True)
replacements = fields.Nested(AssociatedCertificateSchema, missing=[], many=True)
+ roles = fields.Nested(AssociatedRoleSchema, missing=[], many=True)
csr = fields.String(validate=validators.csr)
@@ -73,6 +75,7 @@ class CertificateEditInputSchema(CertificateSchema):
destinations = fields.Nested(AssociatedDestinationSchema, missing=[], many=True)
notifications = fields.Nested(AssociatedNotificationSchema, missing=[], many=True)
replacements = fields.Nested(AssociatedCertificateSchema, missing=[], many=True)
+ roles = fields.Nested(AssociatedRoleSchema, missing=[], many=True)
class CertificateNestedOutputSchema(LemurOutputSchema):
@@ -117,6 +120,7 @@ class CertificateOutputSchema(LemurOutputSchema):
notifications = fields.Nested(NotificationNestedOutputSchema, many=True)
replaces = fields.Nested(CertificateNestedOutputSchema, many=True)
authority = fields.Nested(AuthorityNestedOutputSchema)
+ roles = fields.Nested(RoleNestedOutputSchema, many=True)
class CertificateUploadInputSchema(CertificateSchema):
@@ -130,6 +134,7 @@ class CertificateUploadInputSchema(CertificateSchema):
destinations = fields.Nested(AssociatedDestinationSchema, missing=[], many=True)
notifications = fields.Nested(AssociatedNotificationSchema, missing=[], many=True)
replacements = fields.Nested(AssociatedCertificateSchema, missing=[], many=True)
+ roles = fields.Nested(AssociatedRoleSchema, missing=[], many=True)
@validates_schema
def keys(self, data):
diff --git a/lemur/certificates/service.py b/lemur/certificates/service.py
index 177cab84..c4f0822b 100644
--- a/lemur/certificates/service.py
+++ b/lemur/certificates/service.py
@@ -91,7 +91,7 @@ def export(cert, export_plugin):
return plugin.export(cert.body, cert.chain, cert.private_key, export_plugin['pluginOptions'])
-def update(cert_id, owner, description, active, destinations, notifications, replaces):
+def update(cert_id, owner, description, active, destinations, notifications, replaces, roles):
"""
Updates a certificate
:param cert_id:
@@ -107,6 +107,8 @@ def update(cert_id, owner, description, active, destinations, notifications, rep
cert.active = active
cert.description = description
cert.destinations = destinations
+ cert.notifications = notifications
+ cert.roles = roles
cert.replaces = replaces
cert.owner = owner
diff --git a/lemur/certificates/views.py b/lemur/certificates/views.py
index d3918b8b..cbb54237 100644
--- a/lemur/certificates/views.py
+++ b/lemur/certificates/views.py
@@ -15,7 +15,7 @@ from lemur.common.schema import validate_schema
from lemur.common.utils import paginated_parser
from lemur.auth.service import AuthenticatedResource
-from lemur.auth.permissions import ViewKeyPermission, AuthorityPermission, UpdateCertificatePermission
+from lemur.auth.permissions import ViewKeyPermission, AuthorityPermission, CertificatePermission
from lemur.certificates import service
from lemur.certificates.schemas import certificate_input_schema, certificate_output_schema, \
@@ -519,9 +519,8 @@ class Certificates(AuthenticatedResource):
:statuscode 403: unauthenticated
"""
cert = service.get(certificate_id)
- role = role_service.get_by_name(cert.owner)
- permission = UpdateCertificatePermission(certificate_id, getattr(role, 'name', None))
+ permission = CertificatePermission(cert.id, [x.name for x in cert.roles])
if permission.can():
return service.update(
@@ -531,7 +530,8 @@ class Certificates(AuthenticatedResource):
data['active'],
data['destinations'],
data['notifications'],
- data['replacements']
+ data['replacements'],
+ data['roles']
)
return dict(message='You are not authorized to update this certificate'), 403
@@ -742,8 +742,8 @@ class CertificateExport(AuthenticatedResource):
:statuscode 403: unauthenticated
"""
cert = service.get(certificate_id)
- role = role_service.get_by_name(cert.owner)
- permission = UpdateCertificatePermission(certificate_id, getattr(role, 'name', None))
+
+ permission = CertificatePermission(cert.id, [x.name for x in cert.roles])
options = data['plugin']['plugin_options']
plugin = data['plugin']['plugin_object']
diff --git a/lemur/roles/schemas.py b/lemur/roles/schemas.py
index 52dfac10..fa685d04 100644
--- a/lemur/roles/schemas.py
+++ b/lemur/roles/schemas.py
@@ -30,6 +30,13 @@ class RoleOutputSchema(LemurOutputSchema):
users = fields.Nested(UserNestedOutputSchema, many=True)
+class RoleNestedOutputSchema(LemurOutputSchema):
+ __envelope__ = False
+ id = fields.Integer()
+ name = fields.String()
+ description = fields.String()
+
+
role_input_schema = RoleInputSchema()
role_output_schema = RoleOutputSchema()
roles_output_schema = RoleOutputSchema(many=True)
diff --git a/lemur/roles/service.py b/lemur/roles/service.py
index e4d4b394..b36a8665 100644
--- a/lemur/roles/service.py
+++ b/lemur/roles/service.py
@@ -9,8 +9,6 @@
.. moduleauthor:: Kevin Glisson
"""
-from flask import g
-
from lemur import database
from lemur.roles.models import Role
from lemur.users.models import User
@@ -102,13 +100,6 @@ def render(args):
if authority_id:
query = query.filter(Role.authority_id == authority_id)
- # we make sure that user can see the role - admins can see all
- if not g.current_user.is_admin:
- ids = []
- for role in g.current_user.roles:
- ids.append(role.id)
- query = query.filter(Role.id.in_(ids))
-
if filt:
terms = filt.split(';')
query = database.filter(query, Role, terms)
diff --git a/lemur/static/app/angular/authorities/authority/edit.tpl.html b/lemur/static/app/angular/authorities/authority/edit.tpl.html
index 8859e2e4..f1386328 100644
--- a/lemur/static/app/angular/authorities/authority/edit.tpl.html
+++ b/lemur/static/app/angular/authorities/authority/edit.tpl.html
@@ -1,6 +1,8 @@
diff --git a/lemur/static/app/angular/authorities/authority/tracking.tpl.html b/lemur/static/app/angular/authorities/authority/tracking.tpl.html
index f582d91d..1b766fe5 100644
--- a/lemur/static/app/angular/authorities/authority/tracking.tpl.html
+++ b/lemur/static/app/angular/authorities/authority/tracking.tpl.html
@@ -120,6 +120,12 @@
+
diff --git a/lemur/static/app/angular/certificates/certificate/edit.tpl.html b/lemur/static/app/angular/certificates/certificate/edit.tpl.html
index 7aa4e53a..cf76bbd7 100644
--- a/lemur/static/app/angular/certificates/certificate/edit.tpl.html
+++ b/lemur/static/app/angular/certificates/certificate/edit.tpl.html
@@ -27,6 +27,12 @@
You must give a short description about this authority will be used for, this description should only include alphanumeric characters
+
diff --git a/lemur/static/app/angular/certificates/certificate/tracking.tpl.html b/lemur/static/app/angular/certificates/certificate/tracking.tpl.html
index 3d2d37b6..31bb8921 100644
--- a/lemur/static/app/angular/certificates/certificate/tracking.tpl.html
+++ b/lemur/static/app/angular/certificates/certificate/tracking.tpl.html
@@ -146,6 +146,12 @@
class="help-block">Enter a valid certificate signing request.
+
diff --git a/lemur/static/app/angular/certificates/certificate/upload.tpl.html b/lemur/static/app/angular/certificates/certificate/upload.tpl.html
index ecd33305..26514bf3 100644
--- a/lemur/static/app/angular/certificates/certificate/upload.tpl.html
+++ b/lemur/static/app/angular/certificates/certificate/upload.tpl.html
@@ -81,6 +81,12 @@
class="help-block">Enter a valid certificate.
+
diff --git a/lemur/static/app/angular/certificates/services.js b/lemur/static/app/angular/certificates/services.js
index d9f02846..4f69a889 100644
--- a/lemur/static/app/angular/certificates/services.js
+++ b/lemur/static/app/angular/certificates/services.js
@@ -4,6 +4,16 @@ angular.module('lemur')
.service('CertificateApi', function (LemurRestangular, DomainService) {
LemurRestangular.extendModel('certificates', function (obj) {
return angular.extend(obj, {
+ attachRole: function (role) {
+ this.selectedRole = null;
+ if (this.roles === undefined) {
+ this.roles = [];
+ }
+ this.roles.push(role);
+ },
+ removeRole: function (index) {
+ this.roles.splice(index, 1);
+ },
attachAuthority: function (authority) {
this.authority = authority;
this.authority.maxDate = moment(this.authority.notAfter).subtract(1, 'days').format('YYYY/MM/DD');
diff --git a/lemur/static/app/angular/certificates/view/view.tpl.html b/lemur/static/app/angular/certificates/view/view.tpl.html
index 3426b023..d380059c 100644
--- a/lemur/static/app/angular/certificates/view/view.tpl.html
+++ b/lemur/static/app/angular/certificates/view/view.tpl.html
@@ -121,6 +121,15 @@
+
+ Roles
+
+ -
+ {{ role.name }}
+ {{ role.description}}
+
+
+
Destinations