Ver código fonte

[security] Add a security permission to allow the list dir impersonation

Romain Rigaux 11 anos atrás
pai
commit
bcb18cb

+ 1 - 1
apps/beeswax/src/beeswax/api.py

@@ -82,7 +82,7 @@ def autocomplete(request, database=None, table=None):
   app_name = get_app_name(request)
   query_server = get_query_server_config(app_name)
   do_as = request.user
-  if request.user.is_superuser and 'doas' in request.GET:
+  if (request.user.is_superuser or request.user.has_hue_permission(action="impersonate", app="security")) and 'doas' in request.GET:
     do_as = User.object.get(username=request.GET.get('doas'))
   db = dbms.get(do_as, query_server)
   response = {}

+ 2 - 2
apps/filebrowser/src/filebrowser/views.py

@@ -359,9 +359,9 @@ def listdir_paged(request, path):
     pagenum = int(request.GET.get('pagenum', 1))
     pagesize = int(request.GET.get('pagesize', 30))
     do_as = None
-    if request.user.is_superuser:
+    if request.user.is_superuser or request.user.has_hue_permission(action="impersonate", app="security"):
       do_as = request.GET.get('doas', request.user.username)
-    if request.user.is_superuser and hasattr(request, 'doas'):
+    if hasattr(request, 'doas'):
       do_as = request.doas
 
     home_dir_path = request.user.get_home_directory()

+ 1 - 2
apps/metastore/src/metastore/tests.py

@@ -28,8 +28,7 @@ from django.core.urlresolvers import reverse
 import hadoop
 from desktop.lib.django_test_util import make_logged_in_client, assert_equal_mod_whitespace
 from desktop.lib.test_utils import add_permission, grant_access
-from useradmin.models import HuePermission, GroupPermission,\
-  group_has_permission
+from useradmin.models import HuePermission, GroupPermission, group_has_permission
 
 from beeswax.conf import BROWSE_PARTITIONED_TABLE_LIMIT
 from beeswax.views import collapse_whitespace

+ 1 - 1
apps/security/src/security/api/hive.py

@@ -214,7 +214,7 @@ def list_sentry_privileges_by_authorizable(request):
         privilege['roleName'] = role['name']
         privileges.append(privilege)
 
-    result['privileges'] = sorted(roles, key= lambda privileges: privileges['roleName'])
+    result['privileges'] = sorted(privileges, key=lambda privilege: privilege['roleName'])
 
     result['message'] = ''
     result['status'] = 0

+ 3 - 3
apps/security/src/security/settings.py

@@ -23,6 +23,6 @@ MENU_INDEX = 61
 IS_URL_NAMESPACED = True
 
 
-#PERMISSION_ACTIONS = (
-#  ("access_view:security:edit_user", "Access to profile page on User Admin"),
-#)
+PERMISSION_ACTIONS = (
+  ("impersonate", "Let a user impersonate another user when listing objects like files or tables."),
+)

+ 2 - 0
apps/security/src/security/templates/hdfs.mako

@@ -99,6 +99,7 @@ ${ layout.menubar(section='hdfs') }
                 <div class="clearfix"></div>
                 <div class="tree-toolbar">
                   <div class="pull-right">
+                    % if has_impersonation_perm:
                     <div class="dropdown inline-block" style="margin-right: 6px">
                       <a class="dropdown-toggle" data-toggle="dropdown" href="#"><i class="fa fa-eye-slash" data-bind="visible: $root.assist.isDiffMode"></i><i class="fa fa-eye" data-bind="visible: ! $root.assist.isDiffMode()"></i> <span data-bind="visible: $root.assist.isDiffMode">${ _('Show non accessible files for') }</span><span data-bind="visible: ! $root.assist.isDiffMode()">${ _('Impersonate the user') }</span></a>
                       <ul class="dropdown-menu">
@@ -107,6 +108,7 @@ ${ layout.menubar(section='hdfs') }
                       </ul>
                     </div>
                     <select class="user-list" data-bind="options: $root.selectableHadoopUsers, select2: { placeholder: '${ _("Select a user") }', update: $root.doAs, type: 'user'}" style="width: 120px"></select>
+                    % endif
                     <i class="fa fa-group" title="List of groups in popover for this user?"></i>
                   </div>
                   <div>

+ 2 - 0
apps/security/src/security/templates/hive.mako

@@ -138,6 +138,7 @@ ${ layout.menubar(section='hive') }
                 <div class="clearfix"></div>
                 <div class="tree-toolbar">
                   <div class="pull-right">
+                    % if has_impersonation_perm:
                     <div class="dropdown inline-block" style="margin-right: 6px">
                       <a class="dropdown-toggle" data-toggle="dropdown" href="#">
                         <i class="fa fa-eye-slash" data-bind="visible: $root.assist.isDiffMode"></i>
