You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rl...@apache.org on 2017/07/19 12:41:53 UTC

[3/6] ambari git commit: AMBARI-20861. BE: Extend Ambari REST API to Support User Account Management Improvements (rlevas)

http://git-wip-us.apache.org/repos/asf/ambari/blob/317905e4/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java
index d24780b..d9b8577 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java
@@ -49,46 +49,46 @@ import org.slf4j.LoggerFactory;
 public abstract class BaseService {
   public final static MediaType MEDIA_TYPE_TEXT_CSV_TYPE = new MediaType("text", "csv");
 
-  static final String MSG_SUCCESSFUL_OPERATION = "Successful operation";
-  static final String MSG_REQUEST_ACCEPTED = "Request is accepted, but not completely processed yet";
-  static final String MSG_INVALID_ARGUMENTS = "Invalid arguments";
-  static final String MSG_INVALID_REQUEST = "Invalid request";
-  static final String MSG_CLUSTER_NOT_FOUND = "Cluster not found";
-  static final String MSG_CLUSTER_OR_HOST_NOT_FOUND = "Cluster or host not found";
-  static final String MSG_NOT_AUTHENTICATED = "Not authenticated";
-  static final String MSG_PERMISSION_DENIED = "Not permitted to perform the operation";
-  static final String MSG_SERVER_ERROR = "Internal server error";
-  static final String MSG_RESOURCE_ALREADY_EXISTS = "The requested resource already exists.";
-  static final String MSG_RESOURCE_NOT_FOUND = "The requested resource doesn't exist.";
-
-  static final String QUERY_FIELDS = "fields";
-  static final String QUERY_FILTER_DESCRIPTION = "Filter fields in the response (identifier fields are mandatory)";
-  static final String QUERY_SORT = "sortBy";
-  static final String QUERY_SORT_DESCRIPTION = "Sort resources in result by (asc | desc)";
-  static final String QUERY_PAGE_SIZE = "page_size";
-  static final String QUERY_PAGE_SIZE_DESCRIPTION = "The number of resources to be returned for the paged response.";
-  static final String DEFAULT_PAGE_SIZE = "10";
-  static final String QUERY_FROM = "from";
-  static final String QUERY_FROM_DESCRIPTION = "The starting page resource (inclusive).  \"start\" is also accepted.";
-  static final String QUERY_FROM_VALUES = "range[0, infinity]";
-  static final String DEFAULT_FROM = "0";
-  static final String QUERY_TO = "to";
-  static final String QUERY_TO_DESCRIPTION = "The ending page resource (inclusive).  \"end\" is also accepted.";
-  static final String QUERY_TO_TYPE = "integer";
-  static final String QUERY_TO_VALUES = "range[1, infinity]";
-  static final String QUERY_PREDICATE = "{predicate}";
-  static final String QUERY_PREDICATE_DESCRIPTION = "The predicate to filter resources by. Omitting the predicate will " +
+  public static final String MSG_SUCCESSFUL_OPERATION = "Successful operation";
+  public static final String MSG_REQUEST_ACCEPTED = "Request is accepted, but not completely processed yet";
+  public static final String MSG_INVALID_ARGUMENTS = "Invalid arguments";
+  public static final String MSG_INVALID_REQUEST = "Invalid request";
+  public static final String MSG_CLUSTER_NOT_FOUND = "Cluster not found";
+  public static final String MSG_CLUSTER_OR_HOST_NOT_FOUND = "Cluster or host not found";
+  public static final String MSG_NOT_AUTHENTICATED = "Not authenticated";
+  public static final String MSG_PERMISSION_DENIED = "Not permitted to perform the operation";
+  public static final String MSG_SERVER_ERROR = "Internal server error";
+  public static final String MSG_RESOURCE_ALREADY_EXISTS = "The requested resource already exists.";
+  public static final String MSG_RESOURCE_NOT_FOUND = "The requested resource doesn't exist.";
+
+  public static final String QUERY_FIELDS = "fields";
+  public static final String QUERY_FILTER_DESCRIPTION = "Filter fields in the response (identifier fields are mandatory)";
+  public static final String QUERY_SORT = "sortBy";
+  public static final String QUERY_SORT_DESCRIPTION = "Sort resources in result by (asc | desc)";
+  public static final String QUERY_PAGE_SIZE = "page_size";
+  public static final String QUERY_PAGE_SIZE_DESCRIPTION = "The number of resources to be returned for the paged response.";
+  public static final String DEFAULT_PAGE_SIZE = "10";
+  public static final String QUERY_FROM = "from";
+  public static final String QUERY_FROM_DESCRIPTION = "The starting page resource (inclusive).  \"start\" is also accepted.";
+  public static final String QUERY_FROM_VALUES = "range[0, infinity]";
+  public static final String DEFAULT_FROM = "0";
+  public static final String QUERY_TO = "to";
+  public static final String QUERY_TO_DESCRIPTION = "The ending page resource (inclusive).  \"end\" is also accepted.";
+  public static final String QUERY_TO_TYPE = "integer";
+  public static final String QUERY_TO_VALUES = "range[1, infinity]";
+  public static final String QUERY_PREDICATE = "{predicate}";
+  public static final String QUERY_PREDICATE_DESCRIPTION = "The predicate to filter resources by. Omitting the predicate will " +
       "match all resources.";
 
-  static final String RESPONSE_CONTAINER_LIST = "List";
+  public static final String RESPONSE_CONTAINER_LIST = "List";
 
-  static final String DATA_TYPE_INT = "integer";
-  static final String DATA_TYPE_STRING = "string";
+  public static final String DATA_TYPE_INT = "integer";
+  public static final String DATA_TYPE_STRING = "string";
 
-  static final String PARAM_TYPE_QUERY = "query";
-  static final String PARAM_TYPE_BODY = "body";
+  public static final String PARAM_TYPE_QUERY = "query";
+  public static final String PARAM_TYPE_BODY = "body";
 
-  static final String FIELDS_SEPARATOR = ", ";
+  public static final String FIELDS_SEPARATOR = ", ";
 
   /**
    * Logger instance.

http://git-wip-us.apache.org/repos/asf/ambari/blob/317905e4/ambari-server/src/main/java/org/apache/ambari/server/api/services/users/UserAuthenticationSourceService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/users/UserAuthenticationSourceService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/users/UserAuthenticationSourceService.java
new file mode 100644
index 0000000..8600bbf
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/users/UserAuthenticationSourceService.java
@@ -0,0 +1,223 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.api.services.users;
+
+import static org.apache.ambari.server.controller.internal.UserAuthenticationSourceResourceProvider.AUTHENTICATION_AUTHENTICATION_SOURCE_ID_PROPERTY_ID;
+import static org.apache.ambari.server.controller.internal.UserAuthenticationSourceResourceProvider.AUTHENTICATION_SOURCE_RESOURCE_CATEGORY;
+import static org.apache.ambari.server.controller.internal.UserAuthenticationSourceResourceProvider.AUTHENTICATION_USER_NAME_PROPERTY_ID;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.api.services.BaseService;
+import org.apache.ambari.server.api.services.Request;
+import org.apache.ambari.server.controller.UserAuthenticationSourceResponse;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.HttpStatus;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+/**
+ * Service responsible for user authentication source resource requests.
+ */
+@Path("/users/{userName}/sources")
+@Api(value = "User Authentication Sources", description = "Endpoint for user specific authentication source operations")
+public class UserAuthenticationSourceService extends BaseService {
+
+  private static final String CREATE_REQUEST_TYPE = "org.apache.ambari.server.controller.UserAuthenticationSourceRequestCreateSwagger";
+  private static final String UPDATE_REQUEST_TYPE = "org.apache.ambari.server.controller.UserAuthenticationSourceRequestUpdateSwagger";
+  private static final String AUTHENTICATION_SOURCE_DEFAULT_SORT = AUTHENTICATION_AUTHENTICATION_SOURCE_ID_PROPERTY_ID + ".asc";
+
+  /**
+   * Handles: GET  /users/{userName}/sources
+   * Get all authentication sources for the user.
+   *
+   * @param headers  http headers
+   * @param ui       uri info
+   * @param userName user name
+   * @return user resource instance representation
+   */
+  @GET
+  @Produces("text/plain")
+  @ApiOperation(value = "Get all authentication sources", response = UserAuthenticationSourceResponse.UserAuthenticationSourceResponseSwagger.class, responseContainer = "List")
+  @ApiImplicitParams({
+      @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY, defaultValue = AUTHENTICATION_AUTHENTICATION_SOURCE_ID_PROPERTY_ID + "," + AUTHENTICATION_USER_NAME_PROPERTY_ID),
+      @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY, defaultValue = AUTHENTICATION_SOURCE_DEFAULT_SORT),
+      @ApiImplicitParam(name = QUERY_PAGE_SIZE, value = QUERY_PAGE_SIZE_DESCRIPTION, defaultValue = DEFAULT_PAGE_SIZE, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY),
+      @ApiImplicitParam(name = QUERY_FROM, value = QUERY_FROM_DESCRIPTION, allowableValues = QUERY_FROM_VALUES, defaultValue = DEFAULT_FROM, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY),
+      @ApiImplicitParam(name = QUERY_TO, value = QUERY_TO_DESCRIPTION, allowableValues = QUERY_TO_VALUES, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY),
+  })
+  @ApiResponses({
+      @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+      @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+      @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+      @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
+  })
+  public Response getAuthenticationSources(@Context HttpHeaders headers, @Context UriInfo ui,
+                                           @ApiParam(value = "user name", required = true) @PathParam("userName") String userName) {
+    return handleRequest(headers, null, ui, Request.Type.GET, createResource(userName, null));
+  }
+
+  /**
+   * Handles: GET /users/{userName}/sources/{sourceID}
+   * Get a specific authentication source.
+   *
+   * @param headers  http headers
+   * @param ui       uri info
+   * @param userName user name
+   * @param sourceId authentication source id
+   * @return authentication source instance representation
+   */
+  @GET
+  @Path("{sourceId}")
+  @Produces("text/plain")
+  @ApiOperation(value = "Get user authentication source", response = UserAuthenticationSourceResponse.UserAuthenticationSourceResponseSwagger.class)
+  @ApiImplicitParams({
+      @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY, defaultValue = AUTHENTICATION_SOURCE_RESOURCE_CATEGORY + "/*"),
+  })
+  @ApiResponses({
+      @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+      @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+      @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+      @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
+  })
+  public Response getAuthenticationSource(@Context HttpHeaders headers, @Context UriInfo ui,
+                                          @ApiParam(value = "user name", required = true) @PathParam("userName") String userName,
+                                          @ApiParam(value = "source id", required = true) @PathParam("sourceId") String sourceId) {
+    return handleRequest(headers, null, ui, Request.Type.GET, createResource(userName, sourceId));
+  }
+
+  /**
+   * Creates an authentication source.
+   * Handles: POST /users/{userName}/sources
+   *
+   * @param headers  http headers
+   * @param ui       uri info
+   * @param userName user name
+   * @return information regarding the created user
+   */
+  @POST
+  @Produces("text/plain")
+  @ApiOperation(value = "Create one or more new authentication sources for a user")
+  @ApiImplicitParams({
+      @ApiImplicitParam(dataType = CREATE_REQUEST_TYPE, paramType = PARAM_TYPE_BODY, allowMultiple = true)
+  })
+  @ApiResponses({
+      @ApiResponse(code = HttpStatus.SC_CREATED, message = MSG_SUCCESSFUL_OPERATION),
+      @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED),
+      @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS),
+      @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+      @ApiResponse(code = HttpStatus.SC_CONFLICT, message = MSG_RESOURCE_ALREADY_EXISTS),
+      @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+      @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
+  })
+  public Response createAuthenticationSources(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                              @ApiParam(value = "user name", required = true) @PathParam("userName") String userName) {
+    return handleRequest(headers, body, ui, Request.Type.POST, createResource(userName, null));
+  }
+
+  /**
+   * Creates an authentication source.
+   * Handles: PUT /users/{userName}/sources/{sourceId}
+   *
+   * @param headers  http headers
+   * @param ui       uri info
+   * @param userName user name
+   * @param sourceId authentication source id
+   * @return information regarding the created user
+   */
+  @PUT
+  @Path("{sourceId}")
+  @Produces("text/plain")
+  @ApiOperation(value = "Updates an existing authentication source")
+  @ApiImplicitParams({
+      @ApiImplicitParam(dataType = UPDATE_REQUEST_TYPE, paramType = PARAM_TYPE_BODY)
+  })
+  @ApiResponses({
+      @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED),
+      @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS),
+      @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+      @ApiResponse(code = HttpStatus.SC_CONFLICT, message = MSG_RESOURCE_ALREADY_EXISTS),
+      @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+      @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
+  })
+  public Response updateAuthenticationSource(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                             @ApiParam(value = "user name", required = true) @PathParam("userName") String userName,
+                                             @ApiParam(value = "source id", required = true) @PathParam("sourceId") String sourceId) {
+    return handleRequest(headers, body, ui, Request.Type.PUT, createResource(userName, sourceId));
+  }
+
+  /**
+   * Delete an authentication source.
+   * Handles: DELETE /users/{userName}/sources/{sourceId}
+   *
+   * @param headers  http headers
+   * @param ui       uri info
+   * @param userName user name
+   * @param sourceId authentication source id
+   * @return information regarding the created user
+   */
+  @DELETE
+  @Path("{sourceId}")
+  @Produces("text/plain")
+  @ApiOperation(value = "Deletes an existing authentication source")
+  @ApiResponses({
+      @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+      @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+      @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+      @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
+  })
+  public Response deleteAuthenticationSource(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+                                             @ApiParam(value = "user name", required = true) @PathParam("userName") String userName,
+                                             @ApiParam(value = "source id", required = true) @PathParam("sourceId") String sourceId) {
+    return handleRequest(headers, body, ui, Request.Type.DELETE, createResource(userName, sourceId));
+  }
+
+  protected ResourceInstance createResource(String userName, String sourceId) {
+    final Map<Resource.Type, String> mapIds = new HashMap<>();
+    mapIds.put(Resource.Type.User, StringUtils.lowerCase(userName));
+    mapIds.put(Resource.Type.UserAuthenticationSource, sourceId);
+    return createResource(Resource.Type.UserAuthenticationSource, mapIds);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/317905e4/ambari-server/src/main/java/org/apache/ambari/server/api/services/users/UserService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/users/UserService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/users/UserService.java
index a69ed4e..4eb8587 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/users/UserService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/users/UserService.java
@@ -17,6 +17,9 @@
  */
 package org.apache.ambari.server.api.services.users;
 
+import static org.apache.ambari.server.controller.internal.UserResourceProvider.USER_RESOURCE_CATEGORY;
+import static org.apache.ambari.server.controller.internal.UserResourceProvider.USER_USERNAME_PROPERTY_ID;
+
 import java.util.Collections;
 
 import javax.ws.rs.DELETE;
@@ -31,12 +34,12 @@ import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
-import org.apache.ambari.annotations.ApiIgnore;
 import org.apache.ambari.server.api.resources.ResourceInstance;
 import org.apache.ambari.server.api.services.BaseService;
 import org.apache.ambari.server.api.services.Request;
 import org.apache.ambari.server.controller.UserResponse;
 import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.http.HttpStatus;
 
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
@@ -53,23 +56,32 @@ import io.swagger.annotations.ApiResponses;
 @Api(value = "Users", description = "Endpoint for user specific operations")
 public class UserService extends BaseService {
 
+  private static final String UPDATE_USER_REQUEST_TYPE = "org.apache.ambari.server.controller.UserRequestUpdateUserSwagger";
+  private static final String CREATE_USER_REQUEST_TYPE = "org.apache.ambari.server.controller.UserRequestCreateUserSwagger";
+  private static final String CREATE_USERS_REQUEST_TYPE = "org.apache.ambari.server.controller.UserRequestCreateUsersSwagger";;
+  private static final String USER_DEFAULT_SORT = USER_USERNAME_PROPERTY_ID + ".asc";
+
   /**
    * Gets all users.
    * Handles: GET /users requests.
    */
   @GET
   @Produces("text/plain")
-  @ApiOperation(value = "Get all users", nickname = "UserService#getUsers", notes = "Returns details of all users.", response = UserResponse.class, responseContainer = "List")
+  @ApiOperation(value = "Get all users", response = UserResponse.UserResponseSwagger.class, responseContainer = "List")
   @ApiImplicitParams({
-    @ApiImplicitParam(name = "fields", value = "Filter user details", defaultValue = "Users/*", dataType = "string", paramType = "query"),
-    @ApiImplicitParam(name = "sortBy", value = "Sort users (asc | desc)", defaultValue = "Users/user_name.asc", dataType = "string", paramType = "query"),
-    @ApiImplicitParam(name = "page_size", value = "The number of resources to be returned for the paged response.", defaultValue = "10", dataType = "integer", paramType = "query"),
-    @ApiImplicitParam(name = "from", value = "The starting page resource (inclusive). Valid values are :offset | \"start\"", defaultValue = "0", dataType = "string", paramType = "query"),
-    @ApiImplicitParam(name = "to", value = "The ending page resource (inclusive). Valid values are :offset | \"end\"", dataType = "string", paramType = "query")
+      @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY, defaultValue = USER_USERNAME_PROPERTY_ID),
+      @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY, defaultValue = USER_DEFAULT_SORT),
+      @ApiImplicitParam(name = QUERY_PAGE_SIZE, value = QUERY_PAGE_SIZE_DESCRIPTION, defaultValue = DEFAULT_PAGE_SIZE, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY),
+      @ApiImplicitParam(name = QUERY_FROM, value = QUERY_FROM_DESCRIPTION, allowableValues = QUERY_FROM_VALUES, defaultValue = DEFAULT_FROM, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY),
+      @ApiImplicitParam(name = QUERY_TO, value = QUERY_TO_DESCRIPTION, allowableValues = QUERY_TO_VALUES, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY),
+  })
+  @ApiResponses({
+      @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+      @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+      @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+      @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
   })
