001 /* 002 * Cumulus4j - Securing your data in the cloud - http://cumulus4j.org 003 * Copyright (C) 2011 NightLabs Consulting GmbH 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 package org.cumulus4j.store.crypto.keymanager.rest; 019 020 import javax.ws.rs.Consumes; 021 import javax.ws.rs.GET; 022 import javax.ws.rs.POST; 023 import javax.ws.rs.Path; 024 import javax.ws.rs.PathParam; 025 import javax.ws.rs.Produces; 026 import javax.ws.rs.core.MediaType; 027 028 import org.cumulus4j.keymanager.back.shared.NullResponse; 029 import org.cumulus4j.keymanager.back.shared.Request; 030 import org.cumulus4j.keymanager.back.shared.Response; 031 import org.cumulus4j.store.crypto.keymanager.messagebroker.ActiveKeyManagerChannelRegistration; 032 import org.cumulus4j.store.crypto.keymanager.messagebroker.MessageBroker; 033 import org.cumulus4j.store.crypto.keymanager.messagebroker.MessageBrokerRegistry; 034 035 /** 036 * REST service for the communication channel between key-manager and app-server. 037 * 038 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de 039 */ 040 @Path("KeyManagerChannel") 041 @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) 042 @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) 043 public class KeyManagerChannelService 044 { 045 // private static final Logger logger = LoggerFactory.getLogger(KeyManagerChannelService.class); 046 private MessageBroker messageBroker = MessageBrokerRegistry.sharedInstance().getActiveMessageBroker(); 047 048 // @Context 049 // private HttpServletRequest httpServletRequest; 050 051 private ActiveKeyManagerChannelRegistration registerActiveKeyManagerChannel(String cryptoSessionIDPrefix) 052 { 053 return null; 054 // if (logger.isDebugEnabled()) { 055 // logger.debug("registerKeyManagerChannelUrl: httpServletRequest.getRequestURL() = {}", httpServletRequest.getRequestURL()); 056 // logger.debug("registerKeyManagerChannelUrl: httpServletRequest.getRequestURI() = {}", httpServletRequest.getRequestURI()); 057 // logger.debug("registerKeyManagerChannelUrl: httpServletRequest.getLocalName() = {}", httpServletRequest.getLocalName()); 058 // logger.debug("registerKeyManagerChannelUrl: httpServletRequest.getLocalAddr() = {}", httpServletRequest.getLocalAddr()); 059 // logger.debug("registerKeyManagerChannelUrl: httpServletRequest.getLocalPort() = {}", httpServletRequest.getLocalPort()); 060 // } 061 // 062 // String keyManagerChannelURLPart = "/KeyManagerChannel/"; 063 // String requestURI = httpServletRequest.getRequestURI(); 064 // int idx = requestURI.indexOf(keyManagerChannelURLPart); 065 // if (idx < 0) 066 // throw new IllegalStateException("\"" + keyManagerChannelURLPart + "\" does not occur in requestURI: " + requestURI); 067 // 068 // String keyManagerChannelURI = requestURI.substring(0, idx + keyManagerChannelURLPart.length()); 069 // 070 // String internalKeyManagerChannelProtocol = "http"; // TODO make configurable via system property 071 // String internalKeyManagerChannelHost = httpServletRequest.getLocalName(); // TODO allow overriding (instead of auto-detection) via system property 072 // int internalKeyManagerChannelPort = httpServletRequest.getLocalPort(); // TODO allow overriding (instead of auto-detection) via system property 073 // 074 // String internalKeyManagerChannelURL = ( 075 // internalKeyManagerChannelProtocol + "://" 076 // + internalKeyManagerChannelHost + ':' + internalKeyManagerChannelPort 077 // + keyManagerChannelURI 078 // ); 079 // 080 // ActiveKeyManagerChannelRegistration registration = messageBroker.registerActiveKeyManagerChannel(cryptoSessionIDPrefix, internalKeyManagerChannelURL); 081 // return registration; 082 } 083 084 private void unregisterActiveKeyManagerChannel(ActiveKeyManagerChannelRegistration registration) 085 { 086 // if (registration != null) 087 // messageBroker.unregisterActiveKeyManagerChannel(registration); 088 } 089 090 /** 091 * Test method to allow an administrator to verify the URL in a browser. 092 * @return a string beginning with "OK:". 093 */ 094 @Path("test") 095 @GET 096 @Produces(MediaType.TEXT_PLAIN) 097 public String testGet() 098 { 099 ActiveKeyManagerChannelRegistration registration = registerActiveKeyManagerChannel("test"); 100 unregisterActiveKeyManagerChannel(registration); 101 102 return "OK: " + this.getClass().getName(); 103 } 104 105 // @Path("pushResponse") 106 // @POST 107 // public void pushResponse(Response response) 108 // { 109 // registerLocalClusterNodeKeyManagerChannelUrl(); 110 // 111 // if (response == null) 112 // return; 113 // 114 // // The NullResponse can either be a filler without request and thus needs to be discarded here, 115 // // or it can be a response to a specific request. Hence, we check whether the NullResponse.requestID is null. 116 // if ((response instanceof NullResponse) && response.getRequestID() == null) 117 // return; 118 // 119 // messageBroker.pushResponse(response); 120 // } 121 122 /** 123 * Upload a {@link Response} and fetch the next {@link Request}. If there is no <code>Response</code>, yet, 124 * the key-manager must upload a {@link NullResponse}. This method forwards the <code>response</code> 125 * to {@link MessageBroker#pushResponse(Response)} and then {@link MessageBroker#pollRequest(String) 126 * polls the next request}. 127 * @param cryptoSessionIDPrefix the prefix used by the key-manager, i.e. the unique identifier of the key-manager. 128 * This is used for efficient routing of requests, i.e. by {@link MessageBroker#pollRequest(String)}. 129 * @param response the last response or an instance of {@link NullResponse} (without <code>requestID</code>) 130 * if there is no last request to be replied. 131 * @return the next polled request or <code>null</code> if none popped up before the timeout. 132 */ 133 @Path("nextRequest/{cryptoSessionIDPrefix}") 134 @POST 135 public Request nextRequest(@PathParam("cryptoSessionIDPrefix") String cryptoSessionIDPrefix, Response response) 136 { 137 if (cryptoSessionIDPrefix == null) 138 throw new IllegalArgumentException("cryptoSessionIDPrefix == null"); 139 140 ActiveKeyManagerChannelRegistration registration = registerActiveKeyManagerChannel(cryptoSessionIDPrefix); 141 try { 142 if (response != null && response.getRequestID() != null) { 143 // The NullResponse can either be a filler without request and thus needs to be discarded here, 144 // or it can be a response to a specific request. Hence, we check whether the Response.requestID is null 145 // and don't care about the type at all. If it has a requestID, it must be pushed, no matter what type 146 // it is. Marco :-) 147 messageBroker.pushResponse(response); 148 } 149 150 Request request = messageBroker.pollRequest(cryptoSessionIDPrefix); 151 return request; 152 } finally { 153 unregisterActiveKeyManagerChannel(registration); 154 } 155 } 156 157 }