You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by de...@apache.org on 2018/08/17 16:29:18 UTC

svn commit: r1838269 - in /uima/uima-ducc/trunk: src/main/admin/db_access_check.py uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/utils/HandlersHelper.java

Author: degenaro
Date: Fri Aug 17 16:29:18 2018
New Revision: 1838269

URL: http://svn.apache.org/viewvc?rev=1838269&view=rev
Log:
UIMA-5800 DUCC Web Server (WS) does not honor db.access permissions when changed?

Added:
    uima/uima-ducc/trunk/src/main/admin/db_access_check.py   (with props)
Modified:
    uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/utils/HandlersHelper.java

Added: uima/uima-ducc/trunk/src/main/admin/db_access_check.py
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/src/main/admin/db_access_check.py?rev=1838269&view=auto
==============================================================================
--- uima/uima-ducc/trunk/src/main/admin/db_access_check.py (added)
+++ uima/uima-ducc/trunk/src/main/admin/db_access_check.py Fri Aug 17 16:29:18 2018
@@ -0,0 +1,187 @@
+#!/usr/bin/env python
+# -----------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#	 http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, 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.
+# -----------------------------------------------------------------------
+
+import sys
+
+version_min = [2, 7]
+version_info = sys.version_info
+version_error = False
+if(version_info[0] < version_min[0]):
+	version_error = True
+elif(version_info[0] == version_min[0]):
+	if(version_info[1] < version_min[1]):
+		version_error = True
+if(version_error):
+	print('Python minimum requirement is version '+str(version_min[0])+'.'+str(version_min[1]))
+	sys.exit(1)
+
+import argparse
+import datetime
+import os
+import time
+import traceback
+
+from ducc_util import DuccUtil
+
+# print message
+def output(msg):
+    print msg
+    
+# produce a time stamp
+def get_timestamp():
+    tod = time.time()
+    timestamp = datetime.datetime.fromtimestamp(tod).strftime('%Y-%m-%d %H:%M:%S')      
+    return timestamp
+
+_flag_debug = False
+
+# record debug message
+def debug(mn,text):
+    if(_flag_debug):
+        type ='D'
+        msg = get_timestamp()+' '+type+' '+mn+' '+text
+        output(msg)
+
+# command to check db access authorization
+
+class AccessCheck(DuccUtil):
+	
+	# return method name
+	def _mn(self):
+		return traceback.extract_stack(None,2)[0][2]
+	
+	description = 'Determine if LOOKER can view OWNER database data through examination of db.access file in security directory, typically ~/.ducc.'\
+				+ '  Return 1 if authorized, 0 otherwise.'\
+				+ '  Rules: '\
+				+ '  1. Authorized if OWNER == LOOKER'\
+				+ '  or '\
+				+ '  2. Authorized if OWNER db.access file is readable by all'\
+				+ '  or '\
+				+ '  3. Authorized if LOOKER groups contains the OWNER db.access file group'\
+				+ ''
+	
+	def get_args(self):
+		global _flag_debug
+		parser = argparse.ArgumentParser(description=self.description)
+		parser.add_argument('--owner', '-o', action='store', required=True, help='the user who owns the data')
+		parser.add_argument('--looker', '-l', action='store', required=True, help='the user who views the data')
+		parser.add_argument('--debug', '-d', action='store_true', help='display debugging messages')
+		self.args = parser.parse_args()
+		_flag_debug = self.args.debug
+	
+	# get property from ducc.properties file
+	def get_ducc_property(self, key):
+		value = self.ducc_properties.get(key)
+		text = 'key:'+key+' '+'value:'+value
+		debug(self._mn(),text)
+	
+	# get DUCC security home directory, by default user's $HOME
+	def get_security_home(self):
+		key = 'ducc.security.home'
+		value = self.get_ducc_property(key)
+		if(value == None):
+			home_folder = os.getenv('HOME')
+			value = home_folder.rsplit('/',1)[0]
+		self.ducc_security_home = value
+		text = value
+		debug(self._mn(),text)
+	
+	# get db.access file info, comprising file permissions and file group
+	def get_owner_access_data(self):
+		permissions = '----------'
+		group = ''
+		ducc_ling = self.duccling
+		self.get_security_home()
+		security_file = os.path.join(self.ducc_security_home,self.args.owner,'.ducc','db.access')
+		text = 'security_file:'+security_file
+		debug(self._mn(),text)
+		p0 = '-q'
+		p1 = '-u'
+		p2 = self.args.owner
+		p3 = '/usr/bin/stat'
+		p4 = security_file
+		cmd = ducc_ling+' '+p0+' '+p1+' '+p2+' '+p3+' '+p4
+		text = cmd
+		debug(self._mn(),text)
+		lines = self.popen(ducc_ling,p0,p1,p2,p3,p4)
+		for line in lines:
+			line = line.strip()
+			if('Gid' in line):
+				tokens = line.split()
+				permissions = tokens[1].strip('(').strip(')').split('/')[1]
+				group = tokens[8].strip('(').strip(')').split('/')[1]
+				text = 'permissions:'+permissions+' '+'group:'+group
+		return permissions, group
+	
+	# get looker's groups
+	def get_looker_groups(self):
+		groups = []
+		ducc_ling = self.duccling
+		p0 = '-q'
+		p1 = '-u'
+		p2 = self.args.owner
+		p3 = '/usr/bin/groups'
+		cmd = ducc_ling+' '+p0+' '+p1+' '+p2+' '+p3
+		text = cmd
+		debug(self._mn(),text)
+		lines = self.popen(ducc_ling,p0,p1,p2,p3)
+		for line in lines:
+			line = line.strip()
+			tokens = line.split()
+			groups = tokens
+		return groups
+	
+	# check if looker is authorized to access owner's db info
+	def check_authorization(self):
+		authorized = 0
+		text = 'owner:'+self.args.owner+' '+'looker:'+self.args.looker
+		debug(self._mn(),text)
+		if(self.args.owner == self.args.looker):
+			authorized = 1
+			text = 'authorized:'+str(authorized)+' '+'reason: owner == looker'
+			debug(self._mn(),text)
+		else:
+			file_permissions, file_group = self.get_owner_access_data()
+			text = 'permissions:'+file_permissions+' '+'group:'+file_group
+			debug(self._mn(),text)
+			if(file_permissions[7] == 'r'):
+				authorized = 1
+				text = 'authorized:'+str(authorized)+' '+'reason: owner db.access file readable by all'
+				debug(self._mn(),text)
+			elif(file_permissions[4] == 'r'):
+				looker_groups = self.get_looker_groups()
+				text = 'groups:'+str(looker_groups)
+				debug(self._mn(),text)
+				if(file_group in looker_groups):
+					authorized = 1
+					text = 'authorized:'+str(authorized)+' '+'reason: looker in group assigned to db.access file'
+					debug(self._mn(),text)
+		return authorized
+		
+	def main(self, argv):
+		authorized = 0
+		self.get_args()
+		authorized = self.check_authorization()
+		print str(authorized)
+		sys.exit(authorized)
+		
+if __name__ == '__main__':
+	instance = AccessCheck()
+	instance.main(sys.argv[1:])

