/** * 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. */ package org.apache.sqoop.handler; import org.apache.log4j.Logger; import org.apache.sqoop.audit.AuditLoggerManager; import org.apache.sqoop.common.SqoopException; import org.apache.sqoop.server.common.ServerError; import org.apache.sqoop.json.*; import org.apache.sqoop.model.MPrincipal; import org.apache.sqoop.model.MPrivilege; import org.apache.sqoop.model.MResource; import org.apache.sqoop.model.MRole; import org.apache.sqoop.security.AuthorizationHandler; import org.apache.sqoop.security.AuthorizationManager; import org.apache.sqoop.security.SecurityError; import org.apache.sqoop.server.RequestContext; import org.apache.sqoop.server.RequestHandler; import org.json.simple.JSONObject; import java.io.IOException; import java.util.List; public class AuthorizationRequestHandler implements RequestHandler { /** * enum for representing the actions supported on the authorization */ enum Action { AUTHORIZATION("authorization"), //parent url path ROLES("roles"), //first level url path PRINCIPALS("principals"), //first level url path PRIVILEGES("privileges"), //first level url path CREATE("create"), //second level url path GRANT("grant"), //second level url path REVOKE("revoke"); //second level url path Action(String name) { this.name = name; } String name; public static Action fromString(String name) { if (name != null) { for (Action action : Action.values()) { if (name.equalsIgnoreCase(action.name)) { return action; } } } return null; } } private static final Logger LOG = Logger.getLogger(AuthorizationRequestHandler.class); public AuthorizationRequestHandler() { LOG.info("AuthorizationRequestHandler initialized"); } @Override public JsonBean handleEvent(RequestContext ctx) { Action action = Action.fromString(ctx.getLastURLElement()); String url = ctx.getRequest().getRequestURI(); switch (ctx.getMethod()) { case GET: switch (action) { case ROLES: //url: /authorization/roles return getRoles(ctx); case PRINCIPALS: //url: /authorization/principals return getPrincipal(ctx); case PRIVILEGES: //url: /authorization/privileges return getPrivilege(ctx); default: throw new SqoopException(ServerError.SERVER_0003, "Invalid action in url" + url); } case POST: switch (action) { case CREATE: //url: /authorization/roles/create return createRole(ctx); default: throw new SqoopException(ServerError.SERVER_0003, "Invalid action in url" + url); } case PUT: String[] urlElements = ctx.getUrlElements(); Action first_level_action = Action.fromString(urlElements[urlElements.length - 2]); switch (first_level_action) { case ROLES: switch (action) { case GRANT: //url: /authorization/roles/grant return grantRevokeRole(ctx, true); case REVOKE: //url: /authorization/roles/revoke return grantRevokeRole(ctx, false); default: throw new SqoopException(ServerError.SERVER_0003, "Invalid action in url" + url); } case PRIVILEGES: switch (action) { case GRANT: //url: /authorization/privileges/grant return grantRevokePrivilege(ctx, true); case REVOKE: //url: /authorization/privileges/revoke return grantRevokePrivilege(ctx, false); default: throw new SqoopException(ServerError.SERVER_0003, "Invalid action in url" + url); } default: throw new SqoopException(ServerError.SERVER_0003, "Invalid action in url" + url); } case DELETE: //url: /authorization/roles/{role_name} return dropRole(ctx); default: throw new SqoopException(ServerError.SERVER_0003, "Invalid action in url" + url); } } private JsonBean getRoles(RequestContext ctx) { AuthorizationHandler handler = AuthorizationManager.getAuthorizationHandler(); AuditLoggerManager manager = AuditLoggerManager.getInstance(); String principal_name = ctx.getParameterValue(PRINCIPAL_NAME_QUERY_PARAM); String principal_type = ctx.getParameterValue(PRINCIPAL_TYPE_QUERY_PARAM); if (principal_name != null && principal_type != null) { // get roles by principal MPrincipal principal = new MPrincipal(principal_name, principal_type); manager.logAuditEvent(ctx.getUserName(), ctx.getRequest().getRemoteAddr(), "get", "roles by principal", principal.toString()); return new RolesBean(handler.getRolesByPrincipal(principal)); } else { // get all roles in the system manager.logAuditEvent(ctx.getUserName(), ctx.getRequest().getRemoteAddr(), "get", "roles", "all"); return new RolesBean(handler.getAllRoles()); } } private JsonBean getPrincipal(RequestContext ctx) { AuthorizationHandler handler = AuthorizationManager.getAuthorizationHandler(); AuditLoggerManager manager = AuditLoggerManager.getInstance(); String role_name = ctx.getParameterValue(ROLE_NAME_QUERY_PARAM); if (role_name != null) { // get principal by role MRole role = new MRole(role_name); manager.logAuditEvent(ctx.getUserName(), ctx.getRequest().getRemoteAddr(), "get", "principals by role", role.toString()); return new PrincipalsBean(handler.getPrincipalsByRole(role)); } else { throw new SqoopException(SecurityError.AUTH_0012, "Can't get role name"); } } private JsonBean getPrivilege(RequestContext ctx) { AuthorizationHandler handler = AuthorizationManager.getAuthorizationHandler(); AuditLoggerManager manager = AuditLoggerManager.getInstance(); String principal_name = ctx.getParameterValue(PRINCIPAL_NAME_QUERY_PARAM); String principal_type = ctx.getParameterValue(PRINCIPAL_TYPE_QUERY_PARAM); String resource_name = ctx.getParameterValue(RESOURCE_NAME_QUERY_PARAM); String resource_type = ctx.getParameterValue(RESOURCE_TYPE_QUERY_PARAM); if (principal_name != null && principal_type != null) { // get privilege by principal MPrincipal principal = new MPrincipal(principal_name, principal_type); MResource resource = null; if (resource_name != null && resource_type != null) { resource = new MResource(resource_name, resource_type); } manager.logAuditEvent(ctx.getUserName(), ctx.getRequest().getRemoteAddr(), "get", "privileges by principal", principal.toString()); return new PrivilegesBean(handler.getPrivilegesByPrincipal(principal, resource)); } else { throw new SqoopException(SecurityError.AUTH_0013, "Can't get principal"); } } private JsonBean createRole(RequestContext ctx) { AuthorizationHandler handler = AuthorizationManager.getAuthorizationHandler(); AuditLoggerManager manager = AuditLoggerManager.getInstance(); RoleBean bean = new RoleBean(); try { JSONObject json = JSONUtils.parse(ctx.getRequest().getReader()); bean.restore(json); } catch (IOException e) { throw new SqoopException(ServerError.SERVER_0003, "Can't read request content", e); } // Get role object List<MRole> roles = bean.getRoles(); if (roles.size() != 1) { throw new SqoopException(ServerError.SERVER_0003, "Expected one role but got " + roles.size()); } MRole postedRole = roles.get(0); manager.logAuditEvent(ctx.getUserName(), ctx.getRequest().getRemoteAddr(), "create", "role", postedRole.toString()); handler.createRole(postedRole); return JsonBean.EMPTY_BEAN; } private JsonBean grantRevokeRole(RequestContext ctx, boolean isGrant) { AuthorizationHandler handler = AuthorizationManager.getAuthorizationHandler(); AuditLoggerManager manager = AuditLoggerManager.getInstance(); RolesBean rolesBean = new RolesBean(); PrincipalsBean principalsBean = new PrincipalsBean(); try { JSONObject json = JSONUtils.parse(ctx.getRequest().getReader()); rolesBean.restore(json); principalsBean.restore(json); } catch (IOException e) { throw new SqoopException(ServerError.SERVER_0003, "Can't read request content", e); } // Get role object List<MRole> roles = rolesBean.getRoles(); // Get principal object List<MPrincipal> principals = principalsBean.getPrincipals(); if (isGrant) { manager.logAuditEvent(ctx.getUserName(), ctx.getRequest().getRemoteAddr(), "grant", "role", "principal"); handler.grantRole(principals, roles); } else { manager.logAuditEvent(ctx.getUserName(), ctx.getRequest().getRemoteAddr(), "revoke", "role", "principal"); handler.revokeRole(principals, roles); } return JsonBean.EMPTY_BEAN; } private JsonBean grantRevokePrivilege(RequestContext ctx, boolean isGrant) { AuthorizationHandler handler = AuthorizationManager.getAuthorizationHandler(); AuditLoggerManager manager = AuditLoggerManager.getInstance(); PrincipalsBean principalsBean = new PrincipalsBean(); PrivilegesBean privilegesBean = new PrivilegesBean(); try { JSONObject json = JSONUtils.parse(ctx.getRequest().getReader()); principalsBean.restore(json); try { privilegesBean.restore(json); } catch (Exception e) {//Privilege is null, revoke all privileges from principal privilegesBean = null; } } catch (IOException e) { throw new SqoopException(ServerError.SERVER_0003, "Can't read request content", e); } // Get principal object List<MPrincipal> principals = principalsBean.getPrincipals(); // Get privilege object List<MPrivilege> privileges = privilegesBean == null ? null : privilegesBean.getPrivileges(); if (isGrant) { manager.logAuditEvent(ctx.getUserName(), ctx.getRequest().getRemoteAddr(), "grant", "role", "privilege"); handler.grantPrivileges(principals, privileges); } else { manager.logAuditEvent(ctx.getUserName(), ctx.getRequest().getRemoteAddr(), "revoke", "role", "privilege"); handler.revokePrivileges(principals, privileges); } return JsonBean.EMPTY_BEAN; } private JsonBean dropRole(RequestContext ctx) { AuthorizationHandler handler = AuthorizationManager.getAuthorizationHandler(); AuditLoggerManager manager = AuditLoggerManager.getInstance(); String[] urlElements = ctx.getUrlElements(); //wrong URL if (urlElements.length < 2 || !urlElements[urlElements.length - 2].equals(Action.ROLES.name)) { throw new SqoopException(SecurityError.AUTH_0012, "Can't get role name"); } String role_name = ctx.getLastURLElement(); MRole role = new MRole(role_name); manager.logAuditEvent(ctx.getUserName(), ctx.getRequest().getRemoteAddr(), "delete", "role", role.toString()); handler.dropRole(role); return JsonBean.EMPTY_BEAN; } }