SQOOP-2823: Sqoop2: RESTiliency: Remove repetitive try-catch block for accessing...
[sqoop.git] / server / src / main / java / org / apache / sqoop / handler / AuthorizationRequestHandler.java
1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 package org.apache.sqoop.handler;
19
20 import org.apache.log4j.Logger;
21 import org.apache.sqoop.audit.AuditLoggerManager;
22 import org.apache.sqoop.common.SqoopException;
23 import org.apache.sqoop.core.SqoopConfiguration;
24 import org.apache.sqoop.error.code.CommonRepositoryError;
25 import org.apache.sqoop.repository.Repository;
26 import org.apache.sqoop.repository.RepositoryManager;
27 import org.apache.sqoop.server.common.ServerError;
28 import org.apache.sqoop.json.*;
29 import org.apache.sqoop.model.MPrincipal;
30 import org.apache.sqoop.model.MPrivilege;
31 import org.apache.sqoop.model.MResource;
32 import org.apache.sqoop.model.MRole;
33 import org.apache.sqoop.security.AuthorizationHandler;
34 import org.apache.sqoop.security.AuthorizationManager;
35 import org.apache.sqoop.security.SecurityConstants;
36 import org.apache.sqoop.security.SecurityError;
37 import org.apache.sqoop.server.RequestContext;
38 import org.apache.sqoop.server.RequestHandler;
39 import org.json.simple.JSONObject;
40
41 import java.io.IOException;
42 import java.util.List;
43
44 public class AuthorizationRequestHandler implements RequestHandler {
45 private static final long serialVersionUID = 1L;
46 /**
47 * enum for representing the actions supported on the authorization
48 */
49 enum Action {
50 AUTHORIZATION("authorization"), //parent url path
51 ROLES("roles"), //first level url path
52 PRINCIPALS("principals"), //first level url path
53 PRIVILEGES("privileges"), //first level url path
54 CREATE("create"), //second level url path
55 GRANT("grant"), //second level url path
56 REVOKE("revoke"); //second level url path
57
58 Action(String name) {
59 this.name = name;
60 }
61
62 String name;
63
64 public static Action fromString(String name) {
65 if (name != null) {
66 for (Action action : Action.values()) {
67 if (name.equalsIgnoreCase(action.name)) {
68 return action;
69 }
70 }
71 }
72 return null;
73 }
74 }
75
76 private static final Logger LOG = Logger.getLogger(AuthorizationRequestHandler.class);
77
78 public AuthorizationRequestHandler() {
79 LOG.info("AuthorizationRequestHandler initialized");
80 }
81
82 @Override
83 public JsonBean handleEvent(RequestContext ctx) {
84 Action action = Action.fromString(ctx.getLastURLElement());
85 String url = ctx.getRequest().getRequestURI();
86 switch (ctx.getMethod()) {
87 case GET:
88 switch (action) {
89 case ROLES: //url: /authorization/roles
90 return getRoles(ctx);
91 case PRINCIPALS: //url: /authorization/principals
92 return getPrincipal(ctx);
93 case PRIVILEGES: //url: /authorization/privileges
94 return getPrivilege(ctx);
95 default:
96 throw new SqoopException(ServerError.SERVER_0003, "Invalid action in url" + url);
97 }
98 case POST:
99 switch (action) {
100 case CREATE: //url: /authorization/roles/create
101 return createRole(ctx);
102 default:
103 throw new SqoopException(ServerError.SERVER_0003, "Invalid action in url" + url);
104 }
105 case PUT:
106 String[] urlElements = ctx.getUrlElements();
107 Action first_level_action = Action.fromString(urlElements[urlElements.length - 2]);
108 switch (first_level_action) {
109 case ROLES:
110 switch (action) {
111 case GRANT: //url: /authorization/roles/grant
112 return grantRevokeRole(ctx, true);
113 case REVOKE: //url: /authorization/roles/revoke
114 return grantRevokeRole(ctx, false);
115 default:
116 throw new SqoopException(ServerError.SERVER_0003, "Invalid action in url" + url);
117 }
118 case PRIVILEGES:
119 switch (action) {
120 case GRANT: //url: /authorization/privileges/grant
121 return grantRevokePrivilege(ctx, true);
122 case REVOKE: //url: /authorization/privileges/revoke
123 return grantRevokePrivilege(ctx, false);
124 default:
125 throw new SqoopException(ServerError.SERVER_0003, "Invalid action in url" + url);
126 }
127 default:
128 throw new SqoopException(ServerError.SERVER_0003, "Invalid action in url" + url);
129 }
130 case DELETE: //url: /authorization/roles/{role_name}
131 return dropRole(ctx);
132 default:
133 throw new SqoopException(ServerError.SERVER_0003, "Invalid action in url" + url);
134 }
135 }
136
137 private JsonBean getRoles(RequestContext ctx) {
138 AuthorizationHandler handler = AuthorizationManager.getInstance().getAuthorizationHandler();
139 AuditLoggerManager manager = AuditLoggerManager.getInstance();
140 String principal_name = ctx.getParameterValue(PRINCIPAL_NAME_QUERY_PARAM);
141 String principal_type = ctx.getParameterValue(PRINCIPAL_TYPE_QUERY_PARAM);
142
143 if (principal_name != null && principal_type != null) {
144 // get roles by principal
145 MPrincipal principal = new MPrincipal(principal_name, principal_type);
146 manager.logAuditEvent(ctx.getUserName(),
147 ctx.getRequest().getRemoteAddr(), "get", "roles by principal", principal.toString());
148 return new RoleBean(handler.getRolesByPrincipal(principal));
149 } else {
150 // get all roles in the system
151 manager.logAuditEvent(ctx.getUserName(),
152 ctx.getRequest().getRemoteAddr(), "get", "roles", "all");
153 return new RoleBean(handler.getAllRoles());
154 }
155 }
156
157 private JsonBean getPrincipal(RequestContext ctx) {
158 AuthorizationHandler handler = AuthorizationManager.getInstance().getAuthorizationHandler();
159 AuditLoggerManager manager = AuditLoggerManager.getInstance();
160 String role_name = ctx.getParameterValue(ROLE_NAME_QUERY_PARAM);
161
162 if (role_name != null) {
163 // get principal by role
164 MRole role = new MRole(role_name);
165 manager.logAuditEvent(ctx.getUserName(),
166 ctx.getRequest().getRemoteAddr(), "get", "principals by role", role.toString());
167 return new PrincipalBean(handler.getPrincipalsByRole(role));
168 } else {
169 throw new SqoopException(SecurityError.AUTH_0012, "Can't get role name");
170 }
171 }
172
173 private void checkResourceExists(MResource resource) {
174 if (resource == null) {
175 return;
176 }
177
178 Boolean resourceExists = false;
179 Repository repository = RepositoryManager.getInstance().getRepository();
180 MResource.TYPE type = MResource.TYPE.valueOf(resource.getType());
181
182 if (type == MResource.TYPE.CONNECTOR) {
183 if (repository.findConnector(resource.getName()) != null) {
184 resourceExists = true;
185 }
186 } else if (type == MResource.TYPE.LINK) {
187 if (repository.findLink(resource.getName()) != null) {
188 resourceExists = true;
189 }
190 } else if (type == MResource.TYPE.JOB) {
191 if (repository.findJob(resource.getName()) != null) {
192 resourceExists = true;
193 }
194 } else {
195 // For MResource.Type.SERVER, it must exists
196 resourceExists = true;
197 }
198
199 if (!resourceExists) {
200 throw new SqoopException(CommonRepositoryError.COMMON_0058,
201 "Can't find resource " + resource.toString());
202 }
203 }
204
205 private JsonBean getPrivilege(RequestContext ctx) {
206 AuthorizationHandler handler = AuthorizationManager.getInstance().getAuthorizationHandler();
207 AuditLoggerManager manager = AuditLoggerManager.getInstance();
208 String principal_name = ctx.getParameterValue(PRINCIPAL_NAME_QUERY_PARAM);
209 String principal_type = ctx.getParameterValue(PRINCIPAL_TYPE_QUERY_PARAM);
210 String resource_name = ctx.getParameterValue(RESOURCE_NAME_QUERY_PARAM);
211 String resource_type = ctx.getParameterValue(RESOURCE_TYPE_QUERY_PARAM);
212
213 if (principal_name != null && principal_type != null) {
214 // get privilege by principal
215 MPrincipal principal = new MPrincipal(principal_name, principal_type);
216 MResource resource = null;
217 if (resource_name != null && resource_type != null) {
218 resource = new MResource(resource_name, resource_type);
219 }
220 checkResourceExists(resource);
221 manager.logAuditEvent(ctx.getUserName(),
222 ctx.getRequest().getRemoteAddr(), "get", "privileges by principal", principal.toString());
223 return new PrivilegesBean(handler.getPrivilegesByPrincipal(principal, resource));
224 } else {
225 throw new SqoopException(SecurityError.AUTH_0013, "Can't get principal");
226 }
227 }
228
229 private JsonBean createRole(RequestContext ctx) {
230 AuthorizationHandler handler = AuthorizationManager.getInstance().getAuthorizationHandler();
231 AuditLoggerManager manager = AuditLoggerManager.getInstance();
232
233 RoleBean bean = new RoleBean();
234 bean.restore(JSONUtils.parse(ctx.getReader()));
235
236 // Get role object
237 List<MRole> roles = bean.getRoles();
238
239 if (roles.size() != 1) {
240 throw new SqoopException(ServerError.SERVER_0003, "Expected one role but got " + roles.size());
241 }
242
243 MRole postedRole = roles.get(0);
244
245 manager.logAuditEvent(ctx.getUserName(),
246 ctx.getRequest().getRemoteAddr(), "create", "role", postedRole.toString());
247 handler.createRole(postedRole);
248 return JsonBean.EMPTY_BEAN;
249 }
250
251 private JsonBean grantRevokeRole(RequestContext ctx, boolean isGrant) {
252 AuthorizationHandler handler = AuthorizationManager.getInstance().getAuthorizationHandler();
253 AuditLoggerManager manager = AuditLoggerManager.getInstance();
254
255 RoleBean rolesBean = new RoleBean();
256 PrincipalBean principalsBean = new PrincipalBean();
257
258 JSONObject json = JSONUtils.parse(ctx.getReader());
259 rolesBean.restore(json);
260 principalsBean.restore(json);
261
262 // Get role object
263 List<MRole> roles = rolesBean.getRoles();
264 // Get principal object
265 List<MPrincipal> principals = principalsBean.getPrincipals();
266
267 if (isGrant) {
268 manager.logAuditEvent(ctx.getUserName(),
269 ctx.getRequest().getRemoteAddr(), "grant", "role", "principal");
270 handler.grantRole(principals, roles);
271 } else {
272 manager.logAuditEvent(ctx.getUserName(),
273 ctx.getRequest().getRemoteAddr(), "revoke", "role", "principal");
274 handler.revokeRole(principals, roles);
275 }
276 return JsonBean.EMPTY_BEAN;
277 }
278
279 private JsonBean grantRevokePrivilege(RequestContext ctx, boolean isGrant) {
280 AuthorizationHandler handler = AuthorizationManager.getInstance().getAuthorizationHandler();
281 AuditLoggerManager manager = AuditLoggerManager.getInstance();
282
283 PrincipalBean principalsBean = new PrincipalBean();
284 PrivilegesBean privilegesBean = new PrivilegesBean();
285
286 JSONObject json = JSONUtils.parse(ctx.getReader());
287 principalsBean.restore(json);
288 try {
289 privilegesBean.restore(json);
290 } catch (Exception e) {//Privilege is null, revoke all privileges from principal
291 privilegesBean = null;
292 }
293
294 // Get principal object
295 List<MPrincipal> principals = principalsBean.getPrincipals();
296 // Get privilege object
297 List<MPrivilege> privileges = privilegesBean == null ? null : privilegesBean.getPrivileges();
298
299 String defaultUser = SqoopConfiguration.getInstance().getContext().getString(
300 SecurityConstants.AUTHENTICATION_DEFAULT_USER,
301 SecurityConstants.AUTHENTICATION_DEFAULT_USER_DEFAULT);
302 for (MPrincipal principal : principals) {
303 if (defaultUser.equals(principal.getName())) {
304 throw new SqoopException(SecurityError.AUTH_0015);
305 }
306 }
307
308 if (privileges != null) {
309 for (MPrivilege privilege : privileges) {
310 checkResourceExists(privilege.getResource());
311 }
312 } else if (isGrant){
313 throw new SqoopException(CommonRepositoryError.COMMON_0058,
314 "Resource can't be null");
315 }
316
317 if (isGrant) {
318 manager.logAuditEvent(ctx.getUserName(),
319 ctx.getRequest().getRemoteAddr(), "grant", "role", "privilege");
320 handler.grantPrivileges(principals, privileges);
321 } else {
322 manager.logAuditEvent(ctx.getUserName(),
323 ctx.getRequest().getRemoteAddr(), "revoke", "role", "privilege");
324 handler.revokePrivileges(principals, privileges);
325 }
326 return JsonBean.EMPTY_BEAN;
327 }
328
329 private JsonBean dropRole(RequestContext ctx) {
330 AuthorizationHandler handler = AuthorizationManager.getInstance().getAuthorizationHandler();
331 AuditLoggerManager manager = AuditLoggerManager.getInstance();
332
333 String[] urlElements = ctx.getUrlElements();
334
335 //wrong URL
336 if (urlElements.length < 2 ||
337 !urlElements[urlElements.length - 2].equals(Action.ROLES.name)) {
338 throw new SqoopException(SecurityError.AUTH_0012, "Can't get role name");
339 }
340
341 String role_name = ctx.getLastURLElement();
342 MRole role = new MRole(role_name);
343 manager.logAuditEvent(ctx.getUserName(),
344 ctx.getRequest().getRemoteAddr(), "delete", "role", role.toString());
345 handler.dropRole(role);
346 return JsonBean.EMPTY_BEAN;
347 }
348 }