authorization-service/src/main/java/org/gcube/common/authorizationservice/TokenManager.java

468 lines
16 KiB
Java

package org.gcube.common.authorizationservice;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.annotation.ManagedBean;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
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.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.gcube.common.authorization.library.AuthorizationEntry;
import org.gcube.common.authorization.library.ExternalServiceList;
import org.gcube.common.authorization.library.provider.CalledMethodProvider;
import org.gcube.common.authorization.library.provider.ContainerInfo;
import org.gcube.common.authorization.library.provider.ExternalServiceInfo;
import org.gcube.common.authorization.library.provider.ServiceInfo;
import org.gcube.common.authorization.library.provider.UserInfo;
import org.gcube.common.authorization.library.utils.AuthorizationEntryList;
import org.gcube.common.authorization.library.utils.ListMapper;
import org.gcube.common.authorization.library.utils.MultiServiceTokenRequest;
import org.gcube.common.authorizationservice.filters.AuthorizedCallFilter;
import org.gcube.common.authorizationservice.util.Constants;
import org.gcube.common.authorizationservice.util.TokenPersistence;
import lombok.extern.slf4j.Slf4j;
@Path("token")
@Slf4j
@ManagedBean
public class TokenManager {
@Inject
TokenPersistence persistence;
/**
*
* retrieves the AuthorzationEntry connected to the specified token
*
* @param token
* @return the authorization entry
*/
@GET
@Path("{token}")
@Produces(MediaType.APPLICATION_XML)
public AuthorizationEntry retrieveToken(@NotNull @PathParam("token") String token ) {
CalledMethodProvider.instance.set("retrieve");
log.info("token retreiver called with token {}",token);
AuthorizationEntry info = null;
try {
info = persistence.getAuthorizationEntry(token);
} catch ( Throwable t) {
log.error("erorr on authorization", t);
throw new WebApplicationException(Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("error on authorization").type(MediaType.TEXT_PLAIN).build());
}
log.info("info retrieved {}",info);
if (info == null){
log.error("token {} not found ", token);
throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND)
.entity("token "+token+" not found").type(MediaType.TEXT_PLAIN).build());
}
/*
try{
ScopeProvider.instance.set(info.getContext());
ServiceMap map = ((ScopedServiceMap)ServiceMap.instance).currentMap();
ScopeProvider.instance.reset();
info.setMap(map);
}catch(Throwable e){
log.error("error retrieving map for {}", info.getContext(), e);
}*/
log.debug("returning info {}", info);
return info;
}
/**
*
* retrieves the AuthorzationEntry connected to the specified token
*
* @param token
* @return the authorization entry
*/
@GET
@Path("bunch")
@Produces(MediaType.APPLICATION_XML)
public AuthorizationEntryList retrieveTokenBunch(@NotNull @QueryParam("token") List<String> tokens ) {
CalledMethodProvider.instance.set("retrieve");
log.info("token retreiver in bunch called with tokens {}",tokens);
List<AuthorizationEntry> toReturn = new ArrayList<AuthorizationEntry>();
for (String token : tokens ) {
try {
AuthorizationEntry info = persistence.getAuthorizationEntry(token);
/*
try{
ScopeProvider.instance.set(info.getContext());
DefaultServiceMap map = (DefaultServiceMap)((ScopedServiceMap)ServiceMap.instance).currentMap();
ScopeProvider.instance.reset();
info.setMap(map);
}catch(Throwable e){
log.error("error retrieving map for {}", info.getContext(), e);
}
*/
toReturn.add(info);
}catch(Exception t) {
log.error("erorr on authorization", t);
}
}
log.info("info retrieved {}",toReturn);
if (toReturn.isEmpty()){
log.error("no tokens poassed have been found ");
throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND)
.entity("no tokens poassed have been found ").type(MediaType.TEXT_PLAIN).build());
}
return new AuthorizationEntryList(toReturn);
}
/**
*
* retrieves the AuthorzationEntry connected to the specified token
*
* @param token
* @return the authorization entry
*/
@GET
@Path("resolve/{user}")
public String getTokenByUserAndContext(@NotNull @PathParam("user") String user, @QueryParam("context") String context ) {
CalledMethodProvider.instance.set("retrieve");
log.info("resolving token for user {} in context {}",user, context);
if (context==null){
log.error("null context found");
throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND)
.entity("null context found").type(MediaType.TEXT_PLAIN).build());
}
String token = persistence.getExistingToken(user, context, Constants.DEFAULT_TOKEN_QUALIFIER);
if (token == null){
log.error("token {} not found ", token);
throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND)
.entity("token for user "+user+" in context "+context+" not found").type(MediaType.TEXT_PLAIN).build());
}
//TODO: re-add it with common-scope 2.0
/*
try{
ServiceMap map = .instance.getMap(info.getContext());
info.setMap(map);
}catch(Exception e){
log.error("error retrieving map for {}", info.getContext(), e);
throw new WebApplicationException(Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Error retrieving map").type(MediaType.TEXT_PLAIN).build());
}*/
return token;
}
/**
*
* Generates a token for a user (saving the passed roles) if it doesn't exist yet.
*
* @param userName
* @param roles
* @return the generated token or the token related to the user (if it was already created)
*/
@Path("user")
@PUT
@Consumes(MediaType.APPLICATION_XML)
public String generateUserToken(UserInfo clientId,
@NotNull @QueryParam("context") String context) {
CalledMethodProvider.instance.set("generate");
try{
log.info("generator called with user {} in context {} ",clientId, context);
if (clientId.getId().split(":").length>1) throw new Exception("invalid user id: "+clientId.getId());
String token = persistence.getExistingToken(clientId.getId(), context, Constants.DEFAULT_TOKEN_QUALIFIER);
if (token==null){
token = UUID.randomUUID().toString();
persistence.saveAuthorizationEntry(token, context, clientId , Constants.DEFAULT_TOKEN_QUALIFIER, null);
}
return token;
}catch(Exception e){
log.error("error generating token ",e);
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity("Error Generating Token: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build());
}
}
/**
*
* Generates a token for a user (saving the passed roles) if it doesn't exist yet.
*
* @param userName
* @param roles
* @return the generated token or the token related to the user (if it was already created)
*/
@Path("user/{token}/roles")
@PUT
@Consumes(MediaType.APPLICATION_XML)
public String setRoles(ListMapper roles,
@NotNull @PathParam("token") String token) {
CalledMethodProvider.instance.set("setRoles");
try{
log.info("update roles called");
persistence.updateAuthorizationEntry(token, roles.getList()) ;
return token;
}catch(Exception e){
log.error("error setting roles to token ",e);
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity("Error setting roles to token: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build());
}
}
/**
*
* REmoves a token for a user.
*
* @param userName
* @param roles
* @return the generated token or the token related to the user (if it was already created)
*/
@Path("user")
@DELETE
@Consumes(MediaType.APPLICATION_XML)
public void removeUserToken(@NotNull @QueryParam("client_id") String clientId,
@NotNull @QueryParam("context") String context) {
CalledMethodProvider.instance.set("delete");
try{
log.info("generator called with user {} in context {} ",clientId, context);
if (clientId.split(":").length>1) throw new Exception("invalid user id: "+clientId);
persistence.removeAllAuthorizationsEntryForClientId(context, clientId);
}catch(Exception e){
log.error("error generating token ",e);
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity("Error removing Token: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build());
}
}
/**
*
* Generates a token for a service if it doesn't exist yet.
*
* @param userName
* @param roles
* @return the generated token or the token related to the user (if it was already created)
*/
@Path("service")
@PUT
@Consumes(MediaType.APPLICATION_XML)
public String generateServiceToken(ServiceInfo serviceInfo,
@Context HttpServletRequest req) {
CalledMethodProvider.instance.set("generate");
try{
AuthorizationEntry authInfo = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE);
log.info("generator called with service {} in context {} ",serviceInfo.getId(), authInfo.getContext());
return generateTokenForServiceInfo(serviceInfo, authInfo);
}catch(Exception e){
log.error("error generating token ",e);
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity("Error Generating Token: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build());
}
}
/**
*
* Generates a list of tokens for a service if it doesn't exist yet.
*
* @param userName
* @param MultiServiceTokenRequest entity
* @return a list generated token or the token related to the user (if it was already created)
*/
@Path("service/bunch")
@PUT
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
public ListMapper generateServiceTokenBunch(MultiServiceTokenRequest entity,
@Context HttpServletRequest req) {
CalledMethodProvider.instance.set("generate");
log.info("calling generate service token bunch");
try{
AuthorizationEntry callerInfo = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE);
List<String> tokensToReturn = new ArrayList<String>();
for (String token: entity.getContainerTokens()) {
AuthorizationEntry authInfo = this.retrieveToken(token);
if (authInfo==null) continue;
if (!authInfo.getClientInfo().getId().equals(callerInfo.getClientInfo().getId()))
log.warn("a token with a different ContainerInfo of the caller used, skipping it");
else {
String genToken = generateTokenForServiceInfo(entity.getInfo(), authInfo);
tokensToReturn.add(genToken);
}
}
return new ListMapper(tokensToReturn);
}catch(Exception e){
log.error("error generating tokens ",e);
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity("Error Generating Token: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build());
}
}
/**
*
* Generates a token for an external service if it doesn't exist yet.
*
* @param externalServiceInfo
* @return the generated token or the token related to the external service (if it was already created)
*/
@Path("external/{serviceId}")
@PUT
@Consumes(MediaType.APPLICATION_XML)
public String generateExternalServiceToken(@PathParam("serviceId") String serviceId, @Context HttpServletRequest req) {
try{
CalledMethodProvider.instance.set("generate");
AuthorizationEntry info = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE);
log.info("generator called for external service {} in context {} ",serviceId, info.getContext());
if (serviceId.split(":").length>1) throw new Exception("invalid external service id: "+serviceId);
String token = persistence.getExistingToken(serviceId, info.getContext(), Constants.DEFAULT_TOKEN_QUALIFIER);
if (token==null){
token= UUID.randomUUID().toString();
persistence.saveAuthorizationEntry(token, info.getContext(), new ExternalServiceInfo(serviceId, info.getClientInfo().getId()), Constants.DEFAULT_TOKEN_QUALIFIER, info.getClientInfo().getId());
}
return token;
}catch(Exception e){
log.error("error generating token ",e);
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity("Error Generating Token: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build());
}
}
/**
*
* Generates a token for an external service if it doesn't exist yet.
*
* @param externalServiceInfo
* @return the generated token or the token related to the external service (if it was already created)
*/
@Path("external")
@GET
@Consumes(MediaType.APPLICATION_XML)
public ExternalServiceList getExternalServiceCreated(@Context HttpServletRequest req) {
CalledMethodProvider.instance.set("retrieve");
try{
AuthorizationEntry info = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE);
log.info("get External Service called in context {} by {} ",info.getContext(), info.getClientInfo().getId());
ExternalServiceList toReturn = new ExternalServiceList(persistence.getExistingExternalServices(info.getClientInfo().getId(), info.getContext()));
return toReturn;
}catch(Exception e){
log.error("error generating token ",e);
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity("Error Generating Token: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build());
}
}
@Path("node")
@PUT
@Consumes(MediaType.APPLICATION_XML)
public String generateContainerToken(@NotNull ContainerInfo containerInfo, @QueryParam("context") String context,
@Context HttpServletRequest req) {
CalledMethodProvider.instance.set("generate");
try{
AuthorizationEntry info = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE);
if (context!=null)
return generateTokenForContainerInfo(containerInfo, context);
else if (info!=null){
log.info("generator called for node {} in context {} ",containerInfo.getId(), info.getContext());
return generateTokenForContainerInfo(containerInfo, info);
}
throw new Exception("error trying to activate node (token and context are empty)");
}catch(Exception e){
log.error("error generating token ",e);
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity("Error Generating Token: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build());
}
}
private String generateTokenForContainerInfo(ContainerInfo containerInfo,String context) throws Exception{
if (containerInfo.getId().split(":").length!=2) throw new Exception("invalid container id: "+containerInfo.getId());
String token = persistence.getExistingToken(containerInfo.getId(), context, Constants.DEFAULT_TOKEN_QUALIFIER);
if( token ==null){
token = UUID.randomUUID().toString();;
persistence.saveAuthorizationEntry(token, context, containerInfo, Constants.DEFAULT_TOKEN_QUALIFIER, null);
}
return token;
}
private String generateTokenForContainerInfo(ContainerInfo containerInfo, AuthorizationEntry authInfo) throws Exception{
if (containerInfo.getId().split(":").length!=2) throw new Exception("invalid container id: "+containerInfo.getId());
String token = persistence.getExistingToken(containerInfo.getId(),authInfo.getContext(), Constants.DEFAULT_TOKEN_QUALIFIER);
if( token ==null){
token = UUID.randomUUID().toString();;
persistence.saveAuthorizationEntry(token, authInfo.getContext(), containerInfo, Constants.DEFAULT_TOKEN_QUALIFIER, authInfo.getClientInfo().getId() );
}
return token;
}
private String generateTokenForServiceInfo(ServiceInfo serviceInfo, AuthorizationEntry authInfo) throws Exception{
if (serviceInfo.getId().split(":").length!=3) throw new Exception("invalid service id: "+serviceInfo.getId());
String token = persistence.getExistingToken(serviceInfo.getId(), authInfo.getContext(), Constants.DEFAULT_TOKEN_QUALIFIER);
if( token ==null){
token = UUID.randomUUID().toString();;
persistence.saveAuthorizationEntry(token, authInfo.getContext(), serviceInfo, Constants.DEFAULT_TOKEN_QUALIFIER, authInfo.getClientInfo().getId() );
}
return token;
}
}