Bladeren bron

HPCC-15699 Add column-level security enforcement

Enforce column-level views security for submitted queries.

Signed-off-by: Suk Hwan Hong <suk.hong@gatech.edu>
Suk Hwan Hong 9 jaren geleden
bovenliggende
commit
59ab9c62dd

+ 1 - 0
esp/services/ws_workunits/CMakeLists.txt

@@ -62,6 +62,7 @@ include_directories (
          ./../../../ecl/hql
          ./../../../system/security/securesocket
          ./../../../system/security/shared
+         ./../../../system/security/LdapSecurity
          ./../../../system/include
          ./../../../common/workunit
          ./../../../common/wuwebview

+ 18 - 0
esp/services/ws_workunits/ws_workunitsHelpers.cpp

@@ -29,6 +29,7 @@
 #include "dllserver.hpp"
 #include "wujobq.hpp"
 #include "hqlexpr.hpp"
+#include "ldapsecurity.ipp"
 
 #ifdef _USE_ZLIB
 #include "zcrypt.hpp"
@@ -3004,6 +3005,23 @@ void WsWuHelpers::submitWsWorkunit(IEspContext& context, IConstWorkUnit* cw, con
     const char *paramXml, IArrayOf<IConstNamedValue> *variables, IArrayOf<IConstNamedValue> *debugs, IArrayOf<IConstApplicationValue> *applications)
 {
     ensureWsWorkunitAccess(context, *cw, SecAccess_Write);
+
+#ifndef _NO_LDAP
+    CLdapSecManager* secmgr = dynamic_cast<CLdapSecManager*>(context.querySecManager());
+    if(secmgr == NULL)
+        throw MakeStringException(ECLWATCH_INVALID_SEC_MANAGER, "Security manager is not found");
+
+    if (secmgr->getCheckViewPermissions())
+    {
+        StringArray filenames, columnnames;
+        if (cw->getFieldUsageArray(filenames, columnnames, cluster)) // check view permission only for a query with fieldUsage information
+        {
+            if (!secmgr->authorizeViewScope(*context.queryUser(), filenames, columnnames))
+                throw MakeStringException(ECLWATCH_VIEW_ACCESS_DENIED, "View Access denied");
+        }
+    }
+#endif
+
     switch(cw->getState())
     {
         case WUStateRunning:

+ 2 - 0
esp/smc/SMCLib/eclwatch_errorlist.hpp

@@ -123,5 +123,7 @@
 #define ECLWATCH_RESOURCE_NOT_FOUND         ECLWATCH_ERROR_START+103
 #define ECLWATCH_CANNOT_GET_STATUS_INFO     ECLWATCH_ERROR_START+104
 
+#define ECLWATCH_VIEW_ACCESS_DENIED         ECLWATCH_ERROR_START+105
+
 #endif //_ECLWATCH_ERRORLIST_HPP__
 

+ 40 - 2
system/security/LdapSecurity/ldapsecurity.cpp

@@ -545,6 +545,7 @@ void CLdapSecManager::init(const char *serviceName, IPropertyTree* cfg)
     m_permissionsCache->setTransactionalEnabled(true);
     m_permissionsCache->setSecManager(this);
     m_passwordExpirationWarningDays = cfg->getPropInt(".//@passwordExpirationWarningDays", 10); //Default to 10 days
+    m_checkViewPermissions = cfg->getPropBool(".//@checkViewPermissions", false);
 };
 
 
@@ -865,9 +866,46 @@ bool CLdapSecManager::authorizeFileScope(ISecUser & user, ISecResourceList * res
     return authorizeEx(RT_FILE_SCOPE, user, resources);
 }
 
-bool CLdapSecManager::authorizeViewScope(ISecUser & user, ISecResourceList * resources)
+bool CLdapSecManager::authorizeViewScope(ISecUser & user, StringArray & filenames, StringArray & columnnames)
 {
-    return authorizeEx(RT_VIEW_SCOPE, user, resources);
+    if (filenames.length() != columnnames.length())
+        return false; 
+
+    const char* username = user.getName();
+    StringArray viewnames, viewdescriptions, viewManagedBy;
+
+    queryAllViews(viewnames, viewdescriptions, viewManagedBy);
+
+    // All views where user belongs must pass
+    ForEachItemIn(i, viewnames)
+    {
+        const char* viewname = viewnames.item(i);
+
+        if (userInView(username, viewname))
+        {    
+            Owned<ISecResourceList> resList;
+            resList.setown(new CLdapSecResourceList(viewname));
+
+            // Inefficient loop because we are adding same used columns all over again for each views.
+            // we can improve the performance later if there is a way to rename and reuse same ISecResourceList for each view.
+            ForEachItemIn(j, filenames)
+            {
+                StringBuffer resourceName;
+                resourceName.append("QueryAccessedColumns");
+                resourceName.append(j);
+                ISecResource* res = resList->addResource(resourceName);
+                res->addParameter("file", filenames.item(j));
+                res->addParameter("column", columnnames.item(j));
+            }
+
+            if (!authorizeEx(RT_VIEW_SCOPE, user, resList.get()))
+            {
+                return false;
+            }
+        }
+    }
+
+    return true;
 }
 
 int CLdapSecManager::authorizeWorkunitScope(ISecUser & user, const char * wuscope)

+ 8 - 1
system/security/LdapSecurity/ldapsecurity.ipp

@@ -341,6 +341,7 @@ private:
     bool authenticate(ISecUser* user);
     StringBuffer m_description;
     unsigned m_passwordExpirationWarningDays;
+    bool m_checkViewPermissions;
 
 public:
     IMPLEMENT_IINTERFACE
@@ -359,7 +360,7 @@ public:
     int authorizeEx(SecResourceType rtype, ISecUser& sec_user, const char* resourcename, IEspSecureContext* secureContext = NULL);
     virtual int authorizeFileScope(ISecUser & user, const char * filescope);
     virtual bool authorizeFileScope(ISecUser & user, ISecResourceList * resources);
-    virtual bool authorizeViewScope(ISecUser & user, ISecResourceList * resources);
+    virtual bool authorizeViewScope(ISecUser & user, StringArray & filenames, StringArray & columnnames);
     virtual int authorizeWorkunitScope(ISecUser & user, const char * wuscope);
     virtual bool authorizeWorkunitScope(ISecUser & user, ISecResourceList * resources);
     virtual bool addResources(ISecUser& sec_user, ISecResourceList * resources);
@@ -443,6 +444,12 @@ public:
     {
         return m_passwordExpirationWarningDays;
     }
+
+    virtual bool getCheckViewPermissions()
+    {
+        return m_checkViewPermissions;
+    }
+
     virtual bool createUserScopes();
     virtual aindex_t getManagedFileScopes(IArrayOf<ISecResource>& scopes);
     virtual int queryDefaultPermission(ISecUser& user);

+ 0 - 1
system/security/shared/seclib.hpp

@@ -281,7 +281,6 @@ interface ISecManager : extends IInterface
     virtual int getAccessFlagsEx(SecResourceType rtype, ISecUser & user, const char * resourcename) = 0;
     virtual int authorizeFileScope(ISecUser & user, const char * filescope) = 0;
     virtual bool authorizeFileScope(ISecUser & user, ISecResourceList * resources) = 0;
-    virtual bool authorizeViewScope(ISecUser & user, ISecResourceList * resources) = 0;
     virtual bool addResources(ISecUser & user, ISecResourceList * resources) = 0;
     virtual bool addResourcesEx(SecResourceType rtype, ISecUser & user, ISecResourceList * resources, SecPermissionType ptype, const char * basedn) = 0;
     virtual bool addResourceEx(SecResourceType rtype, ISecUser & user, const char * resourcename, SecPermissionType ptype, const char * basedn) = 0;