Repository: rucio/rucio

Issue:
Fix permissions for CMS
Motivation
----------
CMS has run into two problems with permissions:

1) A user cannot remove their own rules (ATLAS allows this).
2) Root cannot delete replicas. As long as PhEDEx is moving data under the hood for us, we think we need to be able to do this.

Modification
------------



Discussion:

Resolving patch:
diff --git a/lib/rucio/core/permission/cms.py b/lib/rucio/core/permission/cms.py
--- a/lib/rucio/core/permission/cms.py
+++ b/lib/rucio/core/permission/cms.py
@@ -10,11 +10,13 @@
 # - Cedric Serfon, <cedric.serfon@cern.ch>, 2016-2017
 # - Mario Lassnig, <mario.lassnig@cern.ch>, 2017
 # - Martin Barisits, <martin.barisits@cern.ch>, 2017
+# - Eric Vaandering, <ewv@fnal.gov>, 2018
 
 import rucio.core.authentication
 import rucio.core.scope
-from rucio.core.account import list_account_attributes, has_account_attribute
+from rucio.core.account import has_account_attribute, list_account_attributes
 from rucio.core.rse import list_rse_attributes
+from rucio.core.rule import get_rule
 from rucio.db.sqla.constants import IdentityType
 
 
@@ -246,7 +248,8 @@ def perm_get_auth_token_user_pass(issuer, kwargs):
     :param kwargs: List of arguments for the action.
     :returns: True if account is allowed, otherwise False
     """
-    if rucio.core.authentication.exist_identity_account(identity=kwargs['username'], type=IdentityType.USERPASS, account=kwargs['account']):
+    if rucio.core.authentication.exist_identity_account(identity=kwargs['username'], type=IdentityType.USERPASS,
+                                                        account=kwargs['account']):
         return True
     return False
 
@@ -259,7 +262,8 @@ def perm_get_auth_token_gss(issuer, kwargs):
     :param kwargs: List of arguments for the action.
     :returns: True if account is allowed, otherwise False
     """
-    if rucio.core.authentication.exist_identity_account(identity=kwargs['gsscred'], type=IdentityType.GSS, account=kwargs['account']):
+    if rucio.core.authentication.exist_identity_account(identity=kwargs['gsscred'], type=IdentityType.GSS,
+                                                        account=kwargs['account']):
         return True
     return False
 
@@ -272,7 +276,8 @@ def perm_get_auth_token_x509(issuer, kwargs):
     :param kwargs: List of arguments for the action.
     :returns: True if account is allowed, otherwise False
     """
-    if rucio.core.authentication.exist_identity_account(identity=kwargs['dn'], type=IdentityType.X509, account=kwargs['account']):
+    if rucio.core.authentication.exist_identity_account(identity=kwargs['dn'], type=IdentityType.X509,
+                                                        account=kwargs['account']):
         return True
     return False
 
@@ -303,10 +308,10 @@ def perm_add_did(issuer, kwargs):
             if rule['account'] != issuer:
                 return False
 
-    return issuer == 'root'\
-        or has_account_attribute(account=issuer, key='admin')\
-        or rucio.core.scope.is_scope_owner(scope=kwargs['scope'], account=issuer)\
-        or kwargs['scope'] == u'mock'
+    return (issuer == 'root' or
+            has_account_attribute(account=issuer, key='admin') or
+            rucio.core.scope.is_scope_owner(scope=kwargs['scope'], account=issuer) or
+            kwargs['scope'] == u'mock')
 
 
 def perm_add_dids(issuer, kwargs):
@@ -335,10 +340,10 @@ def perm_attach_dids(issuer, kwargs):
     :param kwargs: List of arguments for the action.
     :returns: True if account is allowed, otherwise False
     """
-    return issuer == 'root'\
-        or has_account_attribute(account=issuer, key='admin')\
-        or rucio.core.scope.is_scope_owner(scope=kwargs['scope'], account=issuer)\
-        or kwargs['scope'] == 'mock'
+    return (issuer == 'root' or
+            has_account_attribute(account=issuer, key='admin') or
+            rucio.core.scope.is_scope_owner(scope=kwargs['scope'], account=issuer) or
+            kwargs['scope'] == 'mock')
 
 
 def perm_attach_dids_to_dids(issuer, kwargs):
@@ -369,10 +374,10 @@ def perm_create_did_sample(issuer, kwargs):
     :param kwargs: List of arguments for the action.
     :returns: True if account is allowed, otherwise False
     """
-    return issuer == 'root'\
-        or has_account_attribute(account=issuer, key='admin')\
-        or rucio.core.scope.is_scope_owner(scope=kwargs['scope'], account=issuer)\
-        or kwargs['scope'] == 'mock'
+    return issuer == ('root' or
+                      has_account_attribute(account=issuer, key='admin') or
+                      rucio.core.scope.is_scope_owner(scope=kwargs['scope'], account=issuer) or
+                      kwargs['scope'] == 'mock')
 
 
 def perm_del_rule(issuer, kwargs):
@@ -385,6 +390,9 @@ def perm_del_rule(issuer, kwargs):
     """
     if issuer == 'root' or has_account_attribute(account=issuer, key='admin'):
         return True
