2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.web;
11 import java.net.InetAddress;
12 import java.net.UnknownHostException;
13 import java.util.ArrayList;
14 import java.util.List;
17 import javax.servlet.http.HttpServletRequest;
18 import javax.servlet.http.HttpSession;
20 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
21 import org.opendaylight.controller.connectionmanager.IConnectionManager;
22 import org.opendaylight.controller.sal.authorization.UserLevel;
23 import org.opendaylight.controller.sal.core.Description;
24 import org.opendaylight.controller.sal.core.Node;
25 import org.opendaylight.controller.sal.utils.GlobalConstants;
26 import org.opendaylight.controller.sal.utils.ServiceHelper;
27 import org.opendaylight.controller.sal.utils.Status;
28 import org.opendaylight.controller.sal.utils.StatusCode;
29 import org.opendaylight.controller.switchmanager.ISwitchManager;
30 import org.opendaylight.controller.usermanager.IUserManager;
31 import org.opendaylight.controller.usermanager.UserConfig;
32 import org.springframework.stereotype.Controller;
33 import org.springframework.web.bind.annotation.PathVariable;
34 import org.springframework.web.bind.annotation.RequestMapping;
35 import org.springframework.web.bind.annotation.RequestMethod;
36 import org.springframework.web.bind.annotation.RequestParam;
37 import org.springframework.web.bind.annotation.ResponseBody;
39 import com.google.gson.Gson;
42 @RequestMapping("/admin")
43 public class DaylightWebAdmin {
44 Gson gson = new Gson();
47 * Returns list of clustered controllers. Highlights "this" controller and
48 * if controller is coordinator
49 * @return List<ClusterBean>
51 @RequestMapping("/cluster")
53 public String getClusteredControllers() {
54 IClusterGlobalServices clusterServices = (IClusterGlobalServices) ServiceHelper.getGlobalInstance(
55 IClusterGlobalServices.class, this);
56 if (clusterServices == null) {
59 IConnectionManager connectionManager = (IConnectionManager) ServiceHelper.getGlobalInstance(
60 IConnectionManager.class, this);
61 if (connectionManager == null) {
65 List<ClusterNodeBean> clusterNodes = new ArrayList<ClusterNodeBean>();
67 List<InetAddress> controllers = clusterServices.getClusteredControllers();
68 for (InetAddress controller : controllers) {
69 ClusterNodeBean.Builder clusterBeanBuilder = new ClusterNodeBean.Builder(controller);
71 //get number of connected nodes
72 Set<Node> connectedNodes = connectionManager.getNodes(controller);
73 int numNodes = connectedNodes == null ? 0 : connectedNodes.size();
74 clusterBeanBuilder.nodesConnected(numNodes);
76 //determine if this is the executing controller
77 if (controller.equals(clusterServices.getMyAddress())) {
78 clusterBeanBuilder.highlightMe();
81 //determine whether this is coordinator
82 if (clusterServices.getCoordinatorAddress().equals(controller)) {
83 clusterBeanBuilder.iAmCoordinator();
85 clusterNodes.add(clusterBeanBuilder.build());
88 return gson.toJson(clusterNodes);
92 * Return nodes connected to controller {controller}
94 * - byte[] of the address of the controller
95 * @return List<NodeBean>
97 @RequestMapping("/cluster/controller/{controller}")
99 public String getNodesConnectedToController(@PathVariable("controller") String controller) {
100 IClusterGlobalServices clusterServices = (IClusterGlobalServices) ServiceHelper.getGlobalInstance(
101 IClusterGlobalServices.class, this);
102 if (clusterServices == null) {
105 IConnectionManager connectionManager = (IConnectionManager) ServiceHelper.getGlobalInstance(
106 IConnectionManager.class, this);
107 if (connectionManager == null) {
110 ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class,
111 GlobalConstants.DEFAULT.toString(), this);
112 if (switchManager == null) {
116 byte[] address = gson.fromJson(controller, byte[].class);
117 InetAddress controllerAddress = null;
119 controllerAddress = InetAddress.getByAddress(address);
120 } catch (UnknownHostException e) {
124 List<NodeBean> result = new ArrayList<NodeBean>();
126 Set<Node> nodes = connectionManager.getNodes(controllerAddress);
128 return gson.toJson(result);
130 for (Node node : nodes) {
131 Description description = (Description) switchManager.getNodeProp(node, Description.propertyName);
133 if (description == null || description.getValue().equals("None")) {
134 nodeBean = new NodeBean(node);
136 nodeBean = new NodeBean(node, description.getValue());
138 result.add(nodeBean);
141 return gson.toJson(result);
144 @RequestMapping("/users")
146 public List<UserConfig> getUsers() {
147 IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
148 if (userManager == null) {
152 List<UserConfig> userConfList = userManager.getLocalUserList();
158 * Password in clear text, moving to HTTP/SSL soon
160 @RequestMapping(value = "/users", method = RequestMethod.POST)
162 public String saveLocalUserConfig(@RequestParam(required = true) String json,
163 @RequestParam(required = true) String action, HttpServletRequest request) {
165 IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
166 if (userManager == null) {
167 return "Internal Error";
170 if (!authorize(userManager, UserLevel.NETWORKADMIN, request)) {
171 return "Operation not permitted";
174 Gson gson = new Gson();
175 UserConfig plainConfig = gson.fromJson(json, UserConfig.class);
176 // Recreate using the proper constructor which will hash the password
177 UserConfig config = new UserConfig(plainConfig.getUser(), plainConfig.getPassword(), plainConfig.getRoles());
179 Status result = (action.equals("add")) ? userManager.addLocalUser(config) : userManager.removeLocalUser(config);
180 if (result.isSuccess()) {
181 String userAction = (action.equals("add")) ? "added" : "removed";
182 DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), userAction, config.getUser());
185 return result.getDescription();
188 @RequestMapping(value = "/users/{username}", method = RequestMethod.POST)
190 public String removeLocalUser(@PathVariable("username") String userName, HttpServletRequest request) {
192 String username = request.getUserPrincipal().getName();
193 if (username.equals(userName)) {
194 return "Invalid Request: User cannot delete itself";
197 IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
198 if (userManager == null) {
199 return "Internal Error";
202 if (!authorize(userManager, UserLevel.NETWORKADMIN, request)) {
203 return "Operation not permitted";
206 Status result = userManager.removeLocalUser(userName);
207 if (result.isSuccess()) {
208 DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "removed", userName);
211 return result.getDescription();
214 @RequestMapping(value = "/users/password/{username}", method = RequestMethod.POST)
216 public Status changePassword(
217 @PathVariable("username") String username, HttpServletRequest request,
218 @RequestParam(value = "currentPassword", required=false) String currentPassword,
219 @RequestParam("newPassword") String newPassword) {
220 IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
221 if (userManager == null) {
222 return new Status(StatusCode.NOSERVICE, "User Manager unavailable");
226 String requestingUser = request.getUserPrincipal().getName();
228 //changing own password
229 if (requestingUser.equals(username) ) {
230 status = userManager.changeLocalUserPassword(username, currentPassword, newPassword);
231 //enforce the user to re-login with new password
232 if (status.isSuccess() && !newPassword.equals(currentPassword)) {
233 userManager.userLogout(username);
234 HttpSession session = request.getSession(false);
235 if ( session != null) {
236 session.invalidate();
240 //admin level user resetting other's password
241 } else if (authorize(userManager, UserLevel.NETWORKADMIN, request)) {
243 //Since User Manager doesn't have an unprotected password change API,
244 //we re-create the user with the new password (and current roles).
245 List<String> roles = userManager.getUserRoles(username);
246 UserConfig newConfig = new UserConfig(username, newPassword, roles);
248 //validate before removing existing config, so we don't remove but fail to add
249 status = newConfig.validate();
250 if (!status.isSuccess()) {
254 userManager.userLogout(username);
255 status = userManager.removeLocalUser(username);
256 if (!status.isSuccess()) {
259 if (userManager.addLocalUser(newConfig).isSuccess()) {
260 status = new Status(StatusCode.SUCCESS, "Password for user " + username + " reset successfully.");
263 status = new Status(StatusCode.INTERNALERROR, "Failed resetting password for user " + username + ". User is now removed.");
268 status = new Status(StatusCode.UNAUTHORIZED, "Operation not permitted");
271 if (status.isSuccess()) {
272 DaylightWebUtil.auditlog("User", requestingUser, "changed password for", username);
278 * Is the operation permitted for the given level
281 private boolean authorize(IUserManager userManager, UserLevel level, HttpServletRequest request) {
282 String username = request.getUserPrincipal().getName();
283 UserLevel userLevel = userManager.getUserLevel(username);
284 return userLevel.toNumber() <= level.toNumber();