/* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.controller.usermanager.northbound; import java.net.URI; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.SecurityContext; import javax.ws.rs.core.UriInfo; import org.codehaus.enunciate.jaxrs.ResponseCode; import org.codehaus.enunciate.jaxrs.StatusCodes; import org.codehaus.enunciate.jaxrs.TypeHint; import org.opendaylight.controller.northbound.commons.RestMessages; import org.opendaylight.controller.northbound.commons.exception.BadRequestException; import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException; import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException; import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException; import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils; import org.opendaylight.controller.sal.authorization.UserLevel; import org.opendaylight.controller.sal.utils.ServiceHelper; import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.usermanager.IUserManager; import org.opendaylight.controller.usermanager.UserConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class provides REST APIs to manage users. * This API will only be availalbe via HTTPS. *
*
* Authentication scheme : HTTP Basic
* Authentication realm : opendaylight
* Transport : HTTPS
*
* HTTPS Authentication is disabled by default so to * use UserManager APIs turn on HTTPS on Web Server */ @Path("/") public class UserManagerNorthbound { protected static final Logger logger = LoggerFactory.getLogger(UserManagerNorthbound.class); private String username; @Context UriInfo uriInfo; @Context public void setSecurityContext(SecurityContext context) { if (context != null && context.getUserPrincipal() != null) { username = context.getUserPrincipal().getName(); } } protected String getUserName() { return username; } private void handleNameMismatch(String name, String nameinURL) { if (name == null || nameinURL == null) { throw new BadRequestException(RestMessages.INVALIDDATA.toString() + " : Name is null"); } if (name.equals(nameinURL)) { return; } throw new ResourceConflictException(RestMessages.INVALIDDATA.toString() + " : Name in URL does not match the name in request body"); } /** * Add a user * * @param userConfigData * the {@link UserConfig} user config structure in request body * * @return Response as dictated by the HTTP Response Status code * *
     * Example:
     *
     * Request URL:
     * https://localhost/controller/nb/v2/usermanager/users
     *
     * Request body in XML:
     *  <userConfig>
     *      <user>testuser</user>
     *      <roles>Network-Admin</roles>
     *      <password>pass!23</password>
     *  </userConfig>
     *
     * Request body in JSON:
     * {
     *  "user":"testuser",
     *  "password":"pass!23",
     *  "roles":[
     *       "Network-Admin"
     *       ]
     * }
     * 
*/ @Path("/users") @POST @StatusCodes({ @ResponseCode(code = 201, condition = "User created successfully"), @ResponseCode(code = 400, condition = "Invalid data passed"), @ResponseCode(code = 401, condition = "User not authorized to perform this operation"), @ResponseCode(code = 409, condition = "User name in url conflicts with name in request body"), @ResponseCode(code = 404, condition = "User config is null"), @ResponseCode(code = 500, condition = "Internal Server Error: Addition of user failed"), @ResponseCode(code = 503, condition = "Service unavailable") }) @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) public Response addLocalUser(@TypeHint(UserConfig.class) UserConfig userConfigData) { if (!isAdminUser()) { throw new UnauthorizedException("User is not authorized to perform user management operations "); } // Reconstructing the object so password can be hashed in userConfig UserConfig userCfgObject = new UserConfig(userConfigData.getUser(),userConfigData.getPassword(), userConfigData.getRoles()); IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this); if (userManager == null) { throw new ServiceUnavailableException("UserManager " + RestMessages.SERVICEUNAVAILABLE.toString()); } Status status = userManager.addLocalUser(userCfgObject); if (status.isSuccess()) { NorthboundUtils.auditlog("User", username, "added", userCfgObject.getUser()); URI uri = uriInfo.getAbsolutePathBuilder().path("/"+userCfgObject.getUser()).build(); return Response.created(uri).build(); } return NorthboundUtils.getResponse(status); } /** * Delete a user * * @param userName * name of user to be deleted * @return Response as dictated by the HTTP Response Status code * *
     * Example:
     *
     * Request URL:
     * https://localhost/controller/nb/v2/usermanager/users/testuser
     *
     * 
*/ @Path("/users/{userName}") @DELETE @StatusCodes({ @ResponseCode(code = 204, condition = "User Deleted Successfully"), @ResponseCode(code = 401, condition = "User not authorized to perform this operation"), @ResponseCode(code = 404, condition = "The userName passed was not found"), @ResponseCode(code = 500, condition = "Internal Server Error : Removal of user failed"), @ResponseCode(code = 503, condition = "Service unavailable") }) public Response removeLocalUser(@PathParam("userName") String userToBeRemoved) { if (!isAdminUser()) { throw new UnauthorizedException("User is not authorized to perform user management operations "); } IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this); if (userManager == null) { throw new ServiceUnavailableException("UserManager " + RestMessages.SERVICEUNAVAILABLE.toString()); } Status status = userManager.removeLocalUser(userToBeRemoved); if (status.isSuccess()) { NorthboundUtils.auditlog("User", username, "removed", userToBeRemoved); return Response.noContent().build(); } return NorthboundUtils.getResponse(status); } private boolean isAdminUser(){ // get UserManager's instance IUserManager auth = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this); // check if logged in user has privileges of NETWORK_ADMIN or SYSTEM_ADMIN, if so return true return auth.getUserLevel(getUserName()).ordinal() <= UserLevel.NETWORKADMIN.ordinal(); } }