-  @ApiResponses(value = {
-    @ApiResponse(code = 200, message = "Successful operation", response = UserResponse.class, responseContainer = "List")}
-  )
   public Response getUsers(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
     return handleRequest(headers, body, ui, Request.Type.GET, createUserResource(null));
   }
@@ -78,23 +90,27 @@ public class UserService extends BaseService {
    * Gets a single user.
    * Handles: GET /users/{username} requests
    *
-   * @param headers     http headers
-   * @param ui          uri info
-   * @param userName    the username
+   * @param headers  http headers
+   * @param ui       uri info
+   * @param userName the username
    * @return information regarding the created user
    */
   @GET
   @Path("{userName}")
   @Produces("text/plain")
-  @ApiOperation(value = "Get single user", nickname = "UserService#getUser", notes = "Returns user details.", response = UserResponse.class)
+  @ApiOperation(value = "Get single user", response = UserResponse.UserResponseSwagger.class)
   @ApiImplicitParams({
-    @ApiImplicitParam(name = "fields", value = "Filter user details", defaultValue = "Users", dataType = "string", paramType = "query")
+      @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY, defaultValue = USER_RESOURCE_CATEGORY + "/*"),
+  })
+  @ApiResponses({
+      @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION),
+      @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+      @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+      @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
   })