Propchange: uima/uima-ducc/trunk/src/main/admin/db_access_check.py
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: uima/uima-ducc/trunk/src/main/admin/db_access_check.py
------------------------------------------------------------------------------
    svn:executable = *

Modified: uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/utils/HandlersHelper.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/utils/HandlersHelper.java?rev=1838269&r1=1838268&r2=1838269&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/utils/HandlersHelper.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/utils/HandlersHelper.java Fri Aug 17 16:29:18 2018
@@ -18,7 +18,11 @@
 */
 package org.apache.uima.ducc.ws.utils;
 
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Properties;
 
 import javax.servlet.http.HttpServletRequest;
@@ -237,6 +241,8 @@ public class HandlersHelper {
 		return retVal;
 	}
 	
+	private static File devNull = new File("/dev/null");
+	
 	/**
 	 * Look in service owner's security home for db.access file
 	 * and use it's permissions to determine of logged-in user
@@ -245,26 +251,46 @@ public class HandlersHelper {
 	 */
 	private static boolean isServiceFileAccessForRead(String reqUser, Properties meta) {
 		String location = "isServiceFileAccessForRead";
-		boolean retVal = false;
-		if(reqUser == null) {
-			reqUser = System.getProperty("user.name");
-		}
-		if(reqUser != null) {
-			if(meta != null) {
-				String svcOwner = meta.getProperty(IServicesRegistry.user);
-				if(svcOwner != null) {
-					String home = getSecurityHome(svcOwner.trim());
-					if(home != null) {
-						if(!home.endsWith(File.separator)) {
-							home = home+File.separator;
-						}
-						String path = home+".ducc"+File.separator+"db.access";
-						retVal = isFileReadable(reqUser, path);
-						if(retVal) {
-							duccLogger.debug(location, getDuccId(meta), "user="+reqUser+" "+retVal);
-						}
+		boolean retVal= false;
+		String DUCC_HOME = System.getProperty("DUCC_HOME");
+		String duccmon_pwgen = DUCC_HOME+"/admin/db_access_check.py";
+		String owner = meta.getProperty(IServicesRegistry.user);
+		String looker = reqUser;
+		if(looker == null) {
+			duccLogger.debug(location, null, "looker not specified");
+		}
+		else {
+			List<String> cmd = new ArrayList<String>();
+			cmd.add(duccmon_pwgen);
+			cmd.add("--owner");
+			cmd.add(owner);
+			cmd.add("--looker");
+			cmd.add(looker);
+			String cmdline = String.join(" ", cmd);
+			duccLogger.debug(location, null, "cmdline: "+cmdline);
+			ProcessBuilder pb = new ProcessBuilder(cmd);
+			String authorizedCode = "1";
+			try {
+				pb = pb.redirectError(devNull);
+				Process process = pb.start();
+				String line;
+				BufferedReader bri = new BufferedReader(new InputStreamReader(process.getInputStream()));
+				duccLogger.trace(location, null, "read stdout: start");
+				while ((line = bri.readLine()) != null) {
+					duccLogger.debug(location, null, "stdout: "+line);
+					if(line.startsWith(authorizedCode)) {
+						duccLogger.trace(location, null, "authorized!");
+						retVal = true;
 					}
 				}
+				bri.close();
+				duccLogger.trace(location, null, "read stdout: end");
+				duccLogger.trace(location, null, "process waitfor: start");
+				process.waitFor();
+				duccLogger.trace(location, null, "process waitfor: end");
+			}
+			catch(Exception e) {
+				duccLogger.error(location, null, e);
 			}
 		}
 		return retVal;