Repository: oozie Updated Branches: refs/heads/master c29d9c5fc -> 5f1444496
OOZIE-3126 Add option to allow list of users to access system config (satishsaley) Project: http://git-wip-us.apache.org/repos/asf/oozie/repo Commit: http://git-wip-us.apache.org/repos/asf/oozie/commit/5f144449 Tree: http://git-wip-us.apache.org/repos/asf/oozie/tree/5f144449 Diff: http://git-wip-us.apache.org/repos/asf/oozie/diff/5f144449 Branch: refs/heads/master Commit: 5f1444496b0a105100af5f9a62029b7de0de179f Parents: c29d9c5 Author: satishsaley <[email protected]> Authored: Tue Nov 28 11:00:21 2017 -0800 Committer: satishsaley <[email protected]> Committed: Tue Nov 28 11:00:21 2017 -0800 ---------------------------------------------------------------------- .../oozie/service/AuthorizationService.java | 34 ++++++++++++++- .../oozie/service/ConfigurationService.java | 4 ++ .../apache/oozie/servlet/BaseAdminServlet.java | 21 ++++++++++ .../apache/oozie/servlet/JsonRestServlet.java | 11 +++++ core/src/main/resources/oozie-default.xml | 8 ++++ .../oozie/service/TestAuthorizationService.java | 44 +++++++++++++++++++- release-log.txt | 1 + webapp/src/main/webapp/index.jsp | 5 +++ webapp/src/main/webapp/oozie-console.js | 6 ++- 9 files changed, 129 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/oozie/blob/5f144449/core/src/main/java/org/apache/oozie/service/AuthorizationService.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/oozie/service/AuthorizationService.java b/core/src/main/java/org/apache/oozie/service/AuthorizationService.java index 49bc672..d76e1ea 100644 --- a/core/src/main/java/org/apache/oozie/service/AuthorizationService.java +++ b/core/src/main/java/org/apache/oozie/service/AuthorizationService.java @@ -31,6 +31,7 @@ import java.util.Map; import java.util.ArrayList; import java.util.Set; +import org.apache.commons.lang.StringUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; @@ -79,6 +80,9 @@ public class AuthorizationService implements Service { */ public static final String CONF_ADMIN_GROUPS = CONF_PREFIX + "admin.groups"; + public static final String CONF_SYSTEM_INFO_AUTHORIZED_USERS = CONF_PREFIX + "system.info.authorized.users"; + + /** * File that contains list of admin users for Oozie. */ @@ -89,9 +93,10 @@ public class AuthorizationService implements Service { private Set<String> adminGroups; private Set<String> adminUsers; + private Set<String> sysInfoAuthUsers; private boolean authorizationEnabled; private boolean useDefaultGroupAsAcl; - + private boolean authorizedSystemInfo = false; private final XLog log = XLog.getLog(getClass()); private Instrumentation instrumentation; @@ -113,6 +118,14 @@ public class AuthorizationService implements Service { authorizationEnabled = ConfigUtils.getWithDeprecatedCheck(services.getConf(), CONF_AUTHORIZATION_ENABLED, CONF_SECURITY_ENABLED, false); + String systemInfoAuthUsers = ConfigurationService.get(CONF_SYSTEM_INFO_AUTHORIZED_USERS); + if (!StringUtils.isBlank(systemInfoAuthUsers)) { + authorizedSystemInfo = true; + sysInfoAuthUsers = new HashSet<>(); + for (String user : getTrimmedStrings(systemInfoAuthUsers)) { + sysInfoAuthUsers.add(user); + } + } if (authorizationEnabled) { log.info("Oozie running with authorization enabled"); useDefaultGroupAsAcl = ConfigurationService.getBoolean(CONF_DEFAULT_GROUP_AS_ACL); @@ -292,6 +305,21 @@ public class AuthorizationService implements Service { } /** + * Check if the user is authorized to access system information. + * + * @param user user name. + * @param proxyUser proxy user name. + * @throws AuthorizationException thrown if user does not have admin priviledges. + */ + public void authorizeForSystemInfo(String user, String proxyUser) throws AuthorizationException { + if (authorizationEnabled && authorizedSystemInfo && !(sysInfoAuthUsers.contains(user) || sysInfoAuthUsers + .contains(proxyUser) || isAdmin(user) || isAdmin(proxyUser))) { + incrCounter(INSTR_FAILED_AUTH_COUNTER, 1); + throw new AuthorizationException(ErrorCode.E0503, user); + } + } + + /** * Check if the user has admin privileges. <p> Subclasses should override the {@link #isUserInGroup} method. * * @param user user name. @@ -612,4 +640,8 @@ public class AuthorizationService implements Service { instrumentation.incr(INSTRUMENTATION_GROUP, name, count); } } + + public boolean isAuthorizedSystemInfo() { + return authorizedSystemInfo; + } } http://git-wip-us.apache.org/repos/asf/oozie/blob/5f144449/core/src/main/java/org/apache/oozie/service/ConfigurationService.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/oozie/service/ConfigurationService.java b/core/src/main/java/org/apache/oozie/service/ConfigurationService.java index 4af022f..4707252 100644 --- a/core/src/main/java/org/apache/oozie/service/ConfigurationService.java +++ b/core/src/main/java/org/apache/oozie/service/ConfigurationService.java @@ -529,6 +529,10 @@ public class ConfigurationService implements Service, Instrumentable { return getBoolean(conf, name); } + public static boolean getBoolean(String name, boolean defaultValue) { + return Services.get().getConf().getBoolean(name, defaultValue); + } + public static boolean getBoolean(Configuration conf, String name) { return conf.getBoolean(name, ConfigUtils.BOOLEAN_DEFAULT); } http://git-wip-us.apache.org/repos/asf/oozie/blob/5f144449/core/src/main/java/org/apache/oozie/servlet/BaseAdminServlet.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/oozie/servlet/BaseAdminServlet.java b/core/src/main/java/org/apache/oozie/servlet/BaseAdminServlet.java index 890097b..97c2007 100644 --- a/core/src/main/java/org/apache/oozie/servlet/BaseAdminServlet.java +++ b/core/src/main/java/org/apache/oozie/servlet/BaseAdminServlet.java @@ -127,16 +127,19 @@ public abstract class BaseAdminServlet extends JsonRestServlet { sendJsonResponse(response, HttpServletResponse.SC_OK, json); } else if (resource.equals(RestConstants.ADMIN_OS_ENV_RESOURCE)) { + authorizeForSystemInfo(request); JSONObject json = new JSONObject(); json.putAll(instr.getOSEnv()); sendJsonResponse(response, HttpServletResponse.SC_OK, json); } else if (resource.equals(RestConstants.ADMIN_JAVA_SYS_PROPS_RESOURCE)) { + authorizeForSystemInfo(request); JSONObject json = new JSONObject(); json.putAll(instr.getJavaSystemProperties()); sendJsonResponse(response, HttpServletResponse.SC_OK, json); } else if (resource.equals(RestConstants.ADMIN_CONFIG_RESOURCE)) { + authorizeForSystemInfo(request); JSONObject json = new JSONObject(); json.putAll(instr.getConfiguration()); sendJsonResponse(response, HttpServletResponse.SC_OK, json); @@ -345,6 +348,24 @@ public abstract class BaseAdminServlet extends JsonRestServlet { } } + /** + * Authorize request. + * + * @param request the HttpServletRequest + * @throws XServletException the x servlet exception + */ + private void authorizeForSystemInfo(HttpServletRequest request) throws XServletException { + try { + AuthorizationService auth = Services.get().get(AuthorizationService.class); + if (auth.isAuthorizedSystemInfo()) { + auth.authorizeForSystemInfo(getUser(request), getProxyUser(request)); + } + } + catch (AuthorizationException ex) { + throw new XServletException(HttpServletResponse.SC_UNAUTHORIZED, ex); + } + } + @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { http://git-wip-us.apache.org/repos/asf/oozie/blob/5f144449/core/src/main/java/org/apache/oozie/servlet/JsonRestServlet.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/oozie/servlet/JsonRestServlet.java b/core/src/main/java/org/apache/oozie/servlet/JsonRestServlet.java index 03cf35c..0f22796 100644 --- a/core/src/main/java/org/apache/oozie/servlet/JsonRestServlet.java +++ b/core/src/main/java/org/apache/oozie/servlet/JsonRestServlet.java @@ -584,6 +584,17 @@ public abstract class JsonRestServlet extends HttpServlet { } /** + * Gets proxy user. + * If there is any proxy user, then <code>HttpServletRequest</code> contains proxy user. + * Otherwise it is the normal user. + * @param request + * @return + */ + protected String getProxyUser(HttpServletRequest request) { + return (String) request.getAttribute(USER_NAME); + } + + /** * Set the thread local log info with the given information. * * @param actionid action ID. http://git-wip-us.apache.org/repos/asf/oozie/blob/5f144449/core/src/main/resources/oozie-default.xml ---------------------------------------------------------------------- diff --git a/core/src/main/resources/oozie-default.xml b/core/src/main/resources/oozie-default.xml index 1fd4ee3..7ec64bc 100644 --- a/core/src/main/resources/oozie-default.xml +++ b/core/src/main/resources/oozie-default.xml @@ -329,6 +329,14 @@ </description> </property> + <property> + <name>oozie.service.AuthorizationService.system.info.authorized.users</name> + <value></value> + <description> + Comma separated list of users authorized for web service calls to get system configuration. + </description> + </property> + <!-- InstrumentationService --> <property> http://git-wip-us.apache.org/repos/asf/oozie/blob/5f144449/core/src/test/java/org/apache/oozie/service/TestAuthorizationService.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/oozie/service/TestAuthorizationService.java b/core/src/test/java/org/apache/oozie/service/TestAuthorizationService.java index c32bfc2..ca5b940 100644 --- a/core/src/test/java/org/apache/oozie/service/TestAuthorizationService.java +++ b/core/src/test/java/org/apache/oozie/service/TestAuthorizationService.java @@ -28,6 +28,7 @@ import java.util.Arrays; import java.util.List; import java.util.UUID; +import org.apache.commons.lang.StringUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; @@ -79,6 +80,11 @@ public class TestAuthorizationService extends XDataTestCase { private Services services; private void init(boolean useDefaultGroup, boolean useAdminUsersFile) throws Exception { + init(useDefaultGroup, useAdminUsersFile, StringUtils.EMPTY); + } + + private void init(boolean useDefaultGroup, boolean useAdminUsersFile, String systemInfoAuthUsers) throws + Exception { setSystemProperty(SchemaService.WF_CONF_EXT_SCHEMAS, "wf-ext-schema.xsd"); services = new Services(); @@ -91,9 +97,10 @@ public class TestAuthorizationService extends XDataTestCase { else { conf.set(AuthorizationService.CONF_ADMIN_GROUPS, getTestGroup()); } + conf.set(AuthorizationService.CONF_SYSTEM_INFO_AUTHORIZED_USERS, systemInfoAuthUsers); conf.set(Services.CONF_SERVICE_CLASSES, - conf.get(Services.CONF_SERVICE_CLASSES) + "," + AuthorizationService.class.getName() + - "," + DummyGroupsService.class.getName()); + conf.get(Services.CONF_SERVICE_CLASSES) + "," + AuthorizationService.class.getName() + "," + + DummyGroupsService.class.getName()); conf.set(AuthorizationService.CONF_DEFAULT_GROUP_AS_ACL, Boolean.toString(useDefaultGroup)); services.init(); services.getConf().setBoolean(AuthorizationService.CONF_SECURITY_ENABLED, true); @@ -331,4 +338,37 @@ public class TestAuthorizationService extends XDataTestCase { public void testAdminUsersWithAdminGroup() throws Exception { _testAdminUsers(false, getTestUser(), getTestUser2()); } + + public void testAuthorizedSystemInfoDefaultSuccess() throws Exception { + //AuthorizationService.CONF_SYSTEM_INFO_AUTHORIZED_USERS is empty + init(true, false, StringUtils.EMPTY); + services.get(AuthorizationService.class).authorizeForSystemInfo("regularUser", "proxyUser"); + } + + public void testAuthorizedSystemInfoSuccess() throws Exception { + //Set AuthorizationService.CONF_SYSTEM_INFO_AUTHORIZED_USERS to proxyUser,regularUser + init(true, false, "proxyUser,regularUser"); + + //Use proxyUser in request + services.get(AuthorizationService.class).authorizeForSystemInfo("regularUser1", "proxyUser"); + + //Use regularUser in request + services.get(AuthorizationService.class).authorizeForSystemInfo("regularUser", "proxyUser1"); + + //The proxy user and regular user used in the request are different. Proxy user belongs to one of the + //admin groups in AuthorizationService.CONF_ADMIN_GROUPS + services.get(AuthorizationService.class).authorizeForSystemInfo("regularUser1", getTestUser()); + } + + public void testAuthorizedSystemInfoFailure() throws Exception { + init(true, false, "proxyUser,regularUser"); + try { + services.get(AuthorizationService.class).authorizeForSystemInfo("regularUser1", "proxyUser1"); + fail("Should have thrown exception because regularUser1 or proxyUser1 are not authorized to access system info"); + } + catch (AuthorizationException ex) { + assertEquals("Exception message is different than expected", + "E0503: User [regularUser1] does not have admin " + "privileges", ex.getMessage()); + } + } } http://git-wip-us.apache.org/repos/asf/oozie/blob/5f144449/release-log.txt ---------------------------------------------------------------------- diff --git a/release-log.txt b/release-log.txt index f97b3d5..9a3f7b5 100644 --- a/release-log.txt +++ b/release-log.txt @@ -1,5 +1,6 @@ -- Oozie 5.0.0 release (trunk - unreleased) +OOZIE-3126 Add option to allow list of users to access system config (satishsaley) OOZIE-2900 Retrieve tokens for oozie.launcher.mapreduce.job.hdfs-servers before submission (asasvari) OOZIE-3132 Instrument SLACalculatorMemory (andras.piros) OOZIE-2945 Update SpotBugs to stable version after GA (dbist13 via gezapeti) http://git-wip-us.apache.org/repos/asf/oozie/blob/5f144449/webapp/src/main/webapp/index.jsp ---------------------------------------------------------------------- diff --git a/webapp/src/main/webapp/index.jsp b/webapp/src/main/webapp/index.jsp index 61d32ae..112d336 100644 --- a/webapp/src/main/webapp/index.jsp +++ b/webapp/src/main/webapp/index.jsp @@ -55,11 +55,15 @@ import="org.apache.oozie.sla.service.SLAService" import="org.apache.oozie.service.InstrumentationService" import="org.apache.oozie.service.MetricsInstrumentationService" + import="org.apache.oozie.service.AuthorizationService" + import="org.apache.oozie.service.Services" + %> <% boolean isSLAServiceEnabled = SLAService.isEnabled(); boolean isInstrumentationServiceEnabled = InstrumentationService.isEnabled(); boolean isMetricsInstrumentationServiceEnabled = MetricsInstrumentationService.isEnabled(); + boolean showSystemInfo = !Services.get().get(AuthorizationService.class).isAuthorizedSystemInfo(); %> <div id="oozie-body" style="padding:2"> <div class="x-tab-panel-header x-unselectable x-tab-strip-top" style="width:1048"> @@ -69,6 +73,7 @@ var isSLAServiceEnabled = "<%=isSLAServiceEnabled%>"; var isInstrumentationServiceEnabled = "<%=isInstrumentationServiceEnabled%>"; var isMetricsInstrumentationServiceEnabled = "<%=isMetricsInstrumentationServiceEnabled%>"; + var showSystemInfo = "<%=showSystemInfo%>"; document.title = msg; document.write(msg); </script> http://git-wip-us.apache.org/repos/asf/oozie/blob/5f144449/webapp/src/main/webapp/oozie-console.js ---------------------------------------------------------------------- diff --git a/webapp/src/main/webapp/oozie-console.js b/webapp/src/main/webapp/oozie-console.js index a113b3e..1da42d1 100644 --- a/webapp/src/main/webapp/oozie-console.js +++ b/webapp/src/main/webapp/oozie-console.js @@ -3242,7 +3242,10 @@ function initConsole() { if (isSLAServiceEnabled == "true") { tabs.add(slaDashboard); } - tabs.add(adminGrid); + if(showSystemInfo == "true"){ + tabs.add(adminGrid); + viewConfig.execute(); + } if (isInstrumentationServiceEnabled == "true") { tabs.add(instrumentationArea); } @@ -3279,7 +3282,6 @@ function initConsole() { } }); checkStatus.execute(); - viewConfig.execute(); serverVersion.execute(); if (isInstrumentationServiceEnabled == "true") { viewInstrumentation.execute();