-  @ApiResponses(value = {
-    @ApiResponse(code = 200, message = "Successful operation", response = UserResponse.class)}
-  )
   public Response getUser(String body, @Context HttpHeaders headers, @Context UriInfo ui,
-                          @ApiParam(value = "user name", required = true, defaultValue = "admin") @PathParam("userName") String userName) {
+                          @ApiParam(value = "user name", required = true) @PathParam("userName") String userName) {
     return handleRequest(headers, body, ui, Request.Type.GET, createUserResource(userName));
   }
 
@@ -102,13 +118,27 @@ public class UserService extends BaseService {
    * Creates a user.
    * Handles: POST /users
    *
-   * @param headers     http headers
-   * @param ui          uri info
+   * @param headers http headers
+   * @param ui      uri info
    * @return information regarding the created user
    */
-  @POST @ApiIgnore // until documented
+  @POST
   @Produces("text/plain")
-  public Response createUser(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+  @ApiOperation(value = "Creates one or more users in a single request")
+  @ApiImplicitParams({
+      @ApiImplicitParam(dataType = CREATE_USERS_REQUEST_TYPE, paramType = PARAM_TYPE_BODY, allowMultiple = true)
+  })
+  @ApiResponses({
+      @ApiResponse(code = HttpStatus.SC_CREATED, message = MSG_SUCCESSFUL_OPERATION),
+      @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED),
+      @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS),
+      @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+      @ApiResponse(code = HttpStatus.SC_CONFLICT, message = MSG_RESOURCE_ALREADY_EXISTS),
+      @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+      @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
+  })
+  public Response createUsers(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
     return handleRequest(headers, body, ui, Request.Type.POST, createUserResource(null));
   }
 
@@ -116,22 +146,28 @@ public class UserService extends BaseService {
    * Creates a user.
    * Handles: POST /users/{username}
    *
-   * @param headers     http headers
-   * @param ui          uri info
-   * @param userName    the username
+   * @param headers  http headers
+   * @param ui       uri info
+   * @param userName the username
    * @return information regarding the created user
    */
   @POST
   @Path("{userName}")
   @Produces("text/plain")
-  @ApiOperation(value = "Create new user", nickname = "UserService#createUser", notes = "Creates user resource.")
+  @ApiOperation(value = "Create new user")
   @ApiImplicitParams({
-    @ApiImplicitParam(name = "body", value = "input parameters in json form", required = true, dataType = "org.apache.ambari.server.controller.UserRequest", paramType = "body")
+      @ApiImplicitParam(dataType = CREATE_USER_REQUEST_TYPE, paramType = PARAM_TYPE_BODY)
+  })
+  @ApiResponses({
+      @ApiResponse(code = HttpStatus.SC_CREATED, message = MSG_SUCCESSFUL_OPERATION),
+      @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED),
+      @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS),
+      @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+      @ApiResponse(code = HttpStatus.SC_CONFLICT, message = MSG_RESOURCE_ALREADY_EXISTS),
+      @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+      @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
   })
-  @ApiResponses(value = {
-    @ApiResponse(code = 200, message = "Successful operation"),
-    @ApiResponse(code = 500, message = "Server Error")}
-  )
   public Response createUser(String body, @Context HttpHeaders headers, @Context UriInfo ui,
                              @ApiParam(value = "user name", required = true) @PathParam("userName") String userName) {
     return handleRequest(headers, body, ui, Request.Type.POST, createUserResource(userName));
@@ -141,22 +177,27 @@ public class UserService extends BaseService {
    * Updates a specific user.
    * Handles: PUT /users/{userName}
    *
-   * @param headers     http headers
-   * @param ui          uri info
-   * @param userName   the username
+   * @param headers  http headers
+   * @param ui       uri info
+   * @param userName the username
    * @return information regarding the updated user
    */
   @PUT
   @Path("{userName}")
   @Produces("text/plain")
-  @ApiOperation(value = "Update user detail", nickname = "UserService#updateUser", notes = "Updates user resource.")
+  @ApiOperation(value = "Update user details")
   @ApiImplicitParams({
-    @ApiImplicitParam(name = "body", value = "input parameters in json form", required = true, dataType = "org.apache.ambari.server.controller.UserRequest", paramType = "body")
+      @ApiImplicitParam(dataType = UPDATE_USER_REQUEST_TYPE, paramType = PARAM_TYPE_BODY)
+  })
+  @ApiResponses({
+      @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED),
+      @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS),
+      @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND),
+      @ApiResponse(code = HttpStatus.SC_CONFLICT, message = MSG_RESOURCE_ALREADY_EXISTS),
+      @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED),
+      @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED),
+      @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR),
   })
