Repository: sqoop Updated Branches: refs/heads/sqoop2 072b33d48 -> b5bad957e
SQOOP-1979: Sqoop2: Rest API support (Richard Zhou via Abraham Elmahrek) Project: http://git-wip-us.apache.org/repos/asf/sqoop/repo Commit: http://git-wip-us.apache.org/repos/asf/sqoop/commit/b5bad957 Tree: http://git-wip-us.apache.org/repos/asf/sqoop/tree/b5bad957 Diff: http://git-wip-us.apache.org/repos/asf/sqoop/diff/b5bad957 Branch: refs/heads/sqoop2 Commit: b5bad957e15670e758449aaa6038978819038ce8 Parents: 072b33d Author: Abraham Elmahrek <[email protected]> Authored: Thu Feb 12 16:10:26 2015 -0800 Committer: Abraham Elmahrek <[email protected]> Committed: Thu Feb 12 16:10:26 2015 -0800 ---------------------------------------------------------------------- .../org/apache/sqoop/json/PrincipalBean.java | 105 +++++++ .../org/apache/sqoop/json/PrincipalsBean.java | 63 ++++ .../org/apache/sqoop/json/PrivilegeBean.java | 113 +++++++ .../org/apache/sqoop/json/PrivilegesBean.java | 63 ++++ .../java/org/apache/sqoop/json/RoleBean.java | 103 +++++++ .../java/org/apache/sqoop/json/RolesBean.java | 63 ++++ .../apache/sqoop/security/SecurityError.java | 8 +- .../handler/AuthorizationRequestHandler.java | 301 +++++++++++++++++++ .../sqoop/server/AuthorizationServlet.java | 84 ++++++ .../org/apache/sqoop/server/RequestHandler.java | 5 + server/src/main/webapp/WEB-INF/web.xml | 11 + 11 files changed, 918 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/sqoop/blob/b5bad957/common/src/main/java/org/apache/sqoop/json/PrincipalBean.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/json/PrincipalBean.java b/common/src/main/java/org/apache/sqoop/json/PrincipalBean.java new file mode 100644 index 0000000..1016b4d --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/json/PrincipalBean.java @@ -0,0 +1,105 @@ +/** + * 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.json; + +import org.apache.sqoop.classification.InterfaceAudience; +import org.apache.sqoop.classification.InterfaceStability; +import org.apache.sqoop.model.MPrincipal; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +/** + * + */ [email protected] [email protected] +public class PrincipalBean implements JsonBean { + + public static final String PRINCIPAL = "principal"; + private static final String NAME = "name"; + private static final String TYPE = "type"; + + private List<MPrincipal> principals; + + public List<MPrincipal> getPrincipals() { + return principals; + } + + // For "extract" + public PrincipalBean(MPrincipal principal) { + this(); + this.principals = new ArrayList<MPrincipal>(); + this.principals.add(principal); + } + + public PrincipalBean(List<MPrincipal> principals) { + this(); + this.principals = principals; + } + + // For "restore" + public PrincipalBean() { + } + + @Override + @SuppressWarnings("unchecked") + public JSONObject extract(boolean skipSensitive) { + JSONObject principal = new JSONObject(); + principal.put(PRINCIPAL, extractPrincipal(principals.get(0))); + return principal; + } + + @SuppressWarnings("unchecked") + protected JSONArray extractPrincipals() { + JSONArray principalsArray = new JSONArray(); + for (MPrincipal principal : principals) { + principalsArray.add(extractPrincipal(principal)); + } + return principalsArray; + } + + @SuppressWarnings("unchecked") + private JSONObject extractPrincipal(MPrincipal principal) { + JSONObject object = new JSONObject(); + object.put(NAME, principal.getName()); + object.put(TYPE, principal.getType()); + return object; + } + + @Override + public void restore(JSONObject json) { + principals = new ArrayList<MPrincipal>(); + JSONObject obj = (JSONObject) json.get(PRINCIPAL); + principals.add(restorePrincipal(obj)); + } + + protected void restorePrincipals(JSONArray array) { + principals = new ArrayList<MPrincipal>(); + for (Object obj : array) { + principals.add(restorePrincipal(obj)); + } + } + + private MPrincipal restorePrincipal(Object obj) { + JSONObject object = (JSONObject) obj; + return new MPrincipal((String) object.get(NAME), (String) object.get(TYPE)); + } +} http://git-wip-us.apache.org/repos/asf/sqoop/blob/b5bad957/common/src/main/java/org/apache/sqoop/json/PrincipalsBean.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/json/PrincipalsBean.java b/common/src/main/java/org/apache/sqoop/json/PrincipalsBean.java new file mode 100644 index 0000000..a4d56dc --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/json/PrincipalsBean.java @@ -0,0 +1,63 @@ +/** + * 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.json; + +import org.apache.sqoop.classification.InterfaceAudience; +import org.apache.sqoop.classification.InterfaceStability; +import org.apache.sqoop.model.MPrincipal; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.util.List; + [email protected] [email protected] +public class PrincipalsBean extends PrincipalBean { + + private static final String PRINCIPALS = "principals"; + + // For "extract" + public PrincipalsBean(MPrincipal principal) { + super(principal); + } + + public PrincipalsBean(List<MPrincipal> principals) { + super(principals); + + } + + // For "restore" + public PrincipalsBean() { + } + + @Override + @SuppressWarnings("unchecked") + public JSONObject extract(boolean skipSensitive) { + JSONArray principalsArray = super.extractPrincipals(); + JSONObject principals = new JSONObject(); + principals.put(PRINCIPALS, principalsArray); + return principals; + } + + @Override + public void restore(JSONObject json) { + JSONArray principalsArray = (JSONArray) json.get(PRINCIPALS); + restorePrincipals(principalsArray); + } + +} http://git-wip-us.apache.org/repos/asf/sqoop/blob/b5bad957/common/src/main/java/org/apache/sqoop/json/PrivilegeBean.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/json/PrivilegeBean.java b/common/src/main/java/org/apache/sqoop/json/PrivilegeBean.java new file mode 100644 index 0000000..02ef4b2 --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/json/PrivilegeBean.java @@ -0,0 +1,113 @@ +/** + * 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.json; + +import org.apache.sqoop.classification.InterfaceAudience; +import org.apache.sqoop.classification.InterfaceStability; +import org.apache.sqoop.model.MPrivilege; +import org.apache.sqoop.model.MResource; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +/** + * + */ [email protected] [email protected] +public class PrivilegeBean implements JsonBean { + + public static final String PRIVILEGE = "privilege"; + private static final String RESOURCE_NAME = "resource-name"; + private static final String RESOURCE_TYPE = "resource-type"; + private static final String ACTION = "action"; + private static final String WITH_GRANT_OPTION = "with-grant-option"; + + private List<MPrivilege> privileges; + + public List<MPrivilege> getPrivileges() { + return privileges; + } + + // For "extract" + public PrivilegeBean(MPrivilege privilege) { + this(); + this.privileges = new ArrayList<MPrivilege>(); + this.privileges.add(privilege); + } + + public PrivilegeBean(List<MPrivilege> privileges) { + this(); + this.privileges = privileges; + } + + // For "restore" + public PrivilegeBean() { + } + + @Override + @SuppressWarnings("unchecked") + public JSONObject extract(boolean skipSensitive) { + JSONObject privilege = new JSONObject(); + privilege.put(PRIVILEGE, extractPrivilege(privileges.get(0))); + return privilege; + } + + @SuppressWarnings("unchecked") + protected JSONArray extractPrivileges() { + JSONArray privilegesArray = new JSONArray(); + for (MPrivilege privilege : privileges) { + privilegesArray.add(extractPrivilege(privilege)); + } + return privilegesArray; + } + + @SuppressWarnings("unchecked") + private JSONObject extractPrivilege(MPrivilege privilege) { + JSONObject object = new JSONObject(); + object.put(RESOURCE_NAME, privilege.getResource().getName()); + object.put(RESOURCE_TYPE, privilege.getResource().getType()); + object.put(ACTION, privilege.getAction()); + object.put(WITH_GRANT_OPTION, privilege.isWith_grant_option()); + return object; + } + + @Override + public void restore(JSONObject json) { + privileges = new ArrayList<MPrivilege>(); + JSONObject obj = (JSONObject) json.get(PRIVILEGE); + privileges.add(restorePrivilege(obj)); + } + + protected void restorePrivileges(JSONArray array) { + privileges = new ArrayList<MPrivilege>(); + for (Object obj : array) { + privileges.add(restorePrivilege(obj)); + } + } + + private MPrivilege restorePrivilege(Object obj) { + JSONObject object = (JSONObject) obj; + MResource resource = new MResource( + (String) object.get(RESOURCE_NAME), (String) object.get(RESOURCE_TYPE)); + return new MPrivilege(resource, (String) object.get(ACTION), + Boolean.valueOf(object.get(WITH_GRANT_OPTION).toString())); + } +} http://git-wip-us.apache.org/repos/asf/sqoop/blob/b5bad957/common/src/main/java/org/apache/sqoop/json/PrivilegesBean.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/json/PrivilegesBean.java b/common/src/main/java/org/apache/sqoop/json/PrivilegesBean.java new file mode 100644 index 0000000..fbca54b --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/json/PrivilegesBean.java @@ -0,0 +1,63 @@ +/** + * 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.json; + +import org.apache.sqoop.classification.InterfaceAudience; +import org.apache.sqoop.classification.InterfaceStability; +import org.apache.sqoop.model.MPrivilege; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.util.List; + [email protected] [email protected] +public class PrivilegesBean extends PrivilegeBean { + + private static final String PRIVILEGES = "privileges"; + + // For "extract" + public PrivilegesBean(MPrivilege privilege) { + super(privilege); + } + + public PrivilegesBean(List<MPrivilege> privileges) { + super(privileges); + + } + + // For "restore" + public PrivilegesBean() { + } + + @Override + @SuppressWarnings("unchecked") + public JSONObject extract(boolean skipSensitive) { + JSONArray rolesArray = super.extractPrivileges(); + JSONObject roles = new JSONObject(); + roles.put(PRIVILEGES, rolesArray); + return roles; + } + + @Override + public void restore(JSONObject json) { + JSONArray rolesArray = (JSONArray) json.get(PRIVILEGES); + restorePrivileges(rolesArray); + } + +} http://git-wip-us.apache.org/repos/asf/sqoop/blob/b5bad957/common/src/main/java/org/apache/sqoop/json/RoleBean.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/json/RoleBean.java b/common/src/main/java/org/apache/sqoop/json/RoleBean.java new file mode 100644 index 0000000..e552868 --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/json/RoleBean.java @@ -0,0 +1,103 @@ +/** + * 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.json; + +import org.apache.sqoop.classification.InterfaceAudience; +import org.apache.sqoop.classification.InterfaceStability; +import org.apache.sqoop.model.MRole; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +/** + * + */ [email protected] [email protected] +public class RoleBean implements JsonBean { + + public static final String ROLE = "role"; + private static final String NAME = "name"; + + private List<MRole> roles; + + public List<MRole> getRoles() { + return roles; + } + + // For "extract" + public RoleBean(MRole role) { + this(); + this.roles = new ArrayList<MRole>(); + this.roles.add(role); + } + + public RoleBean(List<MRole> roles) { + this(); + this.roles = roles; + } + + // For "restore" + public RoleBean() { + } + + @Override + @SuppressWarnings("unchecked") + public JSONObject extract(boolean skipSensitive) { + JSONObject role = new JSONObject(); + role.put(ROLE, extractRole(roles.get(0))); + return role; + } + + @SuppressWarnings("unchecked") + protected JSONArray extractRoles() { + JSONArray rolesArray = new JSONArray(); + for (MRole role : roles) { + rolesArray.add(extractRole(role)); + } + return rolesArray; + } + + @SuppressWarnings("unchecked") + private JSONObject extractRole(MRole role) { + JSONObject object = new JSONObject(); + object.put(NAME, role.getName()); + return object; + } + + @Override + public void restore(JSONObject json) { + roles = new ArrayList<MRole>(); + JSONObject obj = (JSONObject) json.get(ROLE); + roles.add(restoreRole(obj)); + } + + protected void restoreRoles(JSONArray array) { + roles = new ArrayList<MRole>(); + for (Object obj : array) { + roles.add(restoreRole(obj)); + } + } + + private MRole restoreRole(Object obj) { + JSONObject object = (JSONObject) obj; + return new MRole((String) object.get(NAME)); + } +} http://git-wip-us.apache.org/repos/asf/sqoop/blob/b5bad957/common/src/main/java/org/apache/sqoop/json/RolesBean.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/sqoop/json/RolesBean.java b/common/src/main/java/org/apache/sqoop/json/RolesBean.java new file mode 100644 index 0000000..da8fc1f --- /dev/null +++ b/common/src/main/java/org/apache/sqoop/json/RolesBean.java @@ -0,0 +1,63 @@ +/** + * 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.json; + +import org.apache.sqoop.classification.InterfaceAudience; +import org.apache.sqoop.classification.InterfaceStability; +import org.apache.sqoop.model.MRole; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import java.util.List; + [email protected] [email protected] +public class RolesBean extends RoleBean { + + private static final String ROLES = "roles"; + + // For "extract" + public RolesBean(MRole role) { + super(role); + } + + public RolesBean(List<MRole> roles) { + super(roles); + + } + + // For "restore" + public RolesBean() { + } + + @Override + @SuppressWarnings("unchecked") + public JSONObject extract(boolean skipSensitive) { + JSONArray rolesArray = super.extractRoles(); + JSONObject roles = new JSONObject(); + roles.put(ROLES, rolesArray); + return roles; + } + + @Override + public void restore(JSONObject json) { + JSONArray rolesArray = (JSONArray) json.get(ROLES); + restoreRoles(rolesArray); + } + +} http://git-wip-us.apache.org/repos/asf/sqoop/blob/b5bad957/core/src/main/java/org/apache/sqoop/security/SecurityError.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/sqoop/security/SecurityError.java b/core/src/main/java/org/apache/sqoop/security/SecurityError.java index 322a98f..ad030f8 100644 --- a/core/src/main/java/org/apache/sqoop/security/SecurityError.java +++ b/core/src/main/java/org/apache/sqoop/security/SecurityError.java @@ -55,7 +55,13 @@ public enum SecurityError implements ErrorCode { AUTH_0010("Unable to find authentication provider"), /** The system was not able to get authentication from http request. */ - AUTH_0011("Unable to get remote authentication from http request"); + AUTH_0011("Unable to get remote authentication from http request"), + + /** The system was not able to get role name from http request. */ + AUTH_0012("Unable to get role name from http request"), + + /** The system was not able to get principal from http request. */ + AUTH_0013("Unable to get principal from http request"); private final String message; http://git-wip-us.apache.org/repos/asf/sqoop/blob/b5bad957/server/src/main/java/org/apache/sqoop/handler/AuthorizationRequestHandler.java ---------------------------------------------------------------------- diff --git a/server/src/main/java/org/apache/sqoop/handler/AuthorizationRequestHandler.java b/server/src/main/java/org/apache/sqoop/handler/AuthorizationRequestHandler.java new file mode 100644 index 0000000..361d14b --- /dev/null +++ b/server/src/main/java/org/apache/sqoop/handler/AuthorizationRequestHandler.java @@ -0,0 +1,301 @@ +/** + * 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.error.code.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 PUT: + String[] urlElements = ctx.getUrlElements(); + Action first_level_action = Action.fromString(urlElements[urlElements.length - 2]); + switch (first_level_action) { + case ROLES: + switch (action) { + case CREATE: //url: /authorization/roles/create + return createRole(ctx); + 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; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/sqoop/blob/b5bad957/server/src/main/java/org/apache/sqoop/server/AuthorizationServlet.java ---------------------------------------------------------------------- diff --git a/server/src/main/java/org/apache/sqoop/server/AuthorizationServlet.java b/server/src/main/java/org/apache/sqoop/server/AuthorizationServlet.java new file mode 100644 index 0000000..65c434d --- /dev/null +++ b/server/src/main/java/org/apache/sqoop/server/AuthorizationServlet.java @@ -0,0 +1,84 @@ +/** + * 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.server; + +import org.apache.sqoop.handler.AuthorizationRequestHandler; +import org.apache.sqoop.json.JsonBean; + +/** + * Provides operations for authorization + * + * PUT /authorization/roles/create + * Create new role with {name} + * + * DELETE /authorization/role/{role-name} + * + * GET /authorization/roles + * Show all roles + * + * GET /authorization/principals?role_name={name} + * Show all principals in role with {name} + * + * GET /authorization/roles?principal_type={type}&principal_name={name} + * Show all roles in principal with {name, type} + * + * PUT /authorization/roles/grant + * Grant a role to a user/group/role + * PUT data of JsonObject role(name) and principal (name, type) + * + * PUT /authorization/roles/revoke + * Revoke a role to a user/group/role + * PUT data of JsonObject role(name) and principal (name, type) + * + * PUT /authorization/privileges/grant + * Grant a privilege to a principal + * PUT data of JsonObject principal(name, type) and privilege (resource-name, resource-type, action, with-grant-option) + * + * PUT /authorization/privileges/revoke + * Revoke a privilege to a principal + * PUT data of JsonObject principal(name, type) and privilege (resource-name, resource-type, action, with-grant-option) + * If privilege is null, then revoke all privileges for principal(name, type) + * + * GET /authorization/privileges?principal_type={type}&principal_name={name}&resource_type={type}&resource_name={name} + * Show all privileges in principal with {name, type} and resource with {resource-name, resource-type} + * If resource is null, then show all privileges in principal with {name, type} + */ +@SuppressWarnings("serial") +public class AuthorizationServlet extends SqoopProtocolServlet { + + private RequestHandler authorizationRequestHandler; + + public AuthorizationServlet() { + authorizationRequestHandler = new AuthorizationRequestHandler(); + } + + @Override + protected JsonBean handleGetRequest(RequestContext ctx) throws Exception { + return authorizationRequestHandler.handleEvent(ctx); + } + + @Override + protected JsonBean handlePutRequest(RequestContext ctx) throws Exception { + return authorizationRequestHandler.handleEvent(ctx); + } + + @Override + protected JsonBean handleDeleteRequest(RequestContext ctx) throws Exception { + return authorizationRequestHandler.handleEvent(ctx); + } +} http://git-wip-us.apache.org/repos/asf/sqoop/blob/b5bad957/server/src/main/java/org/apache/sqoop/server/RequestHandler.java ---------------------------------------------------------------------- diff --git a/server/src/main/java/org/apache/sqoop/server/RequestHandler.java b/server/src/main/java/org/apache/sqoop/server/RequestHandler.java index bd62f31..02eb837 100644 --- a/server/src/main/java/org/apache/sqoop/server/RequestHandler.java +++ b/server/src/main/java/org/apache/sqoop/server/RequestHandler.java @@ -24,6 +24,11 @@ public interface RequestHandler { static final String CONNECTOR_NAME_QUERY_PARAM = "cname"; static final String JOB_NAME_QUERY_PARAM = "jname"; + static final String ROLE_NAME_QUERY_PARAM = "role_name"; + static final String PRINCIPAL_NAME_QUERY_PARAM = "principal_name"; + static final String PRINCIPAL_TYPE_QUERY_PARAM = "principal_type"; + static final String RESOURCE_NAME_QUERY_PARAM = "resource_name"; + static final String RESOURCE_TYPE_QUERY_PARAM = "resource_type"; JsonBean handleEvent(RequestContext ctx); } http://git-wip-us.apache.org/repos/asf/sqoop/blob/b5bad957/server/src/main/webapp/WEB-INF/web.xml ---------------------------------------------------------------------- diff --git a/server/src/main/webapp/WEB-INF/web.xml b/server/src/main/webapp/WEB-INF/web.xml index 85ae26b..60ee8c4 100644 --- a/server/src/main/webapp/WEB-INF/web.xml +++ b/server/src/main/webapp/WEB-INF/web.xml @@ -158,6 +158,17 @@ limitations under the License. <url-pattern>/v1/submissions/*</url-pattern> </servlet-mapping> + <!-- Authorization servlet --> + <servlet> + <servlet-name>authorization.AuthorizationServlet</servlet-name> + <servlet-class>org.apache.sqoop.server.AuthorizationServlet</servlet-class> + <load-on-startup>1</load-on-startup> + </servlet> + + <servlet-mapping> + <servlet-name>authorization.AuthorizationServlet</servlet-name> + <url-pattern>/v1/authorization/*</url-pattern> + </servlet-mapping> </web-app>