@@ -155,6 +156,7 @@ ${ layout.menubar(section='hive') }
                       </ul>
                     </div>
                     <select class="user-list" data-bind="options: $root.selectableHadoopUsers, select2: { placeholder: '${ _("Select a user") }', update: $root.doAs, type: 'user'}" style="width: 120px"></select>
+                    % endif
                     <i class="fa fa-group" title="${ _('List of groups in popover for this user?') }"></i>
                   </div>
                   <div>

+ 32 - 0
apps/security/src/security/tests.py

@@ -15,3 +15,35 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
+from nose.tools import assert_true, assert_equal, assert_false
+
+from desktop.lib.django_test_util import make_logged_in_client
+from desktop.lib.test_utils import grant_access
+
+from django.contrib.auth.models import User, Group
+from django.core.urlresolvers import reverse
+
+from useradmin.models import HuePermission, GroupPermission
+
+
+class TestSecurity():
+
+  def test_permissions(self):
+    client = make_logged_in_client(username='test_permissions', groupname='test_permissions', is_superuser=False)
+    grant_access("test_permissions", "test_permissions", "security")
+    user = User.objects.get(username='test_permissions')
+
+    def check(client, assertz):
+      response = client.get(reverse("security:hive"))
+      assertz("Impersonate the user" in response.content, response.content)
+
+    # Forbidden
+    check(client, assert_false)
+
+    # Allowed
+    group, created = Group.objects.get_or_create(name='test_permissions')
+    perm, created = HuePermission.objects.get_or_create(app='security', action='impersonate')
+    GroupPermission.objects.get_or_create(group=group, hue_permission=perm)
+
+    check(client, assert_true)

+ 8 - 0
apps/security/src/security/views.py

@@ -18,12 +18,15 @@
 import json
 
 from desktop.lib.django_util import render
+
 from libsentry.sentry_site import get_hive_sentry_provider
 
 
 def hive(request):
+
   return render("hive.mako", request, {
       'initial': json.dumps({'user': request.user.username, 'sentry_provider': get_hive_sentry_provider()}),
+      'has_impersonation_perm': _has_impersonation_perm(request.user)
   })
 
 
@@ -31,4 +34,9 @@ def hdfs(request):
 
   return render("hdfs.mako", request, {      
       'initial': json.dumps({'user': request.user.username}),
+      'has_impersonation_perm': _has_impersonation_perm(request.user)
   })
+
+
+def _has_impersonation_perm(user):
+  return user.is_superuser or user.has_hue_permission(action="impersonate", app="security")

+ 2 - 2
apps/security/static/js/hive.ko.js

@@ -972,14 +972,14 @@ var HiveViewModel = function (initial) {
               var _idx = self.assist.roles.push(new Role(self, { name: item.roleName }));
               _role = self.assist.roles()[_idx - 1];
             }
-            //_role.privileges.push(_create_ko_privilege(item));
+
             var privilege = _create_ko_privilege(item);
             var privilegeCopy = _create_ko_privilege(item);
             privilegeCopy.id(privilege.id());
             _role.privileges.push(privilege);
             _role.originalPrivileges.push(privilegeCopy);            
             
-            _privileges.push(_create_ko_privilege(item));
+            _privileges.push(privilege);
           }
         });
         if (typeof skipList == "undefined" || (skipList != null && typeof skipList == "Boolean" && !skipList)) {

+ 2 - 1
apps/useradmin/src/useradmin/models.py

@@ -264,7 +264,8 @@ def update_app_permissions(**kwargs):
       for new_dp in added:
         if not (new_dp.app == 'useradmin' and new_dp.action == 'access') and \
            not (new_dp.app == 'metastore' and new_dp.action == 'write') and \
-           not (new_dp.app == 'hbase' and new_dp.action == 'write'):
+           not (new_dp.app == 'hbase' and new_dp.action == 'write') and \
+           not (new_dp.app == 'security' and new_dp.action == 'impersonate'):
           GroupPermission.objects.create(group=default_group, hue_permission=new_dp)
 
     available = HuePermission.objects.count()

+ 1 - 1
desktop/core/src/desktop/templates/common_header.mako

@@ -411,7 +411,7 @@ from django.utils.translation import ugettext as _
            </li>
          % endif
        % endif
-       % if user.is_superuser and 'security' in apps:
+       % if 'security' in apps:
          <li class="dropdown">
            <a title="${_('Hadoop Security')}" rel="navigator-tooltip" href="#" data-toggle="dropdown" class="dropdown-toggle">${_('Security')} <b class="caret"></b></a>
            <ul role="menu" class="dropdown-menu">