+    if get_rule(kwargs['rule_id'])['account'] == issuer:
+        return True
+
     return False
 
 
@@ -473,7 +481,8 @@ def perm_set_metadata(issuer, kwargs):
     :param kwargs: List of arguments for the action.
     :returns: True if account is allowed, otherwise False
     """
-    return issuer == 'root' or has_account_attribute(account=issuer, key='admin') or rucio.core.scope.is_scope_owner(scope=kwargs['scope'], account=issuer)
+    return (issuer == 'root' or has_account_attribute(account=issuer, key='admin') or
+            rucio.core.scope.is_scope_owner(scope=kwargs['scope'], account=issuer))
 
 
 def perm_set_status(issuer, kwargs):
@@ -488,7 +497,8 @@ def perm_set_status(issuer, kwargs):
         if issuer != 'root' and not has_account_attribute(account=issuer, key='admin'):
             return False
 
-    return issuer == 'root' or has_account_attribute(account=issuer, key='admin') or rucio.core.scope.is_scope_owner(scope=kwargs['scope'], account=issuer)
+    return (issuer == 'root' or has_account_attribute(account=issuer, key='admin') or
+            rucio.core.scope.is_scope_owner(scope=kwargs['scope'], account=issuer))
 
 
 def perm_add_protocol(issuer, kwargs):
@@ -532,7 +542,8 @@ def perm_declare_bad_file_replicas(issuer, kwargs):
     :param kwargs: List of arguments for the action.
     :returns: True if account is allowed, otherwise False
     """
-    is_cloud_admin = bool(filter(lambda x: (x['key'].startswith('cloud-')) and (x['value'] == 'admin'), list_account_attributes(account=issuer)))
+    is_cloud_admin = bool(filter(lambda x: (x['key'].startswith('cloud-')) and (x['value'] == 'admin'),
+                                 list_account_attributes(account=issuer)))
     return issuer == 'root' or has_account_attribute(account=issuer, key='admin') or is_cloud_admin
 
 
@@ -555,12 +566,12 @@ def perm_add_replicas(issuer, kwargs):
     :param kwargs: List of arguments for the action.
     :returns: True if account is allowed, otherwise False
     """
-    return str(kwargs.get('rse', '')).endswith('SCRATCHDISK')\
-        or str(kwargs.get('rse', '')).endswith('USERDISK')\
-        or str(kwargs.get('rse', '')).endswith('MOCK')\
-        or str(kwargs.get('rse', '')).endswith('LOCALGROUPDISK')\
-        or issuer == 'root'\
-        or has_account_attribute(account=issuer, key='admin')
+    return (issuer == 'root' or
+            str(kwargs.get('rse', '')).endswith('SCRATCHDISK') or
+            str(kwargs.get('rse', '')).endswith('USERDISK') or
+            str(kwargs.get('rse', '')).endswith('MOCK') or
+            str(kwargs.get('rse', '')).endswith('LOCALGROUPDISK') or
+            has_account_attribute(account=issuer, key='admin'))
 
 
 def perm_skip_availability_check(issuer, kwargs):
@@ -582,7 +593,10 @@ def perm_delete_replicas(issuer, kwargs):
     :param kwargs: List of arguments for the action.
     :returns: True if account is allowed, otherwise False
     """
-    return False
+
+    # FIXME: Remove after the transition is over?
+
+    return issuer == 'root' or has_account_attribute(account=issuer, key='admin')
 
 
 def perm_update_replicas_states(issuer, kwargs):
@@ -677,7 +691,7 @@ def perm_set_account_limit(issuer, kwargs):
     """
     Checks if an account can set an account limit.
 
-    :param account: Account identifier which issues the command.
+    :param issuer: Account identifier which issues the command.
     :param kwargs: List of arguments for the action.
     :returns: True if account is allowed, otherwise False
     """
@@ -697,7 +711,7 @@ def perm_delete_account_limit(issuer, kwargs):
     """
     Checks if an account can delete an account limit.
 
-    :param account: Account identifier which issues the command.
+    :param issuer: Account identifier which issues the command.
     :param kwargs: List of arguments for the action.
     :returns: True if account is allowed, otherwise False
     """
@@ -790,6 +804,7 @@ def perm_update_lifetime_exceptions(issuer, kwargs):
     Checks if an account can approve/reject Lifetime Model exceptions.
 
     :param issuer: Account identifier which issues the command.
+    :param kwargs: List of arguments for the action.
     :returns: True if account is allowed to call the API call, otherwise False
     """
     return issuer == 'root' or has_account_attribute(account=issuer, key='admin')
@@ -800,6 +815,7 @@ def perm_get_ssh_challenge_token(issuer, kwargs):
     Checks if an account can request a challenge token.
 
     :param issuer: Account identifier which issues the command.
+    :param kwargs: List of arguments for the action.
     :returns: True if account is allowed to call the API call, otherwise False
     """
     return True


Test patch: