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.keymanager.front.webapp; 019 020 import java.io.IOException; 021 022 import javax.ws.rs.Consumes; 023 import javax.ws.rs.DELETE; 024 import javax.ws.rs.GET; 025 import javax.ws.rs.POST; 026 import javax.ws.rs.PUT; 027 import javax.ws.rs.Path; 028 import javax.ws.rs.PathParam; 029 import javax.ws.rs.Produces; 030 import javax.ws.rs.WebApplicationException; 031 import javax.ws.rs.core.MediaType; 032 import javax.ws.rs.core.Response; 033 import javax.ws.rs.core.Response.Status; 034 035 import org.cumulus4j.keymanager.AppServerManager; 036 import org.cumulus4j.keymanager.front.shared.AppServer; 037 import org.cumulus4j.keymanager.front.shared.Error; 038 import org.cumulus4j.keymanager.front.shared.PutAppServerResponse; 039 import org.slf4j.Logger; 040 import org.slf4j.LoggerFactory; 041 042 /** 043 * REST service to manage {@link org.cumulus4j.keymanager.front.shared.AppServer AppServer}s. 044 * 045 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de 046 */ 047 @Path("AppServer") 048 @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) 049 @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) 050 public class AppServerService extends AbstractService 051 { 052 private static final Logger logger = LoggerFactory.getLogger(AppServerService.class); 053 054 /** 055 * Create an instance. 056 */ 057 public AppServerService() { 058 logger.debug("logger: instantiated AppServerService"); 059 } 060 061 /** 062 * Get an <code>AppServer</code>. 063 * @param keyStoreID identifier of the key-store to work with. 064 * @param appServerID identifier of app-server to retrieve. 065 * @return the <code>AppServer</code> or <code>null</code>, if no matching <code>AppServer</code> exists. 066 */ 067 @GET 068 @Path("{keyStoreID}/{appServerID}") 069 public org.cumulus4j.keymanager.front.shared.AppServer getAppServer( 070 @PathParam("keyStoreID") String keyStoreID, 071 @PathParam("appServerID") String appServerID 072 ) 073 { 074 logger.debug("getAppServer: entered"); 075 Auth auth = authenticate(keyStoreID); 076 try { 077 AppServerManager appServerManager = keyStoreManager.getAppServerManager(keyStoreID); 078 org.cumulus4j.keymanager.AppServer appServer = appServerManager.getAppServerForAppServerID(appServerID); 079 if (appServer == null) 080 return null; 081 else { 082 org.cumulus4j.keymanager.front.shared.AppServer as = new org.cumulus4j.keymanager.front.shared.AppServer(); 083 as.setAppServerID(appServer.getAppServerID()); 084 as.setAppServerBaseURL(appServer.getAppServerBaseURL()); 085 return as; 086 } 087 } catch (IOException e) { 088 logger.error("getAppServer: " + e, e); 089 throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(new Error(e)).build()); 090 } finally { 091 auth.clear(); 092 } 093 } 094 095 /** 096 * Get a list of all <code>AppServer</code>s managed by this key-server for the specified key-store. 097 * @param keyStoreID identifier of the key-store to work with. 098 * @return a list of all <code>AppServer</code>s for the specified key-store. Never <code>null</code>, but 099 * it may be an empty list. 100 */ 101 @GET 102 @Path("{keyStoreID}") 103 public org.cumulus4j.keymanager.front.shared.AppServerList getAppServers(@PathParam("keyStoreID") String keyStoreID) 104 { 105 logger.debug("getAppServers: entered"); 106 org.cumulus4j.keymanager.front.shared.AppServerList appServerList = new org.cumulus4j.keymanager.front.shared.AppServerList(); 107 Auth auth = authenticate(keyStoreID); 108 try { 109 AppServerManager appServerManager = keyStoreManager.getAppServerManager(keyStoreID); 110 for (org.cumulus4j.keymanager.AppServer appServer : appServerManager.getAppServers()) { 111 org.cumulus4j.keymanager.front.shared.AppServer as = new org.cumulus4j.keymanager.front.shared.AppServer(); 112 as.setAppServerID(appServer.getAppServerID()); 113 as.setAppServerBaseURL(appServer.getAppServerBaseURL()); 114 appServerList.getAppServers().add(as); 115 } 116 } catch (IOException e) { 117 logger.error("getAppServers: " + e, e); 118 throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(new Error(e)).build()); 119 } finally { 120 auth.clear(); 121 } 122 return appServerList; 123 } 124 125 // /** 126 // * Put an <code>AppServer</code>. 127 // * @param keyStoreID identifier of the key-store to work with. 128 // * @param appServerID identifier of the <code>AppServer</code> (must match 129 // * {@link org.cumulus4j.keymanager.front.shared.AppServer#getAppServerID()}). 130 // * @param appServer the <code>AppServer</code> to be put. 131 // * @deprecated This service method is not used by the unified key manager API. Shall we remove it?! It exists solely for 132 // * reasons of REST-ful service consistency. But maybe we should better remove it and provide ONE single way to handle things. Marco :-) 133 // */ 134 // @Deprecated 135 // @PUT 136 // @Path("{keyStoreID}/{appServerID}") 137 // public void putAppServerWithAppServerIDPath( 138 // @PathParam("keyStoreID") String keyStoreID, 139 // @PathParam("appServerID") String appServerID, 140 // org.cumulus4j.keymanager.front.shared.AppServer appServer 141 // ) 142 // { 143 // logger.debug("putAppServerWithAppServerIDPath: entered"); 144 // 145 // if (appServerID == null) 146 // throw new IllegalArgumentException("How the hell can appServerID be null?!"); 147 // 148 // if (appServer == null) 149 // throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new Error("Missing request-entity!")).build()); 150 // 151 // if (appServer.getAppServerID() == null || appServer.getAppServerID().isEmpty()) 152 // appServer.setAppServerID(appServerID); 153 // else if (!appServerID.equals(appServer.getAppServerID())) 154 // throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new Error("Path's appServerID='" + appServerID + "' does not match entity's appServerID='" + appServer.getAppServerID() + "'!")).build()); 155 // 156 // putAppServer(keyStoreID, appServer); 157 // } 158 159 /** 160 * Compatibility for clients not supporting <code>PUT</code>. This method does the same as (it delegates to) 161 * {@link #putAppServer(String, org.cumulus4j.keymanager.front.shared.AppServer)}. Ajax-Clients (e.g. jQuery in Firefox) seem 162 * not to support <code>PUT</code>. 163 */ 164 @POST 165 @Path("{keyStoreID}") 166 public PutAppServerResponse postAppServer( 167 @PathParam("keyStoreID") String keyStoreID, 168 org.cumulus4j.keymanager.front.shared.AppServer appServer 169 ) { 170 return putAppServer(keyStoreID, appServer); 171 } 172 173 /** 174 * Put an <code>AppServer</code>. 175 * @param keyStoreID identifier of the key-store to work with. 176 * @param appServer the <code>AppServer</code> to be put. Note, that its {@link AppServer#getAppServerID() appServerID} 177 * is ignored! It will be assigned by this method. 178 * @return data that might have been created/changed during the put operation (e.g. the <code>appServerID</code> 179 * is assigned during this method call). 180 */ 181 @PUT 182 @Path("{keyStoreID}") 183 public PutAppServerResponse putAppServer( 184 @PathParam("keyStoreID") String keyStoreID, 185 org.cumulus4j.keymanager.front.shared.AppServer appServer 186 ) 187 { 188 logger.debug("putAppServer: entered"); 189 190 if (appServer == null) 191 throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new Error("Missing request-entity!")).build()); 192 193 // We do not allow to overwrite an existing AppServer with different data for security & stability reasons. 194 // Hence the appServerID is always assigned by this service. We enforce it. Marco :-) 195 appServer.setAppServerID(null); 196 197 Auth auth = authenticate(keyStoreID); 198 try { 199 AppServerManager appServerManager = keyStoreManager.getAppServerManager(keyStoreID); 200 org.cumulus4j.keymanager.AppServer as = new org.cumulus4j.keymanager.AppServer( 201 appServerManager, appServer.getAppServerID(), appServer.getAppServerBaseURL() 202 ); 203 appServerManager.putAppServer(as); // This will assign appServer.appServerID, if that property is null. 204 205 if (as.getAppServerID() == null) // sanity check. 206 throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(new Error(new IllegalStateException("appServer.appServerID is null after registration of appServer!"))).build()); 207 208 // TODO write AppServers to a file (maybe into the keystore?!)! 209 return new PutAppServerResponse(as.getAppServerID()); 210 } catch (IOException e) { 211 logger.error("putAppServer: " + e, e); 212 throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(new Error(e)).build()); 213 } finally { 214 // extra safety => overwrite passwords 215 auth.clear(); 216 } 217 } 218 219 /** 220 * Delete the AppServer. 221 * @param keyStoreID identifier of the key-store to work with. 222 * @param appServerID identifier of app-server to delete. 223 */ 224 @DELETE 225 @Path("{keyStoreID}/{appServerID}") 226 public void deleteAppServer(@PathParam("keyStoreID") String keyStoreID, @PathParam("appServerID") String appServerID) 227 { 228 logger.debug("deleteAppServer: entered"); 229 230 Auth auth = authenticate(keyStoreID); 231 try { 232 AppServerManager appServerManager = keyStoreManager.getAppServerManager(keyStoreID); 233 appServerManager.removeAppServer(appServerID); 234 } catch (IOException e) { 235 logger.error("deleteAppServer: " + e, e); 236 throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(new Error(e)).build()); 237 } finally { 238 // extra safety => overwrite password 239 auth.clear(); 240 } 241 } 242 }