-  @ApiResponses(value = {
-    @ApiResponse(code = 200, message = "Successful operation"),
-    @ApiResponse(code = 500, message = "Server Error")}
-  )
   public Response updateUser(String body, @Context HttpHeaders headers, @Context UriInfo ui,
                              @ApiParam(value = "user name", required = true) @PathParam("userName") String userName) {
 
@@ -170,10 +211,10 @@ public class UserService extends BaseService {
   @DELETE
   @Path("{userName}")
   @Produces("text/plain")
-  @ApiOperation(value = "Delete single user", nickname = "UserService#deleteUser", notes = "Delete user resource.")
+  @ApiOperation(value = "Delete single user")
   @ApiResponses(value = {
-    @ApiResponse(code = 200, message = "Successful operation"),
-    @ApiResponse(code = 500, message = "Server Error")}
+      @ApiResponse(code = 200, message = "Successful operation"),
+      @ApiResponse(code = 500, message = "Server Error")}
   )
   public Response deleteUser(@Context HttpHeaders headers, @Context UriInfo ui,
                              @ApiParam(value = "user name", required = true) @PathParam("userName") String userName) {
@@ -183,8 +224,7 @@ public class UserService extends BaseService {
   /**
    * Create a user resource instance.
    *
-   * @param userName  user name
-   *
+   * @param userName user name
    * @return a user resource instance
    */
   private ResourceInstance createUserResource(String userName) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/317905e4/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index 25d12c7..f2fba6c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -72,6 +72,7 @@ import org.apache.ambari.server.controller.internal.MemberResourceProvider;
 import org.apache.ambari.server.controller.internal.RepositoryVersionResourceProvider;
 import org.apache.ambari.server.controller.internal.ServiceResourceProvider;
 import org.apache.ambari.server.controller.internal.UpgradeResourceProvider;
+import org.apache.ambari.server.controller.internal.UserAuthenticationSourceResourceProvider;
 import org.apache.ambari.server.controller.internal.UserResourceProvider;
 import org.apache.ambari.server.controller.logging.LoggingRequestHelperFactory;
 import org.apache.ambari.server.controller.logging.LoggingRequestHelperFactoryImpl;
@@ -466,6 +467,7 @@ public class ControllerModule extends AbstractModule {
         .implement(ResourceProvider.class, Names.named("repositoryVersion"), RepositoryVersionResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("hostKerberosIdentity"), HostKerberosIdentityResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("user"), UserResourceProvider.class)
+        .implement(ResourceProvider.class, Names.named("userAuthenticationSource"), UserAuthenticationSourceResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("credential"), CredentialResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("kerberosDescriptor"), KerberosDescriptorResourceProvider.class)
         .implement(ResourceProvider.class, Names.named("upgrade"), UpgradeResourceProvider.class)

http://git-wip-us.apache.org/repos/asf/ambari/blob/317905e4/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
index 2454bf7..d5bebf0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java
@@ -52,9 +52,10 @@ public interface ResourceProviderFactory {
       AmbariManagementController managementController);
 
   @Named("user")
-  ResourceProvider getUserResourceProvider(Set<String> propertyIds,
-                                           Map<Type, String> keyPropertyIds,
-                                           AmbariManagementController managementController);
+  ResourceProvider getUserResourceProvider(AmbariManagementController managementController);
+
+  @Named("userAuthenticationSource")
+  ResourceProvider getUserAuthenticationSourceResourceProvider();
 
   @Named("hostKerberosIdentity")
   ResourceProvider getHostKerberosIdentityResourceProvider(AmbariManagementController managementController);

http://git-wip-us.apache.org/repos/asf/ambari/blob/317905e4/ambari-server/src/main/java/org/apache/ambari/server/controller/UserAuthenticationSourceRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/UserAuthenticationSourceRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserAuthenticationSourceRequest.java
new file mode 100644
index 0000000..17297be
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserAuthenticationSourceRequest.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.controller;
+
+import org.apache.ambari.server.controller.internal.UserAuthenticationSourceResourceProvider;
+import org.apache.ambari.server.security.authorization.UserAuthenticationType;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * Represents a user authentication source request.
+ */
+@ApiModel
+public class UserAuthenticationSourceRequest {
+  private final String username;
+  private final Long sourceId;
+  private final UserAuthenticationType authenticationType;
+  private final String key;
+  private final String oldKey;
+
+  public UserAuthenticationSourceRequest(String username, Long sourceId) {
+    this(username, sourceId, null, null);
+
+  }
+
+  public UserAuthenticationSourceRequest(String username, Long sourceId, UserAuthenticationType authenticationType) {
+    this(username, sourceId, authenticationType, null);
+  }
+
+  public UserAuthenticationSourceRequest(String username, Long sourceId, UserAuthenticationType authenticationType, String key) {
+    this(username, sourceId, authenticationType, key, null);
+  }
+
+  public UserAuthenticationSourceRequest(String username, Long sourceId, UserAuthenticationType authenticationType, String key, String oldKey) {
+    this.username = username;
+    this.sourceId = sourceId;
+    this.authenticationType = authenticationType;
+    this.key = key;
+    this.oldKey = oldKey;
+  }
+
+  @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.USER_NAME_PROPERTY_ID, hidden = true)
+  public String getUsername() {
+    return username;
+  }
+
+  @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.AUTHENTICATION_SOURCE_ID_PROPERTY_ID)
+  public Long getSourceId() {
+    return sourceId;
+  }
+
+  @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.AUTHENTICATION_TYPE_PROPERTY_ID)
+  public UserAuthenticationType getAuthenticationType() {
+    return authenticationType;
+  }
+
+  @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.KEY_PROPERTY_ID)
+  public String getKey() {
+    return key;
+  }
+
+  @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.OLD_KEY_PROPERTY_ID)
+  public String getOldKey() {
+    return oldKey;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/317905e4/ambari-server/src/main/java/org/apache/ambari/server/controller/UserAuthenticationSourceRequestCreateSwagger.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/UserAuthenticationSourceRequestCreateSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserAuthenticationSourceRequestCreateSwagger.java
new file mode 100644
index 0000000..72f010a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserAuthenticationSourceRequestCreateSwagger.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.controller;
+
+import org.apache.ambari.server.controller.internal.UserAuthenticationSourceResourceProvider;
+import org.apache.ambari.server.security.authorization.UserAuthenticationType;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * Interface to help correct Swagger documentation generation
+ */
+public interface UserAuthenticationSourceRequestCreateSwagger extends ApiModel {
+  @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.AUTHENTICATION_SOURCE_RESOURCE_CATEGORY)
+  CreateUserAuthenticationSourceInfo getCreateUserAuthenticationSourceRequest();
+
+  interface CreateUserAuthenticationSourceInfo {
+    @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.AUTHENTICATION_TYPE_PROPERTY_ID, required = true)
+    public UserAuthenticationType getAuthenticationType();
+
+    @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.KEY_PROPERTY_ID, required = true)
+    public String getKey();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/317905e4/ambari-server/src/main/java/org/apache/ambari/server/controller/UserAuthenticationSourceRequestUpdateSwagger.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/UserAuthenticationSourceRequestUpdateSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserAuthenticationSourceRequestUpdateSwagger.java
new file mode 100644
index 0000000..3e1aa8c
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserAuthenticationSourceRequestUpdateSwagger.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.controller;
+
+import org.apache.ambari.server.controller.internal.UserAuthenticationSourceResourceProvider;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * Interface to help correct Swagger documentation generation
+ */
+public interface UserAuthenticationSourceRequestUpdateSwagger extends ApiModel {
+  @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.AUTHENTICATION_SOURCE_RESOURCE_CATEGORY)
+  UserAuthenticationSourceRequestUpdateInfo getUpdateUserAuthenticationSourceRequest();
+
+  interface UserAuthenticationSourceRequestUpdateInfo {
+
+    @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.KEY_PROPERTY_ID, required = true)
+    public String getKey();
+
+    @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.OLD_KEY_PROPERTY_ID, required = false)
+    public String getOldKey();
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/317905e4/ambari-server/src/main/java/org/apache/ambari/server/controller/UserAuthenticationSourceResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/UserAuthenticationSourceResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserAuthenticationSourceResponse.java
new file mode 100644
index 0000000..6717ad6
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserAuthenticationSourceResponse.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.controller;
+
+import java.util.Date;
+
+import org.apache.ambari.server.controller.internal.UserAuthenticationSourceResourceProvider;
+import org.apache.ambari.server.security.authorization.UserAuthenticationType;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * Represents a user authentication source.
+ */
+public class UserAuthenticationSourceResponse implements ApiModel {
+
+  private final String userName;
+  private final Long sourceId;
+  private final UserAuthenticationType authenticationType;
+  private final String key;
+
+  private final Date createTime;
+  private final Date updateTime;
+
+  public UserAuthenticationSourceResponse(String userName, Long sourceId, UserAuthenticationType authenticationType, String key, Date createTime, Date updateTime) {
+    this.userName = userName;
+    this.sourceId = sourceId;
+    this.authenticationType = authenticationType;
+    this.key = key;
+    this.createTime = createTime;
+    this.updateTime = updateTime;
+  }
+
+  /**
+   * Returns user name
+   *
+   * @return user name
+   */
+  @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.USER_NAME_PROPERTY_ID, required = true)
+  public String getUserName() {
+    return userName;
+  }
+
+
+  @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.AUTHENTICATION_SOURCE_ID_PROPERTY_ID, required = true)
+  public Long getSourceId() {
+    return sourceId;
+  }
+
+  @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.AUTHENTICATION_TYPE_PROPERTY_ID, required = true)
+  public UserAuthenticationType getAuthenticationType() {
+    return authenticationType;
+  }
+
+  @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.KEY_PROPERTY_ID)
+  public String getKey() {
+    return key;
+  }
+
+  @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.CREATED_PROPERTY_ID)
+  public Date getCreateTime() {
+    return createTime;
+  }
+
+  @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.UPDATED_PROPERTY_ID)
+  public Date getUpdateTime() {
+    return updateTime;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    } else if (o == null || getClass() != o.getClass()) {
+      return false;
+    } else {
+      UserAuthenticationSourceResponse that = (UserAuthenticationSourceResponse) o;
+
+      EqualsBuilder equalsBuilder = new EqualsBuilder();
+      equalsBuilder.append(userName, that.userName);
+      equalsBuilder.append(sourceId, that.sourceId);
+      equalsBuilder.append(authenticationType, that.authenticationType);
+      equalsBuilder.append(key, that.key);
+      equalsBuilder.append(createTime, that.createTime);
+      equalsBuilder.append(updateTime, that.updateTime);
+      return equalsBuilder.isEquals();
+    }
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder hashCodeBuilder = new HashCodeBuilder();
+    hashCodeBuilder.append(userName);
+    hashCodeBuilder.append(sourceId);
+    hashCodeBuilder.append(authenticationType);
+    hashCodeBuilder.append(key);
+    hashCodeBuilder.append(createTime);
+    hashCodeBuilder.append(updateTime);
+    return hashCodeBuilder.toHashCode();
+  }
+
+  /**
+   * Interface to help correct Swagger documentation generation
+   */
+  public interface UserAuthenticationSourceResponseSwagger {
+    @ApiModelProperty(name = UserAuthenticationSourceResourceProvider.AUTHENTICATION_SOURCE_RESOURCE_CATEGORY)
+    @SuppressWarnings("unused")
+    UserAuthenticationSourceResponse getUserAuthenticationSourceResponse();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/317905e4/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequest.java
index 3011d01..d0836a9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequest.java
@@ -17,6 +17,8 @@
  */
 package org.apache.ambari.server.controller;
 
+import org.apache.ambari.server.controller.internal.UserResourceProvider;
+
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
@@ -38,12 +40,12 @@ public class UserRequest {
     this.userName = name;
   }
 
-  @ApiModelProperty(name = "Users/user_name",hidden = true)
+  @ApiModelProperty(name = UserResourceProvider.USERNAME_PROPERTY_ID)
   public String getUsername() {
     return userName;
   }
 
-  @ApiModelProperty(name = "Users/password")
+  @ApiModelProperty(name = UserResourceProvider.PASSWORD_PROPERTY_ID)
   public String getPassword() {
     return password;
   }
@@ -52,7 +54,7 @@ public class UserRequest {
     password = userPass;
   }
 
-  @ApiModelProperty(name = "Users/old_password")
+  @ApiModelProperty(name = UserResourceProvider.OLD_PASSWORD_PROPERTY_ID)
   public String getOldPassword() {
     return oldPassword;
   }
@@ -61,7 +63,7 @@ public class UserRequest {
     oldPassword = oldUserPass;
   }
 
-  @ApiModelProperty(name = "Users/active")
+  @ApiModelProperty(name = UserResourceProvider.ACTIVE_PROPERTY_ID)
   public Boolean isActive() {
     return active;
   }
@@ -70,7 +72,7 @@ public class UserRequest {
     this.active = active;
   }
 
-  @ApiModelProperty(name = "Users/admin")
+  @ApiModelProperty(name = UserResourceProvider.ADMIN_PROPERTY_ID)
   public Boolean isAdmin() {
     return admin;
   }
@@ -79,7 +81,7 @@ public class UserRequest {
     this.admin = admin;
   }
 
-  @ApiModelProperty(name = "Users/display_name")
+  @ApiModelProperty(name = UserResourceProvider.DISPLAY_NAME_PROPERTY_ID)
   public String getDisplayName() {
     return displayName;
   }
@@ -88,7 +90,7 @@ public class UserRequest {
     this.displayName = displayName;
   }
 
-  @ApiModelProperty(name = "Users/local_user_name")
+  @ApiModelProperty(name = UserResourceProvider.LOCAL_USERNAME_PROPERTY_ID)
   public String getLocalUserName() {
     return localUserName;
   }
@@ -103,5 +105,4 @@ public class UserRequest {
     sb.append("User, username=").append(userName);
     return sb.toString();
   }
-
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/317905e4/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequestCreateUserSwagger.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequestCreateUserSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequestCreateUserSwagger.java
new file mode 100644
index 0000000..44b6410
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequestCreateUserSwagger.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.controller;
+
+import org.apache.ambari.server.controller.internal.UserResourceProvider;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * Interface to help correct Swagger documentation generation
+ */
+public interface UserRequestCreateUserSwagger extends ApiModel {
+
+  @ApiModelProperty(name = UserResourceProvider.USER_RESOURCE_CATEGORY)
+  CreateUserInfo getCreateUserRequest();
+
+  interface CreateUserInfo {
+    @ApiModelProperty(name = UserResourceProvider.PASSWORD_PROPERTY_ID)
+    String getPassword();
+
+    @ApiModelProperty(name = UserResourceProvider.ACTIVE_PROPERTY_ID)
+    Boolean isActive();
+
+    @ApiModelProperty(name = UserResourceProvider.ADMIN_PROPERTY_ID)
+    Boolean isAdmin();
+
+    @ApiModelProperty(name = UserResourceProvider.DISPLAY_NAME_PROPERTY_ID)
+    String getDisplayName();
+
+    @ApiModelProperty(name = UserResourceProvider.LOCAL_USERNAME_PROPERTY_ID)
+    String getLocalUserName();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/317905e4/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequestCreateUsersSwagger.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequestCreateUsersSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequestCreateUsersSwagger.java
new file mode 100644
index 0000000..f26ae14
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequestCreateUsersSwagger.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.controller;
+
+import org.apache.ambari.server.controller.internal.UserResourceProvider;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * Interface to help correct Swagger documentation generation
+ */
+public interface UserRequestCreateUsersSwagger extends ApiModel {
+
+  @ApiModelProperty(name = UserResourceProvider.USER_RESOURCE_CATEGORY)
+  CreateUsersInfo getCreateUsersRequest();
+
+  interface CreateUsersInfo {
+    @ApiModelProperty(name = UserResourceProvider.USERNAME_PROPERTY_ID )
+    String getUsername();
+
+    @ApiModelProperty(name = UserResourceProvider.PASSWORD_PROPERTY_ID)
+    String getPassword();
+
+    @ApiModelProperty(name = UserResourceProvider.ACTIVE_PROPERTY_ID)
+    Boolean isActive();
+
+    @ApiModelProperty(name = UserResourceProvider.ADMIN_PROPERTY_ID)
+    Boolean isAdmin();
+
+    @ApiModelProperty(name = UserResourceProvider.DISPLAY_NAME_PROPERTY_ID)
+    String getDisplayName();
+
+    @ApiModelProperty(name = UserResourceProvider.LOCAL_USERNAME_PROPERTY_ID)
+    String getLocalUserName();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/317905e4/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequestUpdateUserSwagger.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequestUpdateUserSwagger.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequestUpdateUserSwagger.java
new file mode 100644
index 0000000..f2b2d84
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserRequestUpdateUserSwagger.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.controller;
+
+import org.apache.ambari.server.controller.internal.UserResourceProvider;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * Interface to help correct Swagger documentation generation
+ */
+public interface UserRequestUpdateUserSwagger extends ApiModel {
+
+  @ApiModelProperty(name = UserResourceProvider.USER_RESOURCE_CATEGORY)
+  UpdateUserInfo getUpdateUserRequest();
+
+  interface UpdateUserInfo {
+    @ApiModelProperty(name = UserResourceProvider.OLD_PASSWORD_PROPERTY_ID)
+    String getOldPassword();
+
+    @ApiModelProperty(name = UserResourceProvider.PASSWORD_PROPERTY_ID)
+    String getPassword();
+
+    @ApiModelProperty(name = UserResourceProvider.ACTIVE_PROPERTY_ID)
+    Boolean isActive();
+
+    @ApiModelProperty(name = UserResourceProvider.ADMIN_PROPERTY_ID)
+    Boolean isAdmin();
+
+    @ApiModelProperty(name = UserResourceProvider.DISPLAY_NAME_PROPERTY_ID)
+    String getDisplayName();
+
+    @ApiModelProperty(name = UserResourceProvider.LOCAL_USERNAME_PROPERTY_ID)
+    String getLocalUserName();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/317905e4/ambari-server/src/main/java/org/apache/ambari/server/controller/UserResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/UserResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserResponse.java
index bcb3aaf..6204aac 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/UserResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/UserResponse.java
@@ -18,8 +18,10 @@
 package org.apache.ambari.server.controller;
 
 import java.util.Collections;
+import java.util.Date;
 import java.util.Set;
 
+import org.apache.ambari.server.controller.internal.UserResourceProvider;
 import org.apache.ambari.server.security.authorization.UserAuthenticationType;
 
 import io.swagger.annotations.ApiModelProperty;
@@ -27,38 +29,48 @@ import io.swagger.annotations.ApiModelProperty;
 /**
  * Represents a user maintenance request.
  */
-public class
-UserResponse implements ApiModel {
+public class UserResponse implements ApiModel {
 
   private final String userName;
+  private final String displayName;
+  private final String localUserName;
   private final UserAuthenticationType authenticationType;
   private final boolean isLdapUser;
   private final boolean isActive;
   private final boolean isAdmin;
   private Set<String> groups = Collections.emptySet();
 
-  public UserResponse(String userName, UserAuthenticationType userType, boolean isLdapUser, boolean isActive, boolean isAdmin) {
+  private final Date createTime;
+  private final Integer consecutiveFailures;
+
+  public UserResponse(String userName, String displayName, String localUserName, UserAuthenticationType userType, boolean isLdapUser, boolean isActive, boolean isAdmin, Integer consecutiveFailures, Date createTime) {
     this.userName = userName;
+    this.displayName = displayName;
+    this.localUserName = localUserName;
     this.authenticationType = userType;
     this.isLdapUser = isLdapUser;
     this.isActive = isActive;
     this.isAdmin = isAdmin;
+    this.consecutiveFailures = consecutiveFailures;
+    this.createTime = createTime;
   }
 
-  public UserResponse(String name, boolean isLdapUser, boolean isActive, boolean isAdmin) {
-    this.userName = name;
-    this.isLdapUser = isLdapUser;
-    this.isActive = isActive;
-    this.isAdmin = isAdmin;
-    this.authenticationType = UserAuthenticationType.LOCAL;
-  }
-
-  @ApiModelProperty(name = "Users/user_name",required = true)
+  @ApiModelProperty(name = UserResourceProvider.USERNAME_PROPERTY_ID)
   public String getUsername() {
     return userName;
   }
 
-  @ApiModelProperty(name = "Users/groups")
+  @ApiModelProperty(name = UserResourceProvider.DISPLAY_NAME_PROPERTY_ID)
+  public String getDisplayName() {
+    return displayName;
+  }
+
+  @ApiModelProperty(name = UserResourceProvider.LOCAL_USERNAME_PROPERTY_ID)
+  public String getLocalUsername() {
+    return localUserName;
+  }
+
+  @ApiModelProperty(name = UserResourceProvider.GROUPS_PROPERTY_ID)
   public Set<String> getGroups() {
     return groups;
   }
@@ -70,34 +82,50 @@ UserResponse implements ApiModel {
   /**
    * @return the isLdapUser
    */
-  @ApiModelProperty(name = "Users/ldap_user")
+  @ApiModelProperty(name = UserResourceProvider.LDAP_USER_PROPERTY_ID)
   public boolean isLdapUser() {
     return isLdapUser;
   }
 
-  @ApiModelProperty(name = "Users/active")
+  @ApiModelProperty(name = UserResourceProvider.ACTIVE_PROPERTY_ID)
   public boolean isActive() {
     return isActive;
   }
 
-  @ApiModelProperty(name = "Users/admin")
+  @ApiModelProperty(name = UserResourceProvider.ADMIN_PROPERTY_ID)
   public boolean isAdmin() {
     return isAdmin;
   }
 
-  @ApiModelProperty(name = "Users/authentication_type")
+  @ApiModelProperty(name = UserResourceProvider.USER_TYPE_PROPERTY_ID)
   public UserAuthenticationType getAuthenticationType() {
     return authenticationType;
   }
 
+  @ApiModelProperty(name = UserResourceProvider.CONSECUTIVE_FAILURES_PROPERTY_ID)
+  public Integer getConsecutiveFailures() {
+    return consecutiveFailures;
+  }
+
+  @ApiModelProperty(name = UserResourceProvider.CREATE_TIME_PROPERTY_ID)
+  public Date getCreateTime() {
+    return createTime;
+  }
+
   @Override
   public boolean equals(Object o) {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
 
     UserResponse that = (UserResponse) o;
 
-    if (userName != null ? !userName.equals(that.userName) : that.userName != null) return false;
+    if (userName != null ? !userName.equals(that.userName) : that.userName != null) {
+      return false;
+    }
     return authenticationType == that.authenticationType;
 
   }
@@ -108,4 +136,12 @@ UserResponse implements ApiModel {
     result = 31 * result + (authenticationType != null ? authenticationType.hashCode() : 0);
     return result;
   }
+
+  /**
+   * Interface to help correct Swagger documentation generation
+   */
+  public interface UserResponseSwagger {
+    @ApiModelProperty(name = UserResourceProvider.USER_RESOURCE_CATEGORY)
+    UserResponse getUserResponse();
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/317905e4/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
index 595b7f9..af2c0e8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
@@ -171,7 +171,9 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori
       case Task:
         return new TaskResourceProvider(propertyIds, keyPropertyIds, managementController);
       case User:
-        return resourceProviderFactory.getUserResourceProvider(propertyIds, keyPropertyIds, managementController);
+        return resourceProviderFactory.getUserResourceProvider(managementController);
+      case UserAuthenticationSource:
+        return resourceProviderFactory.getUserAuthenticationSourceResourceProvider();
       case Group:
         return new GroupResourceProvider(propertyIds, keyPropertyIds, managementController);
       case Member:

http://git-wip-us.apache.org/repos/asf/ambari/blob/317905e4/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProvider.java
new file mode 100644
index 0000000..6a5f528
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UserAuthenticationSourceResourceProvider.java
@@ -0,0 +1,417 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.controller.internal;
+
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.PrivilegeResponse;
+import org.apache.ambari.server.controller.UserAuthenticationSourceRequest;
+import org.apache.ambari.server.controller.UserAuthenticationSourceResponse;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+import org.apache.ambari.server.orm.entities.UserAuthenticationEntity;
+import org.apache.ambari.server.orm.entities.UserEntity;
+import org.apache.ambari.server.security.authorization.AuthorizationException;
+import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.security.authorization.ResourceType;
+import org.apache.ambari.server.security.authorization.RoleAuthorization;
+import org.apache.ambari.server.security.authorization.UserAuthenticationType;
+import org.apache.ambari.server.security.authorization.Users;
+import org.apache.commons.lang.StringUtils;
+import org.apache.velocity.exception.ResourceNotFoundException;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Inject;
+
+/**
+ * Resource provider for user authentication source resources.
+ */
+public class UserAuthenticationSourceResourceProvider extends AbstractAuthorizedResourceProvider {
+
+  public static final String AUTHENTICATION_SOURCE_RESOURCE_CATEGORY = "AuthenticationSourceInfo";
+
+  public static final String AUTHENTICATION_SOURCE_ID_PROPERTY_ID = "source_id";
+  public static final String USER_NAME_PROPERTY_ID = "user_name";
+  public static final String AUTHENTICATION_TYPE_PROPERTY_ID = "authentication_type";
+  public static final String KEY_PROPERTY_ID = "key";
+  public static final String OLD_KEY_PROPERTY_ID = "old_key";
+  public static final String CREATED_PROPERTY_ID = "created";
+  public static final String UPDATED_PROPERTY_ID = "updated";
+
+  public static final String AUTHENTICATION_AUTHENTICATION_SOURCE_ID_PROPERTY_ID = AUTHENTICATION_SOURCE_RESOURCE_CATEGORY + "/" + AUTHENTICATION_SOURCE_ID_PROPERTY_ID;
+  public static final String AUTHENTICATION_USER_NAME_PROPERTY_ID = AUTHENTICATION_SOURCE_RESOURCE_CATEGORY + "/" + USER_NAME_PROPERTY_ID;
+  public static final String AUTHENTICATION_AUTHENTICATION_TYPE_PROPERTY_ID = AUTHENTICATION_SOURCE_RESOURCE_CATEGORY + "/" + AUTHENTICATION_TYPE_PROPERTY_ID;
+  public static final String AUTHENTICATION_KEY_PROPERTY_ID = AUTHENTICATION_SOURCE_RESOURCE_CATEGORY + "/" + KEY_PROPERTY_ID;
+  public static final String AUTHENTICATION_OLD_KEY_PROPERTY_ID = AUTHENTICATION_SOURCE_RESOURCE_CATEGORY + "/" + OLD_KEY_PROPERTY_ID;
+  public static final String AUTHENTICATION_CREATED_PROPERTY_ID = AUTHENTICATION_SOURCE_RESOURCE_CATEGORY + "/" + CREATED_PROPERTY_ID;
+  public static final String AUTHENTICATION_UPDATED_PROPERTY_ID = AUTHENTICATION_SOURCE_RESOURCE_CATEGORY + "/" + UPDATED_PROPERTY_ID;
+
+  private static final Set<String> PK_PROPERTY_IDS = ImmutableSet.of(
+      AUTHENTICATION_AUTHENTICATION_SOURCE_ID_PROPERTY_ID
+  );
+  private static final Set<String> PROPERTY_IDS = ImmutableSet.of(
+      AUTHENTICATION_AUTHENTICATION_SOURCE_ID_PROPERTY_ID,
+      AUTHENTICATION_USER_NAME_PROPERTY_ID,
+      AUTHENTICATION_AUTHENTICATION_TYPE_PROPERTY_ID,
+      AUTHENTICATION_KEY_PROPERTY_ID,
+      AUTHENTICATION_OLD_KEY_PROPERTY_ID,
+      AUTHENTICATION_CREATED_PROPERTY_ID,
+      AUTHENTICATION_UPDATED_PROPERTY_ID
+  );
+  private static final Map<Resource.Type, String> KEY_PROPERTY_IDS = ImmutableMap.of(
+      Resource.Type.User, AUTHENTICATION_USER_NAME_PROPERTY_ID,
+      Resource.Type.UserAuthenticationSource, AUTHENTICATION_AUTHENTICATION_SOURCE_ID_PROPERTY_ID
+  );
+
+  @Inject
+  private Users users;
+
+  /**
+   * Constructor.
+   */
+  public UserAuthenticationSourceResourceProvider() {
+    super(Resource.Type.UserAuthenticationSource, PROPERTY_IDS, KEY_PROPERTY_IDS);
+
+    EnumSet<RoleAuthorization> requiredAuthorizations = EnumSet.of(RoleAuthorization.AMBARI_MANAGE_USERS);
+    setRequiredCreateAuthorizations(requiredAuthorizations);
+    setRequiredDeleteAuthorizations(requiredAuthorizations);
+    setRequiredGetAuthorizations(requiredAuthorizations);
+    setRequiredUpdateAuthorizations(requiredAuthorizations);
+  }
+
+  // ----- PrivilegeResourceProvider -----------------------------------------
+
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return PK_PROPERTY_IDS;
+  }
+
+  @Override
+  public RequestStatus createResourcesAuthorized(Request request)
+      throws SystemException, UnsupportedPropertyException, ResourceAlreadyExistsException, NoSuchParentResourceException {
+    final Set<UserAuthenticationSourceRequest> requests = new HashSet<>();
+    for (Map<String, Object> propertyMap : request.getProperties()) {
+      requests.add(getRequest(propertyMap));
+    }
+
+    createResources(new Command<Void>() {
+      @Override
+      public Void invoke() throws AmbariException {
+        createUserAuthenticationSources(requests);
+        return null;
+      }
+    });
+
+    return getRequestStatus(null);
+  }
+
+  @Override
+  public Set<Resource> getResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+
+    final Set<UserAuthenticationSourceRequest> requests = new HashSet<>();
+    if (predicate == null) {
+      requests.add(getRequest(null));
+    } else {
+      for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+        requests.add(getRequest(propertyMap));
+      }
+    }
+
+    Set<UserAuthenticationSourceResponse> responses = getResources(new Command<Set<UserAuthenticationSourceResponse>>() {
+      @Override
+      public Set<UserAuthenticationSourceResponse> invoke() throws AmbariException, AuthorizationException {
+        return getUserAuthenticationSources(requests);
+      }
+    });
+
+    Set<String> requestedIds = getRequestPropertyIds(request, predicate);
+    Set<Resource> resources = new HashSet<>();
+
+    for (UserAuthenticationSourceResponse response : responses) {
+      resources.add(toResource(response, requestedIds));
+    }
+
+    return resources;
+  }
+
+  @Override
+  public RequestStatus updateResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    final Set<UserAuthenticationSourceRequest> requests = new HashSet<>();
+
+    for (Map<String, Object> propertyMap : getPropertyMaps(request.getProperties().iterator().next(), predicate)) {
+      requests.add(getRequest(propertyMap));
+    }
+
+    modifyResources(new Command<Void>() {
+      @Override
+      public Void invoke() throws AmbariException, AuthorizationException {
+        updateUserAuthenticationSources(requests);
+        return null;
+      }
+    });
+
+    return getRequestStatus(null);
+  }
+
+  @Override
+  public RequestStatus deleteResourcesAuthorized(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException {
+    final Set<UserAuthenticationSourceRequest> requests = new HashSet<>();
+
+    for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+      requests.add(getRequest(propertyMap));
+    }
+
+    modifyResources(new Command<Void>() {
+      @Override
+      public Void invoke() throws AmbariException, AuthorizationException {
+        deleteUserAuthenticationSources(requests);
+        return null;
+      }
+    });
+
+    return getRequestStatus(null);
+  }
+
+  private UserAuthenticationSourceRequest getRequest(Map<String, Object> properties) {
+    String username;
+    Long sourceId;
+    UserAuthenticationType authenticationType;
+    String key;
+    String oldKey;
+
+    if (properties == null) {
+      username = null;
+      sourceId = null;
+      authenticationType = null;
+      key = null;
+      oldKey = null;
+    } else {
+      String tmp;
+
+      username = (String) properties.get(AUTHENTICATION_USER_NAME_PROPERTY_ID);
+      key = (String) properties.get(AUTHENTICATION_KEY_PROPERTY_ID);
+      oldKey = (String) properties.get(AUTHENTICATION_OLD_KEY_PROPERTY_ID);
+
+      tmp = (String) properties.get(AUTHENTICATION_AUTHENTICATION_SOURCE_ID_PROPERTY_ID);
+
+      if (StringUtils.isEmpty(tmp)) {
+        sourceId = null;
+      } else {
+        sourceId = Long.parseLong(tmp);
+      }
+
+      tmp = (String) properties.get(AUTHENTICATION_AUTHENTICATION_TYPE_PROPERTY_ID);
+      if (StringUtils.isEmpty(tmp)) {
+        authenticationType = null;
+      } else {
+        authenticationType = UserAuthenticationType.valueOf(tmp.trim().toUpperCase());
+      }
+    }
+
+    return new UserAuthenticationSourceRequest(username, sourceId, authenticationType, key, oldKey);
+  }
+
+  /**
+   * Creates user authentication sources.
+   *
+   * @param requests the request objects which define the user authentication source.
+   * @throws AmbariException when the user authentication source cannot be created.
+   */
+  private void createUserAuthenticationSources(Set<UserAuthenticationSourceRequest> requests) throws AmbariException {
+    for (UserAuthenticationSourceRequest request : requests) {
+      String username = request.getUsername();
+      if (StringUtils.isEmpty(username)) {
+        throw new AmbariException("Username must be supplied.");
+      }
+
+      UserAuthenticationType authenticationType = request.getAuthenticationType();
+      if (authenticationType == null) {
+        throw new AmbariException("A value authentication type must be supplied.");
+      }
+
+      UserEntity userEntity = users.getUserEntity(username);
+      if (userEntity == null) {
+        throw new AmbariException("There is no user with the supplied username");
+      }
+
+      users.addAuthentication(userEntity, authenticationType, request.getKey());
+    }
+  }
+
+  /**
+   * Gets the users authentication sources identified by the given request objects.
+   *
+   * @param requests the request objects
+   * @return a set of user responses
+   * @throws AmbariException if the user authentication sources could not be read
+   */
+  private Set<UserAuthenticationSourceResponse> getUserAuthenticationSources(Set<UserAuthenticationSourceRequest> requests)
+      throws AmbariException, AuthorizationException {
+
+    Set<UserAuthenticationSourceResponse> responses = new HashSet<>();
+
+    for (UserAuthenticationSourceRequest request : requests) {
+
+      String requestedUsername = request.getUsername();
+      String authenticatedUsername = AuthorizationHelper.getAuthenticatedName();
+
+      // A user authentication source resource may be retrieved by an administrator or the same user.
+      if (!AuthorizationHelper.isAuthorized(ResourceType.AMBARI, null, RoleAuthorization.AMBARI_MANAGE_USERS)) {
+        if (null == requestedUsername) {
+          // Since the authenticated user is not the administrator, force only that user's resource
+          // to be returned
+          requestedUsername = authenticatedUsername;
+        } else if (!requestedUsername.equalsIgnoreCase(authenticatedUsername)) {
+          // Since the authenticated user is not the administrator and is asking for a different user,
+          // throw an AuthorizationException
+          throw new AuthorizationException();
+        }
+      }
+
+      Collection<UserAuthenticationEntity> authenticationEntities = users.getUserAuthenticationEntities(requestedUsername, request.getAuthenticationType());
+      if (authenticationEntities != null) {
+        for (UserAuthenticationEntity authenticationEntity : authenticationEntities) {
+          responses.add(createUserAuthenticationSourceResponse(authenticationEntity));
+        }
+      }
+    }
+
+    return responses;
+  }
+
+  /**
+   * Delete the users authentication sources identified by the given request objects.
+   * <p>
+   * It ia assumed that the user has previously been authorized to perform this operation.
+   *
+   * @param requests the request objects
+   * @throws AmbariException if the user authentication sources could not be read
+   */
+  private void deleteUserAuthenticationSources(Set<UserAuthenticationSourceRequest> requests)
+      throws AmbariException, AuthorizationException {
+
+    for (UserAuthenticationSourceRequest r : requests) {
+      String username = r.getUsername();
+      Long sourceId = r.getSourceId();
+      if (!StringUtils.isEmpty(username) && (sourceId != null)) {
+        users.removeAuthentication(username, sourceId);
+      }
+    }
+  }
+
+  private void updateUserAuthenticationSources(Set<UserAuthenticationSourceRequest> requests) throws AuthorizationException, AmbariException {
+
+    Integer authenticatedUserId = AuthorizationHelper.getAuthenticatedId();
+
+
+    for (UserAuthenticationSourceRequest request : requests) {
+      String requestedUsername = request.getUsername();
+
+      UserEntity userEntity = users.getUserEntity(requestedUsername);
+      if (null == userEntity) {
+        continue;
+      }
+
+      boolean isSelf = authenticatedUserId.equals(userEntity.getUserId());
+      /* **************************************************
+       * Ensure that the authenticated user can change the password for the subject user. At least one
+       * of the following must be true
+       *  * The authenticate user is requesting to change his/her own password for a local authentication source
+       *  * The authenticated user has permissions to manage users
+       *  ************************************************** */
+      if (!isSelf && !AuthorizationHelper.isAuthorized(ResourceType.AMBARI, null, RoleAuthorization.AMBARI_MANAGE_USERS)) {
+        throw new AuthorizationException("You are not authorized perform this operation");
+      }
+
+      UserAuthenticationEntity userAuthenticationEntity = null;
+      Long sourceId = request.getSourceId();
+
+      if (sourceId != null) {
+        List<UserAuthenticationEntity> authenticationEntities = userEntity.getAuthenticationEntities();
+        // Find the relevant authentication entity...
+        for (UserAuthenticationEntity authenticationEntity : authenticationEntities) {
+          if (sourceId.equals(authenticationEntity.getUserAuthenticationId())) {
+            userAuthenticationEntity = authenticationEntity;
+            break;
+          }
+        }
+      }
+
+      if (userAuthenticationEntity == null) {
+        // The requested authentication record was not found....
+        throw new ResourceNotFoundException("The requested authentication source was not found.");
+      }
+
+      // If the authentication_type is set, use it to verify that the found authentication source matches it...
+      if ((request.getAuthenticationType() != null) && (request.getAuthenticationType() != userAuthenticationEntity.getAuthenticationType())) {
+        throw new ResourceNotFoundException("The requested authentication source was not found - mismatch on authentication type");
+      }
+
+      users.modifyAuthentication(userAuthenticationEntity, request.getOldKey(), request.getKey(), isSelf);
+    }
+  }
+
+  private UserAuthenticationSourceResponse createUserAuthenticationSourceResponse(UserAuthenticationEntity entity) {
+    return new UserAuthenticationSourceResponse(entity.getUser().getUserName(),
+        entity.getUserAuthenticationId(),
+        entity.getAuthenticationType(),
+        entity.getAuthenticationKey(),
+        entity.getCreateTime(),
+        entity.getUpdateTime());
+  }
+
+
+  /**
+   * Translate the Response into a Resource
+   *
+   * @param response     {@link PrivilegeResponse}
+   * @param requestedIds the relevant request ids
+   * @return a resource
+   */
+  private Resource toResource(UserAuthenticationSourceResponse response, Set<String> requestedIds) {
+    final ResourceImpl resource = new ResourceImpl(Resource.Type.UserAuthenticationSource);
+
+    setResourceProperty(resource, AUTHENTICATION_USER_NAME_PROPERTY_ID, response.getUserName(), requestedIds);
+    setResourceProperty(resource, AUTHENTICATION_AUTHENTICATION_SOURCE_ID_PROPERTY_ID, response.getSourceId(), requestedIds);
+    setResourceProperty(resource, AUTHENTICATION_AUTHENTICATION_TYPE_PROPERTY_ID, response.getAuthenticationType().name(), requestedIds);
+    setResourceProperty(resource, AUTHENTICATION_CREATED_PROPERTY_ID, response.getCreateTime(), requestedIds);
+    setResourceProperty(resource, AUTHENTICATION_UPDATED_PROPERTY_ID, response.getUpdateTime(), requestedIds);
+
+    // NOTE, AUTHENTICATION_KEY_PROPERTY_ID is not being returned here since we don't want to return
+    // any sensitive information.  Once set that data should stay internal to Ambari.
+
+    return resource;
+  }
+}
\ No newline at end of file