fix roles assigned in the ui for sso (#1017)

This commit fixes the ability to assign roles to people in the ui
when the user is SSO. The idea is if a role is ever assigned via
SSO it becomes a "SSO Role" or a "Third Party" Role. by setting
third_party to true on the role object.

Once a role is marked as third party it can no longer be controlled
through the ui for SSO Users. (for ui users this poses no functional
change). It must be controlled via SSO.
This commit is contained in:
Eric 2017-12-11 14:51:45 -07:00 committed by kevgliss
parent f0c895a008
commit 6edc5180c7
7 changed files with 71 additions and 11 deletions

View File

@ -10,6 +10,8 @@ is 30 days. Every certificate will gain a policy regardless is auto-rotation is
Adds per-user API Keys, requires a database migration.
Adds third_party to roles for external authentication roles, requires a database migration.
.. note:: This version is not yet released and is under active development

View File

@ -65,7 +65,7 @@ class LdapPrincipal():
else:
# we add 'lemur' specific roles, so they do not get marked as removed
for ur in user.roles:
if ur.authority_id:
if not ur.third_party:
roles.add(ur)
# update any changes to the user
@ -97,13 +97,18 @@ class LdapPrincipal():
if self.ldap_default_role:
role = role_service.get_by_name(self.ldap_default_role)
if role:
if not role.third_party:
role = role.set_third_party(role.id, third_party_status=True)
roles.add(role)
# update their 'roles'
role = role_service.get_by_name(self.ldap_principal)
if not role:
description = "auto generated role based on owner: {0}".format(self.ldap_principal)
role = role_service.create(self.ldap_principal, description=description)
role = role_service.create(self.ldap_principal, description=description,
third_party=True)
if not role.third_party:
role = role_service.set_third_party(role.id, third_party_status=True)
roles.add(role)
if not self.ldap_groups_to_roles:
return roles
@ -113,6 +118,8 @@ class LdapPrincipal():
if role:
if ldap_group_name in self.ldap_groups:
current_app.logger.debug("assigning role {0} to ldap user {1}".format(self.ldap_principal, role))
if not role.third_party:
role = role_service.set_third_party(role.id, third_party_status=True)
roles.add(role)
return roles

View File

@ -211,13 +211,17 @@ class Ping(Resource):
for group in profile['googleGroups']:
role = role_service.get_by_name(group)
if not role:
role = role_service.create(group, description='This is a google group based role created by Lemur')
role = role_service.create(group, description='This is a google group based role created by Lemur', third_party=True)
if not role.third_party:
role = role_service.set_third_party(role.id, third_party_status=True)
roles.append(role)
role = role_service.get_by_name(profile['email'])
if not role:
role = role_service.create(profile['email'], description='This is a user specific role')
role = role_service.create(profile['email'], description='This is a user specific role', third_party=True)
if not role.third_party:
role = role_service.set_third_party(role.id, third_party_status=True)
roles.append(role)
@ -226,6 +230,8 @@ class Ping(Resource):
default = role_service.get_by_name(current_app.config['LEMUR_DEFAULT_ROLE'])
if not default:
default = role_service.create(current_app.config['LEMUR_DEFAULT_ROLE'], description='This is the default Lemur role.')
if not default.third_party:
role_service.set_third_party(default.id, third_party_status=True)
roles.append(default)
# if we get an sso user create them an account
@ -242,7 +248,7 @@ class Ping(Resource):
else:
# we add 'lemur' specific roles, so they do not get marked as removed
for ur in user.roles:
if ur.authority_id:
if not ur.third_party:
roles.append(ur)
# update any changes to the user
@ -352,12 +358,16 @@ class OAuth2(Resource):
for group in profile['roles']:
role = role_service.get_by_name(group)
if not role:
role = role_service.create(group, description='This is a group configured by identity provider')
role = role_service.create(group, description='This is a group configured by identity provider', third_party=True)
if not role.third_party:
role = role_service.set_third_party(role.id, third_party_status=True)
roles.append(role)
role = role_service.get_by_name(profile['email'])
if not role:
role = role_service.create(profile['email'], description='This is a user specific role')
role = role_service.create(profile['email'], description='This is a user specific role', third_party=True)
if not role.third_party:
role = role_service.set_third_party(role.id, third_party_status=True)
roles.append(role)
# if we get an sso user create them an account
@ -365,6 +375,8 @@ class OAuth2(Resource):
# every user is an operator (tied to a default role)
if current_app.config.get('LEMUR_DEFAULT_ROLE'):
v = role_service.get_by_name(current_app.config.get('LEMUR_DEFAULT_ROLE'))
if not v.third_party:
v = role_service.set_third_party(v.id, third_party_status=True)
if v:
roles.append(v)
@ -380,7 +392,7 @@ class OAuth2(Resource):
else:
# we add 'lemur' specific roles, so they do not get marked as removed
for ur in user.roles:
if ur.authority_id:
if not ur.third_party:
roles.append(ur)
# update any changes to the user

View File

@ -0,0 +1,22 @@
"""add third party roles to lemur
Revision ID: 5bc47fa7cac4
Revises: c05a8998b371
Create Date: 2017-12-08 14:19:11.903864
"""
# revision identifiers, used by Alembic.
revision = '5bc47fa7cac4'
down_revision = 'c05a8998b371'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.add_column('roles', sa.Column('third_party', sa.Boolean(), nullable=True, default=False))
def downgrade():
op.drop_column('roles', 'third_party')

View File

@ -10,7 +10,7 @@
"""
from sqlalchemy.orm import relationship
from sqlalchemy import Column, Integer, String, Text, ForeignKey
from sqlalchemy import Boolean, Column, Integer, String, Text, ForeignKey
from lemur.database import db
from lemur.utils import Vault
@ -27,6 +27,7 @@ class Role(db.Model):
authority_id = Column(Integer, ForeignKey('authorities.id'))
authorities = relationship("Authority", secondary=roles_authorities, passive_deletes=True, backref="role", cascade='all,delete')
user_id = Column(Integer, ForeignKey('users.id'))
third_party = Column(Boolean)
users = relationship("User", secondary=roles_users, passive_deletes=True, backref="role")
certificates = relationship("Certificate", secondary=roles_certificates, backref="role")

View File

@ -26,6 +26,7 @@ class RoleOutputSchema(LemurOutputSchema):
id = fields.Integer()
name = fields.String()
description = fields.String()
third_party = fields.Boolean()
authorities = fields.Nested(AuthorityNestedOutputSchema, many=True)
users = fields.Nested(UserNestedOutputSchema, many=True)

View File

@ -32,7 +32,22 @@ def update(role_id, name, description, users):
return role
def create(name, password=None, description=None, username=None, users=None):
def set_third_party(role_id, third_party_status=False):
"""
Sets a role to be a third party role. A user should pretty much never
call this directly.
:param role_id:
:param third_party_status:
:return:
"""
role = get(role_id)
role.third_party = third_party_status
database.update(role)
return role
def create(name, password=None, description=None, username=None, users=None, third_party=False):
"""
Create a new role
@ -43,7 +58,7 @@ def create(name, password=None, description=None, username=None, users=None):
:param password:
:return:
"""
role = Role(name=name, description=description, username=username, password=password)
role = Role(name=name, description=description, username=username, password=password, third_party=third_party)
if users:
role.users = users