/* * 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.ranger.rest; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import org.apache.log4j.Logger; import org.apache.ranger.biz.KmsKeyMgr; import org.apache.ranger.common.MessageEnums; import org.apache.ranger.common.RESTErrorUtil; import org.apache.ranger.common.SearchUtil; import org.apache.ranger.common.annotation.RangerAnnotationJSMgrName; import org.apache.ranger.security.context.RangerAPIList; import org.apache.ranger.view.VXKmsKey; import org.apache.ranger.view.VXKmsKeyList; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.sun.jersey.api.client.UniformInterfaceException; @Path("keys") @Component @Scope("request") @RangerAnnotationJSMgrName("KeyMgr") @Transactional(propagation = Propagation.REQUIRES_NEW) public class XKeyREST { private static final Logger logger = Logger.getLogger(XKeyREST.class); private static String UNAUTHENTICATED_MSG = "Unauthenticated : Please check the premission in the policy for the user"; @Autowired KmsKeyMgr keyMgr; @Autowired SearchUtil searchUtil; @Autowired RESTErrorUtil restErrorUtil; /** * Implements the traditional search functionalities for Keys * * @param request * @return */ @GET @Path("/keys") @Produces({ "application/xml", "application/json" }) @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.SEARCH_KEYS + "\")") public VXKmsKeyList searchKeys(@Context HttpServletRequest request, @QueryParam("provider") String provider) { VXKmsKeyList vxKmsKeyList = new VXKmsKeyList(); try{ vxKmsKeyList = keyMgr.searchKeys(request, provider); }catch(Exception e){ handleError(e); } return vxKmsKeyList; } /** * Implements the Rollover key functionality * @param vXKey * @return */ @PUT @Path("/key") @Produces({ "application/xml", "application/json" }) @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.ROLLOVER_KEYS + "\")") public VXKmsKey rolloverKey(@QueryParam("provider") String provider, VXKmsKey vXKey) { VXKmsKey vxKmsKey = new VXKmsKey(); try{ String name = vXKey.getName(); if (name == null || name.isEmpty()) { throw restErrorUtil.createRESTException("Please provide a valid " + "alias.", MessageEnums.INVALID_INPUT_DATA); } if(vXKey.getCipher() == null || vXKey.getCipher().trim().isEmpty()){ vXKey.setCipher(null); } vxKmsKey = keyMgr.rolloverKey(provider, vXKey); }catch(Exception e){ handleError(e); } return vxKmsKey; } /** * Implements the delete key functionality * @param name * @param request */ @DELETE @Path("/key/{alias}") @Produces({ "application/xml", "application/json" }) @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.DELETE_KEY + "\")") public void deleteKey(@PathParam("alias") String name, @QueryParam("provider") String provider, @Context HttpServletRequest request) { try{ if (name == null || name.isEmpty()) { throw restErrorUtil.createRESTException("Please provide a valid " + "alias.", MessageEnums.INVALID_INPUT_DATA); } keyMgr.deleteKey(provider, name); }catch(Exception e){ handleError(e); } } /** * Implements the create key functionality * @param vXKey * @return */ @POST @Path("/key") @Produces({ "application/xml", "application/json" }) @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.CREATE_KEY + "\")") public VXKmsKey createKey(@QueryParam("provider") String provider, VXKmsKey vXKey) { VXKmsKey vxKmsKey = new VXKmsKey(); try{ String name = vXKey.getName(); if (name == null || name.isEmpty()) { throw restErrorUtil.createRESTException("Please provide a valid " + "alias.", MessageEnums.INVALID_INPUT_DATA); } if(vXKey.getCipher() == null || vXKey.getCipher().trim().isEmpty()){ vXKey.setCipher(null); } vxKmsKey = keyMgr.createKey(provider, vXKey); }catch(Exception e){ handleError(e); } return vxKmsKey; } /** * * @param name * @param provider * @return */ @GET @Path("/key/{alias}") @Produces({ "application/xml", "application/json" }) @PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_KEY + "\")") public VXKmsKey getKey(@PathParam("alias") String name,@QueryParam("provider") String provider){ VXKmsKey vxKmsKey = new VXKmsKey(); try{ if (name == null || name.isEmpty()) { throw restErrorUtil.createRESTException("Please provide a valid " + "alias.", MessageEnums.INVALID_INPUT_DATA); } vxKmsKey = keyMgr.getKey(provider, name); }catch(Exception e){ handleError(e); } return vxKmsKey; } private void handleError(Exception e) { String message = e.getMessage(); if (e instanceof UniformInterfaceException){ UniformInterfaceException uie=(UniformInterfaceException)e; message = uie.getResponse().getEntity(String.class); logger.error(message); try { JSONObject objRE = new JSONObject(message); message = objRE.getString("RemoteException"); JSONObject obj = new JSONObject(message); message = obj.getString("message"); } catch (JSONException e1) { message = e1.getMessage(); } } if(!(message==null) && !(message.isEmpty()) && message.contains("Connection refused")){ message = "Connection refused : Please check the KMS provider URL and whether the Ranger KMS is running"; }else if(!(message==null) && !(message.isEmpty()) && (message.contains("response status of 403") || message.contains("HTTP Status 403"))){ message = UNAUTHENTICATED_MSG; }else if(!(message==null) && !(message.isEmpty()) && (message.contains("response status of 401") || message.contains("HTTP Status 401 - Authentication required"))){ message = UNAUTHENTICATED_MSG; } throw restErrorUtil.createRESTException(message, MessageEnums.ERROR_SYSTEM